Subversion Repositories Kolibri OS

Rev

Rev 6536 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.   This is a version (aka dlmalloc) of malloc/free/realloc written by
  3.   Doug Lea and released to the public domain, as explained at
  4.   http://creativecommons.org/licenses/publicdomain.  Send questions,
  5.   comments, complaints, performance data, etc to dl@cs.oswego.edu
  6.  
  7. * Version 2.8.4 Wed May 27 09:56:23 2009  Doug Lea  (dl at gee)
  8.  
  9.    Note: There may be an updated version of this malloc obtainable at
  10.            ftp://gee.cs.oswego.edu/pub/misc/malloc.c
  11.          Check before installing!
  12.  
  13. * Quickstart
  14.  
  15.   This library is all in one file to simplify the most common usage:
  16.   ftp it, compile it (-O3), and link it into another program. All of
  17.   the compile-time options default to reasonable values for use on
  18.   most platforms.  You might later want to step through various
  19.   compile-time and dynamic tuning options.
  20.  
  21.   For convenience, an include file for code using this malloc is at:
  22.      ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.4.h
  23.   You don't really need this .h file unless you call functions not
  24.   defined in your system include files.  The .h file contains only the
  25.   excerpts from this file needed for using this malloc on ANSI C/C++
  26.   systems, so long as you haven't changed compile-time options about
  27.   naming and tuning parameters.  If you do, then you can create your
  28.   own malloc.h that does include all settings by cutting at the point
  29.   indicated below. Note that you may already by default be using a C
  30.   library containing a malloc that is based on some version of this
  31.   malloc (for example in linux). You might still want to use the one
  32.   in this file to customize settings or to avoid overheads associated
  33.   with library versions.
  34.  
  35. */
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <sys/ksys.h>
  40.  
  41.  
  42. struct malloc_chunk {
  43.   size_t               prev_foot;  /* Size of previous chunk (if free).  */
  44.   size_t               head;       /* Size and inuse bits. */
  45.   struct malloc_chunk* fd;         /* double links -- used only if free. */
  46.   struct malloc_chunk* bk;
  47. };
  48.  
  49. typedef struct malloc_chunk  mchunk;
  50. typedef struct malloc_chunk* mchunkptr;
  51. typedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */
  52. typedef unsigned int bindex_t;         /* Described below */
  53. typedef unsigned int binmap_t;         /* Described below */
  54. typedef unsigned int flag_t;           /* The type of various bit flag sets */
  55.  
  56.  
  57.  
  58. /* ------------------- size_t and alignment properties -------------------- */
  59.  
  60. /* The maximum possible size_t value has all bits set */
  61. #define MAX_SIZE_T           (~(size_t)0)
  62.  
  63. #define user_alloc(s) _ksys_alloc(s)
  64. #define user_free _ksys_free
  65.  
  66. /* ------------------- size_t and alignment properties -------------------- */
  67.  
  68. /* The byte and bit size of a size_t */
  69. #define SIZE_T_SIZE         (sizeof(size_t))
  70. #define SIZE_T_BITSIZE      (sizeof(size_t) << 3)
  71.  
  72. /* Some constants coerced to size_t */
  73. /* Annoying but necessary to avoid errors on some platforms */
  74. #define SIZE_T_ZERO         ((size_t)0)
  75. #define SIZE_T_ONE          ((size_t)1)
  76. #define SIZE_T_TWO          ((size_t)2)
  77. #define SIZE_T_FOUR         ((size_t)4)
  78. #define TWO_SIZE_T_SIZES    (SIZE_T_SIZE<<1)
  79. #define FOUR_SIZE_T_SIZES   (SIZE_T_SIZE<<2)
  80. #define SIX_SIZE_T_SIZES    (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
  81. #define HALF_MAX_SIZE_T     (MAX_SIZE_T / 2U)
  82.  
  83. #define USE_LOCK_BIT            (2U)
  84. #define USE_MMAP_BIT            (SIZE_T_ONE)
  85. #define USE_NONCONTIGUOUS_BIT   (4U)
  86.  
  87. /* segment bit set in create_mspace_with_base */
  88. #define EXTERN_BIT              (8U)
  89.  
  90. #define HAVE_MMAP               1
  91. #define CALL_MMAP(s)            MMAP_DEFAULT(s)
  92. #define CALL_MUNMAP(a, s)       MUNMAP_DEFAULT((a), (s))
  93. #define CALL_MREMAP(addr, osz, nsz, mv)     MFAIL
  94.  
  95. #define calloc_must_clear(p)    (!is_mmapped(p))
  96.  
  97. #define MALLOC_FAILURE_ACTION
  98.  
  99. #define MAX_RELEASE_CHECK_RATE  4095
  100. #define NO_SEGMENT_TRAVERSAL    1
  101. #define MALLOC_ALIGNMENT        ((size_t)8U)
  102. #define CHUNK_OVERHEAD          (SIZE_T_SIZE)
  103. #define DEFAULT_GRANULARITY     ((size_t)512U * (size_t)1024U)
  104. #define DEFAULT_MMAP_THRESHOLD  ((size_t)1024U * (size_t)1024U)
  105. #define DEFAULT_TRIM_THRESHOLD  ((size_t)2048U * (size_t)1024U)
  106.  
  107. /* The bit mask value corresponding to MALLOC_ALIGNMENT */
  108. #define CHUNK_ALIGN_MASK    (MALLOC_ALIGNMENT - SIZE_T_ONE)
  109.  
  110. /* True if address a has acceptable alignment */
  111. #define is_aligned(A)       (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
  112.  
  113. /* the number of bytes to offset an address to align it */
  114. #define align_offset(A)\
  115.  ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
  116.   ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
  117.  
  118.  
  119. #define MFAIL                ((void*)(MAX_SIZE_T))
  120. #define CMFAIL               ((char*)(MFAIL)) /* defined for convenience */
  121.  
  122. /* For sys_alloc, enough padding to ensure can malloc request on success */
  123. #define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT)
  124.  
  125. /*
  126.   TOP_FOOT_SIZE is padding at the end of a segment, including space
  127.   that may be needed to place segment records and fenceposts when new
  128.   noncontiguous segments are added.
  129. */
  130. #define TOP_FOOT_SIZE\
  131.   (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
  132.  
  133. /* ------------------- Chunks sizes and alignments ----------------------- */
  134.  
  135. #define MCHUNK_SIZE         (sizeof(mchunk))
  136.  
  137. /* MMapped chunks need a second word of overhead ... */
  138. #define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
  139. /* ... and additional padding for fake next-chunk at foot */
  140. #define MMAP_FOOT_PAD       (FOUR_SIZE_T_SIZES)
  141.  
  142. /* The smallest size we can malloc is an aligned minimal chunk */
  143. #define MIN_CHUNK_SIZE\
  144.   ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
  145.  
  146. /* conversion from malloc headers to user pointers, and back */
  147. #define chunk2mem(p)        ((void*)((char*)(p)       + TWO_SIZE_T_SIZES))
  148. #define mem2chunk(mem)      ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
  149. /* chunk associated with aligned address A */
  150. #define align_as_chunk(A)   (mchunkptr)((A) + align_offset(chunk2mem(A)))
  151.  
  152. /* Bounds on request (not chunk) sizes. */
  153. #define MAX_REQUEST         ((-MIN_CHUNK_SIZE) << 2)
  154. #define MIN_REQUEST         (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
  155.  
  156. /* pad request bytes into a usable size */
  157. #define pad_request(req) \
  158.    (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
  159.  
  160. /* pad request, checking for minimum (but not maximum) */
  161. #define request2size(req) \
  162.   (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
  163.  
  164. /* ------------------ Operations on head and foot fields ----------------- */
  165.  
  166. /*
  167.   The head field of a chunk is or'ed with PINUSE_BIT when previous
  168.   adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
  169.   use, unless mmapped, in which case both bits are cleared.
  170.  
  171.   FLAG4_BIT is not used by this malloc, but might be useful in extensions.
  172. */
  173.  
  174. #define PINUSE_BIT          (SIZE_T_ONE)
  175. #define CINUSE_BIT          (SIZE_T_TWO)
  176. #define FLAG4_BIT           (SIZE_T_FOUR)
  177. #define INUSE_BITS          (PINUSE_BIT|CINUSE_BIT)
  178. #define FLAG_BITS           (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT)
  179.  
  180. /* Head value for fenceposts */
  181. #define FENCEPOST_HEAD      (INUSE_BITS|SIZE_T_SIZE)
  182.  
  183. /* extraction of fields from head words */
  184. #define cinuse(p)           ((p)->head & CINUSE_BIT)
  185. #define pinuse(p)           ((p)->head & PINUSE_BIT)
  186. #define is_inuse(p)         (((p)->head & INUSE_BITS) != PINUSE_BIT)
  187. #define is_mmapped(p)       (((p)->head & INUSE_BITS) == 0)
  188.  
  189. #define chunksize(p)        ((p)->head & ~(FLAG_BITS))
  190.  
  191. #define clear_pinuse(p)     ((p)->head &= ~PINUSE_BIT)
  192.  
  193. /* Treat space at ptr +/- offset as a chunk */
  194. #define chunk_plus_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
  195. #define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
  196.  
  197. /* Ptr to next or previous physical malloc_chunk. */
  198. #define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS)))
  199. #define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
  200.  
  201. /* extract next chunk's pinuse bit */
  202. #define next_pinuse(p)  ((next_chunk(p)->head) & PINUSE_BIT)
  203.  
  204. /* Set size, pinuse bit, and foot */
  205. #define set_size_and_pinuse_of_free_chunk(p, s)\
  206.   ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
  207.  
  208. /* Set size, pinuse bit, foot, and clear next pinuse */
  209. #define set_free_with_pinuse(p, s, n)\
  210.   (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
  211.  
  212. /* Get the internal overhead associated with chunk p */
  213. #define overhead_for(p)\
  214.  (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
  215.  
  216.  
  217. struct malloc_tree_chunk {
  218.   /* The first four fields must be compatible with malloc_chunk */
  219.   size_t                    prev_foot;
  220.   size_t                    head;
  221.   struct malloc_tree_chunk* fd;
  222.   struct malloc_tree_chunk* bk;
  223.  
  224.   struct malloc_tree_chunk* child[2];
  225.   struct malloc_tree_chunk* parent;
  226.   bindex_t                  index;
  227. };
  228.  
  229. typedef struct malloc_tree_chunk  tchunk;
  230. typedef struct malloc_tree_chunk* tchunkptr;
  231. typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
  232.  
  233. /* A little helper macro for trees */
  234. #define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
  235.  
  236.  
  237. struct malloc_segment {
  238.   char*        base;             /* base address */
  239.   size_t       size;             /* allocated size */
  240.   struct malloc_segment* next;   /* ptr to next segment */
  241.   flag_t       sflags;           /* mmap and extern flag */
  242. };
  243.  
  244. #define is_mmapped_segment(S)  ((S)->sflags & USE_MMAP_BIT)
  245. #define is_extern_segment(S)   ((S)->sflags & EXTERN_BIT)
  246.  
  247. typedef struct malloc_segment  msegment;
  248. typedef struct malloc_segment* msegmentptr;
  249.  
  250. /* ---------------------------- malloc_state ----------------------------- */
  251.  
  252. /*
  253.    A malloc_state holds all of the bookkeeping for a space.
  254.    The main fields are:
  255.  
  256.   Top
  257.     The topmost chunk of the currently active segment. Its size is
  258.     cached in topsize.  The actual size of topmost space is
  259.     topsize+TOP_FOOT_SIZE, which includes space reserved for adding
  260.     fenceposts and segment records if necessary when getting more
  261.     space from the system.  The size at which to autotrim top is
  262.     cached from mparams in trim_check, except that it is disabled if
  263.     an autotrim fails.
  264.  
  265.   Designated victim (dv)
  266.     This is the preferred chunk for servicing small requests that
  267.     don't have exact fits.  It is normally the chunk split off most
  268.     recently to service another small request.  Its size is cached in
  269.     dvsize. The link fields of this chunk are not maintained since it
  270.     is not kept in a bin.
  271.  
  272.   SmallBins
  273.     An array of bin headers for free chunks.  These bins hold chunks
  274.     with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
  275.     chunks of all the same size, spaced 8 bytes apart.  To simplify
  276.     use in double-linked lists, each bin header acts as a malloc_chunk
  277.     pointing to the real first node, if it exists (else pointing to
  278.     itself).  This avoids special-casing for headers.  But to avoid
  279.     waste, we allocate only the fd/bk pointers of bins, and then use
  280.     repositioning tricks to treat these as the fields of a chunk.
  281.  
  282.   TreeBins
  283.     Treebins are pointers to the roots of trees holding a range of
  284.     sizes. There are 2 equally spaced treebins for each power of two
  285.     from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
  286.     larger.
  287.  
  288.   Bin maps
  289.     There is one bit map for small bins ("smallmap") and one for
  290.     treebins ("treemap).  Each bin sets its bit when non-empty, and
  291.     clears the bit when empty.  Bit operations are then used to avoid
  292.     bin-by-bin searching -- nearly all "search" is done without ever
  293.     looking at bins that won't be selected.  The bit maps
  294.     conservatively use 32 bits per map word, even if on 64bit system.
  295.     For a good description of some of the bit-based techniques used
  296.     here, see Henry S. Warren Jr's book "Hacker's Delight" (and
  297.     supplement at http://hackersdelight.org/). Many of these are
  298.     intended to reduce the branchiness of paths through malloc etc, as
  299.     well as to reduce the number of memory locations read or written.
  300.  
  301.   Segments
  302.     A list of segments headed by an embedded malloc_segment record
  303.     representing the initial space.
  304.  
  305.   Address check support
  306.     The least_addr field is the least address ever obtained from
  307.     MORECORE or MMAP. Attempted frees and reallocs of any address less
  308.     than this are trapped (unless INSECURE is defined).
  309.  
  310.   Magic tag
  311.     A cross-check field that should always hold same value as mparams.magic.
  312.  
  313.   Flags
  314.     Bits recording whether to use MMAP, locks, or contiguous MORECORE
  315.  
  316.   Statistics
  317.     Each space keeps track of current and maximum system memory
  318.     obtained via MORECORE or MMAP.
  319.  
  320.   Trim support
  321.     Fields holding the amount of unused topmost memory that should trigger
  322.     timming, and a counter to force periodic scanning to release unused
  323.     non-topmost segments.
  324.  
  325.   Locking
  326.     If USE_LOCKS is defined, the "mutex" lock is acquired and released
  327.     around every public call using this mspace.
  328.  
  329.   Extension support
  330.     A void* pointer and a size_t field that can be used to help implement
  331.     extensions to this malloc.
  332. */
  333.  
  334. /* Bin types, widths and sizes */
  335. #define NSMALLBINS        (32U)
  336. #define NTREEBINS         (32U)
  337. #define SMALLBIN_SHIFT    (3U)
  338. #define SMALLBIN_WIDTH    (SIZE_T_ONE << SMALLBIN_SHIFT)
  339. #define TREEBIN_SHIFT     (8U)
  340. #define MIN_LARGE_SIZE    (SIZE_T_ONE << TREEBIN_SHIFT)
  341. #define MAX_SMALL_SIZE    (MIN_LARGE_SIZE - SIZE_T_ONE)
  342. #define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
  343.  
  344. struct malloc_state {
  345.   binmap_t   smallmap;
  346.   binmap_t   treemap;
  347.   size_t     dvsize;
  348.   size_t     topsize;
  349.   char*      least_addr;
  350.   mchunkptr  dv;
  351.   mchunkptr  top;
  352.   size_t     trim_check;
  353.   size_t     release_checks;
  354.   size_t     magic;
  355.   mchunkptr  smallbins[(NSMALLBINS+1)*2];
  356.   tbinptr    treebins[NTREEBINS];
  357.   size_t     footprint;
  358.   size_t     max_footprint;
  359.   flag_t     mflags;
  360.   _LOCK_RECURSIVE_T    lock;     /* locate lock among fields that rarely change */
  361.   msegment   seg;
  362.   void*      extp;      /* Unused but available for extensions */
  363.   size_t     exts;
  364. };
  365.  
  366. typedef struct malloc_state*    mstate;
  367.  
  368. /* ------------- Global malloc_state and malloc_params ------------------- */
  369.  
  370. /*
  371.   malloc_params holds global properties, including those that can be
  372.   dynamically set using mallopt. There is a single instance, mparams,
  373.   initialized in init_mparams. Note that the non-zeroness of "magic"
  374.   also serves as an initialization flag.
  375. */
  376.  
  377. struct malloc_params
  378. {
  379.   volatile size_t magic;
  380.   size_t page_size;
  381.   size_t granularity;
  382.   size_t mmap_threshold;
  383.   size_t trim_threshold;
  384.   flag_t default_mflags;
  385. };
  386.  
  387. static struct malloc_params mparams;
  388.  
  389. /* Ensure mparams initialized */
  390. #define ensure_initialization() (void)(mparams.magic != 0 || init_mparams())
  391.  
  392. static struct malloc_state _gm_;
  393. #define gm                 (&_gm_)
  394. #define is_global(M)       ((M) == &_gm_)
  395.  
  396. #define is_initialized(M)  ((M)->top != 0)
  397.  
  398.  
  399.  
  400.  
  401. __LOCK_INIT_RECURSIVE(static, malloc_global_mutex);
  402.  
  403. #define ACQUIRE_MALLOC_GLOBAL_LOCK()  __lock_acquire_recursive(malloc_global_mutex);
  404. #define RELEASE_MALLOC_GLOBAL_LOCK()  __lock_release_recursive(malloc_global_mutex);
  405.  
  406. #define PREACTION(M)  ( __lock_acquire_recursive((M)->lock))
  407. #define POSTACTION(M) { __lock_release_recursive((M)->lock); }
  408.  
  409. /* ---------------------------- Indexing Bins ---------------------------- */
  410.  
  411. #define is_small(s)         (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
  412. #define small_index(s)      ((s)  >> SMALLBIN_SHIFT)
  413. #define small_index2size(i) ((i)  << SMALLBIN_SHIFT)
  414. #define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))
  415.  
  416. /* addressing by index. See above about smallbin repositioning */
  417. #define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
  418. #define treebin_at(M,i)     (&((M)->treebins[i]))
  419.  
  420.  
  421. #define compute_tree_index(S, I)\
  422. {\
  423.   unsigned int X = S >> TREEBIN_SHIFT;\
  424.   if (X == 0)\
  425.     I = 0;\
  426.   else if (X > 0xFFFF)\
  427.     I = NTREEBINS-1;\
  428.   else {\
  429.     unsigned int K;\
  430.     __asm__("bsrl\t%1, %0\n\t" : "=r" (K) : "g"  (X));\
  431.     I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
  432.   }\
  433. }
  434.  
  435. /* Bit representing maximum resolved size in a treebin at i */
  436. #define bit_for_tree_index(i) \
  437.    (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
  438.  
  439. /* Shift placing maximum resolved bit in a treebin at i as sign bit */
  440. #define leftshift_for_tree_index(i) \
  441.    ((i == NTREEBINS-1)? 0 : \
  442.     ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
  443.  
  444. /* The size of the smallest chunk held in bin with index i */
  445. #define minsize_for_tree_index(i) \
  446.    ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) |  \
  447.    (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
  448.  
  449.  
  450. /* ------------------------ Operations on bin maps ----------------------- */
  451.  
  452. /* bit corresponding to given index */
  453. #define idx2bit(i)              ((binmap_t)(1) << (i))
  454.  
  455. /* Mark/Clear bits with given index */
  456. #define mark_smallmap(M,i)      ((M)->smallmap |=  idx2bit(i))
  457. #define clear_smallmap(M,i)     ((M)->smallmap &= ~idx2bit(i))
  458. #define smallmap_is_marked(M,i) ((M)->smallmap &   idx2bit(i))
  459.  
  460. #define mark_treemap(M,i)       ((M)->treemap  |=  idx2bit(i))
  461. #define clear_treemap(M,i)      ((M)->treemap  &= ~idx2bit(i))
  462. #define treemap_is_marked(M,i)  ((M)->treemap  &   idx2bit(i))
  463.  
  464. /* isolate the least set bit of a bitmap */
  465. #define least_bit(x)         ((x) & -(x))
  466.  
  467. /* mask with all bits to left of least bit of x on */
  468. #define left_bits(x)         ((x<<1) | -(x<<1))
  469.  
  470. /* mask with all bits to left of or equal to least bit of x on */
  471. #define same_or_left_bits(x) ((x) | -(x))
  472.  
  473.  
  474. /* index corresponding to given bit. Use x86 asm if possible */
  475.  
  476. #define compute_bit2idx(X, I)\
  477. {\
  478.   unsigned int J;\
  479.   __asm__("bsfl\t%1, %0\n\t" : "=r" (J) : "g" (X));\
  480.   I = (bindex_t)J;\
  481. }
  482.  
  483.  
  484. #define mark_inuse_foot(M,p,s)
  485.  
  486. /* Get/set size at footer */
  487. #define get_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot)
  488. #define set_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
  489.  
  490. /* Macros for setting head/foot of non-mmapped chunks */
  491.  
  492. /* Set cinuse bit and pinuse bit of next chunk */
  493. #define set_inuse(M,p,s)\
  494.   ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
  495.   ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
  496.  
  497. /* Set cinuse and pinuse of this chunk and pinuse of next chunk */
  498. #define set_inuse_and_pinuse(M,p,s)\
  499.   ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
  500.   ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
  501.  
  502. /* Set size, cinuse and pinuse bit of this chunk */
  503. #define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
  504.   ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
  505.  
  506.  
  507. #define assert(x)
  508. #define RTCHECK(e)  __builtin_expect(e, 1)
  509.  
  510. #define check_free_chunk(M,P)
  511. #define check_inuse_chunk(M,P)
  512. #define check_malloced_chunk(M,P,N)
  513. #define check_mmapped_chunk(M,P)
  514. #define check_malloc_state(M)
  515. #define check_top_chunk(M,P)
  516.  
  517. /* Check if address a is at least as high as any from MORECORE or MMAP */
  518. #define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
  519. /* Check if address of next chunk n is higher than base chunk p */
  520. #define ok_next(p, n)    ((char*)(p) < (char*)(n))
  521. /* Check if p has inuse status */
  522. #define ok_inuse(p)     is_inuse(p)
  523. /* Check if p has its pinuse bit on */
  524. #define ok_pinuse(p)     pinuse(p)
  525.  
  526. #define CORRUPTION_ERROR_ACTION(m)                             \
  527.         do {                                                   \
  528.             /*printf("%s malloc heap corrupted\n",__FUNCTION__); */\
  529.             __asm__("int3");                                   \
  530.         }while(0)                                              \
  531.  
  532.  
  533. #define USAGE_ERROR_ACTION(m, p)                               \
  534.         do {                                                   \
  535.             /*printf("%s malloc heap corrupted\n",__FUNCTION__); */\
  536.             __asm__("int3");                                   \
  537.         }while(0)                                              \
  538.  
  539. /* ----------------------- Operations on smallbins ----------------------- */
  540.  
  541. /*
  542.   Various forms of linking and unlinking are defined as macros.  Even
  543.   the ones for trees, which are very long but have very short typical
  544.   paths.  This is ugly but reduces reliance on inlining support of
  545.   compilers.
  546. */
  547.  
  548. /* Link a free chunk into a smallbin  */
  549. #define insert_small_chunk(M, P, S) {\
  550.   bindex_t I  = small_index(S);\
  551.   mchunkptr B = smallbin_at(M, I);\
  552.   mchunkptr F = B;\
  553.   assert(S >= MIN_CHUNK_SIZE);\
  554.   if (!smallmap_is_marked(M, I))\
  555.     mark_smallmap(M, I);\
  556.   else if (RTCHECK(ok_address(M, B->fd)))\
  557.     F = B->fd;\
  558.   else {\
  559.     CORRUPTION_ERROR_ACTION(M);\
  560.   }\
  561.   B->fd = P;\
  562.   F->bk = P;\
  563.   P->fd = F;\
  564.   P->bk = B;\
  565. }
  566.  
  567. /* Unlink a chunk from a smallbin  */
  568. #define unlink_small_chunk(M, P, S) {\
  569.   mchunkptr F = P->fd;\
  570.   mchunkptr B = P->bk;\
  571.   bindex_t I = small_index(S);\
  572.   assert(P != B);\
  573.   assert(P != F);\
  574.   assert(chunksize(P) == small_index2size(I));\
  575.   if (F == B)\
  576.     clear_smallmap(M, I);\
  577.   else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
  578.                    (B == smallbin_at(M,I) || ok_address(M, B)))) {\
  579.     F->bk = B;\
  580.     B->fd = F;\
  581.   }\
  582.   else {\
  583.     CORRUPTION_ERROR_ACTION(M);\
  584.   }\
  585. }
  586.  
  587. /* Unlink the first chunk from a smallbin */
  588. #define unlink_first_small_chunk(M, B, P, I) {\
  589.   mchunkptr F = P->fd;\
  590.   assert(P != B);\
  591.   assert(P != F);\
  592.   assert(chunksize(P) == small_index2size(I));\
  593.   if (B == F)\
  594.     clear_smallmap(M, I);\
  595.   else if (RTCHECK(ok_address(M, F))) {\
  596.     B->fd = F;\
  597.     F->bk = B;\
  598.   }\
  599.   else {\
  600.     CORRUPTION_ERROR_ACTION(M);\
  601.   }\
  602. }
  603.  
  604. /* Replace dv node, binning the old one */
  605. /* Used only when dvsize known to be small */
  606. #define replace_dv(M, P, S) {\
  607.   size_t DVS = M->dvsize;\
  608.   if (DVS != 0) {\
  609.     mchunkptr DV = M->dv;\
  610.     assert(is_small(DVS));\
  611.     insert_small_chunk(M, DV, DVS);\
  612.   }\
  613.   M->dvsize = S;\
  614.   M->dv = P;\
  615. }
  616.  
  617.  
  618. /* ------------------------- Operations on trees ------------------------- */
  619.  
  620. /* Insert chunk into tree */
  621. #define insert_large_chunk(M, X, S) {\
  622.   tbinptr* H;\
  623.   bindex_t I;\
  624.   compute_tree_index(S, I);\
  625.   H = treebin_at(M, I);\
  626.   X->index = I;\
  627.   X->child[0] = X->child[1] = 0;\
  628.   if (!treemap_is_marked(M, I)) {\
  629.     mark_treemap(M, I);\
  630.     *H = X;\
  631.     X->parent = (tchunkptr)H;\
  632.     X->fd = X->bk = X;\
  633.   }\
  634.   else {\
  635.     tchunkptr T = *H;\
  636.     size_t K = S << leftshift_for_tree_index(I);\
  637.     for (;;) {\
  638.       if (chunksize(T) != S) {\
  639.         tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
  640.         K <<= 1;\
  641.         if (*C != 0)\
  642.           T = *C;\
  643.         else if (RTCHECK(ok_address(M, C))) {\
  644.           *C = X;\
  645.           X->parent = T;\
  646.           X->fd = X->bk = X;\
  647.           break;\
  648.         }\
  649.         else {\
  650.           CORRUPTION_ERROR_ACTION(M);\
  651.           break;\
  652.         }\
  653.       }\
  654.       else {\
  655.         tchunkptr F = T->fd;\
  656.         if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
  657.           T->fd = F->bk = X;\
  658.           X->fd = F;\
  659.           X->bk = T;\
  660.           X->parent = 0;\
  661.           break;\
  662.         }\
  663.         else {\
  664.           CORRUPTION_ERROR_ACTION(M);\
  665.           break;\
  666.         }\
  667.       }\
  668.     }\
  669.   }\
  670. }
  671.  
  672. /*
  673.   Unlink steps:
  674.  
  675.   1. If x is a chained node, unlink it from its same-sized fd/bk links
  676.      and choose its bk node as its replacement.
  677.   2. If x was the last node of its size, but not a leaf node, it must
  678.      be replaced with a leaf node (not merely one with an open left or
  679.      right), to make sure that lefts and rights of descendents
  680.      correspond properly to bit masks.  We use the rightmost descendent
  681.      of x.  We could use any other leaf, but this is easy to locate and
  682.      tends to counteract removal of leftmosts elsewhere, and so keeps
  683.      paths shorter than minimally guaranteed.  This doesn't loop much
  684.      because on average a node in a tree is near the bottom.
  685.   3. If x is the base of a chain (i.e., has parent links) relink
  686.      x's parent and children to x's replacement (or null if none).
  687. */
  688.  
  689. #define unlink_large_chunk(M, X) {\
  690.   tchunkptr XP = X->parent;\
  691.   tchunkptr R;\
  692.   if (X->bk != X) {\
  693.     tchunkptr F = X->fd;\
  694.     R = X->bk;\
  695.     if (RTCHECK(ok_address(M, F))) {\
  696.       F->bk = R;\
  697.       R->fd = F;\
  698.     }\
  699.     else {\
  700.       CORRUPTION_ERROR_ACTION(M);\
  701.     }\
  702.   }\
  703.   else {\
  704.     tchunkptr* RP;\
  705.     if (((R = *(RP = &(X->child[1]))) != 0) ||\
  706.         ((R = *(RP = &(X->child[0]))) != 0)) {\
  707.       tchunkptr* CP;\
  708.       while ((*(CP = &(R->child[1])) != 0) ||\
  709.              (*(CP = &(R->child[0])) != 0)) {\
  710.         R = *(RP = CP);\
  711.       }\
  712.       if (RTCHECK(ok_address(M, RP)))\
  713.         *RP = 0;\
  714.       else {\
  715.         CORRUPTION_ERROR_ACTION(M);\
  716.       }\
  717.     }\
  718.   }\
  719.   if (XP != 0) {\
  720.     tbinptr* H = treebin_at(M, X->index);\
  721.     if (X == *H) {\
  722.       if ((*H = R) == 0) \
  723.         clear_treemap(M, X->index);\
  724.     }\
  725.     else if (RTCHECK(ok_address(M, XP))) {\
  726.       if (XP->child[0] == X) \
  727.         XP->child[0] = R;\
  728.       else \
  729.         XP->child[1] = R;\
  730.     }\
  731.     else\
  732.       CORRUPTION_ERROR_ACTION(M);\
  733.     if (R != 0) {\
  734.       if (RTCHECK(ok_address(M, R))) {\
  735.         tchunkptr C0, C1;\
  736.         R->parent = XP;\
  737.         if ((C0 = X->child[0]) != 0) {\
  738.           if (RTCHECK(ok_address(M, C0))) {\
  739.             R->child[0] = C0;\
  740.             C0->parent = R;\
  741.           }\
  742.           else\
  743.             CORRUPTION_ERROR_ACTION(M);\
  744.         }\
  745.         if ((C1 = X->child[1]) != 0) {\
  746.           if (RTCHECK(ok_address(M, C1))) {\
  747.             R->child[1] = C1;\
  748.             C1->parent = R;\
  749.           }\
  750.           else\
  751.             CORRUPTION_ERROR_ACTION(M);\
  752.         }\
  753.       }\
  754.       else\
  755.         CORRUPTION_ERROR_ACTION(M);\
  756.     }\
  757.   }\
  758. }
  759.  
  760. /* Relays to large vs small bin operations */
  761.  
  762. #define insert_chunk(M, P, S)\
  763.   if (is_small(S)) insert_small_chunk(M, P, S)\
  764.   else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
  765.  
  766. #define unlink_chunk(M, P, S)\
  767.   if (is_small(S)) unlink_small_chunk(M, P, S)\
  768.   else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
  769.  
  770.  
  771. /* -------------------------- system alloc setup ------------------------- */
  772.  
  773. /* Operations on mflags */
  774.  
  775. #define use_lock(M)           ((M)->mflags &   USE_LOCK_BIT)
  776. #define enable_lock(M)        ((M)->mflags |=  USE_LOCK_BIT)
  777. #define disable_lock(M)       ((M)->mflags &= ~USE_LOCK_BIT)
  778.  
  779. #define use_mmap(M)           ((M)->mflags &   USE_MMAP_BIT)
  780. #define enable_mmap(M)        ((M)->mflags |=  USE_MMAP_BIT)
  781. #define disable_mmap(M)       ((M)->mflags &= ~USE_MMAP_BIT)
  782.  
  783. #define use_noncontiguous(M)  ((M)->mflags &   USE_NONCONTIGUOUS_BIT)
  784. #define disable_contiguous(M) ((M)->mflags |=  USE_NONCONTIGUOUS_BIT)
  785.  
  786. #define set_lock(M,L)\
  787.  ((M)->mflags = (L)?\
  788.   ((M)->mflags | USE_LOCK_BIT) :\
  789.   ((M)->mflags & ~USE_LOCK_BIT))
  790.  
  791. /* page-align a size */
  792. #define page_align(S)\
  793.  (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE))
  794.  
  795. /* granularity-align a size */
  796. #define granularity_align(S)\
  797.   (((S) + (mparams.granularity - SIZE_T_ONE))\
  798.    & ~(mparams.granularity - SIZE_T_ONE))
  799.  
  800.  
  801. /* For mmap, use granularity alignment  */
  802. #define mmap_align(S) granularity_align(S)
  803.  
  804. /* For sys_alloc, enough padding to ensure can malloc request on success */
  805. #define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT)
  806.  
  807. #define is_page_aligned(S)\
  808.    (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
  809. #define is_granularity_aligned(S)\
  810.    (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
  811.  
  812. /*  True if segment S holds address A */
  813. #define segment_holds(S, A)\
  814.   ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
  815.  
  816. /* Return segment holding given address */
  817. static msegmentptr segment_holding(mstate m, char* addr)
  818. {
  819.     msegmentptr sp = &m->seg;
  820.     for (;;) {
  821.         if (addr >= sp->base && addr < sp->base + sp->size)
  822.             return sp;
  823.         if ((sp = sp->next) == 0)
  824.             return 0;
  825.     }
  826. }
  827.  
  828. /* Return true if segment contains a segment link */
  829. static int has_segment_link(mstate m, msegmentptr ss)
  830. {
  831.     msegmentptr sp = &m->seg;
  832.     for (;;) {
  833.         if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
  834.             return 1;
  835.         if ((sp = sp->next) == 0)
  836.             return 0;
  837.     }
  838. }
  839.  
  840. static inline void* os_mmap(size_t size)
  841. {
  842.   void* ptr = user_alloc(size);
  843.   return (ptr != 0)? ptr: MFAIL;
  844. }
  845.  
  846. static inline int os_munmap(void* ptr, size_t size)
  847. {
  848.     return (user_free(ptr) != 0) ? 0 : -1;
  849. }
  850.  
  851. #define should_trim(M,s)  ((s) > (M)->trim_check)
  852.  
  853.  
  854. #define MMAP_DEFAULT(s)        os_mmap(s)
  855. #define MUNMAP_DEFAULT(a, s)   os_munmap((a), (s))
  856. #define DIRECT_MMAP_DEFAULT(s) os_mmap(s)
  857.  
  858. #define internal_malloc(m, b) malloc(b)
  859. #define internal_free(m, mem) free(mem)
  860.  
  861. /* -----------------------  Direct-mmapping chunks ----------------------- */
  862.  
  863. /*
  864.   Directly mmapped chunks are set up with an offset to the start of
  865.   the mmapped region stored in the prev_foot field of the chunk. This
  866.   allows reconstruction of the required argument to MUNMAP when freed,
  867.   and also allows adjustment of the returned chunk to meet alignment
  868.   requirements (especially in memalign).
  869. */
  870.  
  871. /* Malloc using mmap */
  872. static void* mmap_alloc(mstate m, size_t nb)
  873. {
  874.   size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
  875.     if (mmsize > nb)       /* Check for wrap around 0 */
  876.     {
  877.         char* mm = (char*)(os_mmap(mmsize));
  878.         if (mm != CMFAIL)
  879.         {
  880.       size_t offset = align_offset(chunk2mem(mm));
  881.       size_t psize = mmsize - offset - MMAP_FOOT_PAD;
  882.       mchunkptr p = (mchunkptr)(mm + offset);
  883.       p->prev_foot = offset;
  884.       p->head = psize;
  885.       mark_inuse_foot(m, p, psize);
  886.       chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
  887.       chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
  888.  
  889.       if (m->least_addr == 0 || mm < m->least_addr)
  890.         m->least_addr = mm;
  891.       if ((m->footprint += mmsize) > m->max_footprint)
  892.         m->max_footprint = m->footprint;
  893.       assert(is_aligned(chunk2mem(p)));
  894.       check_mmapped_chunk(m, p);
  895.       return chunk2mem(p);
  896.     }
  897.   }
  898.   return 0;
  899. }
  900.  
  901. /* Realloc using mmap */
  902. static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb)
  903. {
  904.   size_t oldsize = chunksize(oldp);
  905.   if (is_small(nb)) /* Can't shrink mmap regions below small size */
  906.     return 0;
  907.   /* Keep old chunk if big enough but not too big */
  908.   if (oldsize >= nb + SIZE_T_SIZE &&
  909.       (oldsize - nb) <= (mparams.granularity << 1))
  910.     return oldp;
  911.     else
  912.     {
  913.     size_t offset = oldp->prev_foot;
  914.     size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
  915.     size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
  916.     char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
  917.                                   oldmmsize, newmmsize, 1);
  918.         if (cp != CMFAIL)
  919.         {
  920.       mchunkptr newp = (mchunkptr)(cp + offset);
  921.       size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
  922.       newp->head = psize;
  923.       mark_inuse_foot(m, newp, psize);
  924.       chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
  925.       chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
  926.  
  927.       if (cp < m->least_addr)
  928.         m->least_addr = cp;
  929.       if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
  930.         m->max_footprint = m->footprint;
  931.       check_mmapped_chunk(m, newp);
  932.       return newp;
  933.     }
  934.   }
  935.   return 0;
  936. }
  937.  
  938. /* ---------------------------- setting mparams -------------------------- */
  939.  
  940. /* Initialize mparams */
  941. static int init_mparams(void) {
  942.  
  943.     ACQUIRE_MALLOC_GLOBAL_LOCK();
  944.  
  945.     if (mparams.magic == 0)
  946.     {
  947.         size_t magic;
  948.         size_t psize;
  949.         size_t gsize;
  950.  
  951.         psize = 4096;
  952.         gsize = DEFAULT_GRANULARITY;
  953.  
  954.     /* Sanity-check configuration:
  955.        size_t must be unsigned and as wide as pointer type.
  956.        ints must be at least 4 bytes.
  957.        alignment must be at least 8.
  958.        Alignment, min chunk size, and page size must all be powers of 2.
  959.     */
  960.  
  961.         mparams.granularity = gsize;
  962.         mparams.page_size = psize;
  963.         mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
  964.         mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
  965.         mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
  966.  
  967.     /* Set up lock for main malloc area */
  968.         gm->mflags = mparams.default_mflags;
  969.         __lock_init_recursive(gm->lock);
  970.  
  971.         magic = (size_t)(0x12345678 ^ (size_t)0x55555555U);
  972.         magic |= (size_t)8U;    /* ensure nonzero */
  973.         magic &= ~(size_t)7U;   /* improve chances of fault for bad values */
  974.         mparams.magic = magic;
  975.     }
  976.  
  977.     RELEASE_MALLOC_GLOBAL_LOCK();
  978.     return 1;
  979. }
  980.  
  981. /* -------------------------- mspace management -------------------------- */
  982.  
  983. /* Initialize top chunk and its size */
  984. static void init_top(mstate m, mchunkptr p, size_t psize)
  985. {
  986.   /* Ensure alignment */
  987.   size_t offset = align_offset(chunk2mem(p));
  988.   p = (mchunkptr)((char*)p + offset);
  989.   psize -= offset;
  990.  
  991.   m->top = p;
  992.   m->topsize = psize;
  993.   p->head = psize | PINUSE_BIT;
  994.   /* set size of fake trailing chunk holding overhead space only once */
  995.   chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
  996.   m->trim_check = mparams.trim_threshold; /* reset on each update */
  997. }
  998.  
  999. /* Initialize bins for a new mstate that is otherwise zeroed out */
  1000. static void init_bins(mstate m)
  1001. {
  1002.   /* Establish circular links for smallbins */
  1003.   bindex_t i;
  1004.   for (i = 0; i < NSMALLBINS; ++i) {
  1005.     sbinptr bin = smallbin_at(m,i);
  1006.     bin->fd = bin->bk = bin;
  1007.   }
  1008. }
  1009.  
  1010. /* Allocate chunk and prepend remainder with chunk in successor base. */
  1011. static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
  1012.                            size_t nb)
  1013. {
  1014.   mchunkptr p = align_as_chunk(newbase);
  1015.   mchunkptr oldfirst = align_as_chunk(oldbase);
  1016.   size_t psize = (char*)oldfirst - (char*)p;
  1017.   mchunkptr q = chunk_plus_offset(p, nb);
  1018.   size_t qsize = psize - nb;
  1019.   set_size_and_pinuse_of_inuse_chunk(m, p, nb);
  1020.  
  1021.   assert((char*)oldfirst > (char*)q);
  1022.   assert(pinuse(oldfirst));
  1023.   assert(qsize >= MIN_CHUNK_SIZE);
  1024.  
  1025.   /* consolidate remainder with first chunk of old base */
  1026.   if (oldfirst == m->top) {
  1027.     size_t tsize = m->topsize += qsize;
  1028.     m->top = q;
  1029.     q->head = tsize | PINUSE_BIT;
  1030.     check_top_chunk(m, q);
  1031.   }
  1032.   else if (oldfirst == m->dv) {
  1033.     size_t dsize = m->dvsize += qsize;
  1034.     m->dv = q;
  1035.     set_size_and_pinuse_of_free_chunk(q, dsize);
  1036.   }
  1037.   else {
  1038.     if (!is_inuse(oldfirst)) {
  1039.       size_t nsize = chunksize(oldfirst);
  1040.       unlink_chunk(m, oldfirst, nsize);
  1041.       oldfirst = chunk_plus_offset(oldfirst, nsize);
  1042.       qsize += nsize;
  1043.     }
  1044.     set_free_with_pinuse(q, qsize, oldfirst);
  1045.     insert_chunk(m, q, qsize);
  1046.     check_free_chunk(m, q);
  1047.   }
  1048.  
  1049.   check_malloced_chunk(m, chunk2mem(p), nb);
  1050.   return chunk2mem(p);
  1051. }
  1052.  
  1053. /* Add a segment to hold a new noncontiguous region */
  1054. static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped)
  1055. {
  1056.   /* Determine locations and sizes of segment, fenceposts, old top */
  1057.   char* old_top = (char*)m->top;
  1058.   msegmentptr oldsp = segment_holding(m, old_top);
  1059.   char* old_end = oldsp->base + oldsp->size;
  1060.   size_t ssize = pad_request(sizeof(struct malloc_segment));
  1061.   char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
  1062.   size_t offset = align_offset(chunk2mem(rawsp));
  1063.   char* asp = rawsp + offset;
  1064.   char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
  1065.   mchunkptr sp = (mchunkptr)csp;
  1066.   msegmentptr ss = (msegmentptr)(chunk2mem(sp));
  1067.   mchunkptr tnext = chunk_plus_offset(sp, ssize);
  1068.   mchunkptr p = tnext;
  1069.   int nfences = 0;
  1070.  
  1071.   /* reset top to new space */
  1072.   init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
  1073.  
  1074.   /* Set up segment record */
  1075.   assert(is_aligned(ss));
  1076.   set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
  1077.   *ss = m->seg; /* Push current record */
  1078.   m->seg.base = tbase;
  1079.   m->seg.size = tsize;
  1080.   m->seg.sflags = mmapped;
  1081.   m->seg.next = ss;
  1082.  
  1083.   /* Insert trailing fenceposts */
  1084.   for (;;) {
  1085.     mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
  1086.     p->head = FENCEPOST_HEAD;
  1087.     ++nfences;
  1088.     if ((char*)(&(nextp->head)) < old_end)
  1089.       p = nextp;
  1090.     else
  1091.       break;
  1092.   }
  1093.   assert(nfences >= 2);
  1094.  
  1095.   /* Insert the rest of old top into a bin as an ordinary free chunk */
  1096.   if (csp != old_top) {
  1097.     mchunkptr q = (mchunkptr)old_top;
  1098.     size_t psize = csp - old_top;
  1099.     mchunkptr tn = chunk_plus_offset(q, psize);
  1100.     set_free_with_pinuse(q, psize, tn);
  1101.     insert_chunk(m, q, psize);
  1102.   }
  1103.  
  1104.   check_top_chunk(m, m->top);
  1105. }
  1106.  
  1107. /* -------------------------- System allocation -------------------------- */
  1108.  
  1109. /* Get memory from system using MORECORE or MMAP */
  1110. static void* sys_alloc(mstate m, size_t nb)
  1111. {
  1112.     char* tbase = CMFAIL;
  1113.     size_t tsize = 0;
  1114.     flag_t mmap_flag = 0;
  1115.  
  1116.     ensure_initialization();
  1117.  
  1118.   /* Directly map large chunks, but only if already initialized */
  1119.     if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0)
  1120.     {
  1121.         void* mem = mmap_alloc(m, nb);
  1122.         if (mem != 0)
  1123.             return mem;
  1124.     }
  1125.  
  1126.   /*
  1127.     Try getting memory in any of three ways (in most-preferred to
  1128.     least-preferred order):
  1129.     1. A call to MORECORE that can normally contiguously extend memory.
  1130.        (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
  1131.        or main space is mmapped or a previous contiguous call failed)
  1132.     2. A call to MMAP new space (disabled if not HAVE_MMAP).
  1133.        Note that under the default settings, if MORECORE is unable to
  1134.        fulfill a request, and HAVE_MMAP is true, then mmap is
  1135.        used as a noncontiguous system allocator. This is a useful backup
  1136.        strategy for systems with holes in address spaces -- in this case
  1137.        sbrk cannot contiguously expand the heap, but mmap may be able to
  1138.        find space.
  1139.     3. A call to MORECORE that cannot usually contiguously extend memory.
  1140.        (disabled if not HAVE_MORECORE)
  1141.  
  1142.    In all cases, we need to request enough bytes from system to ensure
  1143.    we can malloc nb bytes upon success, so pad with enough space for
  1144.    top_foot, plus alignment-pad to make sure we don't lose bytes if
  1145.    not on boundary, and round this up to a granularity unit.
  1146.   */
  1147.  
  1148.     if (HAVE_MMAP && tbase == CMFAIL)   /* Try MMAP */
  1149.     {
  1150.         size_t rsize = granularity_align(nb + SYS_ALLOC_PADDING);
  1151.         if (rsize > nb)  /* Fail if wraps around zero */
  1152.         {
  1153.             char* mp = (char*)(CALL_MMAP(rsize));
  1154.             if (mp != CMFAIL)
  1155.             {
  1156.                 tbase = mp;
  1157.                 tsize = rsize;
  1158.                 mmap_flag = USE_MMAP_BIT;
  1159.             }
  1160.         }
  1161.     }
  1162.  
  1163.     if (tbase != CMFAIL)
  1164.     {
  1165.  
  1166.         if ((m->footprint += tsize) > m->max_footprint)
  1167.             m->max_footprint = m->footprint;
  1168.  
  1169.         if (!is_initialized(m))  /* first-time initialization */
  1170.         {
  1171.             if (m->least_addr == 0 || tbase < m->least_addr)
  1172.             m->least_addr = tbase;
  1173.             m->seg.base = tbase;
  1174.             m->seg.size = tsize;
  1175.             m->seg.sflags = mmap_flag;
  1176.             m->magic = mparams.magic;
  1177.             m->release_checks = MAX_RELEASE_CHECK_RATE;
  1178.             init_bins(m);
  1179.  
  1180.             if (is_global(m))
  1181.                 init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
  1182.             else
  1183.             {
  1184.         /* Offset top by embedded malloc_state */
  1185.                 mchunkptr mn = next_chunk(mem2chunk(m));
  1186.                 init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
  1187.             }
  1188.         }
  1189.         else
  1190.         {
  1191.       /* Try to merge with an existing segment */
  1192.             msegmentptr sp = &m->seg;
  1193.       /* Only consider most recent segment if traversal suppressed */
  1194.             while (sp != 0 && tbase != sp->base + sp->size)
  1195.                 sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
  1196.             if (sp != 0 && !is_extern_segment(sp) &&
  1197.                 (sp->sflags & USE_MMAP_BIT) == mmap_flag &&
  1198.                 segment_holds(sp, m->top))  /* append */
  1199.             {
  1200.                 sp->size += tsize;
  1201.                 init_top(m, m->top, m->topsize + tsize);
  1202.             }
  1203.             else
  1204.             {
  1205.                 if (tbase < m->least_addr)
  1206.                     m->least_addr = tbase;
  1207.                 sp = &m->seg;
  1208.                 while (sp != 0 && sp->base != tbase + tsize)
  1209.                     sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
  1210.                 if (sp != 0 && !is_extern_segment(sp) &&
  1211.                    (sp->sflags & USE_MMAP_BIT) == mmap_flag)
  1212.                 {
  1213.                     char* oldbase = sp->base;
  1214.                     sp->base = tbase;
  1215.                     sp->size += tsize;
  1216.                     return prepend_alloc(m, tbase, oldbase, nb);
  1217.                 }
  1218.                 else
  1219.                     add_segment(m, tbase, tsize, mmap_flag);
  1220.             }
  1221.         }
  1222.  
  1223.         if (nb < m->topsize)  /* Allocate from new or extended top space */
  1224.         {
  1225.             size_t rsize = m->topsize -= nb;
  1226.             mchunkptr p = m->top;
  1227.             mchunkptr r = m->top = chunk_plus_offset(p, nb);
  1228.             r->head = rsize | PINUSE_BIT;
  1229.             set_size_and_pinuse_of_inuse_chunk(m, p, nb);
  1230.             check_top_chunk(m, m->top);
  1231.             check_malloced_chunk(m, chunk2mem(p), nb);
  1232.             return chunk2mem(p);
  1233.         }
  1234.     }
  1235.  
  1236.     MALLOC_FAILURE_ACTION;
  1237.     return 0;
  1238. }
  1239.  
  1240.  
  1241. /* -----------------------  system deallocation -------------------------- */
  1242.  
  1243. /* Unmap and unlink any mmapped segments that don't contain used chunks */
  1244. static size_t release_unused_segments(mstate m)
  1245. {
  1246.   size_t released = 0;
  1247.   int nsegs = 0;
  1248.   msegmentptr pred = &m->seg;
  1249.   msegmentptr sp = pred->next;
  1250.     while (sp != 0)
  1251.     {
  1252.     char* base = sp->base;
  1253.     size_t size = sp->size;
  1254.     msegmentptr next = sp->next;
  1255.     ++nsegs;
  1256.         if (is_mmapped_segment(sp) && !is_extern_segment(sp))
  1257.         {
  1258.       mchunkptr p = align_as_chunk(base);
  1259.       size_t psize = chunksize(p);
  1260.       /* Can unmap if first chunk holds entire segment and not pinned */
  1261.             if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE)
  1262.             {
  1263.         tchunkptr tp = (tchunkptr)p;
  1264.         assert(segment_holds(sp, (char*)sp));
  1265.         if (p == m->dv) {
  1266.           m->dv = 0;
  1267.           m->dvsize = 0;
  1268.         }
  1269.         else {
  1270.           unlink_large_chunk(m, tp);
  1271.         }
  1272.                 if (CALL_MUNMAP(base, size) == 0)
  1273.                 {
  1274.           released += size;
  1275.           m->footprint -= size;
  1276.           /* unlink obsoleted record */
  1277.           sp = pred;
  1278.           sp->next = next;
  1279.         }
  1280.         else { /* back out if cannot unmap */
  1281.           insert_large_chunk(m, tp, psize);
  1282.         }
  1283.       }
  1284.     }
  1285.     if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */
  1286.       break;
  1287.     pred = sp;
  1288.     sp = next;
  1289.   }
  1290.   /* Reset check counter */
  1291.   m->release_checks = ((nsegs > MAX_RELEASE_CHECK_RATE)?
  1292.                        nsegs : MAX_RELEASE_CHECK_RATE);
  1293.   return released;
  1294. }
  1295.  
  1296. static int sys_trim(mstate m, size_t pad)
  1297. {
  1298.   size_t released = 0;
  1299.   ensure_initialization();
  1300.     if (pad < MAX_REQUEST && is_initialized(m))
  1301.     {
  1302.     pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
  1303.  
  1304.         if (m->topsize > pad)
  1305.         {
  1306.       /* Shrink top space in granularity-size units, keeping at least one */
  1307.       size_t unit = mparams.granularity;
  1308.       size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
  1309.                       SIZE_T_ONE) * unit;
  1310.       msegmentptr sp = segment_holding(m, (char*)m->top);
  1311.  
  1312.             if (!is_extern_segment(sp))
  1313.             {
  1314.                 if (is_mmapped_segment(sp))
  1315.                 {
  1316.           if (HAVE_MMAP &&
  1317.               sp->size >= extra &&
  1318.                         !has_segment_link(m, sp))  /* can't shrink if pinned */
  1319.                     {
  1320.             size_t newsize = sp->size - extra;
  1321.             /* Prefer mremap, fall back to munmap */
  1322.             if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
  1323.                             (CALL_MUNMAP(sp->base + newsize, extra) == 0))
  1324.                         {
  1325.               released = extra;
  1326.             }
  1327.           }
  1328.         }
  1329.             }
  1330.  
  1331.             if (released != 0)
  1332.             {
  1333.         sp->size -= released;
  1334.         m->footprint -= released;
  1335.         init_top(m, m->top, m->topsize - released);
  1336.         check_top_chunk(m, m->top);
  1337.       }
  1338.     }
  1339.  
  1340.     /* Unmap any unused mmapped segments */
  1341.     if (HAVE_MMAP)
  1342.       released += release_unused_segments(m);
  1343.  
  1344.     /* On failure, disable autotrim to avoid repeated failed future calls */
  1345.     if (released == 0 && m->topsize > m->trim_check)
  1346.       m->trim_check = MAX_SIZE_T;
  1347.   }
  1348.  
  1349.   return (released != 0)? 1 : 0;
  1350. }
  1351.  
  1352.  
  1353.  
  1354. /* ---------------------------- malloc support --------------------------- */
  1355.  
  1356. /* allocate a large request from the best fitting chunk in a treebin */
  1357. static void* tmalloc_large(mstate m, size_t nb) {
  1358.   tchunkptr v = 0;
  1359.   size_t rsize = -nb; /* Unsigned negation */
  1360.   tchunkptr t;
  1361.   bindex_t idx;
  1362.   compute_tree_index(nb, idx);
  1363.   if ((t = *treebin_at(m, idx)) != 0) {
  1364.     /* Traverse tree for this bin looking for node with size == nb */
  1365.     size_t sizebits = nb << leftshift_for_tree_index(idx);
  1366.     tchunkptr rst = 0;  /* The deepest untaken right subtree */
  1367.     for (;;) {
  1368.       tchunkptr rt;
  1369.       size_t trem = chunksize(t) - nb;
  1370.       if (trem < rsize) {
  1371.         v = t;
  1372.         if ((rsize = trem) == 0)
  1373.           break;
  1374.       }
  1375.       rt = t->child[1];
  1376.       t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
  1377.       if (rt != 0 && rt != t)
  1378.         rst = rt;
  1379.       if (t == 0) {
  1380.         t = rst; /* set t to least subtree holding sizes > nb */
  1381.         break;
  1382.       }
  1383.       sizebits <<= 1;
  1384.     }
  1385.   }
  1386.   if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
  1387.     binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
  1388.     if (leftbits != 0) {
  1389.       bindex_t i;
  1390.       binmap_t leastbit = least_bit(leftbits);
  1391.       compute_bit2idx(leastbit, i);
  1392.       t = *treebin_at(m, i);
  1393.     }
  1394.   }
  1395.  
  1396.   while (t != 0) { /* find smallest of tree or subtree */
  1397.     size_t trem = chunksize(t) - nb;
  1398.     if (trem < rsize) {
  1399.       rsize = trem;
  1400.       v = t;
  1401.     }
  1402.     t = leftmost_child(t);
  1403.   }
  1404.  
  1405.   /*  If dv is a better fit, return 0 so malloc will use it */
  1406.   if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
  1407.     if (RTCHECK(ok_address(m, v))) { /* split */
  1408.       mchunkptr r = chunk_plus_offset(v, nb);
  1409.       assert(chunksize(v) == rsize + nb);
  1410.       if (RTCHECK(ok_next(v, r))) {
  1411.         unlink_large_chunk(m, v);
  1412.         if (rsize < MIN_CHUNK_SIZE)
  1413.           set_inuse_and_pinuse(m, v, (rsize + nb));
  1414.         else {
  1415.           set_size_and_pinuse_of_inuse_chunk(m, v, nb);
  1416.           set_size_and_pinuse_of_free_chunk(r, rsize);
  1417.           insert_chunk(m, r, rsize);
  1418.         }
  1419.         return chunk2mem(v);
  1420.       }
  1421.     }
  1422.     CORRUPTION_ERROR_ACTION(m);
  1423.   }
  1424.   return 0;
  1425. }
  1426.  
  1427. /* allocate a small request from the best fitting chunk in a treebin */
  1428. static void* tmalloc_small(mstate m, size_t nb)
  1429. {
  1430.   tchunkptr t, v;
  1431.   size_t rsize;
  1432.   bindex_t i;
  1433.   binmap_t leastbit = least_bit(m->treemap);
  1434.   compute_bit2idx(leastbit, i);
  1435.   v = t = *treebin_at(m, i);
  1436.   rsize = chunksize(t) - nb;
  1437.  
  1438.   while ((t = leftmost_child(t)) != 0) {
  1439.     size_t trem = chunksize(t) - nb;
  1440.     if (trem < rsize) {
  1441.       rsize = trem;
  1442.       v = t;
  1443.     }
  1444.   }
  1445.  
  1446.   if (RTCHECK(ok_address(m, v))) {
  1447.     mchunkptr r = chunk_plus_offset(v, nb);
  1448.     assert(chunksize(v) == rsize + nb);
  1449.     if (RTCHECK(ok_next(v, r))) {
  1450.       unlink_large_chunk(m, v);
  1451.       if (rsize < MIN_CHUNK_SIZE)
  1452.         set_inuse_and_pinuse(m, v, (rsize + nb));
  1453.       else {
  1454.         set_size_and_pinuse_of_inuse_chunk(m, v, nb);
  1455.         set_size_and_pinuse_of_free_chunk(r, rsize);
  1456.         replace_dv(m, r, rsize);
  1457.       }
  1458.       return chunk2mem(v);
  1459.     }
  1460.   }
  1461.  
  1462.   CORRUPTION_ERROR_ACTION(m);
  1463.   return 0;
  1464. }
  1465.  
  1466. /* --------------------------- realloc support --------------------------- */
  1467.  
  1468. static void* internal_realloc(struct _reent *reent_ptr, mstate m, void* oldmem, size_t bytes)
  1469. {
  1470.     if (bytes >= MAX_REQUEST)
  1471.     {
  1472.         MALLOC_FAILURE_ACTION;
  1473.         return 0;
  1474.     }
  1475.  
  1476.     PREACTION(m);
  1477.     {
  1478.         mchunkptr oldp = mem2chunk(oldmem);
  1479.         size_t oldsize = chunksize(oldp);
  1480.         mchunkptr next = chunk_plus_offset(oldp, oldsize);
  1481.         mchunkptr newp = 0;
  1482.         void* extra = 0;
  1483.  
  1484.     /* Try to either shrink or extend into top. Else malloc-copy-free */
  1485.  
  1486.         if (RTCHECK(ok_address(m, oldp) && ok_inuse(oldp) &&
  1487.                     ok_next(oldp, next) && ok_pinuse(next)))
  1488.         {
  1489.             size_t nb = request2size(bytes);
  1490.             if (is_mmapped(oldp))
  1491.                 newp = mmap_resize(m, oldp, nb);
  1492.             else if (oldsize >= nb) { /* already big enough */
  1493.                 size_t rsize = oldsize - nb;
  1494.                 newp = oldp;
  1495.                 if (rsize >= MIN_CHUNK_SIZE)
  1496.                 {
  1497.                     mchunkptr remainder = chunk_plus_offset(newp, nb);
  1498.                     set_inuse(m, newp, nb);
  1499.                     set_inuse_and_pinuse(m, remainder, rsize);
  1500.                     extra = chunk2mem(remainder);
  1501.                 }
  1502.             }
  1503.             else if (next == m->top && oldsize + m->topsize > nb)
  1504.             {
  1505.         /* Expand into top */
  1506.                 size_t newsize = oldsize + m->topsize;
  1507.                 size_t newtopsize = newsize - nb;
  1508.                 mchunkptr newtop = chunk_plus_offset(oldp, nb);
  1509.                 set_inuse(m, oldp, nb);
  1510.                 newtop->head = newtopsize |PINUSE_BIT;
  1511.                 m->top = newtop;
  1512.                 m->topsize = newtopsize;
  1513.                 newp = oldp;
  1514.             }
  1515.         }
  1516.         else {
  1517.             USAGE_ERROR_ACTION(m, oldmem);
  1518.             POSTACTION(m);
  1519.             return 0;
  1520.         }
  1521. #if DEBUG
  1522.         if (newp != 0) {
  1523.             check_inuse_chunk(m, newp); /* Check requires lock */
  1524.         }
  1525. #endif
  1526.  
  1527.         POSTACTION(m);
  1528.  
  1529.         if (newp != 0)
  1530.         {
  1531.             if (extra != 0) {
  1532.                 _free_r(reent_ptr, extra);
  1533.             }
  1534.             return chunk2mem(newp);
  1535.         }
  1536.         else
  1537.         {
  1538.             void* newmem = _malloc_r(reent_ptr, bytes);
  1539.             if (newmem != 0) {
  1540.                 size_t oc = oldsize - overhead_for(oldp);
  1541.                 memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
  1542.                 _free_r(reent_ptr, oldmem);
  1543.             }
  1544.         return newmem;
  1545.         }
  1546.   }
  1547.   return 0;
  1548. }
  1549.  
  1550. /* --------------------------- memalign support -------------------------- */
  1551.  
  1552. static void* internal_memalign(mstate m, size_t alignment, size_t bytes)
  1553. {
  1554.     if (alignment <= MALLOC_ALIGNMENT)    /* Can just use malloc */
  1555.         return internal_malloc(m, bytes);
  1556.     if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
  1557.         alignment = MIN_CHUNK_SIZE;
  1558.     if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
  1559.         size_t a = MALLOC_ALIGNMENT << 1;
  1560.         while (a < alignment) a <<= 1;
  1561.         alignment = a;
  1562.     }
  1563.  
  1564.     if (bytes >= MAX_REQUEST - alignment) {
  1565.         if (m != 0)  { /* Test isn't needed but avoids compiler warning */
  1566.             MALLOC_FAILURE_ACTION;
  1567.         }
  1568.     }
  1569.     else
  1570.     {
  1571.         size_t nb = request2size(bytes);
  1572.         size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
  1573.         char* mem = (char*)internal_malloc(m, req);
  1574.         if (mem != 0)
  1575.         {
  1576.             void* leader = 0;
  1577.             void* trailer = 0;
  1578.             mchunkptr p = mem2chunk(mem);
  1579.  
  1580.             PREACTION(m);
  1581.  
  1582.             if ((((size_t)(mem)) % alignment) != 0)  /* misaligned */
  1583.             {
  1584.         /*
  1585.           Find an aligned spot inside chunk.  Since we need to give
  1586.           back leading space in a chunk of at least MIN_CHUNK_SIZE, if
  1587.           the first calculation places us at a spot with less than
  1588.           MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
  1589.           We've allocated enough total room so that this is always
  1590.           possible.
  1591.         */
  1592.                 char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
  1593.                                                        alignment -
  1594.                                                        SIZE_T_ONE)) &
  1595.                                              -alignment));
  1596.                 char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
  1597.                              br : br+alignment;
  1598.                 mchunkptr newp = (mchunkptr)pos;
  1599.                 size_t leadsize = pos - (char*)(p);
  1600.                 size_t newsize = chunksize(p) - leadsize;
  1601.  
  1602.                 if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
  1603.                     newp->prev_foot = p->prev_foot + leadsize;
  1604.                     newp->head = newsize;
  1605.                 }
  1606.                 else { /* Otherwise, give back leader, use the rest */
  1607.                     set_inuse(m, newp, newsize);
  1608.                     set_inuse(m, p, leadsize);
  1609.                     leader = chunk2mem(p);
  1610.                 }
  1611.                 p = newp;
  1612.             }
  1613.  
  1614.       /* Give back spare room at the end */
  1615.             if (!is_mmapped(p))
  1616.             {
  1617.                 size_t size = chunksize(p);
  1618.                 if (size > nb + MIN_CHUNK_SIZE)
  1619.                 {
  1620.                     size_t remainder_size = size - nb;
  1621.                     mchunkptr remainder = chunk_plus_offset(p, nb);
  1622.                     set_inuse(m, p, nb);
  1623.                     set_inuse(m, remainder, remainder_size);
  1624.                     trailer = chunk2mem(remainder);
  1625.                 }
  1626.             }
  1627.  
  1628.             assert (chunksize(p) >= nb);
  1629.             assert((((size_t)(chunk2mem(p))) % alignment) == 0);
  1630.             check_inuse_chunk(m, p);
  1631.             POSTACTION(m);
  1632.             if (leader != 0) {
  1633.                 internal_free(m, leader);
  1634.             }
  1635.             if (trailer != 0) {
  1636.                 internal_free(m, trailer);
  1637.             }
  1638.             return chunk2mem(p);
  1639.         }
  1640.     }
  1641.     return 0;
  1642. }
  1643.  
  1644. void* memalign(size_t alignment, size_t bytes)
  1645. {
  1646.     return internal_memalign(gm, alignment, bytes);
  1647. }
  1648.  
  1649.  
  1650.  
  1651. void* _malloc_r(struct _reent *reent_ptr, size_t bytes) {
  1652.   /*
  1653.      Basic algorithm:
  1654.      If a small request (< 256 bytes minus per-chunk overhead):
  1655.        1. If one exists, use a remainderless chunk in associated smallbin.
  1656.           (Remainderless means that there are too few excess bytes to
  1657.           represent as a chunk.)
  1658.        2. If it is big enough, use the dv chunk, which is normally the
  1659.           chunk adjacent to the one used for the most recent small request.
  1660.        3. If one exists, split the smallest available chunk in a bin,
  1661.           saving remainder in dv.
  1662.        4. If it is big enough, use the top chunk.
  1663.        5. If available, get memory from system and use it
  1664.      Otherwise, for a large request:
  1665.        1. Find the smallest available binned chunk that fits, and use it
  1666.           if it is better fitting than dv chunk, splitting if necessary.
  1667.        2. If better fitting than any binned chunk, use the dv chunk.
  1668.        3. If it is big enough, use the top chunk.
  1669.        4. If request size >= mmap threshold, try to directly mmap this chunk.
  1670.        5. If available, get memory from system and use it
  1671.  
  1672.      The ugly goto's here ensure that postaction occurs along all paths.
  1673.   */
  1674.  
  1675.   ensure_initialization(); /* initialize in sys_alloc if not using locks */
  1676.  
  1677.     PREACTION(gm);
  1678.    {
  1679.     void* mem;
  1680.     size_t nb;
  1681.  
  1682.         if (bytes <= MAX_SMALL_REQUEST)
  1683.         {
  1684.       bindex_t idx;
  1685.       binmap_t smallbits;
  1686.       nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
  1687.       idx = small_index(nb);
  1688.       smallbits = gm->smallmap >> idx;
  1689.  
  1690.             if ((smallbits & 0x3U) != 0) /* Remainderless fit to a smallbin. */
  1691.             {
  1692.         mchunkptr b, p;
  1693.         idx += ~smallbits & 1;       /* Uses next bin if idx empty */
  1694.         b = smallbin_at(gm, idx);
  1695.         p = b->fd;
  1696.         assert(chunksize(p) == small_index2size(idx));
  1697.         unlink_first_small_chunk(gm, b, p, idx);
  1698.         set_inuse_and_pinuse(gm, p, small_index2size(idx));
  1699.         mem = chunk2mem(p);
  1700.         check_malloced_chunk(gm, mem, nb);
  1701.         goto postaction;
  1702.       }
  1703.             else if (nb > gm->dvsize)
  1704.             {
  1705.                 if (smallbits != 0) /* Use chunk in next nonempty smallbin */
  1706.                 {
  1707.           mchunkptr b, p, r;
  1708.           size_t rsize;
  1709.           bindex_t i;
  1710.           binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
  1711.           binmap_t leastbit = least_bit(leftbits);
  1712.           compute_bit2idx(leastbit, i);
  1713.           b = smallbin_at(gm, i);
  1714.           p = b->fd;
  1715.           assert(chunksize(p) == small_index2size(i));
  1716.           unlink_first_small_chunk(gm, b, p, i);
  1717.           rsize = small_index2size(i) - nb;
  1718.           /* Fit here cannot be remainderless if 4byte sizes */
  1719.           if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
  1720.             set_inuse_and_pinuse(gm, p, small_index2size(i));
  1721.                     else
  1722.                     {
  1723.             set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
  1724.             r = chunk_plus_offset(p, nb);
  1725.             set_size_and_pinuse_of_free_chunk(r, rsize);
  1726.             replace_dv(gm, r, rsize);
  1727.           }
  1728.           mem = chunk2mem(p);
  1729.           check_malloced_chunk(gm, mem, nb);
  1730.           goto postaction;
  1731.         }
  1732.                 else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0)
  1733.                 {
  1734.           check_malloced_chunk(gm, mem, nb);
  1735.           goto postaction;
  1736.         }
  1737.       }
  1738.     }
  1739.     else if (bytes >= MAX_REQUEST)
  1740.       nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
  1741.         else
  1742.         {
  1743.       nb = pad_request(bytes);
  1744.             if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0)
  1745.             {
  1746.         check_malloced_chunk(gm, mem, nb);
  1747.         goto postaction;
  1748.       }
  1749.     }
  1750.  
  1751.     if (nb <= gm->dvsize) {
  1752.       size_t rsize = gm->dvsize - nb;
  1753.       mchunkptr p = gm->dv;
  1754.       if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
  1755.         mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
  1756.         gm->dvsize = rsize;
  1757.         set_size_and_pinuse_of_free_chunk(r, rsize);
  1758.         set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
  1759.       }
  1760.       else { /* exhaust dv */
  1761.         size_t dvs = gm->dvsize;
  1762.         gm->dvsize = 0;
  1763.         gm->dv = 0;
  1764.         set_inuse_and_pinuse(gm, p, dvs);
  1765.       }
  1766.       mem = chunk2mem(p);
  1767.       check_malloced_chunk(gm, mem, nb);
  1768.       goto postaction;
  1769.     }
  1770.     else if (nb < gm->topsize) { /* Split top */
  1771.       size_t rsize = gm->topsize -= nb;
  1772.       mchunkptr p = gm->top;
  1773.       mchunkptr r = gm->top = chunk_plus_offset(p, nb);
  1774.       r->head = rsize | PINUSE_BIT;
  1775.       set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
  1776.       mem = chunk2mem(p);
  1777.       check_top_chunk(gm, gm->top);
  1778.       check_malloced_chunk(gm, mem, nb);
  1779.       goto postaction;
  1780.     }
  1781.  
  1782.     mem = sys_alloc(gm, nb);
  1783.  
  1784.   postaction:
  1785.         POSTACTION(gm);
  1786.     return mem;
  1787.   }
  1788.  
  1789.   return 0;
  1790. }
  1791.  
  1792. void _free_r(struct _reent *reent_ptr, void* mem) {
  1793.   /*
  1794.      Consolidate freed chunks with preceeding or succeeding bordering
  1795.      free chunks, if they exist, and then place in a bin.  Intermixed
  1796.      with special cases for top, dv, mmapped chunks, and usage errors.
  1797.   */
  1798.  
  1799.     if (mem != 0)
  1800.     {
  1801.     mchunkptr p  = mem2chunk(mem);
  1802.  
  1803. #define fm gm
  1804.  
  1805.         PREACTION(fm);
  1806.     {
  1807.       check_inuse_chunk(fm, p);
  1808.             if (RTCHECK(ok_address(fm, p) && ok_inuse(p)))
  1809.             {
  1810.         size_t psize = chunksize(p);
  1811.         mchunkptr next = chunk_plus_offset(p, psize);
  1812.                 if (!pinuse(p))
  1813.                 {
  1814.           size_t prevsize = p->prev_foot;
  1815.                     if (is_mmapped(p))
  1816.                     {
  1817.             psize += prevsize + MMAP_FOOT_PAD;
  1818.             if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
  1819.               fm->footprint -= psize;
  1820.             goto postaction;
  1821.           }
  1822.                     else
  1823.                     {
  1824.             mchunkptr prev = chunk_minus_offset(p, prevsize);
  1825.             psize += prevsize;
  1826.             p = prev;
  1827.                         if (RTCHECK(ok_address(fm, prev)))  /* consolidate backward */
  1828.                         {
  1829.                             if (p != fm->dv)
  1830.                             {
  1831.                 unlink_chunk(fm, p, prevsize);
  1832.               }
  1833.                             else if ((next->head & INUSE_BITS) == INUSE_BITS)
  1834.                             {
  1835.                 fm->dvsize = psize;
  1836.                 set_free_with_pinuse(p, psize, next);
  1837.                 goto postaction;
  1838.               }
  1839.             }
  1840.             else
  1841.               goto erroraction;
  1842.           }
  1843.         }
  1844.  
  1845.                 if (RTCHECK(ok_next(p, next) && ok_pinuse(next)))
  1846.                 {
  1847.                     if (!cinuse(next))    /* consolidate forward */
  1848.                     {
  1849.                         if (next == fm->top)
  1850.                         {
  1851.               size_t tsize = fm->topsize += psize;
  1852.               fm->top = p;
  1853.               p->head = tsize | PINUSE_BIT;
  1854.                             if (p == fm->dv)
  1855.                             {
  1856.                 fm->dv = 0;
  1857.                 fm->dvsize = 0;
  1858.               }
  1859.               if (should_trim(fm, tsize))
  1860.                 sys_trim(fm, 0);
  1861.               goto postaction;
  1862.             }
  1863.                         else if (next == fm->dv)
  1864.                         {
  1865.               size_t dsize = fm->dvsize += psize;
  1866.               fm->dv = p;
  1867.               set_size_and_pinuse_of_free_chunk(p, dsize);
  1868.               goto postaction;
  1869.             }
  1870.                         else
  1871.                         {
  1872.               size_t nsize = chunksize(next);
  1873.               psize += nsize;
  1874.               unlink_chunk(fm, next, nsize);
  1875.               set_size_and_pinuse_of_free_chunk(p, psize);
  1876.                             if (p == fm->dv)
  1877.                             {
  1878.                 fm->dvsize = psize;
  1879.                 goto postaction;
  1880.               }
  1881.             }
  1882.           }
  1883.           else
  1884.             set_free_with_pinuse(p, psize, next);
  1885.  
  1886.                     if (is_small(psize))
  1887.                     {
  1888.             insert_small_chunk(fm, p, psize);
  1889.             check_free_chunk(fm, p);
  1890.           }
  1891.                     else
  1892.                     {
  1893.             tchunkptr tp = (tchunkptr)p;
  1894.             insert_large_chunk(fm, tp, psize);
  1895.             check_free_chunk(fm, p);
  1896.             if (--fm->release_checks == 0)
  1897.               release_unused_segments(fm);
  1898.           }
  1899.           goto postaction;
  1900.         }
  1901.       }
  1902.     erroraction:
  1903.       USAGE_ERROR_ACTION(fm, p);
  1904.     postaction:
  1905.         POSTACTION(fm);
  1906.     }
  1907.   }
  1908. #undef fm
  1909. }
  1910.  
  1911. void* _calloc_r(struct _reent *reent_ptr, size_t n_elements, size_t elem_size) {
  1912.   void* mem;
  1913.   size_t req = 0;
  1914.   if (n_elements != 0) {
  1915.     req = n_elements * elem_size;
  1916.     if (((n_elements | elem_size) & ~(size_t)0xffff) &&
  1917.         (req / n_elements != elem_size))
  1918.       req = MAX_SIZE_T; /* force downstream failure on overflow */
  1919.   }
  1920.   mem = _malloc_r(reent_ptr, req);
  1921.   if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
  1922.     memset(mem, 0, req);
  1923.   return mem;
  1924. }
  1925.  
  1926. void* _realloc_r (struct _reent *reent_ptr, void* oldmem, size_t bytes){
  1927.   if (oldmem == 0)
  1928.     return _malloc_r(reent_ptr, bytes);
  1929. #ifdef REALLOC_ZERO_BYTES_FREES
  1930.   if (bytes == 0) {
  1931.     _free_r(ptr, oldmem);
  1932.     return 0;
  1933.   }
  1934. #endif /* REALLOC_ZERO_BYTES_FREES */
  1935.   else {
  1936. #if ! FOOTERS
  1937.     mstate m = gm;
  1938. #else /* FOOTERS */
  1939.     mstate m = get_mstate_for(mem2chunk(oldmem));
  1940.     if (!ok_magic(m)) {
  1941.       USAGE_ERROR_ACTION(m, oldmem);
  1942.       return 0;
  1943.     }
  1944. #endif /* FOOTERS */
  1945.     return internal_realloc(reent_ptr, m, oldmem, bytes);
  1946.   }
  1947. }
  1948.  
  1949.  
  1950.  
  1951. /* -----------------------------------------------------------------------
  1952. History:
  1953.     V2.8.4 Wed May 27 09:56:23 2009  Doug Lea  (dl at gee)
  1954.       * Use zeros instead of prev foot for is_mmapped
  1955.       * Add mspace_track_large_chunks; thanks to Jean Brouwers
  1956.       * Fix set_inuse in internal_realloc; thanks to Jean Brouwers
  1957.       * Fix insufficient sys_alloc padding when using 16byte alignment
  1958.       * Fix bad error check in mspace_footprint
  1959.       * Adaptations for ptmalloc; thanks to Wolfram Gloger.
  1960.       * Reentrant spin locks; thanks to Earl Chew and others
  1961.       * Win32 improvements; thanks to Niall Douglas and Earl Chew
  1962.       * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options
  1963.       * Extension hook in malloc_state
  1964.       * Various small adjustments to reduce warnings on some compilers
  1965.       * Various configuration extensions/changes for more platforms. Thanks
  1966.          to all who contributed these.
  1967.  
  1968.     V2.8.3 Thu Sep 22 11:16:32 2005  Doug Lea  (dl at gee)
  1969.       * Add max_footprint functions
  1970.       * Ensure all appropriate literals are size_t
  1971.       * Fix conditional compilation problem for some #define settings
  1972.       * Avoid concatenating segments with the one provided
  1973.         in create_mspace_with_base
  1974.       * Rename some variables to avoid compiler shadowing warnings
  1975.       * Use explicit lock initialization.
  1976.       * Better handling of sbrk interference.
  1977.       * Simplify and fix segment insertion, trimming and mspace_destroy
  1978.       * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
  1979.       * Thanks especially to Dennis Flanagan for help on these.
  1980.  
  1981.     V2.8.2 Sun Jun 12 16:01:10 2005  Doug Lea  (dl at gee)
  1982.       * Fix memalign brace error.
  1983.  
  1984.     V2.8.1 Wed Jun  8 16:11:46 2005  Doug Lea  (dl at gee)
  1985.       * Fix improper #endif nesting in C++
  1986.       * Add explicit casts needed for C++
  1987.  
  1988.     V2.8.0 Mon May 30 14:09:02 2005  Doug Lea  (dl at gee)
  1989.       * Use trees for large bins
  1990.       * Support mspaces
  1991.       * Use segments to unify sbrk-based and mmap-based system allocation,
  1992.         removing need for emulation on most platforms without sbrk.
  1993.       * Default safety checks
  1994.       * Optional footer checks. Thanks to William Robertson for the idea.
  1995.       * Internal code refactoring
  1996.       * Incorporate suggestions and platform-specific changes.
  1997.         Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
  1998.         Aaron Bachmann,  Emery Berger, and others.
  1999.       * Speed up non-fastbin processing enough to remove fastbins.
  2000.       * Remove useless cfree() to avoid conflicts with other apps.
  2001.       * Remove internal memcpy, memset. Compilers handle builtins better.
  2002.       * Remove some options that no one ever used and rename others.
  2003.  
  2004.     V2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
  2005.       * Fix malloc_state bitmap array misdeclaration
  2006.  
  2007.     V2.7.1 Thu Jul 25 10:58:03 2002  Doug Lea  (dl at gee)
  2008.       * Allow tuning of FIRST_SORTED_BIN_SIZE
  2009.       * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
  2010.       * Better detection and support for non-contiguousness of MORECORE.
  2011.         Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
  2012.       * Bypass most of malloc if no frees. Thanks To Emery Berger.
  2013.       * Fix freeing of old top non-contiguous chunk im sysmalloc.
  2014.       * Raised default trim and map thresholds to 256K.
  2015.       * Fix mmap-related #defines. Thanks to Lubos Lunak.
  2016.       * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
  2017.       * Branch-free bin calculation
  2018.       * Default trim and mmap thresholds now 256K.
  2019.  
  2020.     V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
  2021.       * Introduce independent_comalloc and independent_calloc.
  2022.         Thanks to Michael Pachos for motivation and help.
  2023.       * Make optional .h file available
  2024.       * Allow > 2GB requests on 32bit systems.
  2025.       * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
  2026.         Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
  2027.         and Anonymous.
  2028.       * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
  2029.         helping test this.)
  2030.       * memalign: check alignment arg
  2031.       * realloc: don't try to shift chunks backwards, since this
  2032.         leads to  more fragmentation in some programs and doesn't
  2033.         seem to help in any others.
  2034.       * Collect all cases in malloc requiring system memory into sysmalloc
  2035.       * Use mmap as backup to sbrk
  2036.       * Place all internal state in malloc_state
  2037.       * Introduce fastbins (although similar to 2.5.1)
  2038.       * Many minor tunings and cosmetic improvements
  2039.       * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
  2040.       * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
  2041.         Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
  2042.       * Include errno.h to support default failure action.
  2043.  
  2044.     V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
  2045.       * return null for negative arguments
  2046.       * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
  2047.          * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
  2048.           (e.g. WIN32 platforms)
  2049.          * Cleanup header file inclusion for WIN32 platforms
  2050.          * Cleanup code to avoid Microsoft Visual C++ compiler complaints
  2051.          * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
  2052.            memory allocation routines
  2053.          * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
  2054.          * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
  2055.            usage of 'assert' in non-WIN32 code
  2056.          * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
  2057.            avoid infinite loop
  2058.       * Always call 'fREe()' rather than 'free()'
  2059.  
  2060.     V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
  2061.       * Fixed ordering problem with boundary-stamping
  2062.  
  2063.     V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
  2064.       * Added pvalloc, as recommended by H.J. Liu
  2065.       * Added 64bit pointer support mainly from Wolfram Gloger
  2066.       * Added anonymously donated WIN32 sbrk emulation
  2067.       * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
  2068.       * malloc_extend_top: fix mask error that caused wastage after
  2069.         foreign sbrks
  2070.       * Add linux mremap support code from HJ Liu
  2071.    
  2072.     V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
  2073.       * Integrated most documentation with the code.
  2074.       * Add support for mmap, with help from
  2075.         Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
  2076.       * Use last_remainder in more cases.
  2077.       * Pack bins using idea from  colin@nyx10.cs.du.edu
  2078.       * Use ordered bins instead of best-fit threshhold
  2079.       * Eliminate block-local decls to simplify tracing and debugging.
  2080.       * Support another case of realloc via move into top
  2081.       * Fix error occuring when initial sbrk_base not word-aligned.  
  2082.       * Rely on page size for units instead of SBRK_UNIT to
  2083.         avoid surprises about sbrk alignment conventions.
  2084.       * Add mallinfo, mallopt. Thanks to Raymond Nijssen
  2085.         (raymond@es.ele.tue.nl) for the suggestion.
  2086.       * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
  2087.       * More precautions for cases where other routines call sbrk,
  2088.         courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
  2089.       * Added macros etc., allowing use in linux libc from
  2090.         H.J. Lu (hjl@gnu.ai.mit.edu)
  2091.       * Inverted this history list
  2092.  
  2093.     V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
  2094.       * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
  2095.       * Removed all preallocation code since under current scheme
  2096.         the work required to undo bad preallocations exceeds
  2097.         the work saved in good cases for most test programs.
  2098.       * No longer use return list or unconsolidated bins since
  2099.         no scheme using them consistently outperforms those that don't
  2100.         given above changes.
  2101.       * Use best fit for very large chunks to prevent some worst-cases.
  2102.       * Added some support for debugging
  2103.  
  2104.     V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
  2105.       * Removed footers when chunks are in use. Thanks to
  2106.         Paul Wilson (wilson@cs.texas.edu) for the suggestion.
  2107.  
  2108.     V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
  2109.       * Added malloc_trim, with help from Wolfram Gloger
  2110.         (wmglo@Dent.MED.Uni-Muenchen.DE).
  2111.  
  2112.     V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
  2113.  
  2114.     V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
  2115.       * realloc: try to expand in both directions
  2116.       * malloc: swap order of clean-bin strategy;
  2117.       * realloc: only conditionally expand backwards
  2118.       * Try not to scavenge used bins
  2119.       * Use bin counts as a guide to preallocation
  2120.       * Occasionally bin return list chunks in first scan
  2121.       * Add a few optimizations from colin@nyx10.cs.du.edu
  2122.  
  2123.     V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
  2124.       * faster bin computation & slightly different binning
  2125.       * merged all consolidations to one part of malloc proper
  2126.          (eliminating old malloc_find_space & malloc_clean_bin)
  2127.       * Scan 2 returns chunks (not just 1)
  2128.       * Propagate failure in realloc if malloc returns 0
  2129.       * Add stuff to allow compilation on non-ANSI compilers
  2130.           from kpv@research.att.com
  2131.      
  2132.     V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
  2133.       * removed potential for odd address access in prev_chunk
  2134.       * removed dependency on getpagesize.h
  2135.       * misc cosmetics and a bit more internal documentation
  2136.       * anticosmetics: mangled names in macros to evade debugger strangeness
  2137.       * tested on sparc, hp-700, dec-mips, rs6000
  2138.           with gcc & native cc (hp, dec only) allowing
  2139.           Detlefs & Zorn comparison study (in SIGPLAN Notices.)
  2140.  
  2141.     Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
  2142.       * Based loosely on libg++-1.2X malloc. (It retains some of the overall
  2143.          structure of old version,  but most details differ.)
  2144.  
  2145. */
  2146.  
  2147.