malloc.c
上传用户:wealth48
上传日期:2022-06-24
资源大小:1701k
文件大小:182k
源码类别:

uCOS

开发平台:

C/C++

  1. #endif
  2. {
  3.   /* same as recycled case ... */
  4.   do_check_remalloced_chunk(p, s);
  5.   /*
  6.     ... plus,  must obey implementation invariant that prev_inuse is
  7.     always true of any allocated chunk; i.e., that each allocated
  8.     chunk borders either a previously allocated and still in-use
  9.     chunk, or the base of its memory arena. This is ensured
  10.     by making all allocations from the the `lowest' part of any found
  11.     chunk.  This does not necessarily hold however for chunks
  12.     recycled via fastbins.
  13.   */
  14.   assert(prev_inuse(p));
  15. }
  16. /*
  17.   Properties of malloc_state.
  18.   This may be useful for debugging malloc, as well as detecting user
  19.   programmer errors that somehow write into malloc_state.
  20.   If you are extending or experimenting with this malloc, you can
  21.   probably figure out how to hack this routine to print out or
  22.   display chunk addresses, sizes, bins, and other instrumentation.
  23. */
  24. static void do_check_malloc_state()
  25. {
  26.   mstate av = get_malloc_state();
  27.   int i;
  28.   mchunkptr p;
  29.   mchunkptr q;
  30.   mbinptr b;
  31.   unsigned int binbit;
  32.   int empty;
  33.   unsigned int idx;
  34.   INTERNAL_SIZE_T size;
  35.   CHUNK_SIZE_T  total = 0;
  36.   int max_fast_bin;
  37.   /* internal size_t must be no wider than pointer type */
  38.   assert(sizeof(INTERNAL_SIZE_T) <= sizeof(char*));
  39.   /* alignment is a power of 2 */
  40.   assert((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-1)) == 0);
  41.   /* cannot run remaining checks until fully initialized */
  42.   if (av->top == 0 || av->top == initial_top(av))
  43.     return;
  44.   /* pagesize is a power of 2 */
  45.   assert((av->pagesize & (av->pagesize-1)) == 0);
  46.   /* properties of fastbins */
  47.   /* max_fast is in allowed range */
  48.   assert(get_max_fast(av) <= request2size(MAX_FAST_SIZE));
  49.   max_fast_bin = fastbin_index(av->max_fast);
  50.   for (i = 0; i < NFASTBINS; ++i) {
  51.     p = av->fastbins[i];
  52.     /* all bins past max_fast are empty */
  53.     if (i > max_fast_bin)
  54.       assert(p == 0);
  55.     while (p != 0) {
  56.       /* each chunk claims to be inuse */
  57.       do_check_inuse_chunk(p);
  58.       total += chunksize(p);
  59.       /* chunk belongs in this bin */
  60.       assert(fastbin_index(chunksize(p)) == i);
  61.       p = p->fd;
  62.     }
  63.   }
  64.   if (total != 0)
  65.     assert(have_fastchunks(av));
  66.   else if (!have_fastchunks(av))
  67.     assert(total == 0);
  68.   /* check normal bins */
  69.   for (i = 1; i < NBINS; ++i) {
  70.     b = bin_at(av,i);
  71.     /* binmap is accurate (except for bin 1 == unsorted_chunks) */
  72.     if (i >= 2) {
  73.       binbit = get_binmap(av,i);
  74.       empty = last(b) == b;
  75.       if (!binbit)
  76.         assert(empty);
  77.       else if (!empty)
  78.         assert(binbit);
  79.     }
  80.     for (p = last(b); p != b; p = p->bk) {
  81.       /* each chunk claims to be free */
  82.       do_check_free_chunk(p);
  83.       size = chunksize(p);
  84.       total += size;
  85.       if (i >= 2) {
  86.         /* chunk belongs in bin */
  87.         idx = bin_index(size);
  88.         assert(idx == i);
  89.         /* lists are sorted */
  90.         if ((CHUNK_SIZE_T) size >= (CHUNK_SIZE_T)(FIRST_SORTED_BIN_SIZE)) {
  91.           assert(p->bk == b || 
  92.                  (CHUNK_SIZE_T)chunksize(p->bk) >= 
  93.                  (CHUNK_SIZE_T)chunksize(p));
  94.         }
  95.       }
  96.       /* chunk is followed by a legal chain of inuse chunks */
  97.       for (q = next_chunk(p);
  98.            (q != av->top && inuse(q) && 
  99.              (CHUNK_SIZE_T)(chunksize(q)) >= MINSIZE);
  100.            q = next_chunk(q))
  101.         do_check_inuse_chunk(q);
  102.     }
  103.   }
  104.   /* top chunk is OK */
  105.   check_chunk(av->top);
  106.   /* sanity checks for statistics */
  107.   assert(total <= (CHUNK_SIZE_T)(av->max_total_mem));
  108.   assert(av->n_mmaps >= 0);
  109.   assert(av->n_mmaps <= av->max_n_mmaps);
  110.   assert((CHUNK_SIZE_T)(av->sbrked_mem) <=
  111.          (CHUNK_SIZE_T)(av->max_sbrked_mem));
  112.   assert((CHUNK_SIZE_T)(av->mmapped_mem) <=
  113.          (CHUNK_SIZE_T)(av->max_mmapped_mem));
  114.   assert((CHUNK_SIZE_T)(av->max_total_mem) >=
  115.          (CHUNK_SIZE_T)(av->mmapped_mem) + (CHUNK_SIZE_T)(av->sbrked_mem));
  116. }
  117. #endif
  118. /* ----------- Routines dealing with system allocation -------------- */
  119. /*
  120.   sysmalloc handles malloc cases requiring more memory from the system.
  121.   On entry, it is assumed that av->top does not have enough
  122.   space to service request for nb bytes, thus requiring that av->top
  123.   be extended or replaced.
  124. */
  125. #if __STD_C
  126. static Void_t* sYSMALLOc(INTERNAL_SIZE_T nb, mstate av)
  127. #else
  128. static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av;
  129. #endif
  130. {
  131.   mchunkptr       old_top;        /* incoming value of av->top */
  132.   INTERNAL_SIZE_T old_size;       /* its size */
  133.   char*           old_end;        /* its end address */
  134.   long            size;           /* arg to first MORECORE or mmap call */
  135.   char*           brk;            /* return value from MORECORE */
  136.   long            correction;     /* arg to 2nd MORECORE call */
  137.   char*           snd_brk;        /* 2nd return val */
  138.   INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
  139.   INTERNAL_SIZE_T end_misalign;   /* partial page left at end of new space */
  140.   char*           aligned_brk;    /* aligned offset into brk */
  141.   mchunkptr       p;              /* the allocated/returned chunk */
  142.   mchunkptr       remainder;      /* remainder from allocation */
  143.   CHUNK_SIZE_T    remainder_size; /* its size */
  144.   CHUNK_SIZE_T    sum;            /* for updating stats */
  145.   size_t          pagemask  = av->pagesize - 1;
  146.   /*
  147.     If there is space available in fastbins, consolidate and retry
  148.     malloc from scratch rather than getting memory from system.  This
  149.     can occur only if nb is in smallbin range so we didn't consolidate
  150.     upon entry to malloc. It is much easier to handle this case here
  151.     than in malloc proper.
  152.   */
  153.   if (have_fastchunks(av)) {
  154.     assert(in_smallbin_range(nb));
  155.     malloc_consolidate(av);
  156.     return mALLOc(nb - MALLOC_ALIGN_MASK);
  157.   }
  158. #if HAVE_MMAP
  159.   /*
  160.     If have mmap, and the request size meets the mmap threshold, and
  161.     the system supports mmap, and there are few enough currently
  162.     allocated mmapped regions, try to directly map this request
  163.     rather than expanding top.
  164.   */
  165.   if ((CHUNK_SIZE_T)(nb) >= (CHUNK_SIZE_T)(av->mmap_threshold) &&
  166.       (av->n_mmaps < av->n_mmaps_max)) {
  167.     char* mm;             /* return value from mmap call*/
  168.     /*
  169.       Round up size to nearest page.  For mmapped chunks, the overhead
  170.       is one SIZE_SZ unit larger than for normal chunks, because there
  171.       is no following chunk whose prev_size field could be used.
  172.     */
  173.     size = (nb + SIZE_SZ + MALLOC_ALIGN_MASK + pagemask) & ~pagemask;
  174.     /* Don't try if size wraps around 0 */
  175.     if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb)) {
  176.       mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE));
  177.       
  178.       if (mm != (char*)(MORECORE_FAILURE)) {
  179.         
  180.         /*
  181.           The offset to the start of the mmapped region is stored
  182.           in the prev_size field of the chunk. This allows us to adjust
  183.           returned start address to meet alignment requirements here 
  184.           and in memalign(), and still be able to compute proper
  185.           address argument for later munmap in free() and realloc().
  186.         */
  187.         
  188.         front_misalign = (INTERNAL_SIZE_T)chunk2mem(mm) & MALLOC_ALIGN_MASK;
  189.         if (front_misalign > 0) {
  190.           correction = MALLOC_ALIGNMENT - front_misalign;
  191.           p = (mchunkptr)(mm + correction);
  192.           p->prev_size = correction;
  193.           set_head(p, (size - correction) |IS_MMAPPED);
  194.         }
  195.         else {
  196.           p = (mchunkptr)mm;
  197.           p->prev_size = 0;
  198.           set_head(p, size|IS_MMAPPED);
  199.         }
  200.         
  201.         /* update statistics */
  202.         
  203.         if (++av->n_mmaps > av->max_n_mmaps) 
  204.           av->max_n_mmaps = av->n_mmaps;
  205.         
  206.         sum = av->mmapped_mem += size;
  207.         if (sum > (CHUNK_SIZE_T)(av->max_mmapped_mem)) 
  208.           av->max_mmapped_mem = sum;
  209.         sum += av->sbrked_mem;
  210.         if (sum > (CHUNK_SIZE_T)(av->max_total_mem)) 
  211.           av->max_total_mem = sum;
  212.         check_chunk(p);
  213.         
  214.         return chunk2mem(p);
  215.       }
  216.     }
  217.   }
  218. #endif
  219.   /* Record incoming configuration of top */
  220.   old_top  = av->top;
  221.   old_size = chunksize(old_top);
  222.   old_end  = (char*)(chunk_at_offset(old_top, old_size));
  223.   brk = snd_brk = (char*)(MORECORE_FAILURE); 
  224.   /* 
  225.      If not the first time through, we require old_size to be
  226.      at least MINSIZE and to have prev_inuse set.
  227.   */
  228.   assert((old_top == initial_top(av) && old_size == 0) || 
  229.          ((CHUNK_SIZE_T) (old_size) >= MINSIZE &&
  230.           prev_inuse(old_top)));
  231.   /* Precondition: not enough current space to satisfy nb request */
  232.   assert((CHUNK_SIZE_T)(old_size) < (CHUNK_SIZE_T)(nb + MINSIZE));
  233.   /* Precondition: all fastbins are consolidated */
  234.   assert(!have_fastchunks(av));
  235.   /* Request enough space for nb + pad + overhead */
  236.   size = nb + av->top_pad + MINSIZE;
  237.   /*
  238.     If contiguous, we can subtract out existing space that we hope to
  239.     combine with new space. We add it back later only if
  240.     we don't actually get contiguous space.
  241.   */
  242.   if (contiguous(av))
  243.     size -= old_size;
  244.   /*
  245.     Round to a multiple of page size.
  246.     If MORECORE is not contiguous, this ensures that we only call it
  247.     with whole-page arguments.  And if MORECORE is contiguous and
  248.     this is not first time through, this preserves page-alignment of
  249.     previous calls. Otherwise, we correct to page-align below.
  250.   */
  251.   size = (size + pagemask) & ~pagemask;
  252.   /*
  253.     Don't try to call MORECORE if argument is so big as to appear
  254.     negative. Note that since mmap takes size_t arg, it may succeed
  255.     below even if we cannot call MORECORE.
  256.   */
  257.   if (size > 0) 
  258.     brk = (char*)(MORECORE(size));
  259.   /*
  260.     If have mmap, try using it as a backup when MORECORE fails or
  261.     cannot be used. This is worth doing on systems that have "holes" in
  262.     address space, so sbrk cannot extend to give contiguous space, but
  263.     space is available elsewhere.  Note that we ignore mmap max count
  264.     and threshold limits, since the space will not be used as a
  265.     segregated mmap region.
  266.   */
  267. #if HAVE_MMAP
  268.   if (brk == (char*)(MORECORE_FAILURE)) {
  269.     /* Cannot merge with old top, so add its size back in */
  270.     if (contiguous(av))
  271.       size = (size + old_size + pagemask) & ~pagemask;
  272.     /* If we are relying on mmap as backup, then use larger units */
  273.     if ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(MMAP_AS_MORECORE_SIZE))
  274.       size = MMAP_AS_MORECORE_SIZE;
  275.     /* Don't try if size wraps around 0 */
  276.     if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb)) {
  277.       brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE));
  278.       
  279.       if (brk != (char*)(MORECORE_FAILURE)) {
  280.         
  281.         /* We do not need, and cannot use, another sbrk call to find end */
  282.         snd_brk = brk + size;
  283.         
  284.         /* 
  285.            Record that we no longer have a contiguous sbrk region. 
  286.            After the first time mmap is used as backup, we do not
  287.            ever rely on contiguous space since this could incorrectly
  288.            bridge regions.
  289.         */
  290.         set_noncontiguous(av);
  291.       }
  292.     }
  293.   }
  294. #endif
  295.   if (brk != (char*)(MORECORE_FAILURE)) {
  296.     av->sbrked_mem += size;
  297.     /*
  298.       If MORECORE extends previous space, we can likewise extend top size.
  299.     */
  300.     
  301.     if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) {
  302.       set_head(old_top, (size + old_size) | PREV_INUSE);
  303.     }
  304.     /*
  305.       Otherwise, make adjustments:
  306.       
  307.       * If the first time through or noncontiguous, we need to call sbrk
  308.         just to find out where the end of memory lies.
  309.       * We need to ensure that all returned chunks from malloc will meet
  310.         MALLOC_ALIGNMENT
  311.       * If there was an intervening foreign sbrk, we need to adjust sbrk
  312.         request size to account for fact that we will not be able to
  313.         combine new space with existing space in old_top.
  314.       * Almost all systems internally allocate whole pages at a time, in
  315.         which case we might as well use the whole last page of request.
  316.         So we allocate enough more memory to hit a page boundary now,
  317.         which in turn causes future contiguous calls to page-align.
  318.     */
  319.     
  320.     else {
  321.       front_misalign = 0;
  322.       end_misalign = 0;
  323.       correction = 0;
  324.       aligned_brk = brk;
  325.       /*
  326.         If MORECORE returns an address lower than we have seen before,
  327.         we know it isn't really contiguous.  This and some subsequent
  328.         checks help cope with non-conforming MORECORE functions and
  329.         the presence of "foreign" calls to MORECORE from outside of
  330.         malloc or by other threads.  We cannot guarantee to detect
  331.         these in all cases, but cope with the ones we do detect.
  332.       */
  333.       if (contiguous(av) && old_size != 0 && brk < old_end) {
  334.         set_noncontiguous(av);
  335.       }
  336.       
  337.       /* handle contiguous cases */
  338.       if (contiguous(av)) { 
  339.         /* 
  340.            We can tolerate forward non-contiguities here (usually due
  341.            to foreign calls) but treat them as part of our space for
  342.            stats reporting.
  343.         */
  344.         if (old_size != 0) 
  345.           av->sbrked_mem += brk - old_end;
  346.         
  347.         /* Guarantee alignment of first new chunk made from this space */
  348.         front_misalign = (INTERNAL_SIZE_T)chunk2mem(brk) & MALLOC_ALIGN_MASK;
  349.         if (front_misalign > 0) {
  350.           /*
  351.             Skip over some bytes to arrive at an aligned position.
  352.             We don't need to specially mark these wasted front bytes.
  353.             They will never be accessed anyway because
  354.             prev_inuse of av->top (and any chunk created from its start)
  355.             is always true after initialization.
  356.           */
  357.           correction = MALLOC_ALIGNMENT - front_misalign;
  358.           aligned_brk += correction;
  359.         }
  360.         
  361.         /*
  362.           If this isn't adjacent to existing space, then we will not
  363.           be able to merge with old_top space, so must add to 2nd request.
  364.         */
  365.         
  366.         correction += old_size;
  367.         
  368.         /* Extend the end address to hit a page boundary */
  369.         end_misalign = (INTERNAL_SIZE_T)(brk + size + correction);
  370.         correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign;
  371.         
  372.         assert(correction >= 0);
  373.         snd_brk = (char*)(MORECORE(correction));
  374.         
  375.         if (snd_brk == (char*)(MORECORE_FAILURE)) {
  376.           /*
  377.             If can't allocate correction, try to at least find out current
  378.             brk.  It might be enough to proceed without failing.
  379.           */
  380.           correction = 0;
  381.           snd_brk = (char*)(MORECORE(0));
  382.         }
  383.         else if (snd_brk < brk) {
  384.           /*
  385.             If the second call gives noncontiguous space even though
  386.             it says it won't, the only course of action is to ignore
  387.             results of second call, and conservatively estimate where
  388.             the first call left us. Also set noncontiguous, so this
  389.             won't happen again, leaving at most one hole.
  390.             
  391.             Note that this check is intrinsically incomplete.  Because
  392.             MORECORE is allowed to give more space than we ask for,
  393.             there is no reliable way to detect a noncontiguity
  394.             producing a forward gap for the second call.
  395.           */
  396.           snd_brk = brk + size;
  397.           correction = 0;
  398.           set_noncontiguous(av);
  399.         }
  400.       }
  401.       
  402.       /* handle non-contiguous cases */
  403.       else { 
  404.         /* MORECORE/mmap must correctly align */
  405.         assert(aligned_OK(chunk2mem(brk)));
  406.         
  407.         /* Find out current end of memory */
  408.         if (snd_brk == (char*)(MORECORE_FAILURE)) {
  409.           snd_brk = (char*)(MORECORE(0));
  410.           av->sbrked_mem += snd_brk - brk - size;
  411.         }
  412.       }
  413.       
  414.       /* Adjust top based on results of second sbrk */
  415.       if (snd_brk != (char*)(MORECORE_FAILURE)) {
  416.         av->top = (mchunkptr)aligned_brk;
  417.         set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
  418.         av->sbrked_mem += correction;
  419.      
  420.         /*
  421.           If not the first time through, we either have a
  422.           gap due to foreign sbrk or a non-contiguous region.  Insert a
  423.           double fencepost at old_top to prevent consolidation with space
  424.           we don't own. These fenceposts are artificial chunks that are
  425.           marked as inuse and are in any case too small to use.  We need
  426.           two to make sizes and alignments work out.
  427.         */
  428.    
  429.         if (old_size != 0) {
  430.           /* 
  431.              Shrink old_top to insert fenceposts, keeping size a
  432.              multiple of MALLOC_ALIGNMENT. We know there is at least
  433.              enough space in old_top to do this.
  434.           */
  435.           old_size = (old_size - 3*SIZE_SZ) & ~MALLOC_ALIGN_MASK;
  436.           set_head(old_top, old_size | PREV_INUSE);
  437.           
  438.           /*
  439.             Note that the following assignments completely overwrite
  440.             old_top when old_size was previously MINSIZE.  This is
  441.             intentional. We need the fencepost, even if old_top otherwise gets
  442.             lost.
  443.           */
  444.           chunk_at_offset(old_top, old_size          )->size =
  445.             SIZE_SZ|PREV_INUSE;
  446.           chunk_at_offset(old_top, old_size + SIZE_SZ)->size =
  447.             SIZE_SZ|PREV_INUSE;
  448.           /* 
  449.              If possible, release the rest, suppressing trimming.
  450.           */
  451.           if (old_size >= MINSIZE) {
  452.             INTERNAL_SIZE_T tt = av->trim_threshold;
  453.             av->trim_threshold = (INTERNAL_SIZE_T)(-1);
  454.             fREe(chunk2mem(old_top));
  455.             av->trim_threshold = tt;
  456.           }
  457.         }
  458.       }
  459.     }
  460.     
  461.     /* Update statistics */
  462.     sum = av->sbrked_mem;
  463.     if (sum > (CHUNK_SIZE_T)(av->max_sbrked_mem))
  464.       av->max_sbrked_mem = sum;
  465.     
  466.     sum += av->mmapped_mem;
  467.     if (sum > (CHUNK_SIZE_T)(av->max_total_mem))
  468.       av->max_total_mem = sum;
  469.     check_malloc_state();
  470.     
  471.     /* finally, do the allocation */
  472.     p = av->top;
  473.     size = chunksize(p);
  474.     
  475.     /* check that one of the above allocation paths succeeded */
  476.     if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb + MINSIZE)) {
  477.       remainder_size = size - nb;
  478.       remainder = chunk_at_offset(p, nb);
  479.       av->top = remainder;
  480.       set_head(p, nb | PREV_INUSE);
  481.       set_head(remainder, remainder_size | PREV_INUSE);
  482.       check_malloced_chunk(p, nb);
  483.       return chunk2mem(p);
  484.     }
  485.   }
  486.   /* catch all failure paths */
  487.   MALLOC_FAILURE_ACTION;
  488.   return 0;
  489. }
  490. /*
  491.   sYSTRIm is an inverse of sorts to sYSMALLOc.  It gives memory back
  492.   to the system (via negative arguments to sbrk) if there is unused
  493.   memory at the `high' end of the malloc pool. It is called
  494.   automatically by free() when top space exceeds the trim
  495.   threshold. It is also called by the public malloc_trim routine.  It
  496.   returns 1 if it actually released any memory, else 0.
  497. */
  498. #if __STD_C
  499. static int sYSTRIm(size_t pad, mstate av)
  500. #else
  501. static int sYSTRIm(pad, av) size_t pad; mstate av;
  502. #endif
  503. {
  504.   long  top_size;        /* Amount of top-most memory */
  505.   long  extra;           /* Amount to release */
  506.   long  released;        /* Amount actually released */
  507.   char* current_brk;     /* address returned by pre-check sbrk call */
  508.   char* new_brk;         /* address returned by post-check sbrk call */
  509.   size_t pagesz;
  510.   pagesz = av->pagesize;
  511.   top_size = chunksize(av->top);
  512.   
  513.   /* Release in pagesize units, keeping at least one page */
  514.   extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz;
  515.   
  516.   if (extra > 0) {
  517.     
  518.     /*
  519.       Only proceed if end of memory is where we last set it.
  520.       This avoids problems if there were foreign sbrk calls.
  521.     */
  522.     current_brk = (char*)(MORECORE(0));
  523.     if (current_brk == (char*)(av->top) + top_size) {
  524.       
  525.       /*
  526.         Attempt to release memory. We ignore MORECORE return value,
  527.         and instead call again to find out where new end of memory is.
  528.         This avoids problems if first call releases less than we asked,
  529.         of if failure somehow altered brk value. (We could still
  530.         encounter problems if it altered brk in some very bad way,
  531.         but the only thing we can do is adjust anyway, which will cause
  532.         some downstream failure.)
  533.       */
  534.       
  535.       MORECORE(-extra);
  536.       new_brk = (char*)(MORECORE(0));
  537.       
  538.       if (new_brk != (char*)MORECORE_FAILURE) {
  539.         released = (long)(current_brk - new_brk);
  540.         
  541.         if (released != 0) {
  542.           /* Success. Adjust top. */
  543.           av->sbrked_mem -= released;
  544.           set_head(av->top, (top_size - released) | PREV_INUSE);
  545.           check_malloc_state();
  546.           return 1;
  547.         }
  548.       }
  549.     }
  550.   }
  551.   return 0;
  552. }
  553. /*
  554.   ------------------------------ malloc ------------------------------
  555. */
  556. #if __STD_C
  557. Void_t* mALLOc(size_t bytes)
  558. #else
  559.   Void_t* mALLOc(bytes) size_t bytes;
  560. #endif
  561. {
  562.   mstate av = get_malloc_state();
  563.   INTERNAL_SIZE_T nb;               /* normalized request size */
  564.   unsigned int    idx;              /* associated bin index */
  565.   mbinptr         bin;              /* associated bin */
  566.   mfastbinptr*    fb;               /* associated fastbin */
  567.   mchunkptr       victim;           /* inspected/selected chunk */
  568.   INTERNAL_SIZE_T size;             /* its size */
  569.   int             victim_index;     /* its bin index */
  570.   mchunkptr       remainder;        /* remainder from a split */
  571.   CHUNK_SIZE_T    remainder_size;   /* its size */
  572.   unsigned int    block;            /* bit map traverser */
  573.   unsigned int    bit;              /* bit map traverser */
  574.   unsigned int    map;              /* current word of binmap */
  575.   mchunkptr       fwd;              /* misc temp for linking */
  576.   mchunkptr       bck;              /* misc temp for linking */
  577.   /*
  578.     Convert request size to internal form by adding SIZE_SZ bytes
  579.     overhead plus possibly more to obtain necessary alignment and/or
  580.     to obtain a size of at least MINSIZE, the smallest allocatable
  581.     size. Also, checked_request2size traps (returning 0) request sizes
  582.     that are so large that they wrap around zero when padded and
  583.     aligned.
  584.   */
  585.   checked_request2size(bytes, nb);
  586.   /*
  587.     Bypass search if no frees yet
  588.    */
  589.   if (!have_anychunks(av)) {
  590.     if (av->max_fast == 0) /* initialization check */
  591.       malloc_consolidate(av);
  592.     goto use_top;
  593.   }
  594.   /*
  595.     If the size qualifies as a fastbin, first check corresponding bin.
  596.   */
  597.   if ((CHUNK_SIZE_T)(nb) <= (CHUNK_SIZE_T)(av->max_fast)) { 
  598.     fb = &(av->fastbins[(fastbin_index(nb))]);
  599.     if ( (victim = *fb) != 0) {
  600.       *fb = victim->fd;
  601.       check_remalloced_chunk(victim, nb);
  602.       return chunk2mem(victim);
  603.     }
  604.   }
  605.   /*
  606.     If a small request, check regular bin.  Since these "smallbins"
  607.     hold one size each, no searching within bins is necessary.
  608.     (For a large request, we need to wait until unsorted chunks are
  609.     processed to find best fit. But for small ones, fits are exact
  610.     anyway, so we can check now, which is faster.)
  611.   */
  612.   if (in_smallbin_range(nb)) {
  613.     idx = smallbin_index(nb);
  614.     bin = bin_at(av,idx);
  615.     if ( (victim = last(bin)) != bin) {
  616.       bck = victim->bk;
  617.       set_inuse_bit_at_offset(victim, nb);
  618.       bin->bk = bck;
  619.       bck->fd = bin;
  620.       
  621.       check_malloced_chunk(victim, nb);
  622.       return chunk2mem(victim);
  623.     }
  624.   }
  625.   /* 
  626.      If this is a large request, consolidate fastbins before continuing.
  627.      While it might look excessive to kill all fastbins before
  628.      even seeing if there is space available, this avoids
  629.      fragmentation problems normally associated with fastbins.
  630.      Also, in practice, programs tend to have runs of either small or
  631.      large requests, but less often mixtures, so consolidation is not 
  632.      invoked all that often in most programs. And the programs that
  633.      it is called frequently in otherwise tend to fragment.
  634.   */
  635.   else {
  636.     idx = largebin_index(nb);
  637.     if (have_fastchunks(av)) 
  638.       malloc_consolidate(av);
  639.   }
  640.   /*
  641.     Process recently freed or remaindered chunks, taking one only if
  642.     it is exact fit, or, if this a small request, the chunk is remainder from
  643.     the most recent non-exact fit.  Place other traversed chunks in
  644.     bins.  Note that this step is the only place in any routine where
  645.     chunks are placed in bins.
  646.   */
  647.     
  648.   while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {
  649.     bck = victim->bk;
  650.     size = chunksize(victim);
  651.     
  652.     /* 
  653.        If a small request, try to use last remainder if it is the
  654.        only chunk in unsorted bin.  This helps promote locality for
  655.        runs of consecutive small requests. This is the only
  656.        exception to best-fit, and applies only when there is
  657.        no exact fit for a small chunk.
  658.     */
  659.     
  660.     if (in_smallbin_range(nb) && 
  661.         bck == unsorted_chunks(av) &&
  662.         victim == av->last_remainder &&
  663.         (CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb + MINSIZE)) {
  664.       
  665.       /* split and reattach remainder */
  666.       remainder_size = size - nb;
  667.       remainder = chunk_at_offset(victim, nb);
  668.       unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
  669.       av->last_remainder = remainder; 
  670.       remainder->bk = remainder->fd = unsorted_chunks(av);
  671.       
  672.       set_head(victim, nb | PREV_INUSE);
  673.       set_head(remainder, remainder_size | PREV_INUSE);
  674.       set_foot(remainder, remainder_size);
  675.       
  676.       check_malloced_chunk(victim, nb);
  677.       return chunk2mem(victim);
  678.     }
  679.     
  680.     /* remove from unsorted list */
  681.     unsorted_chunks(av)->bk = bck;
  682.     bck->fd = unsorted_chunks(av);
  683.     
  684.     /* Take now instead of binning if exact fit */
  685.     
  686.     if (size == nb) {
  687.       set_inuse_bit_at_offset(victim, size);
  688.       check_malloced_chunk(victim, nb);
  689.       return chunk2mem(victim);
  690.     }
  691.     
  692.     /* place chunk in bin */
  693.     
  694.     if (in_smallbin_range(size)) {
  695.       victim_index = smallbin_index(size);
  696.       bck = bin_at(av, victim_index);
  697.       fwd = bck->fd;
  698.     }
  699.     else {
  700.       victim_index = largebin_index(size);
  701.       bck = bin_at(av, victim_index);
  702.       fwd = bck->fd;
  703.       
  704.       if (fwd != bck) {
  705.         /* if smaller than smallest, place first */
  706.         if ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(bck->bk->size)) {
  707.           fwd = bck;
  708.           bck = bck->bk;
  709.         }
  710.         else if ((CHUNK_SIZE_T)(size) >= 
  711.                  (CHUNK_SIZE_T)(FIRST_SORTED_BIN_SIZE)) {
  712.           
  713.           /* maintain large bins in sorted order */
  714.           size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */
  715.           while ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(fwd->size)) 
  716.             fwd = fwd->fd;
  717.           bck = fwd->bk;
  718.         }
  719.       }
  720.     }
  721.       
  722.     mark_bin(av, victim_index);
  723.     victim->bk = bck;
  724.     victim->fd = fwd;
  725.     fwd->bk = victim;
  726.     bck->fd = victim;
  727.   }
  728.   
  729.   /*
  730.     If a large request, scan through the chunks of current bin to
  731.     find one that fits.  (This will be the smallest that fits unless
  732.     FIRST_SORTED_BIN_SIZE has been changed from default.)  This is
  733.     the only step where an unbounded number of chunks might be
  734.     scanned without doing anything useful with them. However the
  735.     lists tend to be short.
  736.   */
  737.   
  738.   if (!in_smallbin_range(nb)) {
  739.     bin = bin_at(av, idx);
  740.     
  741.     for (victim = last(bin); victim != bin; victim = victim->bk) {
  742.       size = chunksize(victim);
  743.       
  744.       if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb)) {
  745.         remainder_size = size - nb;
  746.         unlink(victim, bck, fwd);
  747.         
  748.         /* Exhaust */
  749.         if (remainder_size < MINSIZE)  {
  750.           set_inuse_bit_at_offset(victim, size);
  751.           check_malloced_chunk(victim, nb);
  752.           return chunk2mem(victim);
  753.         }
  754.         /* Split */
  755.         else {
  756.           remainder = chunk_at_offset(victim, nb);
  757.           unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
  758.           remainder->bk = remainder->fd = unsorted_chunks(av);
  759.           set_head(victim, nb | PREV_INUSE);
  760.           set_head(remainder, remainder_size | PREV_INUSE);
  761.           set_foot(remainder, remainder_size);
  762.           check_malloced_chunk(victim, nb);
  763.           return chunk2mem(victim);
  764.         } 
  765.       }
  766.     }    
  767.   }
  768.   /*
  769.     Search for a chunk by scanning bins, starting with next largest
  770.     bin. This search is strictly by best-fit; i.e., the smallest
  771.     (with ties going to approximately the least recently used) chunk
  772.     that fits is selected.
  773.     
  774.     The bitmap avoids needing to check that most blocks are nonempty.
  775.   */
  776.     
  777.   ++idx;
  778.   bin = bin_at(av,idx);
  779.   block = idx2block(idx);
  780.   map = av->binmap[block];
  781.   bit = idx2bit(idx);
  782.   
  783.   for (;;) {
  784.     
  785.     /* Skip rest of block if there are no more set bits in this block.  */
  786.     if (bit > map || bit == 0) {
  787.       do {
  788.         if (++block >= BINMAPSIZE)  /* out of bins */
  789.           goto use_top;
  790.       } while ( (map = av->binmap[block]) == 0);
  791.       
  792.       bin = bin_at(av, (block << BINMAPSHIFT));
  793.       bit = 1;
  794.     }
  795.     
  796.     /* Advance to bin with set bit. There must be one. */
  797.     while ((bit & map) == 0) {
  798.       bin = next_bin(bin);
  799.       bit <<= 1;
  800.       assert(bit != 0);
  801.     }
  802.     
  803.     /* Inspect the bin. It is likely to be non-empty */
  804.     victim = last(bin);
  805.     
  806.     /*  If a false alarm (empty bin), clear the bit. */
  807.     if (victim == bin) {
  808.       av->binmap[block] = map &= ~bit; /* Write through */
  809.       bin = next_bin(bin);
  810.       bit <<= 1;
  811.     }
  812.     
  813.     else {
  814.       size = chunksize(victim);
  815.       
  816.       /*  We know the first chunk in this bin is big enough to use. */
  817.       assert((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb));
  818.       
  819.       remainder_size = size - nb;
  820.       
  821.       /* unlink */
  822.       bck = victim->bk;
  823.       bin->bk = bck;
  824.       bck->fd = bin;
  825.       
  826.       /* Exhaust */
  827.       if (remainder_size < MINSIZE) {
  828.         set_inuse_bit_at_offset(victim, size);
  829.         check_malloced_chunk(victim, nb);
  830.         return chunk2mem(victim);
  831.       }
  832.       
  833.       /* Split */
  834.       else {
  835.         remainder = chunk_at_offset(victim, nb);
  836.         
  837.         unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
  838.         remainder->bk = remainder->fd = unsorted_chunks(av);
  839.         /* advertise as last remainder */
  840.         if (in_smallbin_range(nb)) 
  841.           av->last_remainder = remainder; 
  842.         
  843.         set_head(victim, nb | PREV_INUSE);
  844.         set_head(remainder, remainder_size | PREV_INUSE);
  845.         set_foot(remainder, remainder_size);
  846.         check_malloced_chunk(victim, nb);
  847.         return chunk2mem(victim);
  848.       }
  849.     }
  850.   }
  851.   use_top:    
  852.   /*
  853.     If large enough, split off the chunk bordering the end of memory
  854.     (held in av->top). Note that this is in accord with the best-fit
  855.     search rule.  In effect, av->top is treated as larger (and thus
  856.     less well fitting) than any other available chunk since it can
  857.     be extended to be as large as necessary (up to system
  858.     limitations).
  859.     
  860.     We require that av->top always exists (i.e., has size >=
  861.     MINSIZE) after initialization, so if it would otherwise be
  862.     exhuasted by current request, it is replenished. (The main
  863.     reason for ensuring it exists is that we may need MINSIZE space
  864.     to put in fenceposts in sysmalloc.)
  865.   */
  866.   
  867.   victim = av->top;
  868.   size = chunksize(victim);
  869.   
  870.   if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb + MINSIZE)) {
  871.     remainder_size = size - nb;
  872.     remainder = chunk_at_offset(victim, nb);
  873.     av->top = remainder;
  874.     set_head(victim, nb | PREV_INUSE);
  875.     set_head(remainder, remainder_size | PREV_INUSE);
  876.     
  877.     check_malloced_chunk(victim, nb);
  878.     return chunk2mem(victim);
  879.   }
  880.   
  881.   /* 
  882.      If no space in top, relay to handle system-dependent cases 
  883.   */
  884.   return sYSMALLOc(nb, av);    
  885. }
  886. /*
  887.   ------------------------------ free ------------------------------
  888. */
  889. #if __STD_C
  890. void fREe(Void_t* mem)
  891. #else
  892. void fREe(mem) Void_t* mem;
  893. #endif
  894. {
  895.   mstate av = get_malloc_state();
  896.   mchunkptr       p;           /* chunk corresponding to mem */
  897.   INTERNAL_SIZE_T size;        /* its size */
  898.   mfastbinptr*    fb;          /* associated fastbin */
  899.   mchunkptr       nextchunk;   /* next contiguous chunk */
  900.   INTERNAL_SIZE_T nextsize;    /* its size */
  901.   int             nextinuse;   /* true if nextchunk is used */
  902.   INTERNAL_SIZE_T prevsize;    /* size of previous contiguous chunk */
  903.   mchunkptr       bck;         /* misc temp for linking */
  904.   mchunkptr       fwd;         /* misc temp for linking */
  905.   /* free(0) has no effect */
  906.   if (mem != 0) {
  907.     p = mem2chunk(mem);
  908.     size = chunksize(p);
  909.     check_inuse_chunk(p);
  910.     /*
  911.       If eligible, place chunk on a fastbin so it can be found
  912.       and used quickly in malloc.
  913.     */
  914.     if ((CHUNK_SIZE_T)(size) <= (CHUNK_SIZE_T)(av->max_fast)
  915. #if TRIM_FASTBINS
  916.         /* 
  917.            If TRIM_FASTBINS set, don't place chunks
  918.            bordering top into fastbins
  919.         */
  920.         && (chunk_at_offset(p, size) != av->top)
  921. #endif
  922.         ) {
  923.       set_fastchunks(av);
  924.       fb = &(av->fastbins[fastbin_index(size)]);
  925.       p->fd = *fb;
  926.       *fb = p;
  927.     }
  928.     /*
  929.        Consolidate other non-mmapped chunks as they arrive.
  930.     */
  931.     else if (!chunk_is_mmapped(p)) {
  932.       set_anychunks(av);
  933.       nextchunk = chunk_at_offset(p, size);
  934.       nextsize = chunksize(nextchunk);
  935.       /* consolidate backward */
  936.       if (!prev_inuse(p)) {
  937.         prevsize = p->prev_size;
  938.         size += prevsize;
  939.         p = chunk_at_offset(p, -((long) prevsize));
  940.         unlink(p, bck, fwd);
  941.       }
  942.       if (nextchunk != av->top) {
  943.         /* get and clear inuse bit */
  944.         nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
  945.         set_head(nextchunk, nextsize);
  946.         /* consolidate forward */
  947.         if (!nextinuse) {
  948.           unlink(nextchunk, bck, fwd);
  949.           size += nextsize;
  950.         }
  951.         /*
  952.           Place the chunk in unsorted chunk list. Chunks are
  953.           not placed into regular bins until after they have
  954.           been given one chance to be used in malloc.
  955.         */
  956.         bck = unsorted_chunks(av);
  957.         fwd = bck->fd;
  958.         p->bk = bck;
  959.         p->fd = fwd;
  960.         bck->fd = p;
  961.         fwd->bk = p;
  962.         set_head(p, size | PREV_INUSE);
  963.         set_foot(p, size);
  964.         
  965.         check_free_chunk(p);
  966.       }
  967.       /*
  968.          If the chunk borders the current high end of memory,
  969.          consolidate into top
  970.       */
  971.       else {
  972.         size += nextsize;
  973.         set_head(p, size | PREV_INUSE);
  974.         av->top = p;
  975.         check_chunk(p);
  976.       }
  977.       /*
  978.         If freeing a large space, consolidate possibly-surrounding
  979.         chunks. Then, if the total unused topmost memory exceeds trim
  980.         threshold, ask malloc_trim to reduce top.
  981.         Unless max_fast is 0, we don't know if there are fastbins
  982.         bordering top, so we cannot tell for sure whether threshold
  983.         has been reached unless fastbins are consolidated.  But we
  984.         don't want to consolidate on each free.  As a compromise,
  985.         consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
  986.         is reached.
  987.       */
  988.       if ((CHUNK_SIZE_T)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) { 
  989.         if (have_fastchunks(av)) 
  990.           malloc_consolidate(av);
  991. #ifndef MORECORE_CANNOT_TRIM        
  992.         if ((CHUNK_SIZE_T)(chunksize(av->top)) >= 
  993.             (CHUNK_SIZE_T)(av->trim_threshold))
  994.           sYSTRIm(av->top_pad, av);
  995. #endif
  996.       }
  997.     }
  998.     /*
  999.       If the chunk was allocated via mmap, release via munmap()
  1000.       Note that if HAVE_MMAP is false but chunk_is_mmapped is
  1001.       true, then user must have overwritten memory. There's nothing
  1002.       we can do to catch this error unless DEBUG is set, in which case
  1003.       check_inuse_chunk (above) will have triggered error.
  1004.     */
  1005.     else {
  1006. #if HAVE_MMAP
  1007.       int ret;
  1008.       INTERNAL_SIZE_T offset = p->prev_size;
  1009.       av->n_mmaps--;
  1010.       av->mmapped_mem -= (size + offset);
  1011.       ret = munmap((char*)p - offset, size + offset);
  1012.       /* munmap returns non-zero on failure */
  1013.       assert(ret == 0);
  1014. #endif
  1015.     }
  1016.   }
  1017. }
  1018. /*
  1019.   ------------------------- malloc_consolidate -------------------------
  1020.   malloc_consolidate is a specialized version of free() that tears
  1021.   down chunks held in fastbins.  Free itself cannot be used for this
  1022.   purpose since, among other things, it might place chunks back onto
  1023.   fastbins.  So, instead, we need to use a minor variant of the same
  1024.   code.
  1025.   
  1026.   Also, because this routine needs to be called the first time through
  1027.   malloc anyway, it turns out to be the perfect place to trigger
  1028.   initialization code.
  1029. */
  1030. #if __STD_C
  1031. static void malloc_consolidate(mstate av)
  1032. #else
  1033. static void malloc_consolidate(av) mstate av;
  1034. #endif
  1035. {
  1036.   mfastbinptr*    fb;                 /* current fastbin being consolidated */
  1037.   mfastbinptr*    maxfb;              /* last fastbin (for loop control) */
  1038.   mchunkptr       p;                  /* current chunk being consolidated */
  1039.   mchunkptr       nextp;              /* next chunk to consolidate */
  1040.   mchunkptr       unsorted_bin;       /* bin header */
  1041.   mchunkptr       first_unsorted;     /* chunk to link to */
  1042.   /* These have same use as in free() */
  1043.   mchunkptr       nextchunk;
  1044.   INTERNAL_SIZE_T size;
  1045.   INTERNAL_SIZE_T nextsize;
  1046.   INTERNAL_SIZE_T prevsize;
  1047.   int             nextinuse;
  1048.   mchunkptr       bck;
  1049.   mchunkptr       fwd;
  1050.   /*
  1051.     If max_fast is 0, we know that av hasn't
  1052.     yet been initialized, in which case do so below
  1053.   */
  1054.   if (av->max_fast != 0) {
  1055.     clear_fastchunks(av);
  1056.     unsorted_bin = unsorted_chunks(av);
  1057.     /*
  1058.       Remove each chunk from fast bin and consolidate it, placing it
  1059.       then in unsorted bin. Among other reasons for doing this,
  1060.       placing in unsorted bin avoids needing to calculate actual bins
  1061.       until malloc is sure that chunks aren't immediately going to be
  1062.       reused anyway.
  1063.     */
  1064.     
  1065.     maxfb = &(av->fastbins[fastbin_index(av->max_fast)]);
  1066.     fb = &(av->fastbins[0]);
  1067.     do {
  1068.       if ( (p = *fb) != 0) {
  1069.         *fb = 0;
  1070.         
  1071.         do {
  1072.           check_inuse_chunk(p);
  1073.           nextp = p->fd;
  1074.           
  1075.           /* Slightly streamlined version of consolidation code in free() */
  1076.           size = p->size & ~PREV_INUSE;
  1077.           nextchunk = chunk_at_offset(p, size);
  1078.           nextsize = chunksize(nextchunk);
  1079.           
  1080.           if (!prev_inuse(p)) {
  1081.             prevsize = p->prev_size;
  1082.             size += prevsize;
  1083.             p = chunk_at_offset(p, -((long) prevsize));
  1084.             unlink(p, bck, fwd);
  1085.           }
  1086.           
  1087.           if (nextchunk != av->top) {
  1088.             nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
  1089.             set_head(nextchunk, nextsize);
  1090.             
  1091.             if (!nextinuse) {
  1092.               size += nextsize;
  1093.               unlink(nextchunk, bck, fwd);
  1094.             }
  1095.             
  1096.             first_unsorted = unsorted_bin->fd;
  1097.             unsorted_bin->fd = p;
  1098.             first_unsorted->bk = p;
  1099.             
  1100.             set_head(p, size | PREV_INUSE);
  1101.             p->bk = unsorted_bin;
  1102.             p->fd = first_unsorted;
  1103.             set_foot(p, size);
  1104.           }
  1105.           
  1106.           else {
  1107.             size += nextsize;
  1108.             set_head(p, size | PREV_INUSE);
  1109.             av->top = p;
  1110.           }
  1111.           
  1112.         } while ( (p = nextp) != 0);
  1113.         
  1114.       }
  1115.     } while (fb++ != maxfb);
  1116.   }
  1117.   else {
  1118.     malloc_init_state(av);
  1119.     check_malloc_state();
  1120.   }
  1121. }
  1122. /*
  1123.   ------------------------------ realloc ------------------------------
  1124. */
  1125. #if __STD_C
  1126. Void_t* rEALLOc(Void_t* oldmem, size_t bytes)
  1127. #else
  1128. Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
  1129. #endif
  1130. {
  1131.   mstate av = get_malloc_state();
  1132.   INTERNAL_SIZE_T  nb;              /* padded request size */
  1133.   mchunkptr        oldp;            /* chunk corresponding to oldmem */
  1134.   INTERNAL_SIZE_T  oldsize;         /* its size */
  1135.   mchunkptr        newp;            /* chunk to return */
  1136.   INTERNAL_SIZE_T  newsize;         /* its size */
  1137.   Void_t*          newmem;          /* corresponding user mem */
  1138.   mchunkptr        next;            /* next contiguous chunk after oldp */
  1139.   mchunkptr        remainder;       /* extra space at end of newp */
  1140.   CHUNK_SIZE_T     remainder_size;  /* its size */
  1141.   mchunkptr        bck;             /* misc temp for linking */
  1142.   mchunkptr        fwd;             /* misc temp for linking */
  1143.   CHUNK_SIZE_T     copysize;        /* bytes to copy */
  1144.   unsigned int     ncopies;         /* INTERNAL_SIZE_T words to copy */
  1145.   INTERNAL_SIZE_T* s;               /* copy source */ 
  1146.   INTERNAL_SIZE_T* d;               /* copy destination */
  1147. #ifdef REALLOC_ZERO_BYTES_FREES
  1148.   if (bytes == 0) {
  1149.     fREe(oldmem);
  1150.     return 0;
  1151.   }
  1152. #endif
  1153.   /* realloc of null is supposed to be same as malloc */
  1154.   if (oldmem == 0) return mALLOc(bytes);
  1155.   checked_request2size(bytes, nb);
  1156.   oldp    = mem2chunk(oldmem);
  1157.   oldsize = chunksize(oldp);
  1158.   check_inuse_chunk(oldp);
  1159.   if (!chunk_is_mmapped(oldp)) {
  1160.     if ((CHUNK_SIZE_T)(oldsize) >= (CHUNK_SIZE_T)(nb)) {
  1161.       /* already big enough; split below */
  1162.       newp = oldp;
  1163.       newsize = oldsize;
  1164.     }
  1165.     else {
  1166.       next = chunk_at_offset(oldp, oldsize);
  1167.       /* Try to expand forward into top */
  1168.       if (next == av->top &&
  1169.           (CHUNK_SIZE_T)(newsize = oldsize + chunksize(next)) >=
  1170.           (CHUNK_SIZE_T)(nb + MINSIZE)) {
  1171.         set_head_size(oldp, nb);
  1172.         av->top = chunk_at_offset(oldp, nb);
  1173.         set_head(av->top, (newsize - nb) | PREV_INUSE);
  1174.         return chunk2mem(oldp);
  1175.       }
  1176.       
  1177.       /* Try to expand forward into next chunk;  split off remainder below */
  1178.       else if (next != av->top && 
  1179.                !inuse(next) &&
  1180.                (CHUNK_SIZE_T)(newsize = oldsize + chunksize(next)) >=
  1181.                (CHUNK_SIZE_T)(nb)) {
  1182.         newp = oldp;
  1183.         unlink(next, bck, fwd);
  1184.       }
  1185.       /* allocate, copy, free */
  1186.       else {
  1187.         newmem = mALLOc(nb - MALLOC_ALIGN_MASK);
  1188.         if (newmem == 0)
  1189.           return 0; /* propagate failure */
  1190.       
  1191.         newp = mem2chunk(newmem);
  1192.         newsize = chunksize(newp);
  1193.         
  1194.         /*
  1195.           Avoid copy if newp is next chunk after oldp.
  1196.         */
  1197.         if (newp == next) {
  1198.           newsize += oldsize;
  1199.           newp = oldp;
  1200.         }
  1201.         else {
  1202.           /*
  1203.             Unroll copy of <= 36 bytes (72 if 8byte sizes)
  1204.             We know that contents have an odd number of
  1205.             INTERNAL_SIZE_T-sized words; minimally 3.
  1206.           */
  1207.           
  1208.           copysize = oldsize - SIZE_SZ;
  1209.           s = (INTERNAL_SIZE_T*)(oldmem);
  1210.           d = (INTERNAL_SIZE_T*)(newmem);
  1211.           ncopies = copysize / sizeof(INTERNAL_SIZE_T);
  1212.           assert(ncopies >= 3);
  1213.           
  1214.           if (ncopies > 9)
  1215.             MALLOC_COPY(d, s, copysize);
  1216.           
  1217.           else {
  1218.             *(d+0) = *(s+0);
  1219.             *(d+1) = *(s+1);
  1220.             *(d+2) = *(s+2);
  1221.             if (ncopies > 4) {
  1222.               *(d+3) = *(s+3);
  1223.               *(d+4) = *(s+4);
  1224.               if (ncopies > 6) {
  1225.                 *(d+5) = *(s+5);
  1226.                 *(d+6) = *(s+6);
  1227.                 if (ncopies > 8) {
  1228.                   *(d+7) = *(s+7);
  1229.                   *(d+8) = *(s+8);
  1230.                 }
  1231.               }
  1232.             }
  1233.           }
  1234.           
  1235.           fREe(oldmem);
  1236.           check_inuse_chunk(newp);
  1237.           return chunk2mem(newp);
  1238.         }
  1239.       }
  1240.     }
  1241.     /* If possible, free extra space in old or extended chunk */
  1242.     assert((CHUNK_SIZE_T)(newsize) >= (CHUNK_SIZE_T)(nb));
  1243.     remainder_size = newsize - nb;
  1244.     if (remainder_size < MINSIZE) { /* not enough extra to split off */
  1245.       set_head_size(newp, newsize);
  1246.       set_inuse_bit_at_offset(newp, newsize);
  1247.     }
  1248.     else { /* split remainder */
  1249.       remainder = chunk_at_offset(newp, nb);
  1250.       set_head_size(newp, nb);
  1251.       set_head(remainder, remainder_size | PREV_INUSE);
  1252.       /* Mark remainder as inuse so free() won't complain */
  1253.       set_inuse_bit_at_offset(remainder, remainder_size);
  1254.       fREe(chunk2mem(remainder)); 
  1255.     }
  1256.     check_inuse_chunk(newp);
  1257.     return chunk2mem(newp);
  1258.   }
  1259.   /*
  1260.     Handle mmap cases
  1261.   */
  1262.   else {
  1263. #if HAVE_MMAP
  1264. #if HAVE_MREMAP
  1265.     INTERNAL_SIZE_T offset = oldp->prev_size;
  1266.     size_t pagemask = av->pagesize - 1;
  1267.     char *cp;
  1268.     CHUNK_SIZE_T  sum;
  1269.     
  1270.     /* Note the extra SIZE_SZ overhead */
  1271.     newsize = (nb + offset + SIZE_SZ + pagemask) & ~pagemask;
  1272.     /* don't need to remap if still within same page */
  1273.     if (oldsize == newsize - offset) 
  1274.       return oldmem;
  1275.     cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1);
  1276.     
  1277.     if (cp != (char*)MORECORE_FAILURE) {
  1278.       newp = (mchunkptr)(cp + offset);
  1279.       set_head(newp, (newsize - offset)|IS_MMAPPED);
  1280.       
  1281.       assert(aligned_OK(chunk2mem(newp)));
  1282.       assert((newp->prev_size == offset));
  1283.       
  1284.       /* update statistics */
  1285.       sum = av->mmapped_mem += newsize - oldsize;
  1286.       if (sum > (CHUNK_SIZE_T)(av->max_mmapped_mem)) 
  1287.         av->max_mmapped_mem = sum;
  1288.       sum += av->sbrked_mem;
  1289.       if (sum > (CHUNK_SIZE_T)(av->max_total_mem)) 
  1290.         av->max_total_mem = sum;
  1291.       
  1292.       return chunk2mem(newp);
  1293.     }
  1294. #endif
  1295.     /* Note the extra SIZE_SZ overhead. */
  1296.     if ((CHUNK_SIZE_T)(oldsize) >= (CHUNK_SIZE_T)(nb + SIZE_SZ)) 
  1297.       newmem = oldmem; /* do nothing */
  1298.     else {
  1299.       /* Must alloc, copy, free. */
  1300.       newmem = mALLOc(nb - MALLOC_ALIGN_MASK);
  1301.       if (newmem != 0) {
  1302.         MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ);
  1303.         fREe(oldmem);
  1304.       }
  1305.     }
  1306.     return newmem;
  1307. #else 
  1308.     /* If !HAVE_MMAP, but chunk_is_mmapped, user must have overwritten mem */
  1309.     check_malloc_state();
  1310.     MALLOC_FAILURE_ACTION;
  1311.     return 0;
  1312. #endif
  1313.   }
  1314. }
  1315. /*
  1316.   ------------------------------ memalign ------------------------------
  1317. */
  1318. #if __STD_C
  1319. Void_t* mEMALIGn(size_t alignment, size_t bytes)
  1320. #else
  1321. Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
  1322. #endif
  1323. {
  1324.   INTERNAL_SIZE_T nb;             /* padded  request size */
  1325.   char*           m;              /* memory returned by malloc call */
  1326.   mchunkptr       p;              /* corresponding chunk */
  1327.   char*           brk;            /* alignment point within p */
  1328.   mchunkptr       newp;           /* chunk to return */
  1329.   INTERNAL_SIZE_T newsize;        /* its size */
  1330.   INTERNAL_SIZE_T leadsize;       /* leading space before alignment point */
  1331.   mchunkptr       remainder;      /* spare room at end to split off */
  1332.   CHUNK_SIZE_T    remainder_size; /* its size */
  1333.   INTERNAL_SIZE_T size;
  1334.   /* If need less alignment than we give anyway, just relay to malloc */
  1335.   if (alignment <= MALLOC_ALIGNMENT) return mALLOc(bytes);
  1336.   /* Otherwise, ensure that it is at least a minimum chunk size */
  1337.   if (alignment <  MINSIZE) alignment = MINSIZE;
  1338.   /* Make sure alignment is power of 2 (in case MINSIZE is not).  */
  1339.   if ((alignment & (alignment - 1)) != 0) {
  1340.     size_t a = MALLOC_ALIGNMENT * 2;
  1341.     while ((CHUNK_SIZE_T)a < (CHUNK_SIZE_T)alignment) a <<= 1;
  1342.     alignment = a;
  1343.   }
  1344.   checked_request2size(bytes, nb);
  1345.   /*
  1346.     Strategy: find a spot within that chunk that meets the alignment
  1347.     request, and then possibly free the leading and trailing space.
  1348.   */
  1349.   /* Call malloc with worst case padding to hit alignment. */
  1350.   m  = (char*)(mALLOc(nb + alignment + MINSIZE));
  1351.   if (m == 0) return 0; /* propagate failure */
  1352.   p = mem2chunk(m);
  1353.   if ((((PTR_UINT)(m)) % alignment) != 0) { /* misaligned */
  1354.     /*
  1355.       Find an aligned spot inside chunk.  Since we need to give back
  1356.       leading space in a chunk of at least MINSIZE, if the first
  1357.       calculation places us at a spot with less than MINSIZE leader,
  1358.       we can move to the next aligned spot -- we've allocated enough
  1359.       total room so that this is always possible.
  1360.     */
  1361.     brk = (char*)mem2chunk((PTR_UINT)(((PTR_UINT)(m + alignment - 1)) &
  1362.                            -((signed long) alignment)));
  1363.     if ((CHUNK_SIZE_T)(brk - (char*)(p)) < MINSIZE)
  1364.       brk += alignment;
  1365.     newp = (mchunkptr)brk;
  1366.     leadsize = brk - (char*)(p);
  1367.     newsize = chunksize(p) - leadsize;
  1368.     /* For mmapped chunks, just adjust offset */
  1369.     if (chunk_is_mmapped(p)) {
  1370.       newp->prev_size = p->prev_size + leadsize;
  1371.       set_head(newp, newsize|IS_MMAPPED);
  1372.       return chunk2mem(newp);
  1373.     }
  1374.     /* Otherwise, give back leader, use the rest */
  1375.     set_head(newp, newsize | PREV_INUSE);
  1376.     set_inuse_bit_at_offset(newp, newsize);
  1377.     set_head_size(p, leadsize);
  1378.     fREe(chunk2mem(p));
  1379.     p = newp;
  1380.     assert (newsize >= nb &&
  1381.             (((PTR_UINT)(chunk2mem(p))) % alignment) == 0);
  1382.   }
  1383.   /* Also give back spare room at the end */
  1384.   if (!chunk_is_mmapped(p)) {
  1385.     size = chunksize(p);
  1386.     if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb + MINSIZE)) {
  1387.       remainder_size = size - nb;
  1388.       remainder = chunk_at_offset(p, nb);
  1389.       set_head(remainder, remainder_size | PREV_INUSE);
  1390.       set_head_size(p, nb);
  1391.       fREe(chunk2mem(remainder));
  1392.     }
  1393.   }
  1394.   check_inuse_chunk(p);
  1395.   return chunk2mem(p);
  1396. }
  1397. /*
  1398.   ------------------------------ calloc ------------------------------
  1399. */
  1400. #if __STD_C
  1401. Void_t* cALLOc(size_t n_elements, size_t elem_size)
  1402. #else
  1403. Void_t* cALLOc(n_elements, elem_size) size_t n_elements; size_t elem_size;
  1404. #endif
  1405. {
  1406.   mchunkptr p;
  1407.   CHUNK_SIZE_T  clearsize;
  1408.   CHUNK_SIZE_T  nclears;
  1409.   INTERNAL_SIZE_T* d;
  1410.   Void_t* mem = mALLOc(n_elements * elem_size);
  1411.   if (mem != 0) {
  1412.     p = mem2chunk(mem);
  1413.     if (!chunk_is_mmapped(p))
  1414.     {  
  1415.       /*
  1416.         Unroll clear of <= 36 bytes (72 if 8byte sizes)
  1417.         We know that contents have an odd number of
  1418.         INTERNAL_SIZE_T-sized words; minimally 3.
  1419.       */
  1420.       d = (INTERNAL_SIZE_T*)mem;
  1421.       clearsize = chunksize(p) - SIZE_SZ;
  1422.       nclears = clearsize / sizeof(INTERNAL_SIZE_T);
  1423.       assert(nclears >= 3);
  1424.       if (nclears > 9)
  1425.         MALLOC_ZERO(d, clearsize);
  1426.       else {
  1427.         *(d+0) = 0;
  1428.         *(d+1) = 0;
  1429.         *(d+2) = 0;
  1430.         if (nclears > 4) {
  1431.           *(d+3) = 0;
  1432.           *(d+4) = 0;
  1433.           if (nclears > 6) {
  1434.             *(d+5) = 0;
  1435.             *(d+6) = 0;
  1436.             if (nclears > 8) {
  1437.               *(d+7) = 0;
  1438.               *(d+8) = 0;
  1439.             }
  1440.           }
  1441.         }
  1442.       }
  1443.     }
  1444. #if ! MMAP_CLEARS
  1445.     else
  1446.     {
  1447.       d = (INTERNAL_SIZE_T*)mem;
  1448.       /*
  1449.         Note the additional SIZE_SZ
  1450.       */
  1451.       clearsize = chunksize(p) - 2*SIZE_SZ;
  1452.       MALLOC_ZERO(d, clearsize);
  1453.     }
  1454. #endif
  1455.   }
  1456.   return mem;
  1457. }
  1458. /*
  1459.   ------------------------------ valloc ------------------------------
  1460. */
  1461. #if __STD_C
  1462. Void_t* vALLOc(size_t bytes)
  1463. #else
  1464. Void_t* vALLOc(bytes) size_t bytes;
  1465. #endif
  1466. {
  1467.   /* Ensure initialization */
  1468.   mstate av = get_malloc_state();
  1469.   if (av->max_fast == 0) malloc_consolidate(av);
  1470.   return mEMALIGn(av->pagesize, bytes);
  1471. }
  1472. #if 0
  1473. /*
  1474.   ------------------------------ cfree ------------------------------
  1475. */
  1476. #if __STD_C
  1477. void cFREe(Void_t *mem)
  1478. #else
  1479. void cFREe(mem) Void_t *mem;
  1480. #endif
  1481. {
  1482.   fREe(mem);
  1483. }
  1484. /*
  1485.   ------------------------- independent_calloc -------------------------
  1486. */
  1487. #if __STD_C
  1488. Void_t** iCALLOc(size_t n_elements, size_t elem_size, Void_t* chunks[])
  1489. #else
  1490. Void_t** iCALLOc(n_elements, elem_size, chunks) size_t n_elements; size_t elem_size; Void_t* chunks[];
  1491. #endif
  1492. {
  1493.   size_t sz = elem_size; /* serves as 1-element array */
  1494.   /* opts arg of 3 means all elements are same size, and should be cleared */
  1495.   return iALLOc(n_elements, &sz, 3, chunks);
  1496. }
  1497. /*
  1498.   ------------------------- independent_comalloc -------------------------
  1499. */
  1500. #if __STD_C
  1501. Void_t** iCOMALLOc(size_t n_elements, size_t sizes[], Void_t* chunks[])
  1502. #else
  1503. Void_t** iCOMALLOc(n_elements, sizes, chunks) size_t n_elements; size_t sizes[]; Void_t* chunks[];
  1504. #endif
  1505. {
  1506.   return iALLOc(n_elements, sizes, 0, chunks);
  1507. }
  1508. /*
  1509.   ------------------------------ ialloc ------------------------------
  1510.   ialloc provides common support for independent_X routines, handling all of
  1511.   the combinations that can result.
  1512.   The opts arg has:
  1513.     bit 0 set if all elements are same size (using sizes[0])
  1514.     bit 1 set if elements should be zeroed
  1515. */
  1516. #if __STD_C
  1517. static Void_t** iALLOc(size_t n_elements, 
  1518.                        size_t* sizes,  
  1519.                        int opts,
  1520.                        Void_t* chunks[])
  1521. #else
  1522. static Void_t** iALLOc(n_elements, sizes, opts, chunks) size_t n_elements; size_t* sizes; int opts; Void_t* chunks[];
  1523. #endif
  1524. {
  1525.   mstate av = get_malloc_state();
  1526.   INTERNAL_SIZE_T element_size;   /* chunksize of each element, if all same */
  1527.   INTERNAL_SIZE_T contents_size;  /* total size of elements */
  1528.   INTERNAL_SIZE_T array_size;     /* request size of pointer array */
  1529.   Void_t*         mem;            /* malloced aggregate space */
  1530.   mchunkptr       p;              /* corresponding chunk */
  1531.   INTERNAL_SIZE_T remainder_size; /* remaining bytes while splitting */
  1532.   Void_t**        marray;         /* either "chunks" or malloced ptr array */
  1533.   mchunkptr       array_chunk;    /* chunk for malloced ptr array */
  1534.   int             mmx;            /* to disable mmap */
  1535.   INTERNAL_SIZE_T size;           
  1536.   size_t          i;
  1537.   /* Ensure initialization */
  1538.   if (av->max_fast == 0) malloc_consolidate(av);
  1539.   /* compute array length, if needed */
  1540.   if (chunks != 0) {
  1541.     if (n_elements == 0)
  1542.       return chunks; /* nothing to do */
  1543.     marray = chunks;
  1544.     array_size = 0;
  1545.   }
  1546.   else {
  1547.     /* if empty req, must still return chunk representing empty array */
  1548.     if (n_elements == 0) 
  1549.       return (Void_t**) mALLOc(0);
  1550.     marray = 0;
  1551.     array_size = request2size(n_elements * (sizeof(Void_t*)));
  1552.   }
  1553.   /* compute total element size */
  1554.   if (opts & 0x1) { /* all-same-size */
  1555.     element_size = request2size(*sizes);
  1556.     contents_size = n_elements * element_size;
  1557.   }
  1558.   else { /* add up all the sizes */
  1559.     element_size = 0;
  1560.     contents_size = 0;
  1561.     for (i = 0; i != n_elements; ++i) 
  1562.       contents_size += request2size(sizes[i]);     
  1563.   }
  1564.   /* subtract out alignment bytes from total to minimize overallocation */
  1565.   size = contents_size + array_size - MALLOC_ALIGN_MASK;
  1566.   
  1567.   /* 
  1568.      Allocate the aggregate chunk.
  1569.      But first disable mmap so malloc won't use it, since
  1570.      we would not be able to later free/realloc space internal
  1571.      to a segregated mmap region.
  1572.  */
  1573.   mmx = av->n_mmaps_max;   /* disable mmap */
  1574.   av->n_mmaps_max = 0;
  1575.   mem = mALLOc(size);
  1576.   av->n_mmaps_max = mmx;   /* reset mmap */
  1577.   if (mem == 0) 
  1578.     return 0;
  1579.   p = mem2chunk(mem);
  1580.   assert(!chunk_is_mmapped(p)); 
  1581.   remainder_size = chunksize(p);
  1582.   if (opts & 0x2) {       /* optionally clear the elements */
  1583.     MALLOC_ZERO(mem, remainder_size - SIZE_SZ - array_size);
  1584.   }
  1585.   /* If not provided, allocate the pointer array as final part of chunk */
  1586.   if (marray == 0) {
  1587.     array_chunk = chunk_at_offset(p, contents_size);
  1588.     marray = (Void_t**) (chunk2mem(array_chunk));
  1589.     set_head(array_chunk, (remainder_size - contents_size) | PREV_INUSE);
  1590.     remainder_size = contents_size;
  1591.   }
  1592.   /* split out elements */
  1593.   for (i = 0; ; ++i) {
  1594.     marray[i] = chunk2mem(p);
  1595.     if (i != n_elements-1) {
  1596.       if (element_size != 0) 
  1597.         size = element_size;
  1598.       else
  1599.         size = request2size(sizes[i]);          
  1600.       remainder_size -= size;
  1601.       set_head(p, size | PREV_INUSE);
  1602.       p = chunk_at_offset(p, size);
  1603.     }
  1604.     else { /* the final element absorbs any overallocation slop */
  1605.       set_head(p, remainder_size | PREV_INUSE);
  1606.       break;
  1607.     }
  1608.   }
  1609. #if DEBUG
  1610.   if (marray != chunks) {
  1611.     /* final element must have exactly exhausted chunk */
  1612.     if (element_size != 0) 
  1613.       assert(remainder_size == element_size);
  1614.     else
  1615.       assert(remainder_size == request2size(sizes[i]));
  1616.     check_inuse_chunk(mem2chunk(marray));
  1617.   }
  1618.   for (i = 0; i != n_elements; ++i)
  1619.     check_inuse_chunk(mem2chunk(marray[i]));
  1620. #endif
  1621.   return marray;
  1622. }
  1623. /*
  1624.   ------------------------------ pvalloc ------------------------------
  1625. */
  1626. #if __STD_C
  1627. Void_t* pVALLOc(size_t bytes)
  1628. #else
  1629. Void_t* pVALLOc(bytes) size_t bytes;
  1630. #endif
  1631. {
  1632.   mstate av = get_malloc_state();
  1633.   size_t pagesz;
  1634.   /* Ensure initialization */
  1635.   if (av->max_fast == 0) malloc_consolidate(av);
  1636.   pagesz = av->pagesize;
  1637.   return mEMALIGn(pagesz, (bytes + pagesz - 1) & ~(pagesz - 1));
  1638. }
  1639.    
  1640. /*
  1641.   ------------------------------ malloc_trim ------------------------------
  1642. */
  1643. #if __STD_C
  1644. int mTRIm(size_t pad)
  1645. #else
  1646. int mTRIm(pad) size_t pad;
  1647. #endif
  1648. {
  1649.   mstate av = get_malloc_state();
  1650.   /* Ensure initialization/consolidation */
  1651.   malloc_consolidate(av);
  1652. #ifndef MORECORE_CANNOT_TRIM        
  1653.   return sYSTRIm(pad, av);
  1654. #else
  1655.   return 0;
  1656. #endif
  1657. }
  1658. /*
  1659.   ------------------------- malloc_usable_size -------------------------
  1660. */
  1661. #if __STD_C
  1662. size_t mUSABLe(Void_t* mem)
  1663. #else
  1664. size_t mUSABLe(mem) Void_t* mem;
  1665. #endif
  1666. {
  1667.   mchunkptr p;
  1668.   if (mem != 0) {
  1669.     p = mem2chunk(mem);
  1670.     if (chunk_is_mmapped(p))
  1671.       return chunksize(p) - 2*SIZE_SZ;
  1672.     else if (inuse(p))
  1673.       return chunksize(p) - SIZE_SZ;
  1674.   }
  1675.   return 0;
  1676. }
  1677. /*
  1678.   ------------------------------ mallinfo ------------------------------
  1679. */
  1680. struct mallinfo mALLINFo()
  1681. {
  1682.   mstate av = get_malloc_state();
  1683.   struct mallinfo mi;
  1684.   int i;
  1685.   mbinptr b;
  1686.   mchunkptr p;
  1687.   INTERNAL_SIZE_T avail;
  1688.   INTERNAL_SIZE_T fastavail;
  1689.   int nblocks;
  1690.   int nfastblocks;
  1691.   /* Ensure initialization */
  1692.   if (av->top == 0)  malloc_consolidate(av);
  1693.   check_malloc_state();
  1694.   /* Account for top */
  1695.   avail = chunksize(av->top);
  1696.   nblocks = 1;  /* top always exists */
  1697.   /* traverse fastbins */
  1698.   nfastblocks = 0;
  1699.   fastavail = 0;
  1700.   for (i = 0; i < NFASTBINS; ++i) {
  1701.     for (p = av->fastbins[i]; p != 0; p = p->fd) {
  1702.       ++nfastblocks;
  1703.       fastavail += chunksize(p);
  1704.     }
  1705.   }
  1706.   avail += fastavail;
  1707.   /* traverse regular bins */
  1708.   for (i = 1; i < NBINS; ++i) {
  1709.     b = bin_at(av, i);
  1710.     for (p = last(b); p != b; p = p->bk) {
  1711.       ++nblocks;
  1712.       avail += chunksize(p);
  1713.     }
  1714.   }
  1715.   mi.smblks = nfastblocks;
  1716.   mi.ordblks = nblocks;
  1717.   mi.fordblks = avail;
  1718.   mi.uordblks = av->sbrked_mem - avail;
  1719.   mi.arena = av->sbrked_mem;
  1720.   mi.hblks = av->n_mmaps;
  1721.   mi.hblkhd = av->mmapped_mem;
  1722.   mi.fsmblks = fastavail;
  1723.   mi.keepcost = chunksize(av->top);
  1724.   mi.usmblks = av->max_total_mem;
  1725.   return mi;
  1726. }
  1727. /*
  1728.   ------------------------------ malloc_stats ------------------------------
  1729. */
  1730. void mSTATs()
  1731. {
  1732.   struct mallinfo mi = mALLINFo();
  1733. #ifdef WIN32
  1734.   {
  1735.     CHUNK_SIZE_T  free, reserved, committed;
  1736.     vminfo (&free, &reserved, &committed);
  1737.     fprintf(stderr, "free bytes       = %10lun", 
  1738.             free);
  1739.     fprintf(stderr, "reserved bytes   = %10lun", 
  1740.             reserved);
  1741.     fprintf(stderr, "committed bytes  = %10lun", 
  1742.             committed);
  1743.   }
  1744. #endif
  1745.   fprintf(stderr, "max system bytes = %10lun",
  1746.           (CHUNK_SIZE_T)(mi.usmblks));
  1747.   fprintf(stderr, "system bytes     = %10lun",
  1748.           (CHUNK_SIZE_T)(mi.arena + mi.hblkhd));
  1749.   fprintf(stderr, "in use bytes     = %10lun",
  1750.           (CHUNK_SIZE_T)(mi.uordblks + mi.hblkhd));
  1751. #ifdef WIN32 
  1752.   {
  1753.     CHUNK_SIZE_T  kernel, user;
  1754.     if (cpuinfo (TRUE, &kernel, &user)) {
  1755.       fprintf(stderr, "kernel ms        = %10lun", 
  1756.               kernel);
  1757.       fprintf(stderr, "user ms          = %10lun", 
  1758.               user);
  1759.     }
  1760.   }
  1761. #endif
  1762. }
  1763. /*
  1764.   ------------------------------ mallopt ------------------------------
  1765. */
  1766. #if __STD_C
  1767. int mALLOPt(int param_number, int value)
  1768. #else
  1769. int mALLOPt(param_number, value) int param_number; int value;
  1770. #endif
  1771. {
  1772.   mstate av = get_malloc_state();
  1773.   /* Ensure initialization/consolidation */
  1774.   malloc_consolidate(av);
  1775.   switch(param_number) {
  1776.   case M_MXFAST:
  1777.     if (value >= 0 && value <= MAX_FAST_SIZE) {
  1778.       set_max_fast(av, value);
  1779.       return 1;
  1780.     }
  1781.     else
  1782.       return 0;
  1783.   case M_TRIM_THRESHOLD:
  1784.     av->trim_threshold = value;
  1785.     return 1;
  1786.   case M_TOP_PAD:
  1787.     av->top_pad = value;
  1788.     return 1;
  1789.   case M_MMAP_THRESHOLD:
  1790.     av->mmap_threshold = value;
  1791.     return 1;
  1792.   case M_MMAP_MAX:
  1793. #if !HAVE_MMAP
  1794.     if (value != 0)
  1795.       return 0;
  1796. #endif
  1797.     av->n_mmaps_max = value;
  1798.     return 1;
  1799.   default:
  1800.     return 0;
  1801.   }
  1802. }
  1803. #endif
  1804. /* 
  1805.   -------------------- Alternative MORECORE functions --------------------
  1806. */
  1807. /*
  1808.   General Requirements for MORECORE.
  1809.   The MORECORE function must have the following properties:
  1810.   If MORECORE_CONTIGUOUS is false:
  1811.     * MORECORE must allocate in multiples of pagesize. It will
  1812.       only be called with arguments that are multiples of pagesize.
  1813.     * MORECORE(0) must return an address that is at least 
  1814.       MALLOC_ALIGNMENT aligned. (Page-aligning always suffices.)
  1815.   else (i.e. If MORECORE_CONTIGUOUS is true):
  1816.     * Consecutive calls to MORECORE with positive arguments
  1817.       return increasing addresses, indicating that space has been
  1818.       contiguously extended. 
  1819.     * MORECORE need not allocate in multiples of pagesize.
  1820.       Calls to MORECORE need not have args of multiples of pagesize.
  1821.     * MORECORE need not page-align.
  1822.   In either case:
  1823.     * MORECORE may allocate more memory than requested. (Or even less,
  1824.       but this will generally result in a malloc failure.)
  1825.     * MORECORE must not allocate memory when given argument zero, but
  1826.       instead return one past the end address of memory from previous
  1827.       nonzero call. This malloc does NOT call MORECORE(0)
  1828.       until at least one call with positive arguments is made, so
  1829.       the initial value returned is not important.
  1830.     * Even though consecutive calls to MORECORE need not return contiguous
  1831.       addresses, it must be OK for malloc'ed chunks to span multiple
  1832.       regions in those cases where they do happen to be contiguous.
  1833.     * MORECORE need not handle negative arguments -- it may instead
  1834.       just return MORECORE_FAILURE when given negative arguments.
  1835.       Negative arguments are always multiples of pagesize. MORECORE
  1836.       must not misinterpret negative args as large positive unsigned
  1837.       args. You can suppress all such calls from even occurring by defining
  1838.       MORECORE_CANNOT_TRIM,
  1839.   There is some variation across systems about the type of the
  1840.   argument to sbrk/MORECORE. If size_t is unsigned, then it cannot
  1841.   actually be size_t, because sbrk supports negative args, so it is
  1842.   normally the signed type of the same width as size_t (sometimes
  1843.   declared as "intptr_t", and sometimes "ptrdiff_t").  It doesn't much
  1844.   matter though. Internally, we use "long" as arguments, which should
  1845.   work across all reasonable possibilities.
  1846.   Additionally, if MORECORE ever returns failure for a positive
  1847.   request, and HAVE_MMAP is true, then mmap is used as a noncontiguous
  1848.   system allocator. This is a useful backup strategy for systems with
  1849.   holes in address spaces -- in this case sbrk cannot contiguously
  1850.   expand the heap, but mmap may be able to map noncontiguous space.
  1851.   If you'd like mmap to ALWAYS be used, you can define MORECORE to be
  1852.   a function that always returns MORECORE_FAILURE.
  1853.   Malloc only has limited ability to detect failures of MORECORE
  1854.   to supply contiguous space when it says it can. In particular,
  1855.   multithreaded programs that do not use locks may result in
  1856.   rece conditions across calls to MORECORE that result in gaps
  1857.   that cannot be detected as such, and subsequent corruption.
  1858.   If you are using this malloc with something other than sbrk (or its
  1859.   emulation) to supply memory regions, you probably want to set
  1860.   MORECORE_CONTIGUOUS as false.  As an example, here is a custom
  1861.   allocator kindly contributed for pre-OSX macOS.  It uses virtually
  1862.   but not necessarily physically contiguous non-paged memory (locked
  1863.   in, present and won't get swapped out).  You can use it by
  1864.   uncommenting this section, adding some #includes, and setting up the
  1865.   appropriate defines above:
  1866.       #define MORECORE osMoreCore
  1867.       #define MORECORE_CONTIGUOUS 0
  1868.   There is also a shutdown routine that should somehow be called for
  1869.   cleanup upon program exit.
  1870.   #define MAX_POOL_ENTRIES 100
  1871.   #define MINIMUM_MORECORE_SIZE  (64 * 1024)
  1872.   static int next_os_pool;
  1873.   void *our_os_pools[MAX_POOL_ENTRIES];
  1874.   void *osMoreCore(int size)
  1875.   {
  1876.     void *ptr = 0;
  1877.     static void *sbrk_top = 0;
  1878.     if (size > 0)
  1879.     {
  1880.       if (size < MINIMUM_MORECORE_SIZE)
  1881.          size = MINIMUM_MORECORE_SIZE;
  1882.       if (CurrentExecutionLevel() == kTaskLevel)
  1883.          ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
  1884.       if (ptr == 0)
  1885.       {
  1886.         return (void *) MORECORE_FAILURE;
  1887.       }
  1888.       // save ptrs so they can be freed during cleanup
  1889.       our_os_pools[next_os_pool] = ptr;
  1890.       next_os_pool++;
  1891.       ptr = (void *) ((((CHUNK_SIZE_T) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
  1892.       sbrk_top = (char *) ptr + size;
  1893.       return ptr;
  1894.     }
  1895.     else if (size < 0)
  1896.     {
  1897.       // we don't currently support shrink behavior
  1898.       return (void *) MORECORE_FAILURE;
  1899.     }
  1900.     else
  1901.     {
  1902.       return sbrk_top;
  1903.     }
  1904.   }
  1905.   // cleanup any allocated memory pools
  1906.   // called as last thing before shutting down driver
  1907.   void osCleanupMem(void)
  1908.   {
  1909.     void **ptr;
  1910.     for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
  1911.       if (*ptr)
  1912.       {
  1913.          PoolDeallocate(*ptr);
  1914.          *ptr = 0;
  1915.       }
  1916.   }
  1917. */
  1918. /* 
  1919.   -------------------------------------------------------------- 
  1920.   Emulation of sbrk for win32. 
  1921.   Donated by J. Walter <Walter@GeNeSys-e.de>.
  1922.   For additional information about this code, and malloc on Win32, see 
  1923.      http://www.genesys-e.de/jwalter/
  1924. */
  1925. #ifdef WIN32
  1926. #ifdef _DEBUG
  1927. /* #define TRACE */
  1928. #endif
  1929. /* Support for USE_MALLOC_LOCK */
  1930. #ifdef USE_MALLOC_LOCK
  1931. /* Wait for spin lock */
  1932. static int slwait (int *sl) {
  1933.     while (InterlockedCompareExchange ((void **) sl, (void *) 1, (void *) 0) != 0) 
  1934.     Sleep (0);
  1935.     return 0;
  1936. }
  1937. /* Release spin lock */
  1938. static int slrelease (int *sl) {
  1939.     InterlockedExchange (sl, 0);
  1940.     return 0;
  1941. }
  1942. #ifdef NEEDED
  1943. /* Spin lock for emulation code */
  1944. static int g_sl;
  1945. #endif
  1946. #endif /* USE_MALLOC_LOCK */
  1947. /* getpagesize for windows */
  1948. static long getpagesize (void) {
  1949.     static long g_pagesize = 0;
  1950.     if (! g_pagesize) {
  1951.         SYSTEM_INFO system_info;
  1952.         GetSystemInfo (&system_info);
  1953.         g_pagesize = system_info.dwPageSize;
  1954.     }
  1955.     return g_pagesize;
  1956. }
  1957. static long getregionsize (void) {
  1958.     static long g_regionsize = 0;
  1959.     if (! g_regionsize) {
  1960.         SYSTEM_INFO system_info;
  1961.         GetSystemInfo (&system_info);
  1962.         g_regionsize = system_info.dwAllocationGranularity;
  1963.     }
  1964.     return g_regionsize;
  1965. }
  1966. /* A region list entry */
  1967. typedef struct _region_list_entry {
  1968.     void *top_allocated;
  1969.     void *top_committed;
  1970.     void *top_reserved;
  1971.     long reserve_size;
  1972.     struct _region_list_entry *previous;
  1973. } region_list_entry;
  1974. /* Allocate and link a region entry in the region list */
  1975. static int region_list_append (region_list_entry **last, void *base_reserved, long reserve_size) {
  1976.     region_list_entry *next = HeapAlloc (GetProcessHeap (), 0, sizeof (region_list_entry));
  1977.     if (! next)
  1978.         return FALSE;
  1979.     next->top_allocated = (char *) base_reserved;
  1980.     next->top_committed = (char *) base_reserved;
  1981.     next->top_reserved = (char *) base_reserved + reserve_size;
  1982.     next->reserve_size = reserve_size;
  1983.     next->previous = *last;
  1984.     *last = next;
  1985.     return TRUE;
  1986. }
  1987. /* Free and unlink the last region entry from the region list */
  1988. static int region_list_remove (region_list_entry **last) {
  1989.     region_list_entry *previous = (*last)->previous;
  1990.     if (! HeapFree (GetProcessHeap (), sizeof (region_list_entry), *last))
  1991.         return FALSE;
  1992.     *last = previous;
  1993.     return TRUE;
  1994. }
  1995. #define CEIL(size,to) (((size)+(to)-1)&~((to)-1))
  1996. #define FLOOR(size,to) ((size)&~((to)-1))
  1997. #define SBRK_SCALE  0
  1998. /* #define SBRK_SCALE  1 */
  1999. /* #define SBRK_SCALE  2 */
  2000. /* #define SBRK_SCALE  4  */
  2001. /* sbrk for windows */
  2002. static void *sbrk (long size) {
  2003.     static long g_pagesize, g_my_pagesize;
  2004.     static long g_regionsize, g_my_regionsize;
  2005.     static region_list_entry *g_last;
  2006.     void *result = (void *) MORECORE_FAILURE;
  2007. #ifdef TRACE
  2008.     printf ("sbrk %dn", size);
  2009. #endif
  2010. #if defined (USE_MALLOC_LOCK) && defined (NEEDED)
  2011.     /* Wait for spin lock */
  2012.     slwait (&g_sl);
  2013. #endif
  2014.     /* First time initialization */
  2015.     if (! g_pagesize) {
  2016.         g_pagesize = getpagesize ();
  2017.         g_my_pagesize = g_pagesize << SBRK_SCALE;
  2018.     }
  2019.     if (! g_regionsize) {
  2020.         g_regionsize = getregionsize ();
  2021.         g_my_regionsize = g_regionsize << SBRK_SCALE;
  2022.     }
  2023.     if (! g_last) {
  2024.         if (! region_list_append (&g_last, 0, 0)) 
  2025.            goto sbrk_exit;
  2026.     }
  2027.     /* Assert invariants */
  2028.     assert (g_last);
  2029.     assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_allocated &&
  2030.             g_last->top_allocated <= g_last->top_committed);
  2031.     assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_committed &&
  2032.             g_last->top_committed <= g_last->top_reserved &&
  2033.             (unsigned) g_last->top_committed % g_pagesize == 0);
  2034.     assert ((unsigned) g_last->top_reserved % g_regionsize == 0);
  2035.     assert ((unsigned) g_last->reserve_size % g_regionsize == 0);
  2036.     /* Allocation requested? */
  2037.     if (size >= 0) {
  2038.         /* Allocation size is the requested size */
  2039.         long allocate_size = size;
  2040.         /* Compute the size to commit */
  2041.         long to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;
  2042.         /* Do we reach the commit limit? */
  2043.         if (to_commit > 0) {
  2044.             /* Round size to commit */
  2045.             long commit_size = CEIL (to_commit, g_my_pagesize);
  2046.             /* Compute the size to reserve */
  2047.             long to_reserve = (char *) g_last->top_committed + commit_size - (char *) g_last->top_reserved;
  2048.             /* Do we reach the reserve limit? */
  2049.             if (to_reserve > 0) {
  2050.                 /* Compute the remaining size to commit in the current region */
  2051.                 long remaining_commit_size = (char *) g_last->top_reserved - (char *) g_last->top_committed;
  2052.                 if (remaining_commit_size > 0) {
  2053.                     /* Assert preconditions */
  2054.                     assert ((unsigned) g_last->top_committed % g_pagesize == 0);
  2055.                     assert (0 < remaining_commit_size && remaining_commit_size % g_pagesize == 0); {
  2056.                         /* Commit this */
  2057.                         void *base_committed = VirtualAlloc (g_last->top_committed, remaining_commit_size,
  2058.                                  MEM_COMMIT, PAGE_READWRITE);
  2059.                         /* Check returned pointer for consistency */
  2060.                         if (base_committed != g_last->top_committed)
  2061.                             goto sbrk_exit;
  2062.                         /* Assert postconditions */
  2063.                         assert ((unsigned) base_committed % g_pagesize == 0);
  2064. #ifdef TRACE
  2065.                         printf ("Commit %p %dn", base_committed, remaining_commit_size);
  2066. #endif
  2067.                         /* Adjust the regions commit top */
  2068.                         g_last->top_committed = (char *) base_committed + remaining_commit_size;
  2069.                     }
  2070.                 } {
  2071.                     /* Now we are going to search and reserve. */
  2072.                     int contiguous = -1;
  2073.                     int found = FALSE;
  2074.                     MEMORY_BASIC_INFORMATION memory_info;
  2075.                     void *base_reserved;
  2076.                     long reserve_size;
  2077.                     do {
  2078.                         /* Assume contiguous memory */
  2079.                         contiguous = TRUE;
  2080.                         /* Round size to reserve */
  2081.                         reserve_size = CEIL (to_reserve, g_my_regionsize);
  2082.                         /* Start with the current region's top */
  2083.                         memory_info.BaseAddress = g_last->top_reserved;
  2084.                         /* Assert preconditions */
  2085.                         assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);
  2086.                         assert (0 < reserve_size && reserve_size % g_regionsize == 0);
  2087.                         while (VirtualQuery (memory_info.BaseAddress, &memory_info, sizeof (memory_info))) {
  2088.                             /* Assert postconditions */
  2089.                             assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);
  2090. #ifdef TRACE
  2091.                             printf ("Query %p %d %sn", memory_info.BaseAddress, memory_info.RegionSize, 
  2092.                                     memory_info.State == MEM_FREE ? "FREE": 
  2093.                                     (memory_info.State == MEM_RESERVE ? "RESERVED":
  2094.                                      (memory_info.State == MEM_COMMIT ? "COMMITTED": "?")));
  2095. #endif
  2096.                             /* Region is free, well aligned and big enough: we are done */
  2097.                             if (memory_info.State == MEM_FREE &&
  2098.                                 (unsigned) memory_info.BaseAddress % g_regionsize == 0 &&
  2099.                                 memory_info.RegionSize >= (unsigned) reserve_size) {
  2100.                                 found = TRUE;
  2101.                                 break;
  2102.                             }
  2103.                             /* From now on we can't get contiguous memory! */
  2104.                             contiguous = FALSE;
  2105.                             /* Recompute size to reserve */
  2106.                             reserve_size = CEIL (allocate_size, g_my_regionsize);
  2107.                             memory_info.BaseAddress = (char *) memory_info.BaseAddress + memory_info.RegionSize;
  2108.                             /* Assert preconditions */
  2109.                             assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);
  2110.                             assert (0 < reserve_size && reserve_size % g_regionsize == 0);
  2111.                         }
  2112.                         /* Search failed? */
  2113.                         if (! found) 
  2114.                             goto sbrk_exit;
  2115.                         /* Assert preconditions */
  2116.                         assert ((unsigned) memory_info.BaseAddress % g_regionsize == 0);
  2117.                         assert (0 < reserve_size && reserve_size % g_regionsize == 0);
  2118.                         /* Try to reserve this */
  2119.                         base_reserved = VirtualAlloc (memory_info.BaseAddress, reserve_size, 
  2120.                                   MEM_RESERVE, PAGE_NOACCESS);
  2121.                         if (! base_reserved) {
  2122.                             int rc = GetLastError ();
  2123.                             if (rc != ERROR_INVALID_ADDRESS) 
  2124.                                 goto sbrk_exit;
  2125.                         }
  2126.                         /* A null pointer signals (hopefully) a race condition with another thread. */
  2127.                         /* In this case, we try again. */
  2128.                     } while (! base_reserved);
  2129.                     /* Check returned pointer for consistency */
  2130.                     if (memory_info.BaseAddress && base_reserved != memory_info.BaseAddress)
  2131.                         goto sbrk_exit;
  2132.                     /* Assert postconditions */
  2133.                     assert ((unsigned) base_reserved % g_regionsize == 0);
  2134. #ifdef TRACE
  2135.                     printf ("Reserve %p %dn", base_reserved, reserve_size);
  2136. #endif
  2137.                     /* Did we get contiguous memory? */
  2138.                     if (contiguous) {
  2139.                         long start_size = (char *) g_last->top_committed - (char *) g_last->top_allocated;
  2140.                         /* Adjust allocation size */
  2141.                         allocate_size -= start_size;
  2142.                         /* Adjust the regions allocation top */
  2143.                         g_last->top_allocated = g_last->top_committed;
  2144.                         /* Recompute the size to commit */
  2145.                         to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;
  2146.                         /* Round size to commit */
  2147.                         commit_size = CEIL (to_commit, g_my_pagesize);
  2148.                     } 
  2149.                     /* Append the new region to the list */
  2150.                     if (! region_list_append (&g_last, base_reserved, reserve_size))
  2151.                         goto sbrk_exit;
  2152.                     /* Didn't we get contiguous memory? */
  2153.                     if (! contiguous) {
  2154.                         /* Recompute the size to commit */
  2155.                         to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;
  2156.                         /* Round size to commit */
  2157.                         commit_size = CEIL (to_commit, g_my_pagesize);
  2158.                     }
  2159.                 }
  2160.             } 
  2161.             /* Assert preconditions */
  2162.             assert ((unsigned) g_last->top_committed % g_pagesize == 0);
  2163.             assert (0 < commit_size && commit_size % g_pagesize == 0); {
  2164.                 /* Commit this */
  2165.                 void *base_committed = VirtualAlloc (g_last->top_committed, commit_size, 
  2166.                           MEM_COMMIT, PAGE_READWRITE);
  2167.                 /* Check returned pointer for consistency */
  2168.                 if (base_committed != g_last->top_committed)
  2169.                     goto sbrk_exit;
  2170.                 /* Assert postconditions */
  2171.                 assert ((unsigned) base_committed % g_pagesize == 0);
  2172. #ifdef TRACE
  2173.                 printf ("Commit %p %dn", base_committed, commit_size);
  2174. #endif
  2175.                 /* Adjust the regions commit top */
  2176.                 g_last->top_committed = (char *) base_committed + commit_size;
  2177.             }
  2178.         } 
  2179.         /* Adjust the regions allocation top */
  2180.         g_last->top_allocated = (char *) g_last->top_allocated + allocate_size;
  2181.         result = (char *) g_last->top_allocated - size;
  2182.     /* Deallocation requested? */
  2183.     } else if (size < 0) {
  2184.         long deallocate_size = - size;
  2185.         /* As long as we have a region to release */
  2186.         while ((char *) g_last->top_allocated - deallocate_size < (char *) g_last->top_reserved - g_last->reserve_size) {
  2187.             /* Get the size to release */
  2188.             long release_size = g_last->reserve_size;
  2189.             /* Get the base address */
  2190.             void *base_reserved = (char *) g_last->top_reserved - release_size;
  2191.             /* Assert preconditions */
  2192.             assert ((unsigned) base_reserved % g_regionsize == 0); 
  2193.             assert (0 < release_size && release_size % g_regionsize == 0); {
  2194.                 /* Release this */
  2195.                 int rc = VirtualFree (base_reserved, 0, 
  2196.                                       MEM_RELEASE);
  2197.                 /* Check returned code for consistency */
  2198.                 if (! rc)
  2199.                     goto sbrk_exit;
  2200. #ifdef TRACE
  2201.                 printf ("Release %p %dn", base_reserved, release_size);
  2202. #endif
  2203.             }
  2204.             /* Adjust deallocation size */
  2205.             deallocate_size -= (char *) g_last->top_allocated - (char *) base_reserved;
  2206.             /* Remove the old region from the list */
  2207.             if (! region_list_remove (&g_last))
  2208.                 goto sbrk_exit;
  2209.         } {
  2210.             /* Compute the size to decommit */
  2211.             long to_decommit = (char *) g_last->top_committed - ((char *) g_last->top_allocated - deallocate_size);
  2212.             if (to_decommit >= g_my_pagesize) {
  2213.                 /* Compute the size to decommit */
  2214.                 long decommit_size = FLOOR (to_decommit, g_my_pagesize);
  2215.                 /*  Compute the base address */
  2216.                 void *base_committed = (char *) g_last->top_committed - decommit_size;
  2217.                 /* Assert preconditions */
  2218.                 assert ((unsigned) base_committed % g_pagesize == 0);
  2219.                 assert (0 < decommit_size && decommit_size % g_pagesize == 0); {
  2220.                     /* Decommit this */
  2221.                     int rc = VirtualFree ((char *) base_committed, decommit_size, 
  2222.                                           MEM_DECOMMIT);
  2223.                     /* Check returned code for consistency */
  2224.                     if (! rc)
  2225.                         goto sbrk_exit;
  2226. #ifdef TRACE
  2227.                     printf ("Decommit %p %dn", base_committed, decommit_size);
  2228. #endif
  2229.                 }
  2230.                 /* Adjust deallocation size and regions commit and allocate top */
  2231.                 deallocate_size -= (char *) g_last->top_allocated - (char *) base_committed;
  2232.                 g_last->top_committed = base_committed;
  2233.                 g_last->top_allocated = base_committed;
  2234.             }
  2235.         }
  2236.         /* Adjust regions allocate top */
  2237.         g_last->top_allocated = (char *) g_last->top_allocated - deallocate_size;
  2238.         /* Check for underflow */
  2239.         if ((char *) g_last->top_reserved - g_last->reserve_size > (char *) g_last->top_allocated ||
  2240.             g_last->top_allocated > g_last->top_committed) {
  2241.             /* Adjust regions allocate top */
  2242.             g_last->top_allocated = (char *) g_last->top_reserved - g_last->reserve_size;
  2243.             goto sbrk_exit;
  2244.         }
  2245.         result = g_last->top_allocated;
  2246.     }
  2247.     /* Assert invariants */
  2248.     assert (g_last);
  2249.     assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_allocated &&
  2250.             g_last->top_allocated <= g_last->top_committed);
  2251.     assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_committed &&
  2252.             g_last->top_committed <= g_last->top_reserved &&
  2253.             (unsigned) g_last->top_committed % g_pagesize == 0);
  2254.     assert ((unsigned) g_last->top_reserved % g_regionsize == 0);
  2255.     assert ((unsigned) g_last->reserve_size % g_regionsize == 0);
  2256. sbrk_exit:
  2257. #if defined (USE_MALLOC_LOCK) && defined (NEEDED)
  2258.     /* Release spin lock */
  2259.     slrelease (&g_sl);
  2260. #endif
  2261.     return result;
  2262. }
  2263. /* mmap for windows */
  2264. static void *mmap (void *ptr, long size, long prot, long type, long handle, long arg) {
  2265.     static long g_pagesize;
  2266.     static long g_regionsize;
  2267. #ifdef TRACE
  2268.     printf ("mmap %dn", size);
  2269. #endif
  2270. #if defined (USE_MALLOC_LOCK) && defined (NEEDED)
  2271.     /* Wait for spin lock */
  2272.     slwait (&g_sl);
  2273. #endif
  2274.     /* First time initialization */
  2275.     if (! g_pagesize) 
  2276.         g_pagesize = getpagesize ();
  2277.     if (! g_regionsize) 
  2278.         g_regionsize = getregionsize ();
  2279.     /* Assert preconditions */
  2280.     assert ((unsigned) ptr % g_regionsize == 0);
  2281.     assert (size % g_pagesize == 0);
  2282.     /* Allocate this */
  2283.     ptr = VirtualAlloc (ptr, size,
  2284.     MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);
  2285.     if (! ptr) {
  2286.         ptr = (void *) MORECORE_FAILURE;
  2287.         goto mmap_exit;
  2288.     }
  2289.     /* Assert postconditions */
  2290.     assert ((unsigned) ptr % g_regionsize == 0);
  2291. #ifdef TRACE
  2292.     printf ("Commit %p %dn", ptr, size);
  2293. #endif
  2294. mmap_exit:
  2295. #if defined (USE_MALLOC_LOCK) && defined (NEEDED)
  2296.     /* Release spin lock */
  2297.     slrelease (&g_sl);
  2298. #endif
  2299.     return ptr;
  2300. }
  2301. /* munmap for windows */
  2302. static long munmap (void *ptr, long size) {
  2303.     static long g_pagesize;
  2304.     static long g_regionsize;
  2305.     int rc = MUNMAP_FAILURE;
  2306. #ifdef TRACE
  2307.     printf ("munmap %p %dn", ptr, size);
  2308. #endif
  2309. #if defined (USE_MALLOC_LOCK) && defined (NEEDED)
  2310.     /* Wait for spin lock */
  2311.     slwait (&g_sl);
  2312. #endif
  2313.     /* First time initialization */
  2314.     if (! g_pagesize) 
  2315.         g_pagesize = getpagesize ();
  2316.     if (! g_regionsize) 
  2317.         g_regionsize = getregionsize ();
  2318.     /* Assert preconditions */
  2319.     assert ((unsigned) ptr % g_regionsize == 0);
  2320.     assert (size % g_pagesize == 0);
  2321.     /* Free this */
  2322.     if (! VirtualFree (ptr, 0, 
  2323.                        MEM_RELEASE))
  2324.         goto munmap_exit;
  2325.     rc = 0;
  2326. #ifdef TRACE
  2327.     printf ("Release %p %dn", ptr, size);
  2328. #endif
  2329. munmap_exit:
  2330. #if defined (USE_MALLOC_LOCK) && defined (NEEDED)
  2331.     /* Release spin lock */
  2332.     slrelease (&g_sl);
  2333. #endif
  2334.     return rc;
  2335. }
  2336. static void vminfo (CHUNK_SIZE_T  *free, CHUNK_SIZE_T  *reserved, CHUNK_SIZE_T  *committed) {
  2337.     MEMORY_BASIC_INFORMATION memory_info;
  2338.     memory_info.BaseAddress = 0;
  2339.     *free = *reserved = *committed = 0;
  2340.     while (VirtualQuery (memory_info.BaseAddress, &memory_info, sizeof (memory_info))) {
  2341.         switch (memory_info.State) {
  2342.         case MEM_FREE:
  2343.             *free += memory_info.RegionSize;
  2344.             break;
  2345.         case MEM_RESERVE:
  2346.             *reserved += memory_info.RegionSize;
  2347.             break;
  2348.         case MEM_COMMIT:
  2349.             *committed += memory_info.RegionSize;
  2350.             break;
  2351.         }
  2352.         memory_info.BaseAddress = (char *) memory_info.BaseAddress + memory_info.RegionSize;
  2353.     }
  2354. }
  2355. static int cpuinfo (int whole, CHUNK_SIZE_T  *kernel, CHUNK_SIZE_T  *user) {
  2356.     if (whole) {
  2357.         __int64 creation64, exit64, kernel64, user64;
  2358.         int rc = GetProcessTimes (GetCurrentProcess (), 
  2359.                                   (FILETIME *) &creation64,  
  2360.                                   (FILETIME *) &exit64, 
  2361.                                   (FILETIME *) &kernel64, 
  2362.                                   (FILETIME *) &user64);
  2363.         if (! rc) {
  2364.             *kernel = 0;
  2365.             *user = 0;
  2366.             return FALSE;
  2367.         } 
  2368.         *kernel = (CHUNK_SIZE_T) (kernel64 / 10000);
  2369.         *user = (CHUNK_SIZE_T) (user64 / 10000);
  2370.         return TRUE;
  2371.     } else {
  2372.         __int64 creation64, exit64, kernel64, user64;
  2373.         int rc = GetThreadTimes (GetCurrentThread (), 
  2374.                                  (FILETIME *) &creation64,  
  2375.                                  (FILETIME *) &exit64, 
  2376.                                  (FILETIME *) &kernel64, 
  2377.                                  (FILETIME *) &user64);
  2378.         if (! rc) {
  2379.             *kernel = 0;
  2380.             *user = 0;
  2381.             return FALSE;
  2382.         } 
  2383.         *kernel = (CHUNK_SIZE_T) (kernel64 / 10000);
  2384.         *user = (CHUNK_SIZE_T) (user64 / 10000);
  2385.         return TRUE;
  2386.     }
  2387. }
  2388. #endif /* WIN32 */
  2389. /* ------------------------------------------------------------
  2390. History:
  2391.     V2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
  2392.       * Fix malloc_state bitmap array misdeclaration
  2393.     V2.7.1 Thu Jul 25 10:58:03 2002  Doug Lea  (dl at gee)
  2394.       * Allow tuning of FIRST_SORTED_BIN_SIZE
  2395.       * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
  2396.       * Better detection and support for non-contiguousness of MORECORE. 
  2397.         Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
  2398.       * Bypass most of malloc if no frees. Thanks To Emery Berger.
  2399.       * Fix freeing of old top non-contiguous chunk im sysmalloc.
  2400.       * Raised default trim and map thresholds to 256K.
  2401.       * Fix mmap-related #defines. Thanks to Lubos Lunak.
  2402.       * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
  2403.       * Branch-free bin calculation
  2404.       * Default trim and mmap thresholds now 256K.
  2405.     V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
  2406.       * Introduce independent_comalloc and independent_calloc.
  2407.         Thanks to Michael Pachos for motivation and help.
  2408.       * Make optional .h file available
  2409.       * Allow > 2GB requests on 32bit systems.
  2410.       * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
  2411.         Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
  2412.         and Anonymous.
  2413.       * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for 
  2414.         helping test this.)
  2415.       * memalign: check alignment arg
  2416.       * realloc: don't try to shift chunks backwards, since this
  2417.         leads to  more fragmentation in some programs and doesn't
  2418.         seem to help in any others.
  2419.       * Collect all cases in malloc requiring system memory into sYSMALLOc
  2420.       * Use mmap as backup to sbrk
  2421.       * Place all internal state in malloc_state
  2422.       * Introduce fastbins (although similar to 2.5.1)
  2423.       * Many minor tunings and cosmetic improvements
  2424.       * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK 
  2425.       * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
  2426.         Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
  2427.       * Include errno.h to support default failure action.
  2428.     V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
  2429.       * return null for negative arguments
  2430.       * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
  2431.          * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
  2432.           (e.g. WIN32 platforms)
  2433.          * Cleanup header file inclusion for WIN32 platforms
  2434.          * Cleanup code to avoid Microsoft Visual C++ compiler complaints
  2435.          * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
  2436.            memory allocation routines
  2437.          * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
  2438.          * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
  2439.            usage of 'assert' in non-WIN32 code
  2440.          * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
  2441.            avoid infinite loop
  2442.       * Always call 'fREe()' rather than 'free()'
  2443.     V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
  2444.       * Fixed ordering problem with boundary-stamping
  2445.     V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
  2446.       * Added pvalloc, as recommended by H.J. Liu
  2447.       * Added 64bit pointer support mainly from Wolfram Gloger
  2448.       * Added anonymously donated WIN32 sbrk emulation
  2449.       * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
  2450.       * malloc_extend_top: fix mask error that caused wastage after
  2451.         foreign sbrks
  2452.       * Add linux mremap support code from HJ Liu
  2453.     V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
  2454.       * Integrated most documentation with the code.
  2455.       * Add support for mmap, with help from
  2456.         Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
  2457.       * Use last_remainder in more cases.
  2458.       * Pack bins using idea from  colin@nyx10.cs.du.edu
  2459.       * Use ordered bins instead of best-fit threshhold
  2460.       * Eliminate block-local decls to simplify tracing and debugging.
  2461.       * Support another case of realloc via move into top
  2462.       * Fix error occuring when initial sbrk_base not word-aligned.
  2463.       * Rely on page size for units instead of SBRK_UNIT to
  2464.         avoid surprises about sbrk alignment conventions.
  2465.       * Add mallinfo, mallopt. Thanks to Raymond Nijssen
  2466.         (raymond@es.ele.tue.nl) for the suggestion.
  2467.       * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
  2468.       * More precautions for cases where other routines call sbrk,
  2469.         courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
  2470.       * Added macros etc., allowing use in linux libc from
  2471.         H.J. Lu (hjl@gnu.ai.mit.edu)
  2472.       * Inverted this history list
  2473.     V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
  2474.       * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
  2475.       * Removed all preallocation code since under current scheme
  2476.         the work required to undo bad preallocations exceeds
  2477.         the work saved in good cases for most test programs.
  2478.       * No longer use return list or unconsolidated bins since
  2479.         no scheme using them consistently outperforms those that don't
  2480.         given above changes.
  2481.       * Use best fit for very large chunks to prevent some worst-cases.
  2482.       * Added some support for debugging
  2483.     V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
  2484.       * Removed footers when chunks are in use. Thanks to
  2485.         Paul Wilson (wilson@cs.texas.edu) for the suggestion.
  2486.     V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
  2487.       * Added malloc_trim, with help from Wolfram Gloger
  2488.         (wmglo@Dent.MED.Uni-Muenchen.DE).
  2489.     V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
  2490.     V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
  2491.       * realloc: try to expand in both directions
  2492.       * malloc: swap order of clean-bin strategy;
  2493.       * realloc: only conditionally expand backwards
  2494.       * Try not to scavenge used bins
  2495.       * Use bin counts as a guide to preallocation
  2496.       * Occasionally bin return list chunks in first scan
  2497.       * Add a few optimizations from colin@nyx10.cs.du.edu
  2498.     V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
  2499.       * faster bin computation & slightly different binning
  2500.       * merged all consolidations to one part of malloc proper
  2501.          (eliminating old malloc_find_space & malloc_clean_bin)
  2502.       * Scan 2 returns chunks (not just 1)
  2503.       * Propagate failure in realloc if malloc returns 0
  2504.       * Add stuff to allow compilation on non-ANSI compilers
  2505.           from kpv@research.att.com
  2506.     V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
  2507.       * removed potential for odd address access in prev_chunk
  2508.       * removed dependency on getpagesize.h
  2509.       * misc cosmetics and a bit more internal documentation
  2510.       * anticosmetics: mangled names in macros to evade debugger strangeness
  2511.       * tested on sparc, hp-700, dec-mips, rs6000
  2512.           with gcc & native cc (hp, dec only) allowing
  2513.           Detlefs & Zorn comparison study (in SIGPLAN Notices.)
  2514.     Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
  2515.       * Based loosely on libg++-1.2X malloc. (It retains some of the overall
  2516.          structure of old version,  but most details differ.)
  2517. */
  2518. #endif /* _USE_OWN_MALLOC */