Print this page
libc: adjust brk(0) to return the existing break, and use it to initialize sbrk()

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libc/port/sys/sbrk.c
          +++ new/usr/src/lib/libc/port/sys/sbrk.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  28      -
  29   27  #pragma weak _sbrk = sbrk
  30   28  #pragma weak _brk = brk
  31   29  
  32   30  #include "lint.h"
  33   31  #include <synch.h>
  34   32  #include <errno.h>
  35   33  #include <sys/isa_defs.h>
  36   34  #include <sys/types.h>
  37   35  #include <sys/sysmacros.h>
  38   36  #include <inttypes.h>
  39   37  #include <unistd.h>
  40   38  #include "mtlib.h"
  41   39  #include "libc.h"
  42   40  
  43      -extern int _end;
  44      -void *_nd = &_end;
       41 +void *_nd = NULL;
  45   42  mutex_t __sbrk_lock = DEFAULTMUTEX;
  46   43  
  47      -extern int _brk_unlocked(void *);
  48      -extern void *_sbrk_unlocked(intptr_t);
       44 +extern intptr_t _brk_unlocked(void *);
       45 +void *_sbrk_unlocked(intptr_t);
  49   46  
  50   47  /*
  51   48   * The break must always be at least 8-byte aligned
  52   49   */
  53   50  #if (_MAX_ALIGNMENT < 8)
  54   51  #define ALIGNSZ         8
  55   52  #else
  56   53  #define ALIGNSZ         _MAX_ALIGNMENT
  57   54  #endif
  58   55  
↓ open down ↓ 21 lines elided ↑ open up ↑
  80   77   * We must align the old break because _nd may begin life misaligned.
  81   78   * The addend can be either positive or negative, so there are two
  82   79   * overflow/underflow edge conditions to reject:
  83   80   *
  84   81   *   - the addend is negative and brk + addend < 0.
  85   82   *   - the addend is positive and brk + addend > ULONG_MAX
  86   83   */
  87   84  void *
  88   85  _sbrk_unlocked(intptr_t addend)
  89   86  {
  90      -        char *old_brk = BRKALIGN(_nd);
  91      -        char *new_brk = BRKALIGN(old_brk + addend);
       87 +        char *old_brk;
       88 +        char *new_brk;
       89 +
       90 +        if (_nd == NULL) {
       91 +                _nd = (void *)_brk_unlocked(0);
       92 +        }
       93 +
       94 +        old_brk = BRKALIGN(_nd);
       95 +        new_brk = BRKALIGN(old_brk + addend);
  92   96  
  93   97          if ((addend > 0 && new_brk < old_brk) ||
  94   98              (addend < 0 && new_brk > old_brk)) {
  95   99                  errno = ENOMEM;
  96  100                  return ((void *)-1);
  97  101          }
  98  102          if (_brk_unlocked(new_brk) != 0)
  99  103                  return ((void *)-1);
 100  104          _nd = new_brk;
 101  105          return (old_brk);
↓ open down ↓ 25 lines elided ↑ open up ↑
 127  131          if ((low_align & (low_align - 1)) != 0 ||
 128  132              (high_align & (high_align - 1)) != 0) {
 129  133                  errno = EINVAL;
 130  134                  return ((void *)-1);
 131  135          }
 132  136          low_align = MAX(low_align, ALIGNSZ);
 133  137          high_align = MAX(high_align, ALIGNSZ);
 134  138  
 135  139          lmutex_lock(&__sbrk_lock);
 136  140  
      141 +        if (_nd == NULL) {
      142 +                _nd = (void *)_brk_unlocked(0);
      143 +        }
      144 +
 137  145          old_brk = (uintptr_t)BRKALIGN(_nd);
 138  146          ret_brk = P2ROUNDUP(old_brk, low_align);
 139  147          high_brk = ret_brk + min_size;
 140  148          new_brk = P2ROUNDUP(high_brk, high_align);
 141  149  
 142  150          /*
 143  151           * Check for overflow
 144  152           */
 145  153          if (ret_brk < old_brk || high_brk < ret_brk || new_brk < high_brk) {
 146  154                  lmutex_unlock(&__sbrk_lock);
 147  155                  errno = ENOMEM;
 148  156                  return ((void *)-1);
 149  157          }
 150  158  
 151      -        if ((brk_result = _brk_unlocked((void *)new_brk)) == 0)
      159 +        if ((brk_result = (int)_brk_unlocked((void *)new_brk)) == 0)
 152  160                  _nd = (void *)new_brk;
 153  161          lmutex_unlock(&__sbrk_lock);
 154  162  
 155  163          if (brk_result != 0)
 156  164                  return ((void *)-1);
 157  165  
 158  166          if (actual_size != NULL)
 159  167                  *actual_size = (new_brk - ret_brk);
 160  168          return ((void *)ret_brk);
 161  169  }
 162  170  
 163  171  int
 164  172  brk(void *new_brk)
 165  173  {
 166  174          int result;
 167  175  
      176 +        /*
      177 +         * brk(2) will return the current brk if given an argument of 0, so we
      178 +         * need to fail it here
      179 +         */
      180 +        if (new_brk == 0) {
      181 +                errno = ENOMEM;
      182 +                return (-1);
      183 +        }
      184 +
 168  185          if (!primary_link_map) {
 169  186                  errno = ENOTSUP;
 170  187                  return (-1);
 171  188          }
 172  189          /*
 173  190           * Need to align this here;  _brk_unlocked won't do it for us.
 174  191           */
 175  192          new_brk = BRKALIGN(new_brk);
 176  193  
 177  194          lmutex_lock(&__sbrk_lock);
 178      -        if ((result = _brk_unlocked(new_brk)) == 0)
      195 +        if ((result = (int)_brk_unlocked(new_brk)) == 0)
 179  196                  _nd = new_brk;
 180  197          lmutex_unlock(&__sbrk_lock);
 181  198  
 182  199          return (result);
 183  200  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX