[BACK]Return to jemalloc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / stdlib

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/lib/libc/stdlib/jemalloc.c between version 1.19 and 1.29

version 1.19, 2008/06/23 10:46:25 version 1.29, 2013/09/12 15:35:15
Line 288  __strerror_r(int e, char *s, size_t l)
Line 288  __strerror_r(int e, char *s, size_t l)
 #  define SIZEOF_INT_2POW       2  #  define SIZEOF_INT_2POW       2
 #endif  #endif
   
 /* We can't use TLS in non-PIC programs, since TLS relies on loader magic. */  
 #if (!defined(PIC) && !defined(NO_TLS))  
 #  define NO_TLS  
 #endif  
   
 /*  /*
  * Size and alignment of memory chunks that are allocated by the OS's virtual   * Size and alignment of memory chunks that are allocated by the OS's virtual
  * memory system.   * memory system.
Line 319  __strerror_r(int e, char *s, size_t l)
Line 314  __strerror_r(int e, char *s, size_t l)
 #define SMALL_MAX_DEFAULT       (1 << SMALL_MAX_2POW_DEFAULT)  #define SMALL_MAX_DEFAULT       (1 << SMALL_MAX_2POW_DEFAULT)
   
 /*  /*
  * Maximum desired run header overhead.  Runs are sized as small as possible   * RUN_MAX_OVRHD indicates maximum desired run header overhead.  Runs are sized
  * such that this setting is still honored, without violating other constraints.   * as small as possible such that this setting is still honored, without
  * The goal is to make runs as small as possible without exceeding a per run   * violating other constraints.  The goal is to make runs as small as possible
  * external fragmentation threshold.   * without exceeding a per run external fragmentation threshold.
    *
    * We use binary fixed point math for overhead computations, where the binary
    * point is implicitly RUN_BFP bits to the left.
  *   *
  * Note that it is possible to set this low enough that it cannot be honored   * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be
  * for some/all object sizes, since there is one bit of header overhead per   * honored for some/all object sizes, since there is one bit of header overhead
  * object (plus a constant).  In such cases, this constraint is relaxed.   * per object (plus a constant).  This constraint is relaxed (ignored) for runs
    * that are so small that the per-region overhead is greater than:
  *   *
  * RUN_MAX_OVRHD_RELAX specifies the maximum number of bits per region of   *   (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP))
  * overhead for which RUN_MAX_OVRHD is relaxed.  
  */   */
 #define RUN_MAX_OVRHD           0.015  #define RUN_BFP                 12
 #define RUN_MAX_OVRHD_RELAX     1.5  /*                              \/   Implicit binary fixed point. */
   #define RUN_MAX_OVRHD           0x0000003dU
   #define RUN_MAX_OVRHD_RELAX     0x00001800U
   
 /* Put a cap on small object run size.  This overrides RUN_MAX_OVRHD. */  /* Put a cap on small object run size.  This overrides RUN_MAX_OVRHD. */
 #define RUN_MAX_SMALL_2POW      15  #define RUN_MAX_SMALL_2POW      15
Line 811  static void wrtmessage(const char *p1, c
Line 811  static void wrtmessage(const char *p1, c
 #ifdef MALLOC_STATS  #ifdef MALLOC_STATS
 static void     malloc_printf(const char *format, ...);  static void     malloc_printf(const char *format, ...);
 #endif  #endif
 static char     *umax2s(uintmax_t x, char *s);  static char     *size_t2s(size_t x, char *s);
 static bool     base_pages_alloc(size_t minsize);  static bool     base_pages_alloc(size_t minsize);
 static void     *base_alloc(size_t size);  static void     *base_alloc(size_t size);
 static chunk_node_t *base_chunk_node_alloc(void);  static chunk_node_t *base_chunk_node_alloc(void);
Line 973  malloc_printf(const char *format, ...)
Line 973  malloc_printf(const char *format, ...)
   
 /*  /*
  * We don't want to depend on vsnprintf() for production builds, since that can   * We don't want to depend on vsnprintf() for production builds, since that can
  * cause unnecessary bloat for static binaries.  umax2s() provides minimal   * cause unnecessary bloat for static binaries.  size_t2s() provides minimal
  * integer printing functionality, so that malloc_printf() use can be limited to   * integer printing functionality, so that malloc_printf() use can be limited to
  * MALLOC_STATS code.   * MALLOC_STATS code.
  */   */
 #define UMAX2S_BUFSIZE  21  #define UMAX2S_BUFSIZE  21
 static char *  static char *
 umax2s(uintmax_t x, char *s)  size_t2s(size_t x, char *s)
 {  {
         unsigned i;          unsigned i;
   
         /* Make sure UMAX2S_BUFSIZE is large enough. */          /* Make sure UMAX2S_BUFSIZE is large enough. */
         /* LINTED */          /* LINTED */
         assert(sizeof(uintmax_t) <= 8);          assert(sizeof(size_t) <= 8);
   
         i = UMAX2S_BUFSIZE - 1;          i = UMAX2S_BUFSIZE - 1;
         s[i] = '\0';          s[i] = '\0';
Line 1029  base_pages_alloc(size_t minsize)
Line 1029  base_pages_alloc(size_t minsize)
                          */                           */
                         incr = (intptr_t)chunksize                          incr = (intptr_t)chunksize
                             - (intptr_t)CHUNK_ADDR2OFFSET(brk_cur);                              - (intptr_t)CHUNK_ADDR2OFFSET(brk_cur);
                         if (incr < minsize)                          assert(incr >= 0);
                           if ((size_t)incr < minsize)
                                 incr += csize;                                  incr += csize;
   
                         brk_prev = sbrk(incr);                          brk_prev = sbrk(incr);
Line 1364  chunk_alloc(size_t size)
Line 1365  chunk_alloc(size_t size)
                          */                           */
                         incr = (intptr_t)size                          incr = (intptr_t)size
                             - (intptr_t)CHUNK_ADDR2OFFSET(brk_cur);                              - (intptr_t)CHUNK_ADDR2OFFSET(brk_cur);
                         if (incr == size) {                          if (incr == (intptr_t)size) {
                                 ret = brk_cur;                                  ret = brk_cur;
                         } else {                          } else {
                                 ret = (void *)((intptr_t)brk_cur + incr);                                  ret = (void *)((intptr_t)brk_cur + incr);
Line 2142  arena_bin_run_size_calc(arena_bin_t *bin
Line 2143  arena_bin_run_size_calc(arena_bin_t *bin
         size_t try_run_size, good_run_size;          size_t try_run_size, good_run_size;
         unsigned good_nregs, good_mask_nelms, good_reg0_offset;          unsigned good_nregs, good_mask_nelms, good_reg0_offset;
         unsigned try_nregs, try_mask_nelms, try_reg0_offset;          unsigned try_nregs, try_mask_nelms, try_reg0_offset;
         float max_ovrhd = RUN_MAX_OVRHD;  
   
         assert(min_run_size >= pagesize);          assert(min_run_size >= pagesize);
         assert(min_run_size <= arena_maxclass);          assert(min_run_size <= arena_maxclass);
Line 2160  arena_bin_run_size_calc(arena_bin_t *bin
Line 2160  arena_bin_run_size_calc(arena_bin_t *bin
          */           */
         try_run_size = min_run_size;          try_run_size = min_run_size;
         try_nregs = (unsigned)(((try_run_size - sizeof(arena_run_t)) /          try_nregs = (unsigned)(((try_run_size - sizeof(arena_run_t)) /
             bin->reg_size) + 1); /* Counter-act the first line of the loop. */              bin->reg_size) + 1); /* Counter-act try_nregs-- in loop. */
         do {          do {
                 try_nregs--;                  try_nregs--;
                 try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) +                  try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) +
Line 2194  arena_bin_run_size_calc(arena_bin_t *bin
Line 2194  arena_bin_run_size_calc(arena_bin_t *bin
                 } while (sizeof(arena_run_t) + (sizeof(unsigned) *                  } while (sizeof(arena_run_t) + (sizeof(unsigned) *
                     (try_mask_nelms - 1)) > try_reg0_offset);                      (try_mask_nelms - 1)) > try_reg0_offset);
         } while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL          } while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL
             && max_ovrhd > RUN_MAX_OVRHD_RELAX / ((float)(bin->reg_size << 3))              && RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX
             && ((float)(try_reg0_offset)) / ((float)(try_run_size)) >              && (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size);
             max_ovrhd);  
   
         assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1))          assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1))
             <= good_reg0_offset);              <= good_reg0_offset);
Line 2855  huge_ralloc(void *ptr, size_t size, size
Line 2854  huge_ralloc(void *ptr, size_t size, size
                         /* size_t wrap-around */                          /* size_t wrap-around */
                         return (NULL);                          return (NULL);
                 }                  }
   
                   /*
                    * Remove the old region from the tree now.  If mremap()
                    * returns the region to the system, other thread may
                    * map it for same huge allocation and insert it to the
                    * tree before we acquire the mutex lock again.
                    */
                   malloc_mutex_lock(&chunks_mtx);
                   key.chunk = __DECONST(void *, ptr);
                   /* LINTED */
                   node = RB_FIND(chunk_tree_s, &huge, &key);
                   assert(node != NULL);
                   assert(node->chunk == ptr);
                   assert(node->size == oldcsize);
                   RB_REMOVE(chunk_tree_s, &huge, node);
                   malloc_mutex_unlock(&chunks_mtx);
   
                 newptr = mremap(ptr, oldcsize, NULL, newcsize,                  newptr = mremap(ptr, oldcsize, NULL, newcsize,
                     MAP_ALIGNED(chunksize_2pow));                      MAP_ALIGNED(chunksize_2pow));
                 if (newptr != MAP_FAILED) {                  if (newptr == MAP_FAILED) {
                           /* We still own the old region. */
                           malloc_mutex_lock(&chunks_mtx);
                           RB_INSERT(chunk_tree_s, &huge, node);
                           malloc_mutex_unlock(&chunks_mtx);
                   } else {
                         assert(CHUNK_ADDR2BASE(newptr) == newptr);                          assert(CHUNK_ADDR2BASE(newptr) == newptr);
   
                         /* update tree */                          /* Insert new or resized old region. */
                         malloc_mutex_lock(&chunks_mtx);                          malloc_mutex_lock(&chunks_mtx);
                         key.chunk = __DECONST(void *, ptr);  
                         /* LINTED */  
                         node = RB_FIND(chunk_tree_s, &huge, &key);  
                         assert(node != NULL);  
                         assert(node->chunk == ptr);  
                         assert(node->size == oldcsize);  
                         node->size = newcsize;                          node->size = newcsize;
                         if (ptr != newptr) {                          node->chunk = newptr;
                                 RB_REMOVE(chunk_tree_s, &huge, node);                          RB_INSERT(chunk_tree_s, &huge, node);
                                 node->chunk = newptr;  
                                 RB_INSERT(chunk_tree_s, &huge, node);  
                         }  
 #ifdef MALLOC_STATS  #ifdef MALLOC_STATS
                         huge_nralloc++;                          huge_nralloc++;
                         huge_allocated += newcsize - oldcsize;                          huge_allocated += newcsize - oldcsize;
Line 3201  malloc_print_stats(void)
Line 3213  malloc_print_stats(void)
                     opt_xmalloc ? "X" : "x",                      opt_xmalloc ? "X" : "x",
                     opt_zero ? "Z\n" : "z\n");                      opt_zero ? "Z\n" : "z\n");
   
                 _malloc_message("CPUs: ", umax2s(ncpus, s), "\n", "");                  _malloc_message("CPUs: ", size_t2s(ncpus, s), "\n", "");
                 _malloc_message("Max arenas: ", umax2s(narenas, s), "\n", "");                  _malloc_message("Max arenas: ", size_t2s(narenas, s), "\n", "");
                 _malloc_message("Pointer size: ", umax2s(sizeof(void *), s),                  _malloc_message("Pointer size: ", size_t2s(sizeof(void *), s),
                     "\n", "");                      "\n", "");
                 _malloc_message("Quantum size: ", umax2s(quantum, s), "\n", "");                  _malloc_message("Quantum size: ", size_t2s(quantum, s), "\n", "");
                 _malloc_message("Max small size: ", umax2s(small_max, s), "\n",                  _malloc_message("Max small size: ", size_t2s(small_max, s), "\n",
                     "");                      "");
   
                 _malloc_message("Chunk size: ", umax2s(chunksize, s), "", "");                  _malloc_message("Chunk size: ", size_t2s(chunksize, s), "", "");
                 _malloc_message(" (2^", umax2s(opt_chunk_2pow, s), ")\n", "");                  _malloc_message(" (2^", size_t2s((size_t)opt_chunk_2pow, s),
                       ")\n", "");
   
 #ifdef MALLOC_STATS  #ifdef MALLOC_STATS
                 {                  {
Line 3308  malloc_init_hard(void)
Line 3321  malloc_init_hard(void)
         ssize_t linklen;          ssize_t linklen;
         char buf[PATH_MAX + 1];          char buf[PATH_MAX + 1];
         const char *opts = "";          const char *opts = "";
           int serrno;
   
         malloc_mutex_lock(&init_lock);          malloc_mutex_lock(&init_lock);
         if (malloc_initialized) {          if (malloc_initialized) {
Line 3319  malloc_init_hard(void)
Line 3333  malloc_init_hard(void)
                 return (false);                  return (false);
         }          }
   
           serrno = errno;
         /* Get number of CPUs. */          /* Get number of CPUs. */
         {          {
                 int mib[2];                  int mib[2];
Line 3430  malloc_init_hard(void)
Line 3445  malloc_init_hard(void)
                                         opt_chunk_2pow--;                                          opt_chunk_2pow--;
                                 break;                                  break;
                         case 'K':                          case 'K':
                                 /*                                  if (opt_chunk_2pow + 1 <
                                  * There must be fewer pages in a chunk than                                      (int)(sizeof(size_t) << 3))
                                  * can be recorded by the pos field of  
                                  * arena_chunk_map_t, in order to make POS_FREE  
                                  * special.  
                                  */  
                                 if (opt_chunk_2pow - pagesize_2pow  
                                     < (sizeof(uint32_t) << 3) - 1)  
                                         opt_chunk_2pow++;                                          opt_chunk_2pow++;
                                 break;                                  break;
                         case 'n':                          case 'n':
Line 3504  malloc_init_hard(void)
Line 3513  malloc_init_hard(void)
                         }                          }
                 }                  }
         }          }
           errno = serrno;
   
         /* Take care to call atexit() only once. */          /* Take care to call atexit() only once. */
         if (opt_print_stats) {          if (opt_print_stats) {

Legend:
Removed from v.1.19  
changed lines
  Added in v.1.29

CVSweb <webmaster@jp.NetBSD.org>