<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 6 Sep 2016, at 15:07 PM, Frediano Ziglio <<a href="mailto:fziglio@redhat.com" class="">fziglio@redhat.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 12pt;" class=""><blockquote style="border-left-width: 2px; border-left-style: solid; border-left-color: rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt;" data-mce-style="border-left: 2px solid #1010FF; margin-left: 5px; padding-left: 5px; color: #000; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica,Arial,sans-serif; font-size: 12pt;" class=""><div dir="ltr" class=""><div class="gmail_extra">On Mon, Sep 5, 2016 at 9:26 PM, Frediano Ziglio <span dir="ltr" class=""><<a href="mailto:fziglio@redhat.com" target="_blank" data-mce-href="mailto:fziglio@redhat.com" class="">fziglio@redhat.com</a>></span> wrote:<br class=""><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex" data-mce-style="margin: 0 0 0 .8ex; border-left: 1px #ccc solid; padding-left: 1ex;">Why the rationale was removed?<br class=""><br class=""></blockquote><div class="">By mistake, i'll add it back in the next version. </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex" data-mce-style="margin: 0 0 0 .8ex; border-left: 1px #ccc solid; padding-left: 1ex;">By the way this was a workaround for a VS bug, get Visual Studio 2015 Update 1 (actually we are at update 3)<br class=""></blockquote><div class="">True, however microsoft recommends using visual c++ compiler profile as it is different from the c compiler profile.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Yes, especially if you don't know what you are doing and you don't have a acceptable test suite.<br class=""></div><div class="">I hope that they all don't apply to us.<br class=""></div></div></div></div></blockquote><div><br class=""></div><div><br class=""></div><div>Hi Frediano,</div><div><br class=""></div><div>Actually using Microsoft C++ compiler for C files is recommended because it performs</div><div>more excessive static checks and produces warnings regarding more potential problematic cases.</div><div>And this is definitely a good thing.</div><div><br class=""></div><div>~Dmitry</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 12pt;" class=""><div class=""><br class=""></div><div class="">Frediano<br class=""></div><div class=""><br class=""></div><blockquote style="border-left-width: 2px; border-left-style: solid; border-left-color: rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt;" data-mce-style="border-left: 2px solid #1010FF; margin-left: 5px; padding-left: 5px; color: #000; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica,Arial,sans-serif; font-size: 12pt;" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex" data-mce-style="margin: 0 0 0 .8ex; border-left: 1px #ccc solid; padding-left: 1ex;"><br class=""> Nack<br class=""><br class=""> Frediano<br class=""><br class=""> ><br class=""> > Signed-off-by: Sameeh Jubran <<a href="mailto:sameeh@daynix.com" target="_blank" data-mce-href="mailto:sameeh@daynix.com" class="">sameeh@daynix.com</a>><br class=""> > ---<br class=""> >  qxldod/mspace.c               | 2437<br class=""> >  -----------------------------------------<br class=""> >  qxldod/mspace.cpp             | 2437<br class=""> >  +++++++++++++++++++++++++++++++++++++++++<br class=""> >  qxldod/qxldod.vcxproj         |    2 +-<br class=""> >  qxldod/qxldod.vcxproj.filters |    2 +-<br class=""> >  4 files changed, 2439 insertions(+), 2439 deletions(-)<br class=""> >  delete mode 100755 qxldod/mspace.c<br class=""> >  create mode 100755 qxldod/mspace.cpp<br class=""> ><br class=""> > diff --git a/qxldod/mspace.c b/qxldod/mspace.c<br class=""> > deleted file mode 100755<br class=""> > index d0ba123..0000000<br class=""> > --- a/qxldod/mspace.c<br class=""> > +++ /dev/null<br class=""> > @@ -1,2437 +0,0 @@<br class=""> > -// based on dlmalloc from Doug Lea<br class=""> > -<br class=""> > -<br class=""> > -// quote from the Doug Lea original file<br class=""> > -    /*<br class=""> > -      This is a version (aka dlmalloc) of malloc/free/realloc written by<br class=""> > -      Doug Lea and released to the public domain, as explained at<br class=""> > -      <a href="http://creativecommons.org/licenses/publicdomain" rel="noreferrer" target="_blank" data-mce-href="http://creativecommons.org/licenses/publicdomain" class="">http://creativecommons.org/licenses/publicdomain</a>.  Send questions,<br class=""> > -      comments, complaints, performance data, etc to <a href="mailto:dl@cs.oswego.edu" target="_blank" data-mce-href="mailto:dl@cs.oswego.edu" class="">dl@cs.oswego.edu</a><br class=""> > -<br class=""> > -    * Version 2.8.3 Thu Sep 22 11:16:15 2005  Doug Lea  (dl at gee)<br class=""> > -<br class=""> > -       Note: There may be an updated version of this malloc obtainable at<br class=""> > -               <a href="ftp://gee.cs.oswego.edu/pub/misc/malloc.c" rel="noreferrer" target="_blank" data-mce-href="ftp://gee.cs.oswego.edu/pub/misc/malloc.c" class="">ftp://gee.cs.oswego.edu/pub/misc/malloc.c</a><br class=""> > -             Check before installing!<br class=""> > -    */<br class=""> > -<br class=""> > -<br class=""> > -#include <ntddk.h><br class=""> > -<br class=""> > -#include "mspace.h"<br class=""> > -<br class=""> > -#pragma warning( disable : 4146 ) /* no "unsigned" warnings */<br class=""> > -<br class=""> > -#define MALLOC_ALIGNMENT ((size_t)8U)<br class=""> > -#define USE_LOCKS 0<br class=""> > -#define malloc_getpagesize ((size_t)4096U)<br class=""> > -#define DEFAULT_GRANULARITY malloc_getpagesize<br class=""> > -#define MAX_SIZE_T (~(size_t)0)<br class=""> > -#define MALLOC_FAILURE_ACTION<br class=""> > -#define MALLINFO_FIELD_TYPE size_t<br class=""> > -#define FOOTERS 0<br class=""> > -#define INSECURE 0<br class=""> > -#define PROCEED_ON_ERROR 0<br class=""> > -#define DEBUG 0<br class=""> > -#define ABORT_ON_ASSERT_FAILURE 1<br class=""> > -#define ABORT(user_data) abort_func(user_data)<br class=""> > -#define USE_BUILTIN_FFS 0<br class=""> > -#define USE_DEV_RANDOM 0<br class=""> > -#define PRINT(params) print_func params<br class=""> > -<br class=""> > -<br class=""> > -#define MEMCPY(dest, src, n) RtlCopyMemory(dest, src, n)<br class=""> > -#define MEMCLEAR(dest, n) RtlZeroMemory(dest, n)<br class=""> > -<br class=""> > -<br class=""> > -#define M_GRANULARITY        (-1)<br class=""> > -<br class=""> > -void default_abort_func(void *user_data)<br class=""> > -{<br class=""> > -    for (;;);<br class=""> > -}<br class=""> > -<br class=""> > -void default_print_func(void *user_data, char *format, ...)<br class=""> > -{<br class=""> > -}<br class=""> > -<br class=""> > -static mspace_abort_t abort_func = default_abort_func;<br class=""> > -static mspace_print_t print_func = default_print_func;<br class=""> > -<br class=""> > -void mspace_set_abort_func(mspace_abort_t f)<br class=""> > -{<br class=""> > -    abort_func = f;<br class=""> > -}<br class=""> > -<br class=""> > -void mspace_set_print_func(mspace_print_t f)<br class=""> > -{<br class=""> > -    print_func = f;<br class=""> > -}<br class=""> > -<br class=""> > -/* ------------------------ Mallinfo declarations ------------------------<br class=""> > */<br class=""> > -<br class=""> > -#if !NO_MALLINFO<br class=""> > -/*<br class=""> > -  This version of malloc supports the standard SVID/XPG mallinfo<br class=""> > -  routine that returns a struct containing usage properties and<br class=""> > -  statistics. It should work on any system that has a<br class=""> > -  /usr/include/malloc.h defining struct mallinfo.  The main<br class=""> > -  declaration needed is the mallinfo struct that is returned (by-copy)<br class=""> > -  by mallinfo().  The malloinfo struct contains a bunch of fields that<br class=""> > -  are not even meaningful in this version of malloc.  These fields are<br class=""> > -  are instead filled by mallinfo() with other numbers that might be of<br class=""> > -  interest.<br class=""> > -<br class=""> > -  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a<br class=""> > -  /usr/include/malloc.h file that includes a declaration of struct<br class=""> > -  mallinfo.  If so, it is included; else a compliant version is<br class=""> > -  declared below.  These must be precisely the same for mallinfo() to<br class=""> > -  work.  The original SVID version of this struct, defined on most<br class=""> > -  systems with mallinfo, declares all fields as ints. But some others<br class=""> > -  define as unsigned long. If your system defines the fields using a<br class=""> > -  type of different width than listed here, you MUST #include your<br class=""> > -  system version and #define HAVE_USR_INCLUDE_MALLOC_H.<br class=""> > -*/<br class=""> > -<br class=""> > -/* #define HAVE_USR_INCLUDE_MALLOC_H */<br class=""> > -<br class=""> > -<br class=""> > -struct mallinfo {<br class=""> > -  MALLINFO_FIELD_TYPE arena;    /* non-mmapped space allocated from system<br class=""> > */<br class=""> > -  MALLINFO_FIELD_TYPE ordblks;  /* number of free chunks */<br class=""> > -  MALLINFO_FIELD_TYPE smblks;   /* always 0 */<br class=""> > -  MALLINFO_FIELD_TYPE hblks;    /* always 0 */<br class=""> > -  MALLINFO_FIELD_TYPE hblkhd;   /* space in mmapped regions */<br class=""> > -  MALLINFO_FIELD_TYPE usmblks;  /* maximum total allocated space */<br class=""> > -  MALLINFO_FIELD_TYPE fsmblks;  /* always 0 */<br class=""> > -  MALLINFO_FIELD_TYPE uordblks; /* total allocated space */<br class=""> > -  MALLINFO_FIELD_TYPE fordblks; /* total free space */<br class=""> > -  MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */<br class=""> > -};<br class=""> > -<br class=""> > -#endif /* NO_MALLINFO */<br class=""> > -<br class=""> > -<br class=""> > -<br class=""> > -#ifdef DEBUG<br class=""> > -#if ABORT_ON_ASSERT_FAILURE<br class=""> > -#define assert(user_data, x) if(!(x)) ABORT(user_data)<br class=""> > -#else /* ABORT_ON_ASSERT_FAILURE */<br class=""> > -#include <assert.h><br class=""> > -#endif /* ABORT_ON_ASSERT_FAILURE */<br class=""> > -#else  /* DEBUG */<br class=""> > -#define assert(user_data, x)<br class=""> > -#endif /* DEBUG */<br class=""> > -<br class=""> > -/* ------------------- size_t and alignment properties --------------------<br class=""> > */<br class=""> > -<br class=""> > -/* The byte and bit size of a size_t */<br class=""> > -#define SIZE_T_SIZE         (sizeof(size_t))<br class=""> > -#define SIZE_T_BITSIZE      (sizeof(size_t) << 3)<br class=""> > -<br class=""> > -/* Some constants coerced to size_t */<br class=""> > -/* Annoying but necessary to avoid errors on some plaftorms */<br class=""> > -#define SIZE_T_ZERO         ((size_t)0)<br class=""> > -#define SIZE_T_ONE          ((size_t)1)<br class=""> > -#define SIZE_T_TWO          ((size_t)2)<br class=""> > -#define TWO_SIZE_T_SIZES    (SIZE_T_SIZE<<1)<br class=""> > -#define FOUR_SIZE_T_SIZES   (SIZE_T_SIZE<<2)<br class=""> > -#define SIX_SIZE_T_SIZES    (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)<br class=""> > -#define HALF_MAX_SIZE_T     (MAX_SIZE_T / 2U)<br class=""> > -<br class=""> > -/* The bit mask value corresponding to MALLOC_ALIGNMENT */<br class=""> > -#define CHUNK_ALIGN_MASK    (MALLOC_ALIGNMENT - SIZE_T_ONE)<br class=""> > -<br class=""> > -/* True if address a has acceptable alignment */<br class=""> > -#define is_aligned(A)       (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)<br class=""> > -<br class=""> > -/* the number of bytes to offset an address to align it */<br class=""> > -#define align_offset(A)\<br class=""> > - ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\<br class=""> > -  ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) &<br class=""> > CHUNK_ALIGN_MASK))<br class=""> > -<br class=""> > -/* --------------------------- Lock preliminaries ------------------------<br class=""> > */<br class=""> > -<br class=""> > -#if USE_LOCKS<br class=""> > -<br class=""> > -/*<br class=""> > -  When locks are defined, there are up to two global locks:<br class=""> > -<br class=""> > -  * If HAVE_MORECORE, morecore_mutex protects sequences of calls to<br class=""> > -    MORECORE.  In many cases sys_alloc requires two calls, that should<br class=""> > -    not be interleaved with calls by other threads.  This does not<br class=""> > -    protect against direct calls to MORECORE by other threads not<br class=""> > -    using this lock, so there is still code to cope the best we can on<br class=""> > -    interference.<br class=""> > -<br class=""> > -  * magic_init_mutex ensures that mparams.magic and other<br class=""> > -    unique mparams values are initialized only once.<br class=""> > -*/<br class=""> > -<br class=""> > -<br class=""> > -#define USE_LOCK_BIT               (2U)<br class=""> > -#else  /* USE_LOCKS */<br class=""> > -#define USE_LOCK_BIT               (0U)<br class=""> > -#define INITIAL_LOCK(l)<br class=""> > -#endif /* USE_LOCKS */<br class=""> > -<br class=""> > -#if USE_LOCKS<br class=""> > -#define ACQUIRE_MAGIC_INIT_LOCK()  ACQUIRE_LOCK(&magic_init_mutex);<br class=""> > -#define RELEASE_MAGIC_INIT_LOCK()  RELEASE_LOCK(&magic_init_mutex);<br class=""> > -#else  /* USE_LOCKS */<br class=""> > -#define ACQUIRE_MAGIC_INIT_LOCK()<br class=""> > -#define RELEASE_MAGIC_INIT_LOCK()<br class=""> > -#endif /* USE_LOCKS */<br class=""> > -<br class=""> > -<br class=""> > -<br class=""> > -/* -----------------------  Chunk representations ------------------------<br class=""> > */<br class=""> > -<br class=""> > -/*<br class=""> > -  (The following includes lightly edited explanations by Colin Plumb.)<br class=""> > -<br class=""> > -  The malloc_chunk declaration below is misleading (but accurate and<br class=""> > -  necessary).  It declares a "view" into memory allowing access to<br class=""> > -  necessary fields at known offsets from a given base.<br class=""> > -<br class=""> > -  Chunks of memory are maintained using a `boundary tag' method as<br class=""> > -  originally described by Knuth.  (See the paper by Paul Wilson<br class=""> > -  <a href="ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps" rel="noreferrer" target="_blank" data-mce-href="ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps" class="">ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps</a> for a survey of such<br class=""> > -  techniques.)  Sizes of free chunks are stored both in the front of<br class=""> > -  each chunk and at the end.  This makes consolidating fragmented<br class=""> > -  chunks into bigger chunks fast.  The head fields also hold bits<br class=""> > -  representing whether chunks are free or in use.<br class=""> > -<br class=""> > -  Here are some pictures to make it clearer.  They are "exploded" to<br class=""> > -  show that the state of a chunk can be thought of as extending from<br class=""> > -  the high 31 bits of the head field of its header through the<br class=""> > -  prev_foot and PINUSE_BIT bit of the following chunk header.<br class=""> > -<br class=""> > -  A chunk that's in use looks like:<br class=""> > -<br class=""> > -   chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -           | Size of previous chunk (if P = 1)                             |<br class=""> > -           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|<br class=""> > -         | Size of this chunk                                         1| +-+<br class=""> > -   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -         |                                                               |<br class=""> > -         +-                                                             -+<br class=""> > -         |                                                               |<br class=""> > -         +-                                                             -+<br class=""> > -         |                                                               :<br class=""> > -         +-      size - sizeof(size_t) available payload bytes          -+<br class=""> > -         :                                                               |<br class=""> > - chunk-> +-                                                             -+<br class=""> > -         |                                                               |<br class=""> > -         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|<br class=""> > -       | Size of next chunk (may or may not be in use)               | +-+<br class=""> > - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -<br class=""> > -    And if it's free, it looks like this:<br class=""> > -<br class=""> > -   chunk-> +-                                                             -+<br class=""> > -           | User payload (must be in use, or we would have merged!)       |<br class=""> > -           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|<br class=""> > -         | Size of this chunk                                         0| +-+<br class=""> > -   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -         | Next pointer                                                  |<br class=""> > -         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -         | Prev pointer                                                  |<br class=""> > -         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -         |                                                               :<br class=""> > -         +-      size - sizeof(struct chunk) unused bytes               -+<br class=""> > -         :                                                               |<br class=""> > - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -         | Size of this chunk                                            |<br class=""> > -         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|<br class=""> > -       | Size of next chunk (must be in use, or we would have merged)| +-+<br class=""> > - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -       |                                                               :<br class=""> > -       +- User payload                                                -+<br class=""> > -       :                                                               |<br class=""> > -       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -                                                                     |0|<br class=""> > -                                                                     +-+<br class=""> > -  Note that since we always merge adjacent free chunks, the chunks<br class=""> > -  adjacent to a free chunk must be in use.<br class=""> > -<br class=""> > -  Given a pointer to a chunk (which can be derived trivially from the<br class=""> > -  payload pointer) we can, in O(1) time, find out whether the adjacent<br class=""> > -  chunks are free, and if so, unlink them from the lists that they<br class=""> > -  are on and merge them with the current chunk.<br class=""> > -<br class=""> > -  Chunks always begin on even word boundaries, so the mem portion<br class=""> > -  (which is returned to the user) is also on an even word boundary, and<br class=""> > -  thus at least double-word aligned.<br class=""> > -<br class=""> > -  The P (PINUSE_BIT) bit, stored in the unused low-order bit of the<br class=""> > -  chunk size (which is always a multiple of two words), is an in-use<br class=""> > -  bit for the *previous* chunk.  If that bit is *clear*, then the<br class=""> > -  word before the current chunk size contains the previous chunk<br class=""> > -  size, and can be used to find the front of the previous chunk.<br class=""> > -  The very first chunk allocated always has this bit set, preventing<br class=""> > -  access to non-existent (or non-owned) memory. If pinuse is set for<br class=""> > -  any given chunk, then you CANNOT determine the size of the<br class=""> > -  previous chunk, and might even get a memory addressing fault when<br class=""> > -  trying to do so.<br class=""> > -<br class=""> > -  The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of<br class=""> > -  the chunk size redundantly records whether the current chunk is<br class=""> > -  inuse. This redundancy enables usage checks within free and realloc,<br class=""> > -  and reduces indirection when freeing and consolidating chunks.<br class=""> > -<br class=""> > -  Each freshly allocated chunk must have both cinuse and pinuse set.<br class=""> > -  That is, each allocated chunk borders either a previously allocated<br class=""> > -  and still in-use chunk, or the base of its memory arena. This is<br class=""> > -  ensured by making all allocations from the the `lowest' part of any<br class=""> > -  found chunk.  Further, no free chunk physically borders another one,<br class=""> > -  so each free chunk is known to be preceded and followed by either<br class=""> > -  inuse chunks or the ends of memory.<br class=""> > -<br class=""> > -  Note that the `foot' of the current chunk is actually represented<br class=""> > -  as the prev_foot of the NEXT chunk. This makes it easier to<br class=""> > -  deal with alignments etc but can be very confusing when trying<br class=""> > -  to extend or adapt this code.<br class=""> > -<br class=""> > -  The exceptions to all this are<br class=""> > -<br class=""> > -     1. The special chunk `top' is the top-most available chunk (i.e.,<br class=""> > -        the one bordering the end of available memory). It is treated<br class=""> > -        specially.  Top is never included in any bin, is used only if<br class=""> > -        no other chunk is available, and is released back to the<br class=""> > -        system if it is very large (see M_TRIM_THRESHOLD).  In effect,<br class=""> > -        the top chunk is treated as larger (and thus less well<br class=""> > -        fitting) than any other available chunk.  The top chunk<br class=""> > -        doesn't update its trailing size field since there is no next<br class=""> > -        contiguous chunk that would have to index off it. However,<br class=""> > -        space is still allocated for it (TOP_FOOT_SIZE) to enable<br class=""> > -        separation or merging when space is extended.<br class=""> > -<br class=""> > -     3. Chunks allocated via mmap, which have the lowest-order bit<br class=""> > -        (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set<br class=""> > -        PINUSE_BIT in their head fields.  Because they are allocated<br class=""> > -        one-by-one, each must carry its own prev_foot field, which is<br class=""> > -        also used to hold the offset this chunk has within its mmapped<br class=""> > -        region, which is needed to preserve alignment. Each mmapped<br class=""> > -        chunk is trailed by the first two fields of a fake next-chunk<br class=""> > -        for sake of usage checks.<br class=""> > -<br class=""> > -*/<br class=""> > -<br class=""> > -struct malloc_chunk {<br class=""> > -  size_t               prev_foot;  /* Size of previous chunk (if free).  */<br class=""> > -  size_t               head;       /* Size and inuse bits. */<br class=""> > -  struct malloc_chunk* fd;         /* double links -- used only if free. */<br class=""> > -  struct malloc_chunk* bk;<br class=""> > -};<br class=""> > -<br class=""> > -typedef struct malloc_chunk  mchunk;<br class=""> > -typedef struct malloc_chunk* mchunkptr;<br class=""> > -typedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */<br class=""> > -typedef unsigned int bindex_t;         /* Described below */<br class=""> > -typedef unsigned int binmap_t;         /* Described below */<br class=""> > -typedef unsigned int flag_t;           /* The type of various bit flag sets<br class=""> > */<br class=""> > -<br class=""> > -<br class=""> > -/* ------------------- Chunks sizes and alignments -----------------------<br class=""> > */<br class=""> > -<br class=""> > -#define MCHUNK_SIZE         (sizeof(mchunk))<br class=""> > -<br class=""> > -#if FOOTERS<br class=""> > -#define CHUNK_OVERHEAD      (TWO_SIZE_T_SIZES)<br class=""> > -#else /* FOOTERS */<br class=""> > -#define CHUNK_OVERHEAD      (SIZE_T_SIZE)<br class=""> > -#endif /* FOOTERS */<br class=""> > -<br class=""> > -/* The smallest size we can malloc is an aligned minimal chunk */<br class=""> > -#define MIN_CHUNK_SIZE\<br class=""> > -  ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)<br class=""> > -<br class=""> > -/* conversion from malloc headers to user pointers, and back */<br class=""> > -#define chunk2mem(p)        ((void*)((char*)(p)       + TWO_SIZE_T_SIZES))<br class=""> > -#define mem2chunk(mem)      ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))<br class=""> > -/* chunk associated with aligned address A */<br class=""> > -#define align_as_chunk(A)   (mchunkptr)((A) + align_offset(chunk2mem(A)))<br class=""> > -<br class=""> > -/* Bounds on request (not chunk) sizes. */<br class=""> > -#define MAX_REQUEST         ((-MIN_CHUNK_SIZE) << 2)<br class=""> > -#define MIN_REQUEST         (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)<br class=""> > -<br class=""> > -/* pad request bytes into a usable size */<br class=""> > -#define pad_request(req) \<br class=""> > -   (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)<br class=""> > -<br class=""> > -/* pad request, checking for minimum (but not maximum) */<br class=""> > -#define request2size(req) \<br class=""> > -  (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))<br class=""> > -<br class=""> > -/* ------------------ Operations on head and foot fields -----------------<br class=""> > */<br class=""> > -<br class=""> > -/*<br class=""> > -  The head field of a chunk is or'ed with PINUSE_BIT when previous<br class=""> > -  adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in<br class=""> > -  use. If the chunk was obtained with mmap, the prev_foot field has<br class=""> > -  IS_MMAPPED_BIT set, otherwise holding the offset of the base of the<br class=""> > -  mmapped region to the base of the chunk.<br class=""> > -*/<br class=""> > -<br class=""> > -#define PINUSE_BIT          (SIZE_T_ONE)<br class=""> > -#define CINUSE_BIT          (SIZE_T_TWO)<br class=""> > -#define INUSE_BITS          (PINUSE_BIT|CINUSE_BIT)<br class=""> > -<br class=""> > -/* Head value for fenceposts */<br class=""> > -#define FENCEPOST_HEAD      (INUSE_BITS|SIZE_T_SIZE)<br class=""> > -<br class=""> > -/* extraction of fields from head words */<br class=""> > -#define cinuse(p)           ((p)->head & CINUSE_BIT)<br class=""> > -#define pinuse(p)           ((p)->head & PINUSE_BIT)<br class=""> > -#define chunksize(p)        ((p)->head & ~(INUSE_BITS))<br class=""> > -<br class=""> > -#define clear_pinuse(p)     ((p)->head &= ~PINUSE_BIT)<br class=""> > -#define clear_cinuse(p)     ((p)->head &= ~CINUSE_BIT)<br class=""> > -<br class=""> > -/* Treat space at ptr +/- offset as a chunk */<br class=""> > -#define chunk_plus_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))<br class=""> > -#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))<br class=""> > -<br class=""> > -/* Ptr to next or previous physical malloc_chunk. */<br class=""> > -#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head &<br class=""> > ~INUSE_BITS)))<br class=""> > -#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))<br class=""> > -<br class=""> > -/* extract next chunk's pinuse bit */<br class=""> > -#define next_pinuse(p)  ((next_chunk(p)->head) & PINUSE_BIT)<br class=""> > -<br class=""> > -/* Get/set size at footer */<br class=""> > -#define get_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot)<br class=""> > -#define set_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))<br class=""> > -<br class=""> > -/* Set size, pinuse bit, and foot */<br class=""> > -#define set_size_and_pinuse_of_free_chunk(p, s)\<br class=""> > -  ((p)->head = (s|PINUSE_BIT), set_foot(p, s))<br class=""> > -<br class=""> > -/* Set size, pinuse bit, foot, and clear next pinuse */<br class=""> > -#define set_free_with_pinuse(p, s, n)\<br class=""> > -  (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))<br class=""> > -<br class=""> > -/* Get the internal overhead associated with chunk p */<br class=""> > -#define overhead_for(p) CHUNK_OVERHEAD<br class=""> > -<br class=""> > -/* Return true if malloced space is not necessarily cleared */<br class=""> > -#define calloc_must_clear(p) (1)<br class=""> > -<br class=""> > -<br class=""> > -/* ---------------------- Overlaid data structures -----------------------<br class=""> > */<br class=""> > -<br class=""> > -/*<br class=""> > -  When chunks are not in use, they are treated as nodes of either<br class=""> > -  lists or trees.<br class=""> > -<br class=""> > -  "Small"  chunks are stored in circular doubly-linked lists, and look<br class=""> > -  like this:<br class=""> > -<br class=""> > -    chunk-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             Size of previous chunk<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -    `head:' |             Size of chunk, in bytes<br class=""> > |P|<br class=""> > -      mem-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             Forward pointer to next chunk in list<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             Back pointer to previous chunk in list<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             Unused space (may be 0 bytes long)<br class=""> > .<br class=""> > -            .<br class=""> > .<br class=""> > -            .<br class=""> > |<br class=""> > -nextchunk-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -    `foot:' |             Size of chunk, in bytes<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -<br class=""> > -  Larger chunks are kept in a form of bitwise digital trees (aka<br class=""> > -  tries) keyed on chunksizes.  Because malloc_tree_chunks are only for<br class=""> > -  free chunks greater than 256 bytes, their size doesn't impose any<br class=""> > -  constraints on user chunk sizes.  Each node looks like:<br class=""> > -<br class=""> > -    chunk-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             Size of previous chunk<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -    `head:' |             Size of chunk, in bytes<br class=""> > |P|<br class=""> > -      mem-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             Forward pointer to next chunk of same size<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             Back pointer to previous chunk of same size<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             Pointer to left child (child[0])<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             Pointer to right child (child[1])<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             Pointer to parent<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             bin index of this chunk<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -            |             Unused space<br class=""> > .<br class=""> > -            .<br class=""> > |<br class=""> > -nextchunk-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -    `foot:' |             Size of chunk, in bytes<br class=""> > |<br class=""> > -<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > -<br class=""> > -  Each tree holding treenodes is a tree of unique chunk sizes.  Chunks<br class=""> > -  of the same size are arranged in a circularly-linked list, with only<br class=""> > -  the oldest chunk (the next to be used, in our FIFO ordering)<br class=""> > -  actually in the tree.  (Tree members are distinguished by a non-null<br class=""> > -  parent pointer.)  If a chunk with the same size an an existing node<br class=""> > -  is inserted, it is linked off the existing node using pointers that<br class=""> > -  work in the same way as fd/bk pointers of small chunks.<br class=""> > -<br class=""> > -  Each tree contains a power of 2 sized range of chunk sizes (the<br class=""> > -  smallest is 0x100 <= x < 0x180), which is is divided in half at each<br class=""> > -  tree level, with the chunks in the smaller half of the range (0x100<br class=""> > -  <= x < 0x140 for the top nose) in the left subtree and the larger<br class=""> > -  half (0x140 <= x < 0x180) in the right subtree.  This is, of course,<br class=""> > -  done by inspecting individual bits.<br class=""> > -<br class=""> > -  Using these rules, each node's left subtree contains all smaller<br class=""> > -  sizes than its right subtree.  However, the node at the root of each<br class=""> > -  subtree has no particular ordering relationship to either.  (The<br class=""> > -  dividing line between the subtree sizes is based on trie relation.)<br class=""> > -  If we remove the last chunk of a given size from the interior of the<br class=""> > -  tree, we need to replace it with a leaf node.  The tree ordering<br class=""> > -  rules permit a node to be replaced by any leaf below it.<br class=""> > -<br class=""> > -  The smallest chunk in a tree (a common operation in a best-fit<br class=""> > -  allocator) can be found by walking a path to the leftmost leaf in<br class=""> > -  the tree.  Unlike a usual binary tree, where we follow left child<br class=""> > -  pointers until we reach a null, here we follow the right child<br class=""> > -  pointer any time the left one is null, until we reach a leaf with<br class=""> > -  both child pointers null. The smallest chunk in the tree will be<br class=""> > -  somewhere along that path.<br class=""> > -<br class=""> > -  The worst case number of steps to add, find, or remove a node is<br class=""> > -  bounded by the number of bits differentiating chunks within<br class=""> > -  bins. Under current bin calculations, this ranges from 6 up to 21<br class=""> > -  (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case<br class=""> > -  is of course much better.<br class=""> > -*/<br class=""> > -<br class=""> > -struct malloc_tree_chunk {<br class=""> > -  /* The first four fields must be compatible with malloc_chunk */<br class=""> > -  size_t                    prev_foot;<br class=""> > -  size_t                    head;<br class=""> > -  struct malloc_tree_chunk* fd;<br class=""> > -  struct malloc_tree_chunk* bk;<br class=""> > -<br class=""> > -  struct malloc_tree_chunk* child[2];<br class=""> > -  struct malloc_tree_chunk* parent;<br class=""> > -  bindex_t                  index;<br class=""> > -};<br class=""> > -<br class=""> > -typedef struct malloc_tree_chunk  tchunk;<br class=""> > -typedef struct malloc_tree_chunk* tchunkptr;<br class=""> > -typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */<br class=""> > -<br class=""> > -/* A little helper macro for trees */<br class=""> > -#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] :<br class=""> > (t)->child[1])<br class=""> > -<br class=""> > -/* ----------------------------- Segments --------------------------------<br class=""> > */<br class=""> > -<br class=""> > -/*<br class=""> > -  Each malloc space may include non-contiguous segments, held in a<br class=""> > -  list headed by an embedded malloc_segment record representing the<br class=""> > -  top-most space. Segments also include flags holding properties of<br class=""> > -  the space. Large chunks that are directly allocated by mmap are not<br class=""> > -  included in this list. They are instead independently created and<br class=""> > -  destroyed without otherwise keeping track of them.<br class=""> > -<br class=""> > -  Segment management mainly comes into play for spaces allocated by<br class=""> > -  MMAP.  Any call to MMAP might or might not return memory that is<br class=""> > -  adjacent to an existing segment.  MORECORE normally contiguously<br class=""> > -  extends the current space, so this space is almost always adjacent,<br class=""> > -  which is simpler and faster to deal with. (This is why MORECORE is<br class=""> > -  used preferentially to MMAP when both are available -- see<br class=""> > -  sys_alloc.)  When allocating using MMAP, we don't use any of the<br class=""> > -  hinting mechanisms (inconsistently) supported in various<br class=""> > -  implementations of unix mmap, or distinguish reserving from<br class=""> > -  committing memory. Instead, we just ask for space, and exploit<br class=""> > -  contiguity when we get it.  It is probably possible to do<br class=""> > -  better than this on some systems, but no general scheme seems<br class=""> > -  to be significantly better.<br class=""> > -<br class=""> > -  Management entails a simpler variant of the consolidation scheme<br class=""> > -  used for chunks to reduce fragmentation -- new adjacent memory is<br class=""> > -  normally prepended or appended to an existing segment. However,<br class=""> > -  there are limitations compared to chunk consolidation that mostly<br class=""> > -  reflect the fact that segment processing is relatively infrequent<br class=""> > -  (occurring only when getting memory from system) and that we<br class=""> > -  don't expect to have huge numbers of segments:<br class=""> > -<br class=""> > -  * Segments are not indexed, so traversal requires linear scans.  (It<br class=""> > -    would be possible to index these, but is not worth the extra<br class=""> > -    overhead and complexity for most programs on most platforms.)<br class=""> > -  * New segments are only appended to old ones when holding top-most<br class=""> > -    memory; if they cannot be prepended to others, they are held in<br class=""> > -    different segments.<br class=""> > -<br class=""> > -  Except for the top-most segment of an mstate, each segment record<br class=""> > -  is kept at the tail of its segment. Segments are added by pushing<br class=""> > -  segment records onto the list headed by &mstate.seg for the<br class=""> > -  containing mstate.<br class=""> > -<br class=""> > -  Segment flags control allocation/merge/deallocation policies:<br class=""> > -  * If EXTERN_BIT set, then we did not allocate this segment,<br class=""> > -    and so should not try to deallocate or merge with others.<br class=""> > -    (This currently holds only for the initial segment passed<br class=""> > -    into create_mspace_with_base.)<br class=""> > -  * If IS_MMAPPED_BIT set, the segment may be merged with<br class=""> > -    other surrounding mmapped segments and trimmed/de-allocated<br class=""> > -    using munmap.<br class=""> > -  * If neither bit is set, then the segment was obtained using<br class=""> > -    MORECORE so can be merged with surrounding MORECORE'd segments<br class=""> > -    and deallocated/trimmed using MORECORE with negative arguments.<br class=""> > -*/<br class=""> > -<br class=""> > -struct malloc_segment {<br class=""> > -  char*        base;             /* base address */<br class=""> > -  size_t       size;             /* allocated size */<br class=""> > -  struct malloc_segment* next;   /* ptr to next segment */<br class=""> > -};<br class=""> > -<br class=""> > -typedef struct malloc_segment  msegment;<br class=""> > -typedef struct malloc_segment* msegmentptr;<br class=""> > -<br class=""> > -/* ---------------------------- malloc_state -----------------------------<br class=""> > */<br class=""> > -<br class=""> > -/*<br class=""> > -   A malloc_state holds all of the bookkeeping for a space.<br class=""> > -   The main fields are:<br class=""> > -<br class=""> > -  Top<br class=""> > -    The topmost chunk of the currently active segment. Its size is<br class=""> > -    cached in topsize.  The actual size of topmost space is<br class=""> > -    topsize+TOP_FOOT_SIZE, which includes space reserved for adding<br class=""> > -    fenceposts and segment records if necessary when getting more<br class=""> > -    space from the system.  The size at which to autotrim top is<br class=""> > -    cached from mparams in trim_check, except that it is disabled if<br class=""> > -    an autotrim fails.<br class=""> > -<br class=""> > -  Designated victim (dv)<br class=""> > -    This is the preferred chunk for servicing small requests that<br class=""> > -    don't have exact fits.  It is normally the chunk split off most<br class=""> > -    recently to service another small request.  Its size is cached in<br class=""> > -    dvsize. The link fields of this chunk are not maintained since it<br class=""> > -    is not kept in a bin.<br class=""> > -<br class=""> > -  SmallBins<br class=""> > -    An array of bin headers for free chunks.  These bins hold chunks<br class=""> > -    with sizes less than MIN_LARGE_SIZE bytes. Each bin contains<br class=""> > -    chunks of all the same size, spaced 8 bytes apart.  To simplify<br class=""> > -    use in double-linked lists, each bin header acts as a malloc_chunk<br class=""> > -    pointing to the real first node, if it exists (else pointing to<br class=""> > -    itself).  This avoids special-casing for headers.  But to avoid<br class=""> > -    waste, we allocate only the fd/bk pointers of bins, and then use<br class=""> > -    repositioning tricks to treat these as the fields of a chunk.<br class=""> > -<br class=""> > -  TreeBins<br class=""> > -    Treebins are pointers to the roots of trees holding a range of<br class=""> > -    sizes. There are 2 equally spaced treebins for each power of two<br class=""> > -    from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything<br class=""> > -    larger.<br class=""> > -<br class=""> > -  Bin maps<br class=""> > -    There is one bit map for small bins ("smallmap") and one for<br class=""> > -    treebins ("treemap).  Each bin sets its bit when non-empty, and<br class=""> > -    clears the bit when empty.  Bit operations are then used to avoid<br class=""> > -    bin-by-bin searching -- nearly all "search" is done without ever<br class=""> > -    looking at bins that won't be selected.  The bit maps<br class=""> > -    conservatively use 32 bits per map word, even if on 64bit system.<br class=""> > -    For a good description of some of the bit-based techniques used<br class=""> > -    here, see Henry S. Warren Jr's book "Hacker's Delight" (and<br class=""> > -    supplement at <a href="http://hackersdelight.org/" rel="noreferrer" target="_blank" data-mce-href="http://hackersdelight.org/" class="">http://hackersdelight.org/</a>). Many of these are<br class=""> > -    intended to reduce the branchiness of paths through malloc etc, as<br class=""> > -    well as to reduce the number of memory locations read or written.<br class=""> > -<br class=""> > -  Segments<br class=""> > -    A list of segments headed by an embedded malloc_segment record<br class=""> > -    representing the initial space.<br class=""> > -<br class=""> > -  Address check support<br class=""> > -    The least_addr field is the least address ever obtained from<br class=""> > -    MORECORE or MMAP. Attempted frees and reallocs of any address less<br class=""> > -    than this are trapped (unless INSECURE is defined).<br class=""> > -<br class=""> > -  Magic tag<br class=""> > -    A cross-check field that should always hold same value as mparams.magic.<br class=""> > -<br class=""> > -  Flags<br class=""> > -    Bits recording whether to use MMAP, locks, or contiguous MORECORE<br class=""> > -<br class=""> > -  Statistics<br class=""> > -    Each space keeps track of current and maximum system memory<br class=""> > -    obtained via MORECORE or MMAP.<br class=""> > -<br class=""> > -  Locking<br class=""> > -    If USE_LOCKS is defined, the "mutex" lock is acquired and released<br class=""> > -    around every public call using this mspace.<br class=""> > -*/<br class=""> > -<br class=""> > -/* Bin types, widths and sizes */<br class=""> > -#define NSMALLBINS        (32U)<br class=""> > -#define NTREEBINS         (32U)<br class=""> > -#define SMALLBIN_SHIFT    (3U)<br class=""> > -#define SMALLBIN_WIDTH    (SIZE_T_ONE << SMALLBIN_SHIFT)<br class=""> > -#define TREEBIN_SHIFT     (8U)<br class=""> > -#define MIN_LARGE_SIZE    (SIZE_T_ONE << TREEBIN_SHIFT)<br class=""> > -#define MAX_SMALL_SIZE    (MIN_LARGE_SIZE - SIZE_T_ONE)<br class=""> > -#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK -<br class=""> > CHUNK_OVERHEAD)<br class=""> > -<br class=""> > -struct malloc_state {<br class=""> > -  binmap_t   smallmap;<br class=""> > -  binmap_t   treemap;<br class=""> > -  size_t     dvsize;<br class=""> > -  size_t     topsize;<br class=""> > -  char*      least_addr;<br class=""> > -  mchunkptr  dv;<br class=""> > -  mchunkptr  top;<br class=""> > -  size_t     magic;<br class=""> > -  mchunkptr  smallbins[(NSMALLBINS+1)*2];<br class=""> > -  tbinptr    treebins[NTREEBINS];<br class=""> > -  size_t     footprint;<br class=""> > -  size_t     max_footprint;<br class=""> > -  flag_t     mflags;<br class=""> > -  void      *user_data;<br class=""> > -#if USE_LOCKS<br class=""> > -  MLOCK_T    mutex;     /* locate lock among fields that rarely change */<br class=""> > -#endif /* USE_LOCKS */<br class=""> > -  msegment   seg;<br class=""> > -};<br class=""> > -<br class=""> > -typedef struct malloc_state*    mstate;<br class=""> > -<br class=""> > -/* ------------- Global malloc_state and malloc_params -------------------<br class=""> > */<br class=""> > -<br class=""> > -/*<br class=""> > -  malloc_params holds global properties, including those that can be<br class=""> > -  dynamically set using mallopt. There is a single instance, mparams,<br class=""> > -  initialized in init_mparams.<br class=""> > -*/<br class=""> > -<br class=""> > -struct malloc_params {<br class=""> > -  size_t magic;<br class=""> > -  size_t page_size;<br class=""> > -  size_t granularity;<br class=""> > -  flag_t default_mflags;<br class=""> > -};<br class=""> > -<br class=""> > -static struct malloc_params mparams;<br class=""> > -<br class=""> > -/* The global malloc_state used for all non-"mspace" calls */<br class=""> > -//static struct malloc_state _gm_;<br class=""> > -//#define gm                 (&_gm_)<br class=""> > -//#define is_global(M)       ((M) == &_gm_)<br class=""> > -#define is_initialized(M)  ((M)->top != 0)<br class=""> > -<br class=""> > -/* -------------------------- system alloc setup -------------------------<br class=""> > */<br class=""> > -<br class=""> > -/* Operations on mflags */<br class=""> > -<br class=""> > -#define use_lock(M)           ((M)->mflags &   USE_LOCK_BIT)<br class=""> > -#define enable_lock(M)        ((M)->mflags |=  USE_LOCK_BIT)<br class=""> > -#define disable_lock(M)       ((M)->mflags &= ~USE_LOCK_BIT)<br class=""> > -<br class=""> > -#define set_lock(M,L)\<br class=""> > - ((M)->mflags = (L)?\<br class=""> > -  ((M)->mflags | USE_LOCK_BIT) :\<br class=""> > -  ((M)->mflags & ~USE_LOCK_BIT))<br class=""> > -<br class=""> > -/* page-align a size */<br class=""> > -#define page_align(S)\<br class=""> > - (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))<br class=""> > -<br class=""> > -/* granularity-align a size */<br class=""> > -#define granularity_align(S)\<br class=""> > -  (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))<br class=""> > -<br class=""> > -#define is_page_aligned(S)\<br class=""> > -   (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)<br class=""> > -#define is_granularity_aligned(S)\<br class=""> > -   (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)<br class=""> > -<br class=""> > -/*  True if segment S holds address A */<br class=""> > -#define segment_holds(S, A)\<br class=""> > -  ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)<br class=""> > -<br class=""> > -/* Return segment holding given address */<br class=""> > -static msegmentptr segment_holding(mstate m, char* addr) {<br class=""> > -  msegmentptr sp = &m->seg;<br class=""> > -  for (;;) {<br class=""> > -    if (addr >= sp->base && addr < sp->base + sp->size)<br class=""> > -      return sp;<br class=""> > -    if ((sp = sp->next) == 0)<br class=""> > -      return 0;<br class=""> > -  }<br class=""> > -}<br class=""> > -<br class=""> > -/* Return true if segment contains a segment link */<br class=""> > -static int has_segment_link(mstate m, msegmentptr ss) {<br class=""> > -  msegmentptr sp = &m->seg;<br class=""> > -  for (;;) {<br class=""> > -    if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)<br class=""> > -      return 1;<br class=""> > -    if ((sp = sp->next) == 0)<br class=""> > -      return 0;<br class=""> > -  }<br class=""> > -}<br class=""> > -<br class=""> > -<br class=""> > -<br class=""> > -/*<br class=""> > -  TOP_FOOT_SIZE is padding at the end of a segment, including space<br class=""> > -  that may be needed to place segment records and fenceposts when new<br class=""> > -  noncontiguous segments are added.<br class=""> > -*/<br class=""> > -#define TOP_FOOT_SIZE\<br class=""> > -  (align_offset(chunk2mem(0))+pad_request(sizeof(struct<br class=""> > malloc_segment))+MIN_CHUNK_SIZE)<br class=""> > -<br class=""> > -<br class=""> > -/* -------------------------------  Hooks --------------------------------<br class=""> > */<br class=""> > -<br class=""> > -/*<br class=""> > -  PREACTION should be defined to return 0 on success, and nonzero on<br class=""> > -  failure. If you are not using locking, you can redefine these to do<br class=""> > -  anything you like.<br class=""> > -*/<br class=""> > -<br class=""> > -#if USE_LOCKS<br class=""> > -<br class=""> > -/* Ensure locks are initialized */<br class=""> > -#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())<br class=""> > -<br class=""> > -#define PREACTION(M)  ((GLOBALLY_INITIALIZE() || use_lock(M))?<br class=""> > ACQUIRE_LOCK(&(M)->mutex) : 0)<br class=""> > -#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }<br class=""> > -#else /* USE_LOCKS */<br class=""> > -<br class=""> > -#ifndef PREACTION<br class=""> > -#define PREACTION(M) (0)<br class=""> > -#endif  /* PREACTION */<br class=""> > -<br class=""> > -#ifndef POSTACTION<br class=""> > -#define POSTACTION(M)<br class=""> > -#endif  /* POSTACTION */<br class=""> > -<br class=""> > -#endif /* USE_LOCKS */<br class=""> > -<br class=""> > -/*<br class=""> > -  CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.<br class=""> > -  USAGE_ERROR_ACTION is triggered on detected bad frees and<br class=""> > -  reallocs. The argument p is an address that might have triggered the<br class=""> > -  fault. It is ignored by the two predefined actions, but might be<br class=""> > -  useful in custom actions that try to help diagnose errors.<br class=""> > -*/<br class=""> > -<br class=""> > -#if PROCEED_ON_ERROR<br class=""> > -<br class=""> > -/* A count of the number of corruption errors causing resets */<br class=""> > -int malloc_corruption_error_count;<br class=""> > -<br class=""> > -/* default corruption action */<br class=""> > -static void reset_on_error(mstate m);<br class=""> > -<br class=""> > -#define CORRUPTION_ERROR_ACTION(m)  reset_on_error(m)<br class=""> > -#define USAGE_ERROR_ACTION(m, p)<br class=""> > -<br class=""> > -#else /* PROCEED_ON_ERROR */<br class=""> > -<br class=""> > -#ifndef CORRUPTION_ERROR_ACTION<br class=""> > -#define CORRUPTION_ERROR_ACTION(m) ABORT(m->user_data)<br class=""> > -#endif /* CORRUPTION_ERROR_ACTION */<br class=""> > -<br class=""> > -#ifndef USAGE_ERROR_ACTION<br class=""> > -#define USAGE_ERROR_ACTION(m,p) ABORT(m->user_data)<br class=""> > -#endif /* USAGE_ERROR_ACTION */<br class=""> > -<br class=""> > -#endif /* PROCEED_ON_ERROR */<br class=""> > -<br class=""> > -/* -------------------------- Debugging setup ----------------------------<br class=""> > */<br class=""> > -<br class=""> > -#if ! DEBUG<br class=""> > -<br class=""> > -#define check_free_chunk(M,P)<br class=""> > -#define check_inuse_chunk(M,P)<br class=""> > -#define check_malloced_chunk(M,P,N)<br class=""> > -#define check_malloc_state(M)<br class=""> > -#define check_top_chunk(M,P)<br class=""> > -<br class=""> > -#else /* DEBUG */<br class=""> > -#define check_free_chunk(M,P)       do_check_free_chunk(M,P)<br class=""> > -#define check_inuse_chunk(M,P)      do_check_inuse_chunk(M,P)<br class=""> > -#define check_top_chunk(M,P)        do_check_top_chunk(M,P)<br class=""> > -#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)<br class=""> > -#define check_malloc_state(M)       do_check_malloc_state(M)<br class=""> > -<br class=""> > -static void   do_check_any_chunk(mstate m, mchunkptr p);<br class=""> > -static void   do_check_top_chunk(mstate m, mchunkptr p);<br class=""> > -static void   do_check_inuse_chunk(mstate m, mchunkptr p);<br class=""> > -static void   do_check_free_chunk(mstate m, mchunkptr p);<br class=""> > -static void   do_check_malloced_chunk(mstate m, void* mem, size_t s);<br class=""> > -static void   do_check_tree(mstate m, tchunkptr t);<br class=""> > -static void   do_check_treebin(mstate m, bindex_t i);<br class=""> > -static void   do_check_smallbin(mstate m, bindex_t i);<br class=""> > -static void   do_check_malloc_state(mstate m);<br class=""> > -static int    bin_find(mstate m, mchunkptr x);<br class=""> > -static size_t traverse_and_check(mstate m);<br class=""> > -#endif /* DEBUG */<br class=""> > -<br class=""> > -/* ---------------------------- Indexing Bins ----------------------------<br class=""> > */<br class=""> > -<br class=""> > -#define is_small(s)         (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)<br class=""> > -#define small_index(s)      ((s)  >> SMALLBIN_SHIFT)<br class=""> > -#define small_index2size(i) ((i)  << SMALLBIN_SHIFT)<br class=""> > -#define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))<br class=""> > -<br class=""> > -/* addressing by index. See above about smallbin repositioning */<br class=""> > -#define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))<br class=""> > -#define treebin_at(M,i)     (&((M)->treebins[i]))<br class=""> > -<br class=""> > -/* assign tree index for size S to variable I */<br class=""> > -#if defined(__GNUC__) && defined(i386)<br class=""> > -#define compute_tree_index(S, I)\<br class=""> > -{\<br class=""> > -  size_t X = S >> TREEBIN_SHIFT;\<br class=""> > -  if (X == 0)\<br class=""> > -    I = 0;\<br class=""> > -  else if (X > 0xFFFF)\<br class=""> > -    I = NTREEBINS-1;\<br class=""> > -  else {\<br class=""> > -    unsigned int K;\<br class=""> > -    __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm"  (X));\<br class=""> > -    I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\<br class=""> > -  }\<br class=""> > -}<br class=""> > -#else /* GNUC */<br class=""> > -#define compute_tree_index(S, I)\<br class=""> > -{\<br class=""> > -  size_t X = S >> TREEBIN_SHIFT;\<br class=""> > -  if (X == 0)\<br class=""> > -    I = 0;\<br class=""> > -  else if (X > 0xFFFF)\<br class=""> > -    I = NTREEBINS-1;\<br class=""> > -  else {\<br class=""> > -    unsigned int Y = (unsigned int)X;\<br class=""> > -    unsigned int N = ((Y - 0x100) >> 16) & 8;\<br class=""> > -    unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\<br class=""> > -    N += K;\<br class=""> > -    N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\<br class=""> > -    K = 14 - N + ((Y <<= K) >> 15);\<br class=""> > -    I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\<br class=""> > -  }\<br class=""> > -}<br class=""> > -#endif /* GNUC */<br class=""> > -<br class=""> > -/* Bit representing maximum resolved size in a treebin at i */<br class=""> > -#define bit_for_tree_index(i) \<br class=""> > -   (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)<br class=""> > -<br class=""> > -/* Shift placing maximum resolved bit in a treebin at i as sign bit */<br class=""> > -#define leftshift_for_tree_index(i) \<br class=""> > -   ((i == NTREEBINS-1)? 0 : \<br class=""> > -    ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))<br class=""> > -<br class=""> > -/* The size of the smallest chunk held in bin with index i */<br class=""> > -#define minsize_for_tree_index(i) \<br class=""> > -   ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) |  \<br class=""> > -   (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))<br class=""> > -<br class=""> > -/* ------------------------ Operations on bin maps -----------------------<br class=""> > */<br class=""> > -<br class=""> > -/* bit corresponding to given index */<br class=""> > -#define idx2bit(i)              ((binmap_t)(1) << (i))<br class=""> > -<br class=""> > -/* Mark/Clear bits with given index */<br class=""> > -#define mark_smallmap(M,i)      ((M)->smallmap |=  idx2bit(i))<br class=""> > -#define clear_smallmap(M,i)     ((M)->smallmap &= ~idx2bit(i))<br class=""> > -#define smallmap_is_marked(M,i) ((M)->smallmap &   idx2bit(i))<br class=""> > -<br class=""> > -#define mark_treemap(M,i)       ((M)->treemap  |=  idx2bit(i))<br class=""> > -#define clear_treemap(M,i)      ((M)->treemap  &= ~idx2bit(i))<br class=""> > -#define treemap_is_marked(M,i)  ((M)->treemap  &   idx2bit(i))<br class=""> > -<br class=""> > -/* index corresponding to given bit */<br class=""> > -<br class=""> > -#if defined(__GNUC__) && defined(i386)<br class=""> > -#define compute_bit2idx(X, I)\<br class=""> > -{\<br class=""> > -  unsigned int J;\<br class=""> > -  __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\<br class=""> > -  I = (bindex_t)J;\<br class=""> > -}<br class=""> > -<br class=""> > -#else /* GNUC */<br class=""> > -#if  USE_BUILTIN_FFS<br class=""> > -#define compute_bit2idx(X, I) I = ffs(X)-1<br class=""> > -<br class=""> > -#else /* USE_BUILTIN_FFS */<br class=""> > -#define compute_bit2idx(X, I)\<br class=""> > -{\<br class=""> > -  unsigned int Y = X - 1;\<br class=""> > -  unsigned int K = Y >> (16-4) & 16;\<br class=""> > -  unsigned int N = K;        Y >>= K;\<br class=""> > -  N += K = Y >> (8-3) &  8;  Y >>= K;\<br class=""> > -  N += K = Y >> (4-2) &  4;  Y >>= K;\<br class=""> > -  N += K = Y >> (2-1) &  2;  Y >>= K;\<br class=""> > -  N += K = Y >> (1-0) &  1;  Y >>= K;\<br class=""> > -  I = (bindex_t)(N + Y);\<br class=""> > -}<br class=""> > -#endif /* USE_BUILTIN_FFS */<br class=""> > -#endif /* GNUC */<br class=""> > -<br class=""> > -/* isolate the least set bit of a bitmap */<br class=""> > -#define least_bit(x)         ((x) & -(x))<br class=""> > -<br class=""> > -/* mask with all bits to left of least bit of x on */<br class=""> > -#define left_bits(x)         ((x<<1) | -(x<<1))<br class=""> > -<br class=""> > -/* mask with all bits to left of or equal to least bit of x on */<br class=""> > -#define same_or_left_bits(x) ((x) | -(x))<br class=""> > -<br class=""> > -<br class=""> > -/* ----------------------- Runtime Check Support -------------------------<br class=""> > */<br class=""> > -<br class=""> > -/*<br class=""> > -  For security, the main invariant is that malloc/free/etc never<br class=""> > -  writes to a static address other than malloc_state, unless static<br class=""> > -  malloc_state itself has been corrupted, which cannot occur via<br class=""> > -  malloc (because of these checks). In essence this means that we<br class=""> > -  believe all pointers, sizes, maps etc held in malloc_state, but<br class=""> > -  check all of those linked or offsetted from other embedded data<br class=""> > -  structures.  These checks are interspersed with main code in a way<br class=""> > -  that tends to minimize their run-time cost.<br class=""> > -<br class=""> > -  When FOOTERS is defined, in addition to range checking, we also<br class=""> > -  verify footer fields of inuse chunks, which can be used guarantee<br class=""> > -  that the mstate controlling malloc/free is intact.  This is a<br class=""> > -  streamlined version of the approach described by William Robertson<br class=""> > -  et al in "Run-time Detection of Heap-based Overflows" LISA'03<br class=""> > -  <a href="http://www.usenix.org/events/lisa03/tech/robertson.html" rel="noreferrer" target="_blank" data-mce-href="http://www.usenix.org/events/lisa03/tech/robertson.html" class="">http://www.usenix.org/events/lisa03/tech/robertson.html</a> The footer<br class=""> > -  of an inuse chunk holds the xor of its mstate and a random seed,<br class=""> > -  that is checked upon calls to free() and realloc().  This is<br class=""> > -  (probablistically) unguessable from outside the program, but can be<br class=""> > -  computed by any code successfully malloc'ing any chunk, so does not<br class=""> > -  itself provide protection against code that has already broken<br class=""> > -  security through some other means.  Unlike Robertson et al, we<br class=""> > -  always dynamically check addresses of all offset chunks (previous,<br class=""> > -  next, etc). This turns out to be cheaper than relying on hashes.<br class=""> > -*/<br class=""> > -<br class=""> > -#if !INSECURE<br class=""> > -/* Check if address a is at least as high as any from MORECORE or MMAP */<br class=""> > -#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)<br class=""> > -/* Check if address of next chunk n is higher than base chunk p */<br class=""> > -#define ok_next(p, n)    ((char*)(p) < (char*)(n))<br class=""> > -/* Check if p has its cinuse bit on */<br class=""> > -#define ok_cinuse(p)     cinuse(p)<br class=""> > -/* Check if p has its pinuse bit on */<br class=""> > -#define ok_pinuse(p)     pinuse(p)<br class=""> > -<br class=""> > -#else /* !INSECURE */<br class=""> > -#define ok_address(M, a) (1)<br class=""> > -#define ok_next(b, n)    (1)<br class=""> > -#define ok_cinuse(p)     (1)<br class=""> > -#define ok_pinuse(p)     (1)<br class=""> > -#endif /* !INSECURE */<br class=""> > -<br class=""> > -#if (FOOTERS && !INSECURE)<br class=""> > -/* Check if (alleged) mstate m has expected magic field */<br class=""> > -#define ok_magic(M)      ((M)->magic == mparams.magic)<br class=""> > -#else  /* (FOOTERS && !INSECURE) */<br class=""> > -#define ok_magic(M)      (1)<br class=""> > -#endif /* (FOOTERS && !INSECURE) */<br class=""> > -<br class=""> > -<br class=""> > -/* In gcc, use __builtin_expect to minimize impact of checks */<br class=""> > -#if !INSECURE<br class=""> > -#if defined(__GNUC__) && __GNUC__ >= 3<br class=""> > -#define RTCHECK(e)  __builtin_expect(e, 1)<br class=""> > -#else /* GNUC */<br class=""> > -#define RTCHECK(e)  (e)<br class=""> > -#endif /* GNUC */<br class=""> > -#else /* !INSECURE */<br class=""> > -#define RTCHECK(e)  (1)<br class=""> > -#endif /* !INSECURE */<br class=""> > -<br class=""> > -/* macros to set up inuse chunks with or without footers */<br class=""> > -<br class=""> > -#if !FOOTERS<br class=""> > -<br class=""> > -#define mark_inuse_foot(M,p,s)<br class=""> > -<br class=""> > -/* Set cinuse bit and pinuse bit of next chunk */<br class=""> > -#define set_inuse(M,p,s)\<br class=""> > -  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\<br class=""> > -  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)<br class=""> > -<br class=""> > -/* Set cinuse and pinuse of this chunk and pinuse of next chunk */<br class=""> > -#define set_inuse_and_pinuse(M,p,s)\<br class=""> > -  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\<br class=""> > -  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)<br class=""> > -<br class=""> > -/* Set size, cinuse and pinuse bit of this chunk */<br class=""> > -#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\<br class=""> > -  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))<br class=""> > -<br class=""> > -#else /* FOOTERS */<br class=""> > -<br class=""> > -/* Set foot of inuse chunk to be xor of mstate and seed */<br class=""> > -#define mark_inuse_foot(M,p,s)\<br class=""> > -  (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^<br class=""> > mparams.magic))<br class=""> > -<br class=""> > -#define get_mstate_for(p)\<br class=""> > -  ((mstate)(((mchunkptr)((char*)(p) +\<br class=""> > -    (chunksize(p))))->prev_foot ^ mparams.magic))<br class=""> > -<br class=""> > -#define set_inuse(M,p,s)\<br class=""> > -  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\<br class=""> > -  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \<br class=""> > -  mark_inuse_foot(M,p,s))<br class=""> > -<br class=""> > -#define set_inuse_and_pinuse(M,p,s)\<br class=""> > -  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\<br class=""> > -  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\<br class=""> > - mark_inuse_foot(M,p,s))<br class=""> > -<br class=""> > -#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\<br class=""> > -  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\<br class=""> > -  mark_inuse_foot(M, p, s))<br class=""> > -<br class=""> > -#endif /* !FOOTERS */<br class=""> > -<br class=""> > -/* ---------------------------- setting mparams --------------------------<br class=""> > */<br class=""> > -<br class=""> > -/* Initialize mparams */<br class=""> > -static int init_mparams(void) {<br class=""> > -  if (mparams.page_size == 0) {<br class=""> > -    size_t s;<br class=""> > -<br class=""> > -    mparams.default_mflags = USE_LOCK_BIT;<br class=""> > -<br class=""> > -#if (FOOTERS && !INSECURE)<br class=""> > -    {<br class=""> > -#if USE_DEV_RANDOM<br class=""> > -      int fd;<br class=""> > -      unsigned char buf[sizeof(size_t)];<br class=""> > -      /* Try to use /dev/urandom, else fall back on using time */<br class=""> > -      if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&<br class=""> > -          read(fd, buf, sizeof(buf)) == sizeof(buf)) {<br class=""> > -        s = *((size_t *) buf);<br class=""> > -        close(fd);<br class=""> > -      }<br class=""> > -      else<br class=""> > -#endif /* USE_DEV_RANDOM */<br class=""> > -        s = (size_t)(time(0) ^ (size_t)0x55555555U);<br class=""> > -<br class=""> > -      s |= (size_t)8U;    /* ensure nonzero */<br class=""> > -      s &= ~(size_t)7U;   /* improve chances of fault for bad values */<br class=""> > -<br class=""> > -    }<br class=""> > -#else /* (FOOTERS && !INSECURE) */<br class=""> > -    s = (size_t)0x58585858U;<br class=""> > -#endif /* (FOOTERS && !INSECURE) */<br class=""> > -    ACQUIRE_MAGIC_INIT_LOCK();<br class=""> > -    if (mparams.magic == 0) {<br class=""> > -      mparams.magic = s;<br class=""> > -      /* Set up lock for main malloc area */<br class=""> > -      //INITIAL_LOCK(&gm->mutex);<br class=""> > -      //gm->mflags = mparams.default_mflags;<br class=""> > -    }<br class=""> > -    RELEASE_MAGIC_INIT_LOCK();<br class=""> > -<br class=""> > -<br class=""> > -    mparams.page_size = malloc_getpagesize;<br class=""> > -    mparams.granularity = ((DEFAULT_GRANULARITY != 0)?<br class=""> > -                           DEFAULT_GRANULARITY : mparams.page_size);<br class=""> > -<br class=""> > -    /* Sanity-check configuration:<br class=""> > -       size_t must be unsigned and as wide as pointer type.<br class=""> > -       ints must be at least 4 bytes.<br class=""> > -       alignment must be at least 8.<br class=""> > -       Alignment, min chunk size, and page size must all be powers of 2.<br class=""> > -    */<br class=""> > -    if ((sizeof(size_t) != sizeof(char*)) ||<br class=""> > -        (MAX_SIZE_T < MIN_CHUNK_SIZE)  ||<br class=""> > -        (sizeof(int) < 4)  ||<br class=""> > -        (MALLOC_ALIGNMENT < (size_t)8U) ||<br class=""> > -        ((MALLOC_ALIGNMENT    & (MALLOC_ALIGNMENT-SIZE_T_ONE))    != 0) ||<br class=""> > -        ((MCHUNK_SIZE         & (MCHUNK_SIZE-SIZE_T_ONE))         != 0) ||<br class=""> > -        ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||<br class=""> > -        ((mparams.page_size   & (mparams.page_size-SIZE_T_ONE))   != 0))<br class=""> > -      ABORT(NULL);<br class=""> > -  }<br class=""> > -  return 0;<br class=""> > -}<br class=""> > -<br class=""> > -/* support for mallopt */<br class=""> > -static int change_mparam(int param_number, int value) {<br class=""> > -  size_t val = (size_t)value;<br class=""> > -  init_mparams();<br class=""> > -  switch(param_number) {<br class=""> > -  case M_GRANULARITY:<br class=""> > -    if (val >= mparams.page_size && ((val & (val-1)) == 0)) {<br class=""> > -      mparams.granularity = val;<br class=""> > -      return 1;<br class=""> > -    }<br class=""> > -    else<br class=""> > -      return 0;<br class=""> > -  default:<br class=""> > -    return 0;<br class=""> > -  }<br class=""> > -}<br class=""> > -<br class=""> > -#if DEBUG<br class=""> > -/* ------------------------- Debugging Support ---------------------------<br class=""> > */<br class=""> > -<br class=""> > -/* Check properties of any chunk, whether free, inuse, mmapped etc  */<br class=""> > -static void do_check_any_chunk(mstate m, mchunkptr p) {<br class=""> > -  assert(m->user_data, (is_aligned(chunk2mem(p))) || (p->head ==<br class=""> > FENCEPOST_HEAD));<br class=""> > -  assert(m->user_data, ok_address(m, p));<br class=""> > -}<br class=""> > -<br class=""> > -/* Check properties of top chunk */<br class=""> > -static void do_check_top_chunk(mstate m, mchunkptr p) {<br class=""> > -  msegmentptr sp = segment_holding(m, (char*)p);<br class=""> > -  size_t  sz = chunksize(p);<br class=""> > -  assert(m->user_data, sp != 0);<br class=""> > -  assert(m->user_data, (is_aligned(chunk2mem(p))) || (p->head ==<br class=""> > FENCEPOST_HEAD));<br class=""> > -  assert(m->user_data, ok_address(m, p));<br class=""> > -  assert(m->user_data, sz == m->topsize);<br class=""> > -  assert(m->user_data, sz > 0);<br class=""> > -  assert(m->user_data, sz == ((sp->base + sp->size) - (char*)p) -<br class=""> > TOP_FOOT_SIZE);<br class=""> > -  assert(m->user_data, pinuse(p));<br class=""> > -  assert(m->user_data, !next_pinuse(p));<br class=""> > -}<br class=""> > -<br class=""> > -/* Check properties of inuse chunks */<br class=""> > -static void do_check_inuse_chunk(mstate m, mchunkptr p) {<br class=""> > -  do_check_any_chunk(m, p);<br class=""> > -  assert(m->user_data, cinuse(p));<br class=""> > -  assert(m->user_data, next_pinuse(p));<br class=""> > -  /* If not pinuse, previous chunk has OK offset */<br class=""> > -  assert(m->user_data, pinuse(p) || next_chunk(prev_chunk(p)) == p);<br class=""> > -}<br class=""> > -<br class=""> > -/* Check properties of free chunks */<br class=""> > -static void do_check_free_chunk(mstate m, mchunkptr p) {<br class=""> > -  size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);<br class=""> > -  mchunkptr next = chunk_plus_offset(p, sz);<br class=""> > -  do_check_any_chunk(m, p);<br class=""> > -  assert(m->user_data, !cinuse(p));<br class=""> > -  assert(m->user_data, !next_pinuse(p));<br class=""> > -  if (p != m->dv && p != m->top) {<br class=""> > -    if (sz >= MIN_CHUNK_SIZE) {<br class=""> > -      assert(m->user_data, (sz & CHUNK_ALIGN_MASK) == 0);<br class=""> > -      assert(m->user_data, is_aligned(chunk2mem(p)));<br class=""> > -      assert(m->user_data, next->prev_foot == sz);<br class=""> > -      assert(m->user_data, pinuse(p));<br class=""> > -      assert(m->user_data, next == m->top || cinuse(next));<br class=""> > -      assert(m->user_data, p->fd->bk == p);<br class=""> > -      assert(m->user_data, p->bk->fd == p);<br class=""> > -    }<br class=""> > -    else  /* markers are always of size SIZE_T_SIZE */<br class=""> > -      assert(m->user_data, sz == SIZE_T_SIZE);<br class=""> > -  }<br class=""> > -}<br class=""> > -<br class=""> > -/* Check properties of malloced chunks at the point they are malloced */<br class=""> > -static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {<br class=""> > -  if (mem != 0) {<br class=""> > -    mchunkptr p = mem2chunk(mem);<br class=""> > -    size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);<br class=""> > -    do_check_inuse_chunk(m, p);<br class=""> > -    assert(m->user_data, (sz & CHUNK_ALIGN_MASK) == 0);<br class=""> > -    assert(m->user_data, sz >= MIN_CHUNK_SIZE);<br class=""> > -    assert(m->user_data, sz >= s);<br class=""> > -    /* size is less than MIN_CHUNK_SIZE more than request */<br class=""> > -    assert(m->user_data, sz < (s + MIN_CHUNK_SIZE));<br class=""> > -  }<br class=""> > -}<br class=""> > -<br class=""> > -/* Check a tree and its subtrees.  */<br class=""> > -static void do_check_tree(mstate m, tchunkptr t) {<br class=""> > -  tchunkptr head = 0;<br class=""> > -  tchunkptr u = t;<br class=""> > -  bindex_t tindex = t->index;<br class=""> > -  size_t tsize = chunksize(t);<br class=""> > -  bindex_t idx;<br class=""> > -  compute_tree_index(tsize, idx);<br class=""> > -  assert(m->user_data, tindex == idx);<br class=""> > -  assert(m->user_data, tsize >= MIN_LARGE_SIZE);<br class=""> > -  assert(m->user_data, tsize >= minsize_for_tree_index(idx));<br class=""> > -  assert(m->user_data, (idx == NTREEBINS-1) || (tsize <<br class=""> > minsize_for_tree_index((idx+1))));<br class=""> > -<br class=""> > -  do { /* traverse through chain of same-sized nodes */<br class=""> > -    do_check_any_chunk(m, ((mchunkptr)u));<br class=""> > -    assert(m->user_data, u->index == tindex);<br class=""> > -    assert(m->user_data, chunksize(u) == tsize);<br class=""> > -    assert(m->user_data, !cinuse(u));<br class=""> > -    assert(m->user_data, !next_pinuse(u));<br class=""> > -    assert(m->user_data, u->fd->bk == u);<br class=""> > -    assert(m->user_data, u->bk->fd == u);<br class=""> > -    if (u->parent == 0) {<br class=""> > -      assert(m->user_data, u->child[0] == 0);<br class=""> > -      assert(m->user_data, u->child[1] == 0);<br class=""> > -    }<br class=""> > -    else {<br class=""> > -      assert(m->user_data, head == 0); /* only one node on chain has parent<br class=""> > */<br class=""> > -      head = u;<br class=""> > -      assert(m->user_data, u->parent != u);<br class=""> > -      assert(m->user_data, u->parent->child[0] == u ||<br class=""> > -             u->parent->child[1] == u ||<br class=""> > -             *((tbinptr*)(u->parent)) == u);<br class=""> > -      if (u->child[0] != 0) {<br class=""> > -        assert(m->user_data, u->child[0]->parent == u);<br class=""> > -        assert(m->user_data, u->child[0] != u);<br class=""> > -        do_check_tree(m, u->child[0]);<br class=""> > -      }<br class=""> > -      if (u->child[1] != 0) {<br class=""> > -        assert(m->user_data, u->child[1]->parent == u);<br class=""> > -        assert(m->user_data, u->child[1] != u);<br class=""> > -        do_check_tree(m, u->child[1]);<br class=""> > -      }<br class=""> > -      if (u->child[0] != 0 && u->child[1] != 0) {<br class=""> > -        assert(m->user_data, chunksize(u->child[0]) <<br class=""> > chunksize(u->child[1]));<br class=""> > -      }<br class=""> > -    }<br class=""> > -    u = u->fd;<br class=""> > -  } while (u != t);<br class=""> > -  assert(m->user_data, head != 0);<br class=""> > -}<br class=""> > -<br class=""> > -/*  Check all the chunks in a treebin.  */<br class=""> > -static void do_check_treebin(mstate m, bindex_t i) {<br class=""> > -  tbinptr* tb = treebin_at(m, i);<br class=""> > -  tchunkptr t = *tb;<br class=""> > -  int empty = (m->treemap & (1U << i)) == 0;<br class=""> > -  if (t == 0)<br class=""> > -    assert(m->user_data, empty);<br class=""> > -  if (!empty)<br class=""> > -    do_check_tree(m, t);<br class=""> > -}<br class=""> > -<br class=""> > -/*  Check all the chunks in a smallbin.  */<br class=""> > -static void do_check_smallbin(mstate m, bindex_t i) {<br class=""> > -  sbinptr b = smallbin_at(m, i);<br class=""> > -  mchunkptr p = b->bk;<br class=""> > -  unsigned int empty = (m->smallmap & (1U << i)) == 0;<br class=""> > -  if (p == b)<br class=""> > -    assert(m->user_data, empty);<br class=""> > -  if (!empty) {<br class=""> > -    for (; p != b; p = p->bk) {<br class=""> > -      size_t size = chunksize(p);<br class=""> > -      mchunkptr q;<br class=""> > -      /* each chunk claims to be free */<br class=""> > -      do_check_free_chunk(m, p);<br class=""> > -      /* chunk belongs in bin */<br class=""> > -      assert(m->user_data, small_index(size) == i);<br class=""> > -      assert(m->user_data, p->bk == b || chunksize(p->bk) == chunksize(p));<br class=""> > -      /* chunk is followed by an inuse chunk */<br class=""> > -      q = next_chunk(p);<br class=""> > -      if (q->head != FENCEPOST_HEAD)<br class=""> > -        do_check_inuse_chunk(m, q);<br class=""> > -    }<br class=""> > -  }<br class=""> > -}<br class=""> > -<br class=""> > -/* Find x in a bin. Used in other check functions. */<br class=""> > -static int bin_find(mstate m, mchunkptr x) {<br class=""> > -  size_t size = chunksize(x);<br class=""> > -  if (is_small(size)) {<br class=""> > -    bindex_t sidx = small_index(size);<br class=""> > -    sbinptr b = smallbin_at(m, sidx);<br class=""> > -    if (smallmap_is_marked(m, sidx)) {<br class=""> > -      mchunkptr p = b;<br class=""> > -      do {<br class=""> > -        if (p == x)<br class=""> > -          return 1;<br class=""> > -      } while ((p = p->fd) != b);<br class=""> > -    }<br class=""> > -  }<br class=""> > -  else {<br class=""> > -    bindex_t tidx;<br class=""> > -    compute_tree_index(size, tidx);<br class=""> > -    if (treemap_is_marked(m, tidx)) {<br class=""> > -      tchunkptr t = *treebin_at(m, tidx);<br class=""> > -      size_t sizebits = size << leftshift_for_tree_index(tidx);<br class=""> > -      while (t != 0 && chunksize(t) != size) {<br class=""> > -        t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];<br class=""> > -        sizebits <<= 1;<br class=""> > -      }<br class=""> > -      if (t != 0) {<br class=""> > -        tchunkptr u = t;<br class=""> > -        do {<br class=""> > -          if (u == (tchunkptr)x)<br class=""> > -            return 1;<br class=""> > -        } while ((u = u->fd) != t);<br class=""> > -      }<br class=""> > -    }<br class=""> > -  }<br class=""> > -  return 0;<br class=""> > -}<br class=""> > -<br class=""> > -/* Traverse each chunk and check it; return total */<br class=""> > -static size_t traverse_and_check(mstate m) {<br class=""> > -  size_t sum = 0;<br class=""> > -  if (is_initialized(m)) {<br class=""> > -    msegmentptr s = &m->seg;<br class=""> > -    sum += m->topsize + TOP_FOOT_SIZE;<br class=""> > -    while (s != 0) {<br class=""> > -      mchunkptr q = align_as_chunk(s->base);<br class=""> > -      mchunkptr lastq = 0;<br class=""> > -      assert(m->user_data, pinuse(q));<br class=""> > -      while (segment_holds(s, q) &&<br class=""> > -             q != m->top && q->head != FENCEPOST_HEAD) {<br class=""> > -        sum += chunksize(q);<br class=""> > -        if (cinuse(q)) {<br class=""> > -          assert(m->user_data, !bin_find(m, q));<br class=""> > -          do_check_inuse_chunk(m, q);<br class=""> > -        }<br class=""> > -        else {<br class=""> > -          assert(m->user_data, q == m->dv || bin_find(m, q));<br class=""> > -          assert(m->user_data, lastq == 0 || cinuse(lastq)); /* Not 2<br class=""> > consecutive free */<br class=""> > -          do_check_free_chunk(m, q);<br class=""> > -        }<br class=""> > -        lastq = q;<br class=""> > -        q = next_chunk(q);<br class=""> > -      }<br class=""> > -      s = s->next;<br class=""> > -    }<br class=""> > -  }<br class=""> > -  return sum;<br class=""> > -}<br class=""> > -<br class=""> > -/* Check all properties of malloc_state. */<br class=""> > -static void do_check_malloc_state(mstate m) {<br class=""> > -  bindex_t i;<br class=""> > -  size_t total;<br class=""> > -  /* check bins */<br class=""> > -  for (i = 0; i < NSMALLBINS; ++i)<br class=""> > -    do_check_smallbin(m, i);<br class=""> > -  for (i = 0; i < NTREEBINS; ++i)<br class=""> > -    do_check_treebin(m, i);<br class=""> > -<br class=""> > -  if (m->dvsize != 0) { /* check dv chunk */<br class=""> > -    do_check_any_chunk(m, m->dv);<br class=""> > -    assert(m->user_data, m->dvsize == chunksize(m->dv));<br class=""> > -    assert(m->user_data, m->dvsize >= MIN_CHUNK_SIZE);<br class=""> > -    assert(m->user_data, bin_find(m, m->dv) == 0);<br class=""> > -  }<br class=""> > -<br class=""> > -  if (m->top != 0) {   /* check top chunk */<br class=""> > -    do_check_top_chunk(m, m->top);<br class=""> > -    assert(m->user_data, m->topsize == chunksize(m->top));<br class=""> > -    assert(m->user_data, m->topsize > 0);<br class=""> > -    assert(m->user_data, bin_find(m, m->top) == 0);<br class=""> > -  }<br class=""> > -<br class=""> > -  total = traverse_and_check(m);<br class=""> > -  assert(m->user_data, total <= m->footprint);<br class=""> > -  assert(m->user_data, m->footprint <= m->max_footprint);<br class=""> > -}<br class=""> > -#endif /* DEBUG */<br class=""> > -<br class=""> > -/* ----------------------------- statistics ------------------------------<br class=""> > */<br class=""> > -<br class=""> > -#if !NO_MALLINFO<br class=""> > -static struct mallinfo internal_mallinfo(mstate m) {<br class=""> > -  struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };<br class=""> > -  if (!PREACTION(m)) {<br class=""> > -    check_malloc_state(m);<br class=""> > -    if (is_initialized(m)) {<br class=""> > -      size_t nfree = SIZE_T_ONE; /* top always free */<br class=""> > -      size_t mfree = m->topsize + TOP_FOOT_SIZE;<br class=""> > -      size_t sum = mfree;<br class=""> > -      msegmentptr s = &m->seg;<br class=""> > -      while (s != 0) {<br class=""> > -        mchunkptr q = align_as_chunk(s->base);<br class=""> > -        while (segment_holds(s, q) &&<br class=""> > -               q != m->top && q->head != FENCEPOST_HEAD) {<br class=""> > -          size_t sz = chunksize(q);<br class=""> > -          sum += sz;<br class=""> > -          if (!cinuse(q)) {<br class=""> > -            mfree += sz;<br class=""> > -            ++nfree;<br class=""> > -          }<br class=""> > -          q = next_chunk(q);<br class=""> > -        }<br class=""> > -        s = s->next;<br class=""> > -      }<br class=""> > -<br class=""> > -      nm.arena    = sum;<br class=""> > -      nm.ordblks  = nfree;<br class=""> > -      nm.hblkhd   = m->footprint - sum;<br class=""> > -      nm.usmblks  = m->max_footprint;<br class=""> > -      nm.uordblks = m->footprint - mfree;<br class=""> > -      nm.fordblks = mfree;<br class=""> > -      nm.keepcost = m->topsize;<br class=""> > -    }<br class=""> > -<br class=""> > -    POSTACTION(m);<br class=""> > -  }<br class=""> > -  return nm;<br class=""> > -}<br class=""> > -#endif /* !NO_MALLINFO */<br class=""> > -<br class=""> > -static void internal_malloc_stats(mstate m) {<br class=""> > -  if (!PREACTION(m)) {<br class=""> > -    size_t maxfp = 0;<br class=""> > -    size_t fp = 0;<br class=""> > -    size_t used = 0;<br class=""> > -    check_malloc_state(m);<br class=""> > -    if (is_initialized(m)) {<br class=""> > -      msegmentptr s = &m->seg;<br class=""> > -      maxfp = m->max_footprint;<br class=""> > -      fp = m->footprint;<br class=""> > -      used = fp - (m->topsize + TOP_FOOT_SIZE);<br class=""> > -<br class=""> > -      while (s != 0) {<br class=""> > -        mchunkptr q = align_as_chunk(s->base);<br class=""> > -        while (segment_holds(s, q) &&<br class=""> > -               q != m->top && q->head != FENCEPOST_HEAD) {<br class=""> > -          if (!cinuse(q))<br class=""> > -            used -= chunksize(q);<br class=""> > -          q = next_chunk(q);<br class=""> > -        }<br class=""> > -        s = s->next;<br class=""> > -      }<br class=""> > -    }<br class=""> > -<br class=""> > -    PRINT((m->user_data, "max system bytes = %10lu\n", (unsigned<br class=""> > long)(maxfp)));<br class=""> > -    PRINT((m->user_data, "system bytes     = %10lu\n", (unsigned<br class=""> > long)(fp)));<br class=""> > -    PRINT((m->user_data, "in use bytes     = %10lu\n", (unsigned<br class=""> > long)(used)));<br class=""> > -<br class=""> > -    POSTACTION(m);<br class=""> > -  }<br class=""> > -}<br class=""> > -<br class=""> > -/* ----------------------- Operations on smallbins -----------------------<br class=""> > */<br class=""> > -<br class=""> > -/*<br class=""> > -  Various forms of linking and unlinking are defined as macros.  Even<br class=""> > -  the ones for trees, which are very long but have very short typical<br class=""> > -  paths.  This is ugly but reduces reliance on inlining support of<br class=""> > -  compilers.<br class=""> > -*/<br class=""> > -<br class=""> > -/* Link a free chunk into a smallbin  */<br class=""> > -#define insert_small_chunk(M, P, S) {\<br class=""> > -  bindex_t I  = small_index(S);\<br class=""> > -  mchunkptr B = smallbin_at(M, I);\<br class=""> > -  mchunkptr F = B;\<br class=""> > -  assert((M)->user_data, S >= MIN_CHUNK_SIZE);\<br class=""> > -  if (!smallmap_is_marked(M, I))\<br class=""> > -    mark_smallmap(M, I);\<br class=""> > -  else if (RTCHECK(ok_address(M, B->fd)))\<br class=""> > -    F = B->fd;\<br class=""> > -  else {\<br class=""> > -    CORRUPTION_ERROR_ACTION(M);\<br class=""> > -  }\<br class=""> > -  B->fd = P;\<br class=""> > -  F->bk = P;\<br class=""> > -  P->fd = F;\<br class=""> > -  P->bk = B;\<br class=""> > -}<br class=""> > -<br class=""> > -/* Unlink a chunk from a smallbin  */<br class=""> > -#define unlink_small_chunk(M, P, S) {\<br class=""> > -  mchunkptr F = P->fd;\<br class=""> > -  mchunkptr B = P->bk;\<br class=""> > -  bindex_t I = small_index(S);\<br class=""> > -  assert((M)->user_data, P != B);\<br class=""> > -  assert((M)->user_data, P != F);\<br class=""> > -  assert((M)->user_data, chunksize(P) == small_index2size(I));\<br class=""> > -  if (F == B)\<br class=""> > -    clear_smallmap(M, I);\<br class=""> > -  else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\<br class=""> > -                   (B == smallbin_at(M,I) || ok_address(M, B)))) {\<br class=""> > -    F->bk = B;\<br class=""> > -    B->fd = F;\<br class=""> > -  }\<br class=""> > -  else {\<br class=""> > -    CORRUPTION_ERROR_ACTION(M);\<br class=""> > -  }\<br class=""> > -}<br class=""> > -<br class=""> > -/* Unlink the first chunk from a smallbin */<br class=""> > -#define unlink_first_small_chunk(M, B, P, I) {\<br class=""> > -  mchunkptr F = P->fd;\<br class=""> > -  assert((M)->user_data, P != B);\<br class=""> > -  assert((M)->user_data, P != F);\<br class=""> > -  assert((M)->user_data, chunksize(P) == small_index2size(I));\<br class=""> > -  if (B == F)\<br class=""> > -    clear_smallmap(M, I);\<br class=""> > -  else if (RTCHECK(ok_address(M, F))) {\<br class=""> > -    B->fd = F;\<br class=""> > -    F->bk = B;\<br class=""> > -  }\<br class=""> > -  else {\<br class=""> > -    CORRUPTION_ERROR_ACTION(M);\<br class=""> > -  }\<br class=""> > -}<br class=""> > -<br class=""> > -/* Replace dv node, binning the old one */<br class=""> > -/* Used only when dvsize known to be small */<br class=""> > -#define replace_dv(M, P, S) {\<br class=""> > -  size_t DVS = M->dvsize;\<br class=""> > -  if (DVS != 0) {\<br class=""> > -    mchunkptr DV = M->dv;\<br class=""> > -    assert((M)->user_data, is_small(DVS));\<br class=""> > -    insert_small_chunk(M, DV, DVS);\<br class=""> > -  }\<br class=""> > -  M->dvsize = S;\<br class=""> > -  M->dv = P;\<br class=""> > -}<br class=""> > -<br class=""> > -<br class=""> > -/* ------------------------- Operations on trees -------------------------<br class=""> > */<br class=""> > -<br class=""> > -/* Insert chunk into tree */<br class=""> > -#define insert_large_chunk(M, X, S) {\<br class=""> > -  tbinptr* H;\<br class=""> > -  bindex_t I;\<br class=""> > -  compute_tree_index(S, I);\<br class=""> > -  H = treebin_at(M, I);\<br class=""> > -  X->index = I;\<br class=""> > -  X->child[0] = X->child[1] = 0;\<br class=""> > -  if (!treemap_is_marked(M, I)) {\<br class=""> > -    mark_treemap(M, I);\<br class=""> > -    *H = X;\<br class=""> > -    X->parent = (tchunkptr)H;\<br class=""> > -    X->fd = X->bk = X;\<br class=""> > -  }\<br class=""> > -  else {\<br class=""> > -    tchunkptr T = *H;\<br class=""> > -    size_t K = S << leftshift_for_tree_index(I);\<br class=""> > -    for (;;) {\<br class=""> > -      if (chunksize(T) != S) {\<br class=""> > -        tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\<br class=""> > -        K <<= 1;\<br class=""> > -        if (*C != 0)\<br class=""> > -          T = *C;\<br class=""> > -        else if (RTCHECK(ok_address(M, C))) {\<br class=""> > -          *C = X;\<br class=""> > -          X->parent = T;\<br class=""> > -          X->fd = X->bk = X;\<br class=""> > -          break;\<br class=""> > -        }\<br class=""> > -        else {\<br class=""> > -          CORRUPTION_ERROR_ACTION(M);\<br class=""> > -          break;\<br class=""> > -        }\<br class=""> > -      }\<br class=""> > -      else {\<br class=""> > -        tchunkptr F = T->fd;\<br class=""> > -        if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\<br class=""> > -          T->fd = F->bk = X;\<br class=""> > -          X->fd = F;\<br class=""> > -          X->bk = T;\<br class=""> > -          X->parent = 0;\<br class=""> > -          break;\<br class=""> > -        }\<br class=""> > -        else {\<br class=""> > -          CORRUPTION_ERROR_ACTION(M);\<br class=""> > -          break;\<br class=""> > -        }\<br class=""> > -      }\<br class=""> > -    }\<br class=""> > -  }\<br class=""> > -}<br class=""> > -<br class=""> > -/*<br class=""> > -  Unlink steps:<br class=""> > -<br class=""> > -  1. If x is a chained node, unlink it from its same-sized fd/bk links<br class=""> > -     and choose its bk node as its replacement.<br class=""> > -  2. If x was the last node of its size, but not a leaf node, it must<br class=""> > -     be replaced with a leaf node (not merely one with an open left or<br class=""> > -     right), to make sure that lefts and rights of descendents<br class=""> > -     correspond properly to bit masks.  We use the rightmost descendent<br class=""> > -     of x.  We could use any other leaf, but this is easy to locate and<br class=""> > -     tends to counteract removal of leftmosts elsewhere, and so keeps<br class=""> > -     paths shorter than minimally guaranteed.  This doesn't loop much<br class=""> > -     because on average a node in a tree is near the bottom.<br class=""> > -  3. If x is the base of a chain (i.e., has parent links) relink<br class=""> > -     x's parent and children to x's replacement (or null if none).<br class=""> > -*/<br class=""> > -<br class=""> > -#define unlink_large_chunk(M, X) {\<br class=""> > -  tchunkptr XP = X->parent;\<br class=""> > -  tchunkptr R;\<br class=""> > -  if (X->bk != X) {\<br class=""> > -    tchunkptr F = X->fd;\<br class=""> > -    R = X->bk;\<br class=""> > -    if (RTCHECK(ok_address(M, F))) {\<br class=""> > -      F->bk = R;\<br class=""> > -      R->fd = F;\<br class=""> > -    }\<br class=""> > -    else {\<br class=""> > -      CORRUPTION_ERROR_ACTION(M);\<br class=""> > -    }\<br class=""> > -  }\<br class=""> > -  else {\<br class=""> > -    tchunkptr* RP;\<br class=""> > -    if (((R = *(RP = &(X->child[1]))) != 0) ||\<br class=""> > -        ((R = *(RP = &(X->child[0]))) != 0)) {\<br class=""> > -      tchunkptr* CP;\<br class=""> > -      while ((*(CP = &(R->child[1])) != 0) ||\<br class=""> > -             (*(CP = &(R->child[0])) != 0)) {\<br class=""> > -        R = *(RP = CP);\<br class=""> > -      }\<br class=""> > -      if (RTCHECK(ok_address(M, RP)))\<br class=""> > -        *RP = 0;\<br class=""> > -      else {\<br class=""> > -        CORRUPTION_ERROR_ACTION(M);\<br class=""> > -      }\<br class=""> > -    }\<br class=""> > -  }\<br class=""> > -  if (XP != 0) {\<br class=""> > -    tbinptr* H = treebin_at(M, X->index);\<br class=""> > -    if (X == *H) {\<br class=""> > -      if ((*H = R) == 0) \<br class=""> > -        clear_treemap(M, X->index);\<br class=""> > -    }\<br class=""> > -    else if (RTCHECK(ok_address(M, XP))) {\<br class=""> > -      if (XP->child[0] == X) \<br class=""> > -        XP->child[0] = R;\<br class=""> > -      else \<br class=""> > -        XP->child[1] = R;\<br class=""> > -    }\<br class=""> > -    else\<br class=""> > -      CORRUPTION_ERROR_ACTION(M);\<br class=""> > -    if (R != 0) {\<br class=""> > -      if (RTCHECK(ok_address(M, R))) {\<br class=""> > -        tchunkptr C0, C1;\<br class=""> > -        R->parent = XP;\<br class=""> > -        if ((C0 = X->child[0]) != 0) {\<br class=""> > -          if (RTCHECK(ok_address(M, C0))) {\<br class=""> > -            R->child[0] = C0;\<br class=""> > -            C0->parent = R;\<br class=""> > -          }\<br class=""> > -          else\<br class=""> > -            CORRUPTION_ERROR_ACTION(M);\<br class=""> > -        }\<br class=""> > -        if ((C1 = X->child[1]) != 0) {\<br class=""> > -          if (RTCHECK(ok_address(M, C1))) {\<br class=""> > -            R->child[1] = C1;\<br class=""> > -            C1->parent = R;\<br class=""> > -          }\<br class=""> > -          else\<br class=""> > -            CORRUPTION_ERROR_ACTION(M);\<br class=""> > -        }\<br class=""> > -      }\<br class=""> > -      else\<br class=""> > -        CORRUPTION_ERROR_ACTION(M);\<br class=""> > -    }\<br class=""> > -  }\<br class=""> > -}<br class=""> > -<br class=""> > -/* Relays to large vs small bin operations */<br class=""> > -<br class=""> > -#define insert_chunk(M, P, S)\<br class=""> > -  if (is_small(S)) insert_small_chunk(M, P, S)\<br class=""> > -  else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }<br class=""> > -<br class=""> > -#define unlink_chunk(M, P, S)\<br class=""> > -  if (is_small(S)) unlink_small_chunk(M, P, S)\<br class=""> > -  else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }<br class=""> > -<br class=""> > -<br class=""> > -/* Relays to internal calls to malloc/free from realloc, memalign etc */<br class=""> > -<br class=""> > -#define internal_malloc(m, b) mspace_malloc(m, b)<br class=""> > -#define internal_free(m, mem) mspace_free(m,mem);<br class=""> > -<br class=""> > -<br class=""> > -/* -------------------------- mspace management --------------------------<br class=""> > */<br class=""> > -<br class=""> > -/* Initialize top chunk and its size */<br class=""> > -static void init_top(mstate m, mchunkptr p, size_t psize) {<br class=""> > -  /* Ensure alignment */<br class=""> > -  size_t offset = align_offset(chunk2mem(p));<br class=""> > -  p = (mchunkptr)((char*)p + offset);<br class=""> > -  psize -= offset;<br class=""> > -<br class=""> > -  m->top = p;<br class=""> > -  m->topsize = psize;<br class=""> > -  p->head = psize | PINUSE_BIT;<br class=""> > -  /* set size of fake trailing chunk holding overhead space only once */<br class=""> > -  chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;<br class=""> > -}<br class=""> > -<br class=""> > -/* Initialize bins for a new mstate that is otherwise zeroed out */<br class=""> > -static void init_bins(mstate m) {<br class=""> > -  /* Establish circular links for smallbins */<br class=""> > -  bindex_t i;<br class=""> > -  for (i = 0; i < NSMALLBINS; ++i) {<br class=""> > -    sbinptr bin = smallbin_at(m,i);<br class=""> > -    bin->fd = bin->bk = bin;<br class=""> > -  }<br class=""> > -}<br class=""> > -<br class=""> > -#if PROCEED_ON_ERROR<br class=""> > -<br class=""> > -/* default corruption action */<br class=""> > -static void reset_on_error(mstate m) {<br class=""> > -  int i;<br class=""> > -  ++malloc_corruption_error_count;<br class=""> > -  /* Reinitialize fields to forget about all memory */<br class=""> > -  m->smallbins = m->treebins = 0;<br class=""> > -  m->dvsize = m->topsize = 0;<br class=""> > -  m->seg.base = 0;<br class=""> > -  m->seg.size = 0;<br class=""> > -  m->seg.next = 0;<br class=""> > -  m->top = m->dv = 0;<br class=""> > -  for (i = 0; i < NTREEBINS; ++i)<br class=""> > -    *treebin_at(m, i) = 0;<br class=""> > -  init_bins(m);<br class=""> > -}<br class=""> > -#endif /* PROCEED_ON_ERROR */<br class=""> > -<br class=""> > -/* Allocate chunk and prepend remainder with chunk in successor base. */<br class=""> > -static void* prepend_alloc(mstate m, char* newbase, char* oldbase,<br class=""> > -                           size_t nb) {<br class=""> > -  mchunkptr p = align_as_chunk(newbase);<br class=""> > -  mchunkptr oldfirst = align_as_chunk(oldbase);<br class=""> > -  size_t psize = (char*)oldfirst - (char*)p;<br class=""> > -  mchunkptr q = chunk_plus_offset(p, nb);<br class=""> > -  size_t qsize = psize - nb;<br class=""> > -  set_size_and_pinuse_of_inuse_chunk(m, p, nb);<br class=""> > -<br class=""> > -  assert(m->user_data, (char*)oldfirst > (char*)q);<br class=""> > -  assert(m->user_data, pinuse(oldfirst));<br class=""> > -  assert(m->user_data, qsize >= MIN_CHUNK_SIZE);<br class=""> > -<br class=""> > -  /* consolidate remainder with first chunk of old base */<br class=""> > -  if (oldfirst == m->top) {<br class=""> > -    size_t tsize = m->topsize += qsize;<br class=""> > -    m->top = q;<br class=""> > -    q->head = tsize | PINUSE_BIT;<br class=""> > -    check_top_chunk(m, q);<br class=""> > -  }<br class=""> > -  else if (oldfirst == m->dv) {<br class=""> > -    size_t dsize = m->dvsize += qsize;<br class=""> > -    m->dv = q;<br class=""> > -    set_size_and_pinuse_of_free_chunk(q, dsize);<br class=""> > -  }<br class=""> > -  else {<br class=""> > -    if (!cinuse(oldfirst)) {<br class=""> > -      size_t nsize = chunksize(oldfirst);<br class=""> > -      unlink_chunk(m, oldfirst, nsize);<br class=""> > -      oldfirst = chunk_plus_offset(oldfirst, nsize);<br class=""> > -      qsize += nsize;<br class=""> > -    }<br class=""> > -    set_free_with_pinuse(q, qsize, oldfirst);<br class=""> > -    insert_chunk(m, q, qsize);<br class=""> > -    check_free_chunk(m, q);<br class=""> > -  }<br class=""> > -<br class=""> > -  check_malloced_chunk(m, chunk2mem(p), nb);<br class=""> > -  return chunk2mem(p);<br class=""> > -}<br class=""> > -<br class=""> > -/* -------------------------- System allocation --------------------------<br class=""> > */<br class=""> > -<br class=""> > -/* Get memory from system using MORECORE or MMAP */<br class=""> > -static void* sys_alloc(mstate m, size_t nb) {<br class=""> > -  MALLOC_FAILURE_ACTION;<br class=""> > -  return 0;<br class=""> > -}<br class=""> > -<br class=""> > -/* ---------------------------- malloc support ---------------------------<br class=""> > */<br class=""> > -<br class=""> > -/* allocate a large request from the best fitting chunk in a treebin */<br class=""> > -static void* tmalloc_large(mstate m, size_t nb) {<br class=""> > -  tchunkptr v = 0;<br class=""> > -  size_t rsize = -nb; /* Unsigned negation */<br class=""> > -  tchunkptr t;<br class=""> > -  bindex_t idx;<br class=""> > -  compute_tree_index(nb, idx);<br class=""> > -<br class=""> > -  if ((t = *treebin_at(m, idx)) != 0) {<br class=""> > -    /* Traverse tree for this bin looking for node with size == nb */<br class=""> > -    size_t sizebits = nb << leftshift_for_tree_index(idx);<br class=""> > -    tchunkptr rst = 0;  /* The deepest untaken right subtree */<br class=""> > -    for (;;) {<br class=""> > -      tchunkptr rt;<br class=""> > -      size_t trem = chunksize(t) - nb;<br class=""> > -      if (trem < rsize) {<br class=""> > -        v = t;<br class=""> > -        if ((rsize = trem) == 0)<br class=""> > -          break;<br class=""> > -      }<br class=""> > -      rt = t->child[1];<br class=""> > -      t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];<br class=""> > -      if (rt != 0 && rt != t)<br class=""> > -        rst = rt;<br class=""> > -      if (t == 0) {<br class=""> > -        t = rst; /* set t to least subtree holding sizes > nb */<br class=""> > -        break;<br class=""> > -      }<br class=""> > -      sizebits <<= 1;<br class=""> > -    }<br class=""> > -  }<br class=""> > -<br class=""> > -  if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */<br class=""> > -    binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;<br class=""> > -    if (leftbits != 0) {<br class=""> > -      bindex_t i;<br class=""> > -      binmap_t leastbit = least_bit(leftbits);<br class=""> > -      compute_bit2idx(leastbit, i);<br class=""> > -      t = *treebin_at(m, i);<br class=""> > -    }<br class=""> > -  }<br class=""> > -<br class=""> > -  while (t != 0) { /* find smallest of tree or subtree */<br class=""> > -    size_t trem = chunksize(t) - nb;<br class=""> > -    if (trem < rsize) {<br class=""> > -      rsize = trem;<br class=""> > -      v = t;<br class=""> > -    }<br class=""> > -    t = leftmost_child(t);<br class=""> > -  }<br class=""> > -<br class=""> > -  /*  If dv is a better fit, return 0 so malloc will use it */<br class=""> > -  if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {<br class=""> > -    if (RTCHECK(ok_address(m, v))) { /* split */<br class=""> > -      mchunkptr r = chunk_plus_offset(v, nb);<br class=""> > -      assert(m->user_data, chunksize(v) == rsize + nb);<br class=""> > -      if (RTCHECK(ok_next(v, r))) {<br class=""> > -        unlink_large_chunk(m, v);<br class=""> > -        if (rsize < MIN_CHUNK_SIZE)<br class=""> > -          set_inuse_and_pinuse(m, v, (rsize + nb));<br class=""> > -        else {<br class=""> > -          set_size_and_pinuse_of_inuse_chunk(m, v, nb);<br class=""> > -          set_size_and_pinuse_of_free_chunk(r, rsize);<br class=""> > -          insert_chunk(m, r, rsize);<br class=""> > -        }<br class=""> > -        return chunk2mem(v);<br class=""> > -      }<br class=""> > -    }<br class=""> > -    CORRUPTION_ERROR_ACTION(m);<br class=""> > -  }<br class=""> > -  return 0;<br class=""> > -}<br class=""> > -<br class=""> > -/* allocate a small request from the best fitting chunk in a treebin */<br class=""> > -static void* tmalloc_small(mstate m, size_t nb) {<br class=""> > -  tchunkptr t, v;<br class=""> > -  size_t rsize;<br class=""> > -  bindex_t i;<br class=""> > -  binmap_t leastbit = least_bit(m->treemap);<br class=""> > -  compute_bit2idx(leastbit, i);<br class=""> > -<br class=""> > -  v = t = *treebin_at(m, i);<br class=""> > -  rsize = chunksize(t) - nb;<br class=""> > -<br class=""> > -  while ((t = leftmost_child(t)) != 0) {<br class=""> > -    size_t trem = chunksize(t) - nb;<br class=""> > -    if (trem < rsize) {<br class=""> > -      rsize = trem;<br class=""> > -      v = t;<br class=""> > -    }<br class=""> > -  }<br class=""> > -<br class=""> > -  if (RTCHECK(ok_address(m, v))) {<br class=""> > -    mchunkptr r = chunk_plus_offset(v, nb);<br class=""> > -    assert(m->user_data, chunksize(v) == rsize + nb);<br class=""> > -    if (RTCHECK(ok_next(v, r))) {<br class=""> > -      unlink_large_chunk(m, v);<br class=""> > -      if (rsize < MIN_CHUNK_SIZE)<br class=""> > -        set_inuse_and_pinuse(m, v, (rsize + nb));<br class=""> > -      else {<br class=""> > -        set_size_and_pinuse_of_inuse_chunk(m, v, nb);<br class=""> > -        set_size_and_pinuse_of_free_chunk(r, rsize);<br class=""> > -        replace_dv(m, r, rsize);<br class=""> > -      }<br class=""> > -      return chunk2mem(v);<br class=""> > -    }<br class=""> > -  }<br class=""> > -<br class=""> > -  CORRUPTION_ERROR_ACTION(m);<br class=""> > -  return 0;<br class=""> > -}<br class=""> > -<br class=""> > -/* --------------------------- realloc support ---------------------------<br class=""> > */<br class=""> > -<br class=""> > -static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {<br class=""> > -  if (bytes >= MAX_REQUEST) {<br class=""> > -    MALLOC_FAILURE_ACTION;<br class=""> > -    return 0;<br class=""> > -  }<br class=""> > -  if (!PREACTION(m)) {<br class=""> > -    mchunkptr oldp = mem2chunk(oldmem);<br class=""> > -    size_t oldsize = chunksize(oldp);<br class=""> > -    mchunkptr next = chunk_plus_offset(oldp, oldsize);<br class=""> > -    mchunkptr newp = 0;<br class=""> > -    void* extra = 0;<br class=""> > -<br class=""> > -    /* Try to either shrink or extend into top. Else malloc-copy-free */<br class=""> > -<br class=""> > -    if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&<br class=""> > -                ok_next(oldp, next) && ok_pinuse(next))) {<br class=""> > -      size_t nb = request2size(bytes);<br class=""> > -      if (oldsize >= nb) { /* already big enough */<br class=""> > -        size_t rsize = oldsize - nb;<br class=""> > -        newp = oldp;<br class=""> > -        if (rsize >= MIN_CHUNK_SIZE) {<br class=""> > -          mchunkptr remainder = chunk_plus_offset(newp, nb);<br class=""> > -          set_inuse(m, newp, nb);<br class=""> > -          set_inuse(m, remainder, rsize);<br class=""> > -          extra = chunk2mem(remainder);<br class=""> > -        }<br class=""> > -      }<br class=""> > -      else if (next == m->top && oldsize + m->topsize > nb) {<br class=""> > -        /* Expand into top */<br class=""> > -        size_t newsize = oldsize + m->topsize;<br class=""> > -        size_t newtopsize = newsize - nb;<br class=""> > -        mchunkptr newtop = chunk_plus_offset(oldp, nb);<br class=""> > -        set_inuse(m, oldp, nb);<br class=""> > -        newtop->head = newtopsize |PINUSE_BIT;<br class=""> > -        m->top = newtop;<br class=""> > -        m->topsize = newtopsize;<br class=""> > -        newp = oldp;<br class=""> > -      }<br class=""> > -    }<br class=""> > -    else {<br class=""> > -      USAGE_ERROR_ACTION(m, oldmem);<br class=""> > -      POSTACTION(m);<br class=""> > -      return 0;<br class=""> > -    }<br class=""> > -<br class=""> > -    POSTACTION(m);<br class=""> > -<br class=""> > -    if (newp != 0) {<br class=""> > -      if (extra != 0) {<br class=""> > -        internal_free(m, extra);<br class=""> > -      }<br class=""> > -      check_inuse_chunk(m, newp);<br class=""> > -      return chunk2mem(newp);<br class=""> > -    }<br class=""> > -    else {<br class=""> > -      void* newmem = internal_malloc(m, bytes);<br class=""> > -      if (newmem != 0) {<br class=""> > -        size_t oc = oldsize - overhead_for(oldp);<br class=""> > -        MEMCPY(newmem, oldmem, (oc < bytes)? oc : bytes);<br class=""> > -        internal_free(m, oldmem);<br class=""> > -      }<br class=""> > -      return newmem;<br class=""> > -    }<br class=""> > -  }<br class=""> > -  return 0;<br class=""> > -}<br class=""> > -<br class=""> > -/* --------------------------- memalign support --------------------------<br class=""> > */<br class=""> > -<br class=""> > -static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {<br class=""> > -  if (alignment <= MALLOC_ALIGNMENT)    /* Can just use malloc */<br class=""> > -    return internal_malloc(m, bytes);<br class=""> > -  if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size<br class=""> > */<br class=""> > -    alignment = MIN_CHUNK_SIZE;<br class=""> > -  if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */<br class=""> > -    size_t a = MALLOC_ALIGNMENT << 1;<br class=""> > -    while (a < alignment) a <<= 1;<br class=""> > -    alignment = a;<br class=""> > -  }<br class=""> > -<br class=""> > -  if (bytes >= MAX_REQUEST - alignment) {<br class=""> > -    if (m != 0)  { /* Test isn't needed but avoids compiler warning */<br class=""> > -      MALLOC_FAILURE_ACTION;<br class=""> > -    }<br class=""> > -  }<br class=""> > -  else {<br class=""> > -    size_t nb = request2size(bytes);<br class=""> > -    size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;<br class=""> > -    char* mem = (char*)internal_malloc(m, req);<br class=""> > -    if (mem != 0) {<br class=""> > -      void* leader = 0;<br class=""> > -      void* trailer = 0;<br class=""> > -      mchunkptr p = mem2chunk(mem);<br class=""> > -<br class=""> > -      if (PREACTION(m)) return 0;<br class=""> > -      if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */<br class=""> > -        /*<br class=""> > -          Find an aligned spot inside chunk.  Since we need to give<br class=""> > -          back leading space in a chunk of at least MIN_CHUNK_SIZE, if<br class=""> > -          the first calculation places us at a spot with less than<br class=""> > -          MIN_CHUNK_SIZE leader, we can move to the next aligned spot.<br class=""> > -          We've allocated enough total room so that this is always<br class=""> > -          possible.<br class=""> > -        */<br class=""> > -        char* br = (char*)mem2chunk((size_t)(((size_t)(mem +<br class=""> > -                                                       alignment -<br class=""> > -                                                       SIZE_T_ONE)) &<br class=""> > -                                             -alignment));<br class=""> > -        char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?<br class=""> > -          br : br+alignment;<br class=""> > -        mchunkptr newp = (mchunkptr)pos;<br class=""> > -        size_t leadsize = pos - (char*)(p);<br class=""> > -        size_t newsize = chunksize(p) - leadsize;<br class=""> > -<br class=""> > -        /* Otherwise, give back leader, use the rest */<br class=""> > -        set_inuse(m, newp, newsize);<br class=""> > -        set_inuse(m, p, leadsize);<br class=""> > -        leader = chunk2mem(p);<br class=""> > -<br class=""> > -        p = newp;<br class=""> > -      }<br class=""> > -<br class=""> > -      assert(m->user_data, chunksize(p) >= nb);<br class=""> > -      assert(m->user_data, (((size_t)(chunk2mem(p))) % alignment) == 0);<br class=""> > -      check_inuse_chunk(m, p);<br class=""> > -      POSTACTION(m);<br class=""> > -      if (leader != 0) {<br class=""> > -        internal_free(m, leader);<br class=""> > -      }<br class=""> > -      if (trailer != 0) {<br class=""> > -        internal_free(m, trailer);<br class=""> > -      }<br class=""> > -      return chunk2mem(p);<br class=""> > -    }<br class=""> > -  }<br class=""> > -  return 0;<br class=""> > -}<br class=""> > -<br class=""> > -/* ----------------------------- user mspaces ----------------------------<br class=""> > */<br class=""> > -<br class=""> > -static mstate init_user_mstate(char* tbase, size_t tsize, void *user_data) {<br class=""> > -  size_t msize = pad_request(sizeof(struct malloc_state));<br class=""> > -  mchunkptr mn;<br class=""> > -  mchunkptr msp = align_as_chunk(tbase);<br class=""> > -  mstate m = (mstate)(chunk2mem(msp));<br class=""> > -  MEMCLEAR(m, msize);<br class=""> > -  INITIAL_LOCK(&m->mutex);<br class=""> > -  msp->head = (msize|PINUSE_BIT|CINUSE_BIT);<br class=""> > -  m->seg.base = m->least_addr = tbase;<br class=""> > -  m->seg.size = m->footprint = m->max_footprint = tsize;<br class=""> > -  m->magic = mparams.magic;<br class=""> > -  m->mflags = mparams.default_mflags;<br class=""> > -  m->user_data = user_data;<br class=""> > -  init_bins(m);<br class=""> > -  mn = next_chunk(mem2chunk(m));<br class=""> > -  init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);<br class=""> > -  check_top_chunk(m, m->top);<br class=""> > -  return m;<br class=""> > -}<br class=""> > -<br class=""> > -mspace create_mspace_with_base(void* base, size_t capacity, int locked, void<br class=""> > *user_data) {<br class=""> > -  mstate m = 0;<br class=""> > -  size_t msize = pad_request(sizeof(struct malloc_state));<br class=""> > -  init_mparams(); /* Ensure pagesize etc initialized */<br class=""> > -<br class=""> > -  if (capacity > msize + TOP_FOOT_SIZE &&<br class=""> > -      capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {<br class=""> > -    m = init_user_mstate((char*)base, capacity, user_data);<br class=""> > -    set_lock(m, locked);<br class=""> > -  }<br class=""> > -  return (mspace)m;<br class=""> > -}<br class=""> > -<br class=""> > -/*<br class=""> > -  mspace versions of routines are near-clones of the global<br class=""> > -  versions. This is not so nice but better than the alternatives.<br class=""> > -*/<br class=""> > -<br class=""> > -<br class=""> > -void* mspace_malloc(mspace msp, size_t bytes) {<br class=""> > -  mstate ms = (mstate)msp;<br class=""> > -  if (!ok_magic(ms)) {<br class=""> > -    USAGE_ERROR_ACTION(ms,ms);<br class=""> > -    return 0;<br class=""> > -  }<br class=""> > -  if (!PREACTION(ms)) {<br class=""> > -    void* mem;<br class=""> > -    size_t nb;<br class=""> > -    if (bytes <= MAX_SMALL_REQUEST) {<br class=""> > -      bindex_t idx;<br class=""> > -      binmap_t smallbits;<br class=""> > -      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);<br class=""> > -      idx = small_index(nb);<br class=""> > -      smallbits = ms->smallmap >> idx;<br class=""> > -<br class=""> > -      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */<br class=""> > -        mchunkptr b, p;<br class=""> > -        idx += ~smallbits & 1;       /* Uses next bin if idx empty */<br class=""> > -        b = smallbin_at(ms, idx);<br class=""> > -        p = b->fd;<br class=""> > -        assert(ms->user_data, chunksize(p) == small_index2size(idx));<br class=""> > -        unlink_first_small_chunk(ms, b, p, idx);<br class=""> > -        set_inuse_and_pinuse(ms, p, small_index2size(idx));<br class=""> > -        mem = chunk2mem(p);<br class=""> > -        check_malloced_chunk(ms, mem, nb);<br class=""> > -        goto postaction;<br class=""> > -      }<br class=""> > -<br class=""> > -      else if (nb > ms->dvsize) {<br class=""> > -        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */<br class=""> > -          mchunkptr b, p, r;<br class=""> > -          size_t rsize;<br class=""> > -          bindex_t i;<br class=""> > -          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));<br class=""> > -          binmap_t leastbit = least_bit(leftbits);<br class=""> > -          compute_bit2idx(leastbit, i);<br class=""> > -          b = smallbin_at(ms, i);<br class=""> > -          p = b->fd;<br class=""> > -          assert(ms->user_data, chunksize(p) == small_index2size(i));<br class=""> > -          unlink_first_small_chunk(ms, b, p, i);<br class=""> > -          rsize = small_index2size(i) - nb;<br class=""> > -          /* Fit here cannot be remainderless if 4byte sizes */<br class=""> > -          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)<br class=""> > -            set_inuse_and_pinuse(ms, p, small_index2size(i));<br class=""> > -          else {<br class=""> > -            set_size_and_pinuse_of_inuse_chunk(ms, p, nb);<br class=""> > -            r = chunk_plus_offset(p, nb);<br class=""> > -            set_size_and_pinuse_of_free_chunk(r, rsize);<br class=""> > -            replace_dv(ms, r, rsize);<br class=""> > -          }<br class=""> > -          mem = chunk2mem(p);<br class=""> > -          check_malloced_chunk(ms, mem, nb);<br class=""> > -          goto postaction;<br class=""> > -        }<br class=""> > -<br class=""> > -        else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {<br class=""> > -          check_malloced_chunk(ms, mem, nb);<br class=""> > -          goto postaction;<br class=""> > -        }<br class=""> > -      }<br class=""> > -    }<br class=""> > -    else if (bytes >= MAX_REQUEST)<br class=""> > -      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc)<br class=""> > */<br class=""> > -    else {<br class=""> > -      nb = pad_request(bytes);<br class=""> > -      if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {<br class=""> > -        check_malloced_chunk(ms, mem, nb);<br class=""> > -        goto postaction;<br class=""> > -      }<br class=""> > -    }<br class=""> > -<br class=""> > -    if (nb <= ms->dvsize) {<br class=""> > -      size_t rsize = ms->dvsize - nb;<br class=""> > -      mchunkptr p = ms->dv;<br class=""> > -      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */<br class=""> > -        mchunkptr r = ms->dv = chunk_plus_offset(p, nb);<br class=""> > -        ms->dvsize = rsize;<br class=""> > -        set_size_and_pinuse_of_free_chunk(r, rsize);<br class=""> > -        set_size_and_pinuse_of_inuse_chunk(ms, p, nb);<br class=""> > -      }<br class=""> > -      else { /* exhaust dv */<br class=""> > -        size_t dvs = ms->dvsize;<br class=""> > -        ms->dvsize = 0;<br class=""> > -        ms->dv = 0;<br class=""> > -        set_inuse_and_pinuse(ms, p, dvs);<br class=""> > -      }<br class=""> > -      mem = chunk2mem(p);<br class=""> > -      check_malloced_chunk(ms, mem, nb);<br class=""> > -      goto postaction;<br class=""> > -    }<br class=""> > -<br class=""> > -    else if (nb < ms->topsize) { /* Split top */<br class=""> > -      size_t rsize = ms->topsize -= nb;<br class=""> > -      mchunkptr p = ms->top;<br class=""> > -      mchunkptr r = ms->top = chunk_plus_offset(p, nb);<br class=""> > -      r->head = rsize | PINUSE_BIT;<br class=""> > -      set_size_and_pinuse_of_inuse_chunk(ms, p, nb);<br class=""> > -      mem = chunk2mem(p);<br class=""> > -      check_top_chunk(ms, ms->top);<br class=""> > -      check_malloced_chunk(ms, mem, nb);<br class=""> > -      goto postaction;<br class=""> > -    }<br class=""> > -<br class=""> > -    mem = sys_alloc(ms, nb);<br class=""> > -<br class=""> > -  postaction:<br class=""> > -    POSTACTION(ms);<br class=""> > -    return mem;<br class=""> > -  }<br class=""> > -<br class=""> > -  return 0;<br class=""> > -}<br class=""> > -<br class=""> > -void mspace_free(mspace msp, void* mem) {<br class=""> > -  if (mem != 0) {<br class=""> > -    mchunkptr p  = mem2chunk(mem);<br class=""> > -#if FOOTERS<br class=""> > -    mstate fm = get_mstate_for(p);<br class=""> > -#else /* FOOTERS */<br class=""> > -    mstate fm = (mstate)msp;<br class=""> > -#endif /* FOOTERS */<br class=""> > -    if (!ok_magic(fm)) {<br class=""> > -      USAGE_ERROR_ACTION(fm, p);<br class=""> > -      return;<br class=""> > -    }<br class=""> > -    if (!PREACTION(fm)) {<br class=""> > -      check_inuse_chunk(fm, p);<br class=""> > -      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {<br class=""> > -        size_t psize = chunksize(p);<br class=""> > -        mchunkptr next = chunk_plus_offset(p, psize);<br class=""> > -        if (!pinuse(p)) {<br class=""> > -          size_t prevsize = p->prev_foot;<br class=""> > -<br class=""> > -          mchunkptr prev = chunk_minus_offset(p, prevsize);<br class=""> > -          psize += prevsize;<br class=""> > -          p = prev;<br class=""> > -          if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */<br class=""> > -            if (p != fm->dv) {<br class=""> > -              unlink_chunk(fm, p, prevsize);<br class=""> > -            }<br class=""> > -            else if ((next->head & INUSE_BITS) == INUSE_BITS) {<br class=""> > -              fm->dvsize = psize;<br class=""> > -              set_free_with_pinuse(p, psize, next);<br class=""> > -              goto postaction;<br class=""> > -            }<br class=""> > -          }<br class=""> > -          else<br class=""> > -            goto erroraction;<br class=""> > -        }<br class=""> > -<br class=""> > -        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {<br class=""> > -          if (!cinuse(next)) {  /* consolidate forward */<br class=""> > -            if (next == fm->top) {<br class=""> > -              size_t tsize = fm->topsize += psize;<br class=""> > -              fm->top = p;<br class=""> > -              p->head = tsize | PINUSE_BIT;<br class=""> > -              if (p == fm->dv) {<br class=""> > -                fm->dv = 0;<br class=""> > -                fm->dvsize = 0;<br class=""> > -              }<br class=""> > -              goto postaction;<br class=""> > -            }<br class=""> > -            else if (next == fm->dv) {<br class=""> > -              size_t dsize = fm->dvsize += psize;<br class=""> > -              fm->dv = p;<br class=""> > -              set_size_and_pinuse_of_free_chunk(p, dsize);<br class=""> > -              goto postaction;<br class=""> > -            }<br class=""> > -            else {<br class=""> > -              size_t nsize = chunksize(next);<br class=""> > -              psize += nsize;<br class=""> > -              unlink_chunk(fm, next, nsize);<br class=""> > -              set_size_and_pinuse_of_free_chunk(p, psize);<br class=""> > -              if (p == fm->dv) {<br class=""> > -                fm->dvsize = psize;<br class=""> > -                goto postaction;<br class=""> > -              }<br class=""> > -            }<br class=""> > -          }<br class=""> > -          else<br class=""> > -            set_free_with_pinuse(p, psize, next);<br class=""> > -          insert_chunk(fm, p, psize);<br class=""> > -          check_free_chunk(fm, p);<br class=""> > -          goto postaction;<br class=""> > -        }<br class=""> > -      }<br class=""> > -    erroraction:<br class=""> > -      USAGE_ERROR_ACTION(fm, p);<br class=""> > -    postaction:<br class=""> > -      POSTACTION(fm);<br class=""> > -    }<br class=""> > -  }<br class=""> > -}<br class=""> > -<br class=""> > -void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {<br class=""> > -  void* mem;<br class=""> > -  size_t req = 0;<br class=""> > -  mstate ms = (mstate)msp;<br class=""> > -  if (!ok_magic(ms)) {<br class=""> > -    USAGE_ERROR_ACTION(ms,ms);<br class=""> > -    return 0;<br class=""> > -  }<br class=""> > -  if (n_elements != 0) {<br class=""> > -    req = n_elements * elem_size;<br class=""> > -    if (((n_elements | elem_size) & ~(size_t)0xffff) &&<br class=""> > -        (req / n_elements != elem_size))<br class=""> > -      req = MAX_SIZE_T; /* force downstream failure on overflow */<br class=""> > -  }<br class=""> > -  mem = internal_malloc(ms, req);<br class=""> > -  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))<br class=""> > -    MEMCLEAR(mem, req);<br class=""> > -  return mem;<br class=""> > -}<br class=""> > -<br class=""> > -void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {<br class=""> > -  if (oldmem == 0)<br class=""> > -    return mspace_malloc(msp, bytes);<br class=""> > -#ifdef REALLOC_ZERO_BYTES_FREES<br class=""> > -  if (bytes == 0) {<br class=""> > -    mspace_free(msp, oldmem);<br class=""> > -    return 0;<br class=""> > -  }<br class=""> > -#endif /* REALLOC_ZERO_BYTES_FREES */<br class=""> > -  else {<br class=""> > -#if FOOTERS<br class=""> > -    mchunkptr p  = mem2chunk(oldmem);<br class=""> > -    mstate ms = get_mstate_for(p);<br class=""> > -#else /* FOOTERS */<br class=""> > -    mstate ms = (mstate)msp;<br class=""> > -#endif /* FOOTERS */<br class=""> > -    if (!ok_magic(ms)) {<br class=""> > -      USAGE_ERROR_ACTION(ms,ms);<br class=""> > -      return 0;<br class=""> > -    }<br class=""> > -    return internal_realloc(ms, oldmem, bytes);<br class=""> > -  }<br class=""> > -}<br class=""> > -<br class=""> > -void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {<br class=""> > -  mstate ms = (mstate)msp;<br class=""> > -  if (!ok_magic(ms)) {<br class=""> > -    USAGE_ERROR_ACTION(ms,ms);<br class=""> > -    return 0;<br class=""> > -  }<br class=""> > -  return internal_memalign(ms, alignment, bytes);<br class=""> > -}<br class=""> > -<br class=""> > -void mspace_malloc_stats(mspace msp) {<br class=""> > -  mstate ms = (mstate)msp;<br class=""> > -  if (ok_magic(ms)) {<br class=""> > -    internal_malloc_stats(ms);<br class=""> > -  }<br class=""> > -  else {<br class=""> > -    USAGE_ERROR_ACTION(ms,ms);<br class=""> > -  }<br class=""> > -}<br class=""> > -<br class=""> > -size_t mspace_footprint(mspace msp) {<br class=""> > -  size_t result;<br class=""> > -  mstate ms = (mstate)msp;<br class=""> > -  if (ok_magic(ms)) {<br class=""> > -    result = ms->footprint;<br class=""> > -  } else {<br class=""> > -    USAGE_ERROR_ACTION(ms,ms);<br class=""> > -  }<br class=""> > -  return result;<br class=""> > -}<br class=""> > -<br class=""> > -<br class=""> > -size_t mspace_max_footprint(mspace msp) {<br class=""> > -  size_t result;<br class=""> > -  mstate ms = (mstate)msp;<br class=""> > -  if (ok_magic(ms)) {<br class=""> > -    result = ms->max_footprint;<br class=""> > -  } else {<br class=""> > -    USAGE_ERROR_ACTION(ms,ms);<br class=""> > -  }<br class=""> > -  return result;<br class=""> > -}<br class=""> > -<br class=""> > -<br class=""> > -#if !NO_MALLINFO<br class=""> > -struct mallinfo mspace_mallinfo(mspace msp) {<br class=""> > -  mstate ms = (mstate)msp;<br class=""> > -  if (!ok_magic(ms)) {<br class=""> > -    USAGE_ERROR_ACTION(ms,ms);<br class=""> > -  }<br class=""> > -  return internal_mallinfo(ms);<br class=""> > -}<br class=""> > -#endif /* NO_MALLINFO */<br class=""> > -<br class=""> > -int mspace_mallopt(int param_number, int value) {<br class=""> > -  return change_mparam(param_number, value);<br class=""> > -}<br class=""> > -<br class=""> > diff --git a/qxldod/mspace.cpp b/qxldod/mspace.cpp<br class=""> > new file mode 100755<br class=""> > index 0000000..d0ba123<br class=""> > --- /dev/null<br class=""> > +++ b/qxldod/mspace.cpp<br class=""> > @@ -0,0 +1,2437 @@<br class=""> > +// based on dlmalloc from Doug Lea<br class=""> > +<br class=""> > +<br class=""> > +// quote from the Doug Lea original file<br class=""> > +    /*<br class=""> > +      This is a version (aka dlmalloc) of malloc/free/realloc written by<br class=""> > +      Doug Lea and released to the public domain, as explained at<br class=""> > +      <a href="http://creativecommons.org/licenses/publicdomain" rel="noreferrer" target="_blank" data-mce-href="http://creativecommons.org/licenses/publicdomain" class="">http://creativecommons.org/licenses/publicdomain</a>.  Send questions,<br class=""> > +      comments, complaints, performance data, etc to <a href="mailto:dl@cs.oswego.edu" target="_blank" data-mce-href="mailto:dl@cs.oswego.edu" class="">dl@cs.oswego.edu</a><br class=""> > +<br class=""> > +    * Version 2.8.3 Thu Sep 22 11:16:15 2005  Doug Lea  (dl at gee)<br class=""> > +<br class=""> > +       Note: There may be an updated version of this malloc obtainable at<br class=""> > +               <a href="ftp://gee.cs.oswego.edu/pub/misc/malloc.c" rel="noreferrer" target="_blank" data-mce-href="ftp://gee.cs.oswego.edu/pub/misc/malloc.c" class="">ftp://gee.cs.oswego.edu/pub/misc/malloc.c</a><br class=""> > +             Check before installing!<br class=""> > +    */<br class=""> > +<br class=""> > +<br class=""> > +#include <ntddk.h><br class=""> > +<br class=""> > +#include "mspace.h"<br class=""> > +<br class=""> > +#pragma warning( disable : 4146 ) /* no "unsigned" warnings */<br class=""> > +<br class=""> > +#define MALLOC_ALIGNMENT ((size_t)8U)<br class=""> > +#define USE_LOCKS 0<br class=""> > +#define malloc_getpagesize ((size_t)4096U)<br class=""> > +#define DEFAULT_GRANULARITY malloc_getpagesize<br class=""> > +#define MAX_SIZE_T (~(size_t)0)<br class=""> > +#define MALLOC_FAILURE_ACTION<br class=""> > +#define MALLINFO_FIELD_TYPE size_t<br class=""> > +#define FOOTERS 0<br class=""> > +#define INSECURE 0<br class=""> > +#define PROCEED_ON_ERROR 0<br class=""> > +#define DEBUG 0<br class=""> > +#define ABORT_ON_ASSERT_FAILURE 1<br class=""> > +#define ABORT(user_data) abort_func(user_data)<br class=""> > +#define USE_BUILTIN_FFS 0<br class=""> > +#define USE_DEV_RANDOM 0<br class=""> > +#define PRINT(params) print_func params<br class=""> > +<br class=""> > +<br class=""> > +#define MEMCPY(dest, src, n) RtlCopyMemory(dest, src, n)<br class=""> > +#define MEMCLEAR(dest, n) RtlZeroMemory(dest, n)<br class=""> > +<br class=""> > +<br class=""> > +#define M_GRANULARITY        (-1)<br class=""> > +<br class=""> > +void default_abort_func(void *user_data)<br class=""> > +{<br class=""> > +    for (;;);<br class=""> > +}<br class=""> > +<br class=""> > +void default_print_func(void *user_data, char *format, ...)<br class=""> > +{<br class=""> > +}<br class=""> > +<br class=""> > +static mspace_abort_t abort_func = default_abort_func;<br class=""> > +static mspace_print_t print_func = default_print_func;<br class=""> > +<br class=""> > +void mspace_set_abort_func(mspace_abort_t f)<br class=""> > +{<br class=""> > +    abort_func = f;<br class=""> > +}<br class=""> > +<br class=""> > +void mspace_set_print_func(mspace_print_t f)<br class=""> > +{<br class=""> > +    print_func = f;<br class=""> > +}<br class=""> > +<br class=""> > +/* ------------------------ Mallinfo declarations ------------------------<br class=""> > */<br class=""> > +<br class=""> > +#if !NO_MALLINFO<br class=""> > +/*<br class=""> > +  This version of malloc supports the standard SVID/XPG mallinfo<br class=""> > +  routine that returns a struct containing usage properties and<br class=""> > +  statistics. It should work on any system that has a<br class=""> > +  /usr/include/malloc.h defining struct mallinfo.  The main<br class=""> > +  declaration needed is the mallinfo struct that is returned (by-copy)<br class=""> > +  by mallinfo().  The malloinfo struct contains a bunch of fields that<br class=""> > +  are not even meaningful in this version of malloc.  These fields are<br class=""> > +  are instead filled by mallinfo() with other numbers that might be of<br class=""> > +  interest.<br class=""> > +<br class=""> > +  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a<br class=""> > +  /usr/include/malloc.h file that includes a declaration of struct<br class=""> > +  mallinfo.  If so, it is included; else a compliant version is<br class=""> > +  declared below.  These must be precisely the same for mallinfo() to<br class=""> > +  work.  The original SVID version of this struct, defined on most<br class=""> > +  systems with mallinfo, declares all fields as ints. But some others<br class=""> > +  define as unsigned long. If your system defines the fields using a<br class=""> > +  type of different width than listed here, you MUST #include your<br class=""> > +  system version and #define HAVE_USR_INCLUDE_MALLOC_H.<br class=""> > +*/<br class=""> > +<br class=""> > +/* #define HAVE_USR_INCLUDE_MALLOC_H */<br class=""> > +<br class=""> > +<br class=""> > +struct mallinfo {<br class=""> > +  MALLINFO_FIELD_TYPE arena;    /* non-mmapped space allocated from system<br class=""> > */<br class=""> > +  MALLINFO_FIELD_TYPE ordblks;  /* number of free chunks */<br class=""> > +  MALLINFO_FIELD_TYPE smblks;   /* always 0 */<br class=""> > +  MALLINFO_FIELD_TYPE hblks;    /* always 0 */<br class=""> > +  MALLINFO_FIELD_TYPE hblkhd;   /* space in mmapped regions */<br class=""> > +  MALLINFO_FIELD_TYPE usmblks;  /* maximum total allocated space */<br class=""> > +  MALLINFO_FIELD_TYPE fsmblks;  /* always 0 */<br class=""> > +  MALLINFO_FIELD_TYPE uordblks; /* total allocated space */<br class=""> > +  MALLINFO_FIELD_TYPE fordblks; /* total free space */<br class=""> > +  MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */<br class=""> > +};<br class=""> > +<br class=""> > +#endif /* NO_MALLINFO */<br class=""> > +<br class=""> > +<br class=""> > +<br class=""> > +#ifdef DEBUG<br class=""> > +#if ABORT_ON_ASSERT_FAILURE<br class=""> > +#define assert(user_data, x) if(!(x)) ABORT(user_data)<br class=""> > +#else /* ABORT_ON_ASSERT_FAILURE */<br class=""> > +#include <assert.h><br class=""> > +#endif /* ABORT_ON_ASSERT_FAILURE */<br class=""> > +#else  /* DEBUG */<br class=""> > +#define assert(user_data, x)<br class=""> > +#endif /* DEBUG */<br class=""> > +<br class=""> > +/* ------------------- size_t and alignment properties --------------------<br class=""> > */<br class=""> > +<br class=""> > +/* The byte and bit size of a size_t */<br class=""> > +#define SIZE_T_SIZE         (sizeof(size_t))<br class=""> > +#define SIZE_T_BITSIZE      (sizeof(size_t) << 3)<br class=""> > +<br class=""> > +/* Some constants coerced to size_t */<br class=""> > +/* Annoying but necessary to avoid errors on some plaftorms */<br class=""> > +#define SIZE_T_ZERO         ((size_t)0)<br class=""> > +#define SIZE_T_ONE          ((size_t)1)<br class=""> > +#define SIZE_T_TWO          ((size_t)2)<br class=""> > +#define TWO_SIZE_T_SIZES    (SIZE_T_SIZE<<1)<br class=""> > +#define FOUR_SIZE_T_SIZES   (SIZE_T_SIZE<<2)<br class=""> > +#define SIX_SIZE_T_SIZES    (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)<br class=""> > +#define HALF_MAX_SIZE_T     (MAX_SIZE_T / 2U)<br class=""> > +<br class=""> > +/* The bit mask value corresponding to MALLOC_ALIGNMENT */<br class=""> > +#define CHUNK_ALIGN_MASK    (MALLOC_ALIGNMENT - SIZE_T_ONE)<br class=""> > +<br class=""> > +/* True if address a has acceptable alignment */<br class=""> > +#define is_aligned(A)       (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)<br class=""> > +<br class=""> > +/* the number of bytes to offset an address to align it */<br class=""> > +#define align_offset(A)\<br class=""> > + ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\<br class=""> > +  ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) &<br class=""> > CHUNK_ALIGN_MASK))<br class=""> > +<br class=""> > +/* --------------------------- Lock preliminaries ------------------------<br class=""> > */<br class=""> > +<br class=""> > +#if USE_LOCKS<br class=""> > +<br class=""> > +/*<br class=""> > +  When locks are defined, there are up to two global locks:<br class=""> > +<br class=""> > +  * If HAVE_MORECORE, morecore_mutex protects sequences of calls to<br class=""> > +    MORECORE.  In many cases sys_alloc requires two calls, that should<br class=""> > +    not be interleaved with calls by other threads.  This does not<br class=""> > +    protect against direct calls to MORECORE by other threads not<br class=""> > +    using this lock, so there is still code to cope the best we can on<br class=""> > +    interference.<br class=""> > +<br class=""> > +  * magic_init_mutex ensures that mparams.magic and other<br class=""> > +    unique mparams values are initialized only once.<br class=""> > +*/<br class=""> > +<br class=""> > +<br class=""> > +#define USE_LOCK_BIT               (2U)<br class=""> > +#else  /* USE_LOCKS */<br class=""> > +#define USE_LOCK_BIT               (0U)<br class=""> > +#define INITIAL_LOCK(l)<br class=""> > +#endif /* USE_LOCKS */<br class=""> > +<br class=""> > +#if USE_LOCKS<br class=""> > +#define ACQUIRE_MAGIC_INIT_LOCK()  ACQUIRE_LOCK(&magic_init_mutex);<br class=""> > +#define RELEASE_MAGIC_INIT_LOCK()  RELEASE_LOCK(&magic_init_mutex);<br class=""> > +#else  /* USE_LOCKS */<br class=""> > +#define ACQUIRE_MAGIC_INIT_LOCK()<br class=""> > +#define RELEASE_MAGIC_INIT_LOCK()<br class=""> > +#endif /* USE_LOCKS */<br class=""> > +<br class=""> > +<br class=""> > +<br class=""> > +/* -----------------------  Chunk representations ------------------------<br class=""> > */<br class=""> > +<br class=""> > +/*<br class=""> > +  (The following includes lightly edited explanations by Colin Plumb.)<br class=""> > +<br class=""> > +  The malloc_chunk declaration below is misleading (but accurate and<br class=""> > +  necessary).  It declares a "view" into memory allowing access to<br class=""> > +  necessary fields at known offsets from a given base.<br class=""> > +<br class=""> > +  Chunks of memory are maintained using a `boundary tag' method as<br class=""> > +  originally described by Knuth.  (See the paper by Paul Wilson<br class=""> > +  <a href="ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps" rel="noreferrer" target="_blank" data-mce-href="ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps" class="">ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps</a> for a survey of such<br class=""> > +  techniques.)  Sizes of free chunks are stored both in the front of<br class=""> > +  each chunk and at the end.  This makes consolidating fragmented<br class=""> > +  chunks into bigger chunks fast.  The head fields also hold bits<br class=""> > +  representing whether chunks are free or in use.<br class=""> > +<br class=""> > +  Here are some pictures to make it clearer.  They are "exploded" to<br class=""> > +  show that the state of a chunk can be thought of as extending from<br class=""> > +  the high 31 bits of the head field of its header through the<br class=""> > +  prev_foot and PINUSE_BIT bit of the following chunk header.<br class=""> > +<br class=""> > +  A chunk that's in use looks like:<br class=""> > +<br class=""> > +   chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +           | Size of previous chunk (if P = 1)                             |<br class=""> > +           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|<br class=""> > +         | Size of this chunk                                         1| +-+<br class=""> > +   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +         |                                                               |<br class=""> > +         +-                                                             -+<br class=""> > +         |                                                               |<br class=""> > +         +-                                                             -+<br class=""> > +         |                                                               :<br class=""> > +         +-      size - sizeof(size_t) available payload bytes          -+<br class=""> > +         :                                                               |<br class=""> > + chunk-> +-                                                             -+<br class=""> > +         |                                                               |<br class=""> > +         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|<br class=""> > +       | Size of next chunk (may or may not be in use)               | +-+<br class=""> > + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +<br class=""> > +    And if it's free, it looks like this:<br class=""> > +<br class=""> > +   chunk-> +-                                                             -+<br class=""> > +           | User payload (must be in use, or we would have merged!)       |<br class=""> > +           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|<br class=""> > +         | Size of this chunk                                         0| +-+<br class=""> > +   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +         | Next pointer                                                  |<br class=""> > +         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +         | Prev pointer                                                  |<br class=""> > +         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +         |                                                               :<br class=""> > +         +-      size - sizeof(struct chunk) unused bytes               -+<br class=""> > +         :                                                               |<br class=""> > + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +         | Size of this chunk                                            |<br class=""> > +         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|<br class=""> > +       | Size of next chunk (must be in use, or we would have merged)| +-+<br class=""> > + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +       |                                                               :<br class=""> > +       +- User payload                                                -+<br class=""> > +       :                                                               |<br class=""> > +       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +                                                                     |0|<br class=""> > +                                                                     +-+<br class=""> > +  Note that since we always merge adjacent free chunks, the chunks<br class=""> > +  adjacent to a free chunk must be in use.<br class=""> > +<br class=""> > +  Given a pointer to a chunk (which can be derived trivially from the<br class=""> > +  payload pointer) we can, in O(1) time, find out whether the adjacent<br class=""> > +  chunks are free, and if so, unlink them from the lists that they<br class=""> > +  are on and merge them with the current chunk.<br class=""> > +<br class=""> > +  Chunks always begin on even word boundaries, so the mem portion<br class=""> > +  (which is returned to the user) is also on an even word boundary, and<br class=""> > +  thus at least double-word aligned.<br class=""> > +<br class=""> > +  The P (PINUSE_BIT) bit, stored in the unused low-order bit of the<br class=""> > +  chunk size (which is always a multiple of two words), is an in-use<br class=""> > +  bit for the *previous* chunk.  If that bit is *clear*, then the<br class=""> > +  word before the current chunk size contains the previous chunk<br class=""> > +  size, and can be used to find the front of the previous chunk.<br class=""> > +  The very first chunk allocated always has this bit set, preventing<br class=""> > +  access to non-existent (or non-owned) memory. If pinuse is set for<br class=""> > +  any given chunk, then you CANNOT determine the size of the<br class=""> > +  previous chunk, and might even get a memory addressing fault when<br class=""> > +  trying to do so.<br class=""> > +<br class=""> > +  The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of<br class=""> > +  the chunk size redundantly records whether the current chunk is<br class=""> > +  inuse. This redundancy enables usage checks within free and realloc,<br class=""> > +  and reduces indirection when freeing and consolidating chunks.<br class=""> > +<br class=""> > +  Each freshly allocated chunk must have both cinuse and pinuse set.<br class=""> > +  That is, each allocated chunk borders either a previously allocated<br class=""> > +  and still in-use chunk, or the base of its memory arena. This is<br class=""> > +  ensured by making all allocations from the the `lowest' part of any<br class=""> > +  found chunk.  Further, no free chunk physically borders another one,<br class=""> > +  so each free chunk is known to be preceded and followed by either<br class=""> > +  inuse chunks or the ends of memory.<br class=""> > +<br class=""> > +  Note that the `foot' of the current chunk is actually represented<br class=""> > +  as the prev_foot of the NEXT chunk. This makes it easier to<br class=""> > +  deal with alignments etc but can be very confusing when trying<br class=""> > +  to extend or adapt this code.<br class=""> > +<br class=""> > +  The exceptions to all this are<br class=""> > +<br class=""> > +     1. The special chunk `top' is the top-most available chunk (i.e.,<br class=""> > +        the one bordering the end of available memory). It is treated<br class=""> > +        specially.  Top is never included in any bin, is used only if<br class=""> > +        no other chunk is available, and is released back to the<br class=""> > +        system if it is very large (see M_TRIM_THRESHOLD).  In effect,<br class=""> > +        the top chunk is treated as larger (and thus less well<br class=""> > +        fitting) than any other available chunk.  The top chunk<br class=""> > +        doesn't update its trailing size field since there is no next<br class=""> > +        contiguous chunk that would have to index off it. However,<br class=""> > +        space is still allocated for it (TOP_FOOT_SIZE) to enable<br class=""> > +        separation or merging when space is extended.<br class=""> > +<br class=""> > +     3. Chunks allocated via mmap, which have the lowest-order bit<br class=""> > +        (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set<br class=""> > +        PINUSE_BIT in their head fields.  Because they are allocated<br class=""> > +        one-by-one, each must carry its own prev_foot field, which is<br class=""> > +        also used to hold the offset this chunk has within its mmapped<br class=""> > +        region, which is needed to preserve alignment. Each mmapped<br class=""> > +        chunk is trailed by the first two fields of a fake next-chunk<br class=""> > +        for sake of usage checks.<br class=""> > +<br class=""> > +*/<br class=""> > +<br class=""> > +struct malloc_chunk {<br class=""> > +  size_t               prev_foot;  /* Size of previous chunk (if free).  */<br class=""> > +  size_t               head;       /* Size and inuse bits. */<br class=""> > +  struct malloc_chunk* fd;         /* double links -- used only if free. */<br class=""> > +  struct malloc_chunk* bk;<br class=""> > +};<br class=""> > +<br class=""> > +typedef struct malloc_chunk  mchunk;<br class=""> > +typedef struct malloc_chunk* mchunkptr;<br class=""> > +typedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */<br class=""> > +typedef unsigned int bindex_t;         /* Described below */<br class=""> > +typedef unsigned int binmap_t;         /* Described below */<br class=""> > +typedef unsigned int flag_t;           /* The type of various bit flag sets<br class=""> > */<br class=""> > +<br class=""> > +<br class=""> > +/* ------------------- Chunks sizes and alignments -----------------------<br class=""> > */<br class=""> > +<br class=""> > +#define MCHUNK_SIZE         (sizeof(mchunk))<br class=""> > +<br class=""> > +#if FOOTERS<br class=""> > +#define CHUNK_OVERHEAD      (TWO_SIZE_T_SIZES)<br class=""> > +#else /* FOOTERS */<br class=""> > +#define CHUNK_OVERHEAD      (SIZE_T_SIZE)<br class=""> > +#endif /* FOOTERS */<br class=""> > +<br class=""> > +/* The smallest size we can malloc is an aligned minimal chunk */<br class=""> > +#define MIN_CHUNK_SIZE\<br class=""> > +  ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)<br class=""> > +<br class=""> > +/* conversion from malloc headers to user pointers, and back */<br class=""> > +#define chunk2mem(p)        ((void*)((char*)(p)       + TWO_SIZE_T_SIZES))<br class=""> > +#define mem2chunk(mem)      ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))<br class=""> > +/* chunk associated with aligned address A */<br class=""> > +#define align_as_chunk(A)   (mchunkptr)((A) + align_offset(chunk2mem(A)))<br class=""> > +<br class=""> > +/* Bounds on request (not chunk) sizes. */<br class=""> > +#define MAX_REQUEST         ((-MIN_CHUNK_SIZE) << 2)<br class=""> > +#define MIN_REQUEST         (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)<br class=""> > +<br class=""> > +/* pad request bytes into a usable size */<br class=""> > +#define pad_request(req) \<br class=""> > +   (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)<br class=""> > +<br class=""> > +/* pad request, checking for minimum (but not maximum) */<br class=""> > +#define request2size(req) \<br class=""> > +  (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))<br class=""> > +<br class=""> > +/* ------------------ Operations on head and foot fields -----------------<br class=""> > */<br class=""> > +<br class=""> > +/*<br class=""> > +  The head field of a chunk is or'ed with PINUSE_BIT when previous<br class=""> > +  adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in<br class=""> > +  use. If the chunk was obtained with mmap, the prev_foot field has<br class=""> > +  IS_MMAPPED_BIT set, otherwise holding the offset of the base of the<br class=""> > +  mmapped region to the base of the chunk.<br class=""> > +*/<br class=""> > +<br class=""> > +#define PINUSE_BIT          (SIZE_T_ONE)<br class=""> > +#define CINUSE_BIT          (SIZE_T_TWO)<br class=""> > +#define INUSE_BITS          (PINUSE_BIT|CINUSE_BIT)<br class=""> > +<br class=""> > +/* Head value for fenceposts */<br class=""> > +#define FENCEPOST_HEAD      (INUSE_BITS|SIZE_T_SIZE)<br class=""> > +<br class=""> > +/* extraction of fields from head words */<br class=""> > +#define cinuse(p)           ((p)->head & CINUSE_BIT)<br class=""> > +#define pinuse(p)           ((p)->head & PINUSE_BIT)<br class=""> > +#define chunksize(p)        ((p)->head & ~(INUSE_BITS))<br class=""> > +<br class=""> > +#define clear_pinuse(p)     ((p)->head &= ~PINUSE_BIT)<br class=""> > +#define clear_cinuse(p)     ((p)->head &= ~CINUSE_BIT)<br class=""> > +<br class=""> > +/* Treat space at ptr +/- offset as a chunk */<br class=""> > +#define chunk_plus_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))<br class=""> > +#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))<br class=""> > +<br class=""> > +/* Ptr to next or previous physical malloc_chunk. */<br class=""> > +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head &<br class=""> > ~INUSE_BITS)))<br class=""> > +#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))<br class=""> > +<br class=""> > +/* extract next chunk's pinuse bit */<br class=""> > +#define next_pinuse(p)  ((next_chunk(p)->head) & PINUSE_BIT)<br class=""> > +<br class=""> > +/* Get/set size at footer */<br class=""> > +#define get_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot)<br class=""> > +#define set_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))<br class=""> > +<br class=""> > +/* Set size, pinuse bit, and foot */<br class=""> > +#define set_size_and_pinuse_of_free_chunk(p, s)\<br class=""> > +  ((p)->head = (s|PINUSE_BIT), set_foot(p, s))<br class=""> > +<br class=""> > +/* Set size, pinuse bit, foot, and clear next pinuse */<br class=""> > +#define set_free_with_pinuse(p, s, n)\<br class=""> > +  (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))<br class=""> > +<br class=""> > +/* Get the internal overhead associated with chunk p */<br class=""> > +#define overhead_for(p) CHUNK_OVERHEAD<br class=""> > +<br class=""> > +/* Return true if malloced space is not necessarily cleared */<br class=""> > +#define calloc_must_clear(p) (1)<br class=""> > +<br class=""> > +<br class=""> > +/* ---------------------- Overlaid data structures -----------------------<br class=""> > */<br class=""> > +<br class=""> > +/*<br class=""> > +  When chunks are not in use, they are treated as nodes of either<br class=""> > +  lists or trees.<br class=""> > +<br class=""> > +  "Small"  chunks are stored in circular doubly-linked lists, and look<br class=""> > +  like this:<br class=""> > +<br class=""> > +    chunk-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             Size of previous chunk<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +    `head:' |             Size of chunk, in bytes<br class=""> > |P|<br class=""> > +      mem-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             Forward pointer to next chunk in list<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             Back pointer to previous chunk in list<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             Unused space (may be 0 bytes long)<br class=""> > .<br class=""> > +            .<br class=""> > .<br class=""> > +            .<br class=""> > |<br class=""> > +nextchunk-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +    `foot:' |             Size of chunk, in bytes<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +<br class=""> > +  Larger chunks are kept in a form of bitwise digital trees (aka<br class=""> > +  tries) keyed on chunksizes.  Because malloc_tree_chunks are only for<br class=""> > +  free chunks greater than 256 bytes, their size doesn't impose any<br class=""> > +  constraints on user chunk sizes.  Each node looks like:<br class=""> > +<br class=""> > +    chunk-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             Size of previous chunk<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +    `head:' |             Size of chunk, in bytes<br class=""> > |P|<br class=""> > +      mem-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             Forward pointer to next chunk of same size<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             Back pointer to previous chunk of same size<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             Pointer to left child (child[0])<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             Pointer to right child (child[1])<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             Pointer to parent<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             bin index of this chunk<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +            |             Unused space<br class=""> > .<br class=""> > +            .<br class=""> > |<br class=""> > +nextchunk-><br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +    `foot:' |             Size of chunk, in bytes<br class=""> > |<br class=""> > +<br class=""> > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br class=""> > +<br class=""> > +  Each tree holding treenodes is a tree of unique chunk sizes.  Chunks<br class=""> > +  of the same size are arranged in a circularly-linked list, with only<br class=""> > +  the oldest chunk (the next to be used, in our FIFO ordering)<br class=""> > +  actually in the tree.  (Tree members are distinguished by a non-null<br class=""> > +  parent pointer.)  If a chunk with the same size an an existing node<br class=""> > +  is inserted, it is linked off the existing node using pointers that<br class=""> > +  work in the same way as fd/bk pointers of small chunks.<br class=""> > +<br class=""> > +  Each tree contains a power of 2 sized range of chunk sizes (the<br class=""> > +  smallest is 0x100 <= x < 0x180), which is is divided in half at each<br class=""> > +  tree level, with the chunks in the smaller half of the range (0x100<br class=""> > +  <= x < 0x140 for the top nose) in the left subtree and the larger<br class=""> > +  half (0x140 <= x < 0x180) in the right subtree.  This is, of course,<br class=""> > +  done by inspecting individual bits.<br class=""> > +<br class=""> > +  Using these rules, each node's left subtree contains all smaller<br class=""> > +  sizes than its right subtree.  However, the node at the root of each<br class=""> > +  subtree has no particular ordering relationship to either.  (The<br class=""> > +  dividing line between the subtree sizes is based on trie relation.)<br class=""> > +  If we remove the last chunk of a given size from the interior of the<br class=""> > +  tree, we need to replace it with a leaf node.  The tree ordering<br class=""> > +  rules permit a node to be replaced by any leaf below it.<br class=""> > +<br class=""> > +  The smallest chunk in a tree (a common operation in a best-fit<br class=""> > +  allocator) can be found by walking a path to the leftmost leaf in<br class=""> > +  the tree.  Unlike a usual binary tree, where we follow left child<br class=""> > +  pointers until we reach a null, here we follow the right child<br class=""> > +  pointer any time the left one is null, until we reach a leaf with<br class=""> > +  both child pointers null. The smallest chunk in the tree will be<br class=""> > +  somewhere along that path.<br class=""> > +<br class=""> > +  The worst case number of steps to add, find, or remove a node is<br class=""> > +  bounded by the number of bits differentiating chunks within<br class=""> > +  bins. Under current bin calculations, this ranges from 6 up to 21<br class=""> > +  (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case<br class=""> > +  is of course much better.<br class=""> > +*/<br class=""> > +<br class=""> > +struct malloc_tree_chunk {<br class=""> > +  /* The first four fields must be compatible with malloc_chunk */<br class=""> > +  size_t                    prev_foot;<br class=""> > +  size_t                    head;<br class=""> > +  struct malloc_tree_chunk* fd;<br class=""> > +  struct malloc_tree_chunk* bk;<br class=""> > +<br class=""> > +  struct malloc_tree_chunk* child[2];<br class=""> > +  struct malloc_tree_chunk* parent;<br class=""> > +  bindex_t                  index;<br class=""> > +};<br class=""> > +<br class=""> > +typedef struct malloc_tree_chunk  tchunk;<br class=""> > +typedef struct malloc_tree_chunk* tchunkptr;<br class=""> > +typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */<br class=""> > +<br class=""> > +/* A little helper macro for trees */<br class=""> > +#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] :<br class=""> > (t)->child[1])<br class=""> > +<br class=""> > +/* ----------------------------- Segments --------------------------------<br class=""> > */<br class=""> > +<br class=""> > +/*<br class=""> > +  Each malloc space may include non-contiguous segments, held in a<br class=""> > +  list headed by an embedded malloc_segment record representing the<br class=""> > +  top-most space. Segments also include flags holding properties of<br class=""> > +  the space. Large chunks that are directly allocated by mmap are not<br class=""> > +  included in this list. They are instead independently created and<br class=""> > +  destroyed without otherwise keeping track of them.<br class=""> > +<br class=""> > +  Segment management mainly comes into play for spaces allocated by<br class=""> > +  MMAP.  Any call to MMAP might or might not return memory that is<br class=""> > +  adjacent to an existing segment.  MORECORE normally contiguously<br class=""> > +  extends the current space, so this space is almost always adjacent,<br class=""> > +  which is simpler and faster to deal with. (This is why MORECORE is<br class=""> > +  used preferentially to MMAP when both are available -- see<br class=""> > +  sys_alloc.)  When allocating using MMAP, we don't use any of the<br class=""> > +  hinting mechanisms (inconsistently) supported in various<br class=""> > +  implementations of unix mmap, or distinguish reserving from<br class=""> > +  committing memory. Instead, we just ask for space, and exploit<br class=""> > +  contiguity when we get it.  It is probably possible to do<br class=""> > +  better than this on some systems, but no general scheme seems<br class=""> > +  to be significantly better.<br class=""> > +<br class=""> > +  Management entails a simpler variant of the consolidation scheme<br class=""> > +  used for chunks to reduce fragmentation -- new adjacent memory is<br class=""> > +  normally prepended or appended to an existing segment. However,<br class=""> > +  there are limitations compared to chunk consolidation that mostly<br class=""> > +  reflect the fact that segment processing is relatively infrequent<br class=""> > +  (occurring only when getting memory from system) and that we<br class=""> > +  don't expect to have huge numbers of segments:<br class=""> > +<br class=""> > +  * Segments are not indexed, so traversal requires linear scans.  (It<br class=""> > +    would be possible to index these, but is not worth the extra<br class=""> > +    overhead and complexity for most programs on most platforms.)<br class=""> > +  * New segments are only appended to old ones when holding top-most<br class=""> > +    memory; if they cannot be prepended to others, they are held in<br class=""> > +    different segments.<br class=""> > +<br class=""> > +  Except for the top-most segment of an mstate, each segment record<br class=""> > +  is kept at the tail of its segment. Segments are added by pushing<br class=""> > +  segment records onto the list headed by &mstate.seg for the<br class=""> > +  containing mstate.<br class=""> > +<br class=""> > +  Segment flags control allocation/merge/deallocation policies:<br class=""> > +  * If EXTERN_BIT set, then we did not allocate this segment,<br class=""> > +    and so should not try to deallocate or merge with others.<br class=""> > +    (This currently holds only for the initial segment passed<br class=""> > +    into create_mspace_with_base.)<br class=""> > +  * If IS_MMAPPED_BIT set, the segment may be merged with<br class=""> > +    other surrounding mmapped segments and trimmed/de-allocated<br class=""> > +    using munmap.<br class=""> > +  * If neither bit is set, then the segment was obtained using<br class=""> > +    MORECORE so can be merged with surrounding MORECORE'd segments<br class=""> > +    and deallocated/trimmed using MORECORE with negative arguments.<br class=""> > +*/<br class=""> > +<br class=""> > +struct malloc_segment {<br class=""> > +  char*        base;             /* base address */<br class=""> > +  size_t       size;             /* allocated size */<br class=""> > +  struct malloc_segment* next;   /* ptr to next segment */<br class=""> > +};<br class=""> > +<br class=""> > +typedef struct malloc_segment  msegment;<br class=""> > +typedef struct malloc_segment* msegmentptr;<br class=""> > +<br class=""> > +/* ---------------------------- malloc_state -----------------------------<br class=""> > */<br class=""> > +<br class=""> > +/*<br class=""> > +   A malloc_state holds all of the bookkeeping for a space.<br class=""> > +   The main fields are:<br class=""> > +<br class=""> > +  Top<br class=""> > +    The topmost chunk of the currently active segment. Its size is<br class=""> > +    cached in topsize.  The actual size of topmost space is<br class=""> > +    topsize+TOP_FOOT_SIZE, which includes space reserved for adding<br class=""> > +    fenceposts and segment records if necessary when getting more<br class=""> > +    space from the system.  The size at which to autotrim top is<br class=""> > +    cached from mparams in trim_check, except that it is disabled if<br class=""> > +    an autotrim fails.<br class=""> > +<br class=""> > +  Designated victim (dv)<br class=""> > +    This is the preferred chunk for servicing small requests that<br class=""> > +    don't have exact fits.  It is normally the chunk split off most<br class=""> > +    recently to service another small request.  Its size is cached in<br class=""> > +    dvsize. The link fields of this chunk are not maintained since it<br class=""> > +    is not kept in a bin.<br class=""> > +<br class=""> > +  SmallBins<br class=""> > +    An array of bin headers for free chunks.  These bins hold chunks<br class=""> > +    with sizes less than MIN_LARGE_SIZE bytes. Each bin contains<br class=""> > +    chunks of all the same size, spaced 8 bytes apart.  To simplify<br class=""> > +    use in double-linked lists, each bin header acts as a malloc_chunk<br class=""> > +    pointing to the real first node, if it exists (else pointing to<br class=""> > +    itself).  This avoids special-casing for headers.  But to avoid<br class=""> > +    waste, we allocate only the fd/bk pointers of bins, and then use<br class=""> > +    repositioning tricks to treat these as the fields of a chunk.<br class=""> > +<br class=""> > +  TreeBins<br class=""> > +    Treebins are pointers to the roots of trees holding a range of<br class=""> > +    sizes. There are 2 equally spaced treebins for each power of two<br class=""> > +    from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything<br class=""> > +    larger.<br class=""> > +<br class=""> > +  Bin maps<br class=""> > +    There is one bit map for small bins ("smallmap") and one for<br class=""> > +    treebins ("treemap).  Each bin sets its bit when non-empty, and<br class=""> > +    clears the bit when empty.  Bit operations are then used to avoid<br class=""> > +    bin-by-bin searching -- nearly all "search" is done without ever<br class=""> > +    looking at bins that won't be selected.  The bit maps<br class=""> > +    conservatively use 32 bits per map word, even if on 64bit system.<br class=""> > +    For a good description of some of the bit-based techniques used<br class=""> > +    here, see Henry S. Warren Jr's book "Hacker's Delight" (and<br class=""> > +    supplement at <a href="http://hackersdelight.org/" rel="noreferrer" target="_blank" data-mce-href="http://hackersdelight.org/" class="">http://hackersdelight.org/</a>). Many of these are<br class=""> > +    intended to reduce the branchiness of paths through malloc etc, as<br class=""> > +    well as to reduce the number of memory locations read or written.<br class=""> > +<br class=""> > +  Segments<br class=""> > +    A list of segments headed by an embedded malloc_segment record<br class=""> > +    representing the initial space.<br class=""> > +<br class=""> > +  Address check support<br class=""> > +    The least_addr field is the least address ever obtained from<br class=""> > +    MORECORE or MMAP. Attempted frees and reallocs of any address less<br class=""> > +    than this are trapped (unless INSECURE is defined).<br class=""> > +<br class=""> > +  Magic tag<br class=""> > +    A cross-check field that should always hold same value as mparams.magic.<br class=""> > +<br class=""> > +  Flags<br class=""> > +    Bits recording whether to use MMAP, locks, or contiguous MORECORE<br class=""> > +<br class=""> > +  Statistics<br class=""> > +    Each space keeps track of current and maximum system memory<br class=""> > +    obtained via MORECORE or MMAP.<br class=""> > +<br class=""> > +  Locking<br class=""> > +    If USE_LOCKS is defined, the "mutex" lock is acquired and released<br class=""> > +    around every public call using this mspace.<br class=""> > +*/<br class=""> > +<br class=""> > +/* Bin types, widths and sizes */<br class=""> > +#define NSMALLBINS        (32U)<br class=""> > +#define NTREEBINS         (32U)<br class=""> > +#define SMALLBIN_SHIFT    (3U)<br class=""> > +#define SMALLBIN_WIDTH    (SIZE_T_ONE << SMALLBIN_SHIFT)<br class=""> > +#define TREEBIN_SHIFT     (8U)<br class=""> > +#define MIN_LARGE_SIZE    (SIZE_T_ONE << TREEBIN_SHIFT)<br class=""> > +#define MAX_SMALL_SIZE    (MIN_LARGE_SIZE - SIZE_T_ONE)<br class=""> > +#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK -<br class=""> > CHUNK_OVERHEAD)<br class=""> > +<br class=""> > +struct malloc_state {<br class=""> > +  binmap_t   smallmap;<br class=""> > +  binmap_t   treemap;<br class=""> > +  size_t     dvsize;<br class=""> > +  size_t     topsize;<br class=""> > +  char*      least_addr;<br class=""> > +  mchunkptr  dv;<br class=""> > +  mchunkptr  top;<br class=""> > +  size_t     magic;<br class=""> > +  mchunkptr  smallbins[(NSMALLBINS+1)*2];<br class=""> > +  tbinptr    treebins[NTREEBINS];<br class=""> > +  size_t     footprint;<br class=""> > +  size_t     max_footprint;<br class=""> > +  flag_t     mflags;<br class=""> > +  void      *user_data;<br class=""> > +#if USE_LOCKS<br class=""> > +  MLOCK_T    mutex;     /* locate lock among fields that rarely change */<br class=""> > +#endif /* USE_LOCKS */<br class=""> > +  msegment   seg;<br class=""> > +};<br class=""> > +<br class=""> > +typedef struct malloc_state*    mstate;<br class=""> > +<br class=""> > +/* ------------- Global malloc_state and malloc_params -------------------<br class=""> > */<br class=""> > +<br class=""> > +/*<br class=""> > +  malloc_params holds global properties, including those that can be<br class=""> > +  dynamically set using mallopt. There is a single instance, mparams,<br class=""> > +  initialized in init_mparams.<br class=""> > +*/<br class=""> > +<br class=""> > +struct malloc_params {<br class=""> > +  size_t magic;<br class=""> > +  size_t page_size;<br class=""> > +  size_t granularity;<br class=""> > +  flag_t default_mflags;<br class=""> > +};<br class=""> > +<br class=""> > +static struct malloc_params mparams;<br class=""> > +<br class=""> > +/* The global malloc_state used for all non-"mspace" calls */<br class=""> > +//static struct malloc_state _gm_;<br class=""> > +//#define gm                 (&_gm_)<br class=""> > +//#define is_global(M)       ((M) == &_gm_)<br class=""> > +#define is_initialized(M)  ((M)->top != 0)<br class=""> > +<br class=""> > +/* -------------------------- system alloc setup -------------------------<br class=""> > */<br class=""> > +<br class=""> > +/* Operations on mflags */<br class=""> > +<br class=""> > +#define use_lock(M)           ((M)->mflags &   USE_LOCK_BIT)<br class=""> > +#define enable_lock(M)        ((M)->mflags |=  USE_LOCK_BIT)<br class=""> > +#define disable_lock(M)       ((M)->mflags &= ~USE_LOCK_BIT)<br class=""> > +<br class=""> > +#define set_lock(M,L)\<br class=""> > + ((M)->mflags = (L)?\<br class=""> > +  ((M)->mflags | USE_LOCK_BIT) :\<br class=""> > +  ((M)->mflags & ~USE_LOCK_BIT))<br class=""> > +<br class=""> > +/* page-align a size */<br class=""> > +#define page_align(S)\<br class=""> > + (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))<br class=""> > +<br class=""> > +/* granularity-align a size */<br class=""> > +#define granularity_align(S)\<br class=""> > +  (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))<br class=""> > +<br class=""> > +#define is_page_aligned(S)\<br class=""> > +   (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)<br class=""> > +#define is_granularity_aligned(S)\<br class=""> > +   (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)<br class=""> > +<br class=""> > +/*  True if segment S holds address A */<br class=""> > +#define segment_holds(S, A)\<br class=""> > +  ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)<br class=""> > +<br class=""> > +/* Return segment holding given address */<br class=""> > +static msegmentptr segment_holding(mstate m, char* addr) {<br class=""> > +  msegmentptr sp = &m->seg;<br class=""> > +  for (;;) {<br class=""> > +    if (addr >= sp->base && addr < sp->base + sp->size)<br class=""> > +      return sp;<br class=""> > +    if ((sp = sp->next) == 0)<br class=""> > +      return 0;<br class=""> > +  }<br class=""> > +}<br class=""> > +<br class=""> > +/* Return true if segment contains a segment link */<br class=""> > +static int has_segment_link(mstate m, msegmentptr ss) {<br class=""> > +  msegmentptr sp = &m->seg;<br class=""> > +  for (;;) {<br class=""> > +    if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)<br class=""> > +      return 1;<br class=""> > +    if ((sp = sp->next) == 0)<br class=""> > +      return 0;<br class=""> > +  }<br class=""> > +}<br class=""> > +<br class=""> > +<br class=""> > +<br class=""> > +/*<br class=""> > +  TOP_FOOT_SIZE is padding at the end of a segment, including space<br class=""> > +  that may be needed to place segment records and fenceposts when new<br class=""> > +  noncontiguous segments are added.<br class=""> > +*/<br class=""> > +#define TOP_FOOT_SIZE\<br class=""> > +  (align_offset(chunk2mem(0))+pad_request(sizeof(struct<br class=""> > malloc_segment))+MIN_CHUNK_SIZE)<br class=""> > +<br class=""> > +<br class=""> > +/* -------------------------------  Hooks --------------------------------<br class=""> > */<br class=""> > +<br class=""> > +/*<br class=""> > +  PREACTION should be defined to return 0 on success, and nonzero on<br class=""> > +  failure. If you are not using locking, you can redefine these to do<br class=""> > +  anything you like.<br class=""> > +*/<br class=""> > +<br class=""> > +#if USE_LOCKS<br class=""> > +<br class=""> > +/* Ensure locks are initialized */<br class=""> > +#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())<br class=""> > +<br class=""> > +#define PREACTION(M)  ((GLOBALLY_INITIALIZE() || use_lock(M))?<br class=""> > ACQUIRE_LOCK(&(M)->mutex) : 0)<br class=""> > +#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }<br class=""> > +#else /* USE_LOCKS */<br class=""> > +<br class=""> > +#ifndef PREACTION<br class=""> > +#define PREACTION(M) (0)<br class=""> > +#endif  /* PREACTION */<br class=""> > +<br class=""> > +#ifndef POSTACTION<br class=""> > +#define POSTACTION(M)<br class=""> > +#endif  /* POSTACTION */<br class=""> > +<br class=""> > +#endif /* USE_LOCKS */<br class=""> > +<br class=""> > +/*<br class=""> > +  CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.<br class=""> > +  USAGE_ERROR_ACTION is triggered on detected bad frees and<br class=""> > +  reallocs. The argument p is an address that might have triggered the<br class=""> > +  fault. It is ignored by the two predefined actions, but might be<br class=""> > +  useful in custom actions that try to help diagnose errors.<br class=""> > +*/<br class=""> > +<br class=""> > +#if PROCEED_ON_ERROR<br class=""> > +<br class=""> > +/* A count of the number of corruption errors causing resets */<br class=""> > +int malloc_corruption_error_count;<br class=""> > +<br class=""> > +/* default corruption action */<br class=""> > +static void reset_on_error(mstate m);<br class=""> > +<br class=""> > +#define CORRUPTION_ERROR_ACTION(m)  reset_on_error(m)<br class=""> > +#define USAGE_ERROR_ACTION(m, p)<br class=""> > +<br class=""> > +#else /* PROCEED_ON_ERROR */<br class=""> > +<br class=""> > +#ifndef CORRUPTION_ERROR_ACTION<br class=""> > +#define CORRUPTION_ERROR_ACTION(m) ABORT(m->user_data)<br class=""> > +#endif /* CORRUPTION_ERROR_ACTION */<br class=""> > +<br class=""> > +#ifndef USAGE_ERROR_ACTION<br class=""> > +#define USAGE_ERROR_ACTION(m,p) ABORT(m->user_data)<br class=""> > +#endif /* USAGE_ERROR_ACTION */<br class=""> > +<br class=""> > +#endif /* PROCEED_ON_ERROR */<br class=""> > +<br class=""> > +/* -------------------------- Debugging setup ----------------------------<br class=""> > */<br class=""> > +<br class=""> > +#if ! DEBUG<br class=""> > +<br class=""> > +#define check_free_chunk(M,P)<br class=""> > +#define check_inuse_chunk(M,P)<br class=""> > +#define check_malloced_chunk(M,P,N)<br class=""> > +#define check_malloc_state(M)<br class=""> > +#define check_top_chunk(M,P)<br class=""> > +<br class=""> > +#else /* DEBUG */<br class=""> > +#define check_free_chunk(M,P)       do_check_free_chunk(M,P)<br class=""> > +#define check_inuse_chunk(M,P)      do_check_inuse_chunk(M,P)<br class=""> > +#define check_top_chunk(M,P)        do_check_top_chunk(M,P)<br class=""> > +#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)<br class=""> > +#define check_malloc_state(M)       do_check_malloc_state(M)<br class=""> > +<br class=""> > +static void   do_check_any_chunk(mstate m, mchunkptr p);<br class=""> > +static void   do_check_top_chunk(mstate m, mchunkptr p);<br class=""> > +static void   do_check_inuse_chunk(mstate m, mchunkptr p);<br class=""> > +static void   do_check_free_chunk(mstate m, mchunkptr p);<br class=""> > +static void   do_check_malloced_chunk(mstate m, void* mem, size_t s);<br class=""> > +static void   do_check_tree(mstate m, tchunkptr t);<br class=""> > +static void   do_check_treebin(mstate m, bindex_t i);<br class=""> > +static void   do_check_smallbin(mstate m, bindex_t i);<br class=""> > +static void   do_check_malloc_state(mstate m);<br class=""> > +static int    bin_find(mstate m, mchunkptr x);<br class=""> > +static size_t traverse_and_check(mstate m);<br class=""> > +#endif /* DEBUG */<br class=""> > +<br class=""> > +/* ---------------------------- Indexing Bins ----------------------------<br class=""> > */<br class=""> > +<br class=""> > +#define is_small(s)         (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)<br class=""> > +#define small_index(s)      ((s)  >> SMALLBIN_SHIFT)<br class=""> > +#define small_index2size(i) ((i)  << SMALLBIN_SHIFT)<br class=""> > +#define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))<br class=""> > +<br class=""> > +/* addressing by index. See above about smallbin repositioning */<br class=""> > +#define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))<br class=""> > +#define treebin_at(M,i)     (&((M)->treebins[i]))<br class=""> > +<br class=""> > +/* assign tree index for size S to variable I */<br class=""> > +#if defined(__GNUC__) && defined(i386)<br class=""> > +#define compute_tree_index(S, I)\<br class=""> > +{\<br class=""> > +  size_t X = S >> TREEBIN_SHIFT;\<br class=""> > +  if (X == 0)\<br class=""> > +    I = 0;\<br class=""> > +  else if (X > 0xFFFF)\<br class=""> > +    I = NTREEBINS-1;\<br class=""> > +  else {\<br class=""> > +    unsigned int K;\<br class=""> > +    __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm"  (X));\<br class=""> > +    I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\<br class=""> > +  }\<br class=""> > +}<br class=""> > +#else /* GNUC */<br class=""> > +#define compute_tree_index(S, I)\<br class=""> > +{\<br class=""> > +  size_t X = S >> TREEBIN_SHIFT;\<br class=""> > +  if (X == 0)\<br class=""> > +    I = 0;\<br class=""> > +  else if (X > 0xFFFF)\<br class=""> > +    I = NTREEBINS-1;\<br class=""> > +  else {\<br class=""> > +    unsigned int Y = (unsigned int)X;\<br class=""> > +    unsigned int N = ((Y - 0x100) >> 16) & 8;\<br class=""> > +    unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\<br class=""> > +    N += K;\<br class=""> > +    N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\<br class=""> > +    K = 14 - N + ((Y <<= K) >> 15);\<br class=""> > +    I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\<br class=""> > +  }\<br class=""> > +}<br class=""> > +#endif /* GNUC */<br class=""> > +<br class=""> > +/* Bit representing maximum resolved size in a treebin at i */<br class=""> > +#define bit_for_tree_index(i) \<br class=""> > +   (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)<br class=""> > +<br class=""> > +/* Shift placing maximum resolved bit in a treebin at i as sign bit */<br class=""> > +#define leftshift_for_tree_index(i) \<br class=""> > +   ((i == NTREEBINS-1)? 0 : \<br class=""> > +    ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))<br class=""> > +<br class=""> > +/* The size of the smallest chunk held in bin with index i */<br class=""> > +#define minsize_for_tree_index(i) \<br class=""> > +   ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) |  \<br class=""> > +   (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))<br class=""> > +<br class=""> > +/* ------------------------ Operations on bin maps -----------------------<br class=""> > */<br class=""> > +<br class=""> > +/* bit corresponding to given index */<br class=""> > +#define idx2bit(i)              ((binmap_t)(1) << (i))<br class=""> > +<br class=""> > +/* Mark/Clear bits with given index */<br class=""> > +#define mark_smallmap(M,i)      ((M)->smallmap |=  idx2bit(i))<br class=""> > +#define clear_smallmap(M,i)     ((M)->smallmap &= ~idx2bit(i))<br class=""> > +#define smallmap_is_marked(M,i) ((M)->smallmap &   idx2bit(i))<br class=""> > +<br class=""> > +#define mark_treemap(M,i)       ((M)->treemap  |=  idx2bit(i))<br class=""> > +#define clear_treemap(M,i)      ((M)->treemap  &= ~idx2bit(i))<br class=""> > +#define treemap_is_marked(M,i)  ((M)->treemap  &   idx2bit(i))<br class=""> > +<br class=""> > +/* index corresponding to given bit */<br class=""> > +<br class=""> > +#if defined(__GNUC__) && defined(i386)<br class=""> > +#define compute_bit2idx(X, I)\<br class=""> > +{\<br class=""> > +  unsigned int J;\<br class=""> > +  __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\<br class=""> > +  I = (bindex_t)J;\<br class=""> > +}<br class=""> > +<br class=""> > +#else /* GNUC */<br class=""> > +#if  USE_BUILTIN_FFS<br class=""> > +#define compute_bit2idx(X, I) I = ffs(X)-1<br class=""> > +<br class=""> > +#else /* USE_BUILTIN_FFS */<br class=""> > +#define compute_bit2idx(X, I)\<br class=""> > +{\<br class=""> > +  unsigned int Y = X - 1;\<br class=""> > +  unsigned int K = Y >> (16-4) & 16;\<br class=""> > +  unsigned int N = K;        Y >>= K;\<br class=""> > +  N += K = Y >> (8-3) &  8;  Y >>= K;\<br class=""> > +  N += K = Y >> (4-2) &  4;  Y >>= K;\<br class=""> > +  N += K = Y >> (2-1) &  2;  Y >>= K;\<br class=""> > +  N += K = Y >> (1-0) &  1;  Y >>= K;\<br class=""> > +  I = (bindex_t)(N + Y);\<br class=""> > +}<br class=""> > +#endif /* USE_BUILTIN_FFS */<br class=""> > +#endif /* GNUC */<br class=""> > +<br class=""> > +/* isolate the least set bit of a bitmap */<br class=""> > +#define least_bit(x)         ((x) & -(x))<br class=""> > +<br class=""> > +/* mask with all bits to left of least bit of x on */<br class=""> > +#define left_bits(x)         ((x<<1) | -(x<<1))<br class=""> > +<br class=""> > +/* mask with all bits to left of or equal to least bit of x on */<br class=""> > +#define same_or_left_bits(x) ((x) | -(x))<br class=""> > +<br class=""> > +<br class=""> > +/* ----------------------- Runtime Check Support -------------------------<br class=""> > */<br class=""> > +<br class=""> > +/*<br class=""> > +  For security, the main invariant is that malloc/free/etc never<br class=""> > +  writes to a static address other than malloc_state, unless static<br class=""> > +  malloc_state itself has been corrupted, which cannot occur via<br class=""> > +  malloc (because of these checks). In essence this means that we<br class=""> > +  believe all pointers, sizes, maps etc held in malloc_state, but<br class=""> > +  check all of those linked or offsetted from other embedded data<br class=""> > +  structures.  These checks are interspersed with main code in a way<br class=""> > +  that tends to minimize their run-time cost.<br class=""> > +<br class=""> > +  When FOOTERS is defined, in addition to range checking, we also<br class=""> > +  verify footer fields of inuse chunks, which can be used guarantee<br class=""> > +  that the mstate controlling malloc/free is intact.  This is a<br class=""> > +  streamlined version of the approach described by William Robertson<br class=""> > +  et al in "Run-time Detection of Heap-based Overflows" LISA'03<br class=""> > +  <a href="http://www.usenix.org/events/lisa03/tech/robertson.html" rel="noreferrer" target="_blank" data-mce-href="http://www.usenix.org/events/lisa03/tech/robertson.html" class="">http://www.usenix.org/events/lisa03/tech/robertson.html</a> The footer<br class=""> > +  of an inuse chunk holds the xor of its mstate and a random seed,<br class=""> > +  that is checked upon calls to free() and realloc().  This is<br class=""> > +  (probablistically) unguessable from outside the program, but can be<br class=""> > +  computed by any code successfully malloc'ing any chunk, so does not<br class=""> > +  itself provide protection against code that has already broken<br class=""> > +  security through some other means.  Unlike Robertson et al, we<br class=""> > +  always dynamically check addresses of all offset chunks (previous,<br class=""> > +  next, etc). This turns out to be cheaper than relying on hashes.<br class=""> > +*/<br class=""> > +<br class=""> > +#if !INSECURE<br class=""> > +/* Check if address a is at least as high as any from MORECORE or MMAP */<br class=""> > +#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)<br class=""> > +/* Check if address of next chunk n is higher than base chunk p */<br class=""> > +#define ok_next(p, n)    ((char*)(p) < (char*)(n))<br class=""> > +/* Check if p has its cinuse bit on */<br class=""> > +#define ok_cinuse(p)     cinuse(p)<br class=""> > +/* Check if p has its pinuse bit on */<br class=""> > +#define ok_pinuse(p)     pinuse(p)<br class=""> > +<br class=""> > +#else /* !INSECURE */<br class=""> > +#define ok_address(M, a) (1)<br class=""> > +#define ok_next(b, n)    (1)<br class=""> > +#define ok_cinuse(p)     (1)<br class=""> > +#define ok_pinuse(p)     (1)<br class=""> > +#endif /* !INSECURE */<br class=""> > +<br class=""> > +#if (FOOTERS && !INSECURE)<br class=""> > +/* Check if (alleged) mstate m has expected magic field */<br class=""> > +#define ok_magic(M)      ((M)->magic == mparams.magic)<br class=""> > +#else  /* (FOOTERS && !INSECURE) */<br class=""> > +#define ok_magic(M)      (1)<br class=""> > +#endif /* (FOOTERS && !INSECURE) */<br class=""> > +<br class=""> > +<br class=""> > +/* In gcc, use __builtin_expect to minimize impact of checks */<br class=""> > +#if !INSECURE<br class=""> > +#if defined(__GNUC__) && __GNUC__ >= 3<br class=""> > +#define RTCHECK(e)  __builtin_expect(e, 1)<br class=""> > +#else /* GNUC */<br class=""> > +#define RTCHECK(e)  (e)<br class=""> > +#endif /* GNUC */<br class=""> > +#else /* !INSECURE */<br class=""> > +#define RTCHECK(e)  (1)<br class=""> > +#endif /* !INSECURE */<br class=""> > +<br class=""> > +/* macros to set up inuse chunks with or without footers */<br class=""> > +<br class=""> > +#if !FOOTERS<br class=""> > +<br class=""> > +#define mark_inuse_foot(M,p,s)<br class=""> > +<br class=""> > +/* Set cinuse bit and pinuse bit of next chunk */<br class=""> > +#define set_inuse(M,p,s)\<br class=""> > +  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\<br class=""> > +  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)<br class=""> > +<br class=""> > +/* Set cinuse and pinuse of this chunk and pinuse of next chunk */<br class=""> > +#define set_inuse_and_pinuse(M,p,s)\<br class=""> > +  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\<br class=""> > +  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)<br class=""> > +<br class=""> > +/* Set size, cinuse and pinuse bit of this chunk */<br class=""> > +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\<br class=""> > +  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))<br class=""> > +<br class=""> > +#else /* FOOTERS */<br class=""> > +<br class=""> > +/* Set foot of inuse chunk to be xor of mstate and seed */<br class=""> > +#define mark_inuse_foot(M,p,s)\<br class=""> > +  (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^<br class=""> > mparams.magic))<br class=""> > +<br class=""> > +#define get_mstate_for(p)\<br class=""> > +  ((mstate)(((mchunkptr)((char*)(p) +\<br class=""> > +    (chunksize(p))))->prev_foot ^ mparams.magic))<br class=""> > +<br class=""> > +#define set_inuse(M,p,s)\<br class=""> > +  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\<br class=""> > +  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \<br class=""> > +  mark_inuse_foot(M,p,s))<br class=""> > +<br class=""> > +#define set_inuse_and_pinuse(M,p,s)\<br class=""> > +  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\<br class=""> > +  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\<br class=""> > + mark_inuse_foot(M,p,s))<br class=""> > +<br class=""> > +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\<br class=""> > +  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\<br class=""> > +  mark_inuse_foot(M, p, s))<br class=""> > +<br class=""> > +#endif /* !FOOTERS */<br class=""> > +<br class=""> > +/* ---------------------------- setting mparams --------------------------<br class=""> > */<br class=""> > +<br class=""> > +/* Initialize mparams */<br class=""> > +static int init_mparams(void) {<br class=""> > +  if (mparams.page_size == 0) {<br class=""> > +    size_t s;<br class=""> > +<br class=""> > +    mparams.default_mflags = USE_LOCK_BIT;<br class=""> > +<br class=""> > +#if (FOOTERS && !INSECURE)<br class=""> > +    {<br class=""> > +#if USE_DEV_RANDOM<br class=""> > +      int fd;<br class=""> > +      unsigned char buf[sizeof(size_t)];<br class=""> > +      /* Try to use /dev/urandom, else fall back on using time */<br class=""> > +      if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&<br class=""> > +          read(fd, buf, sizeof(buf)) == sizeof(buf)) {<br class=""> > +        s = *((size_t *) buf);<br class=""> > +        close(fd);<br class=""> > +      }<br class=""> > +      else<br class=""> > +#endif /* USE_DEV_RANDOM */<br class=""> > +        s = (size_t)(time(0) ^ (size_t)0x55555555U);<br class=""> > +<br class=""> > +      s |= (size_t)8U;    /* ensure nonzero */<br class=""> > +      s &= ~(size_t)7U;   /* improve chances of fault for bad values */<br class=""> > +<br class=""> > +    }<br class=""> > +#else /* (FOOTERS && !INSECURE) */<br class=""> > +    s = (size_t)0x58585858U;<br class=""> > +#endif /* (FOOTERS && !INSECURE) */<br class=""> > +    ACQUIRE_MAGIC_INIT_LOCK();<br class=""> > +    if (mparams.magic == 0) {<br class=""> > +      mparams.magic = s;<br class=""> > +      /* Set up lock for main malloc area */<br class=""> > +      //INITIAL_LOCK(&gm->mutex);<br class=""> > +      //gm->mflags = mparams.default_mflags;<br class=""> > +    }<br class=""> > +    RELEASE_MAGIC_INIT_LOCK();<br class=""> > +<br class=""> > +<br class=""> > +    mparams.page_size = malloc_getpagesize;<br class=""> > +    mparams.granularity = ((DEFAULT_GRANULARITY != 0)?<br class=""> > +                           DEFAULT_GRANULARITY : mparams.page_size);<br class=""> > +<br class=""> > +    /* Sanity-check configuration:<br class=""> > +       size_t must be unsigned and as wide as pointer type.<br class=""> > +       ints must be at least 4 bytes.<br class=""> > +       alignment must be at least 8.<br class=""> > +       Alignment, min chunk size, and page size must all be powers of 2.<br class=""> > +    */<br class=""> > +    if ((sizeof(size_t) != sizeof(char*)) ||<br class=""> > +        (MAX_SIZE_T < MIN_CHUNK_SIZE)  ||<br class=""> > +        (sizeof(int) < 4)  ||<br class=""> > +        (MALLOC_ALIGNMENT < (size_t)8U) ||<br class=""> > +        ((MALLOC_ALIGNMENT    & (MALLOC_ALIGNMENT-SIZE_T_ONE))    != 0) ||<br class=""> > +        ((MCHUNK_SIZE         & (MCHUNK_SIZE-SIZE_T_ONE))         != 0) ||<br class=""> > +        ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||<br class=""> > +        ((mparams.page_size   & (mparams.page_size-SIZE_T_ONE))   != 0))<br class=""> > +      ABORT(NULL);<br class=""> > +  }<br class=""> > +  return 0;<br class=""> > +}<br class=""> > +<br class=""> > +/* support for mallopt */<br class=""> > +static int change_mparam(int param_number, int value) {<br class=""> > +  size_t val = (size_t)value;<br class=""> > +  init_mparams();<br class=""> > +  switch(param_number) {<br class=""> > +  case M_GRANULARITY:<br class=""> > +    if (val >= mparams.page_size && ((val & (val-1)) == 0)) {<br class=""> > +      mparams.granularity = val;<br class=""> > +      return 1;<br class=""> > +    }<br class=""> > +    else<br class=""> > +      return 0;<br class=""> > +  default:<br class=""> > +    return 0;<br class=""> > +  }<br class=""> > +}<br class=""> > +<br class=""> > +#if DEBUG<br class=""> > +/* ------------------------- Debugging Support ---------------------------<br class=""> > */<br class=""> > +<br class=""> > +/* Check properties of any chunk, whether free, inuse, mmapped etc  */<br class=""> > +static void do_check_any_chunk(mstate m, mchunkptr p) {<br class=""> > +  assert(m->user_data, (is_aligned(chunk2mem(p))) || (p->head ==<br class=""> > FENCEPOST_HEAD));<br class=""> > +  assert(m->user_data, ok_address(m, p));<br class=""> > +}<br class=""> > +<br class=""> > +/* Check properties of top chunk */<br class=""> > +static void do_check_top_chunk(mstate m, mchunkptr p) {<br class=""> > +  msegmentptr sp = segment_holding(m, (char*)p);<br class=""> > +  size_t  sz = chunksize(p);<br class=""> > +  assert(m->user_data, sp != 0);<br class=""> > +  assert(m->user_data, (is_aligned(chunk2mem(p))) || (p->head ==<br class=""> > FENCEPOST_HEAD));<br class=""> > +  assert(m->user_data, ok_address(m, p));<br class=""> > +  assert(m->user_data, sz == m->topsize);<br class=""> > +  assert(m->user_data, sz > 0);<br class=""> > +  assert(m->user_data, sz == ((sp->base + sp->size) - (char*)p) -<br class=""> > TOP_FOOT_SIZE);<br class=""> > +  assert(m->user_data, pinuse(p));<br class=""> > +  assert(m->user_data, !next_pinuse(p));<br class=""> > +}<br class=""> > +<br class=""> > +/* Check properties of inuse chunks */<br class=""> > +static void do_check_inuse_chunk(mstate m, mchunkptr p) {<br class=""> > +  do_check_any_chunk(m, p);<br class=""> > +  assert(m->user_data, cinuse(p));<br class=""> > +  assert(m->user_data, next_pinuse(p));<br class=""> > +  /* If not pinuse, previous chunk has OK offset */<br class=""> > +  assert(m->user_data, pinuse(p) || next_chunk(prev_chunk(p)) == p);<br class=""> > +}<br class=""> > +<br class=""> > +/* Check properties of free chunks */<br class=""> > +static void do_check_free_chunk(mstate m, mchunkptr p) {<br class=""> > +  size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);<br class=""> > +  mchunkptr next = chunk_plus_offset(p, sz);<br class=""> > +  do_check_any_chunk(m, p);<br class=""> > +  assert(m->user_data, !cinuse(p));<br class=""> > +  assert(m->user_data, !next_pinuse(p));<br class=""> > +  if (p != m->dv && p != m->top) {<br class=""> > +    if (sz >= MIN_CHUNK_SIZE) {<br class=""> > +      assert(m->user_data, (sz & CHUNK_ALIGN_MASK) == 0);<br class=""> > +      assert(m->user_data, is_aligned(chunk2mem(p)));<br class=""> > +      assert(m->user_data, next->prev_foot == sz);<br class=""> > +      assert(m->user_data, pinuse(p));<br class=""> > +      assert(m->user_data, next == m->top || cinuse(next));<br class=""> > +      assert(m->user_data, p->fd->bk == p);<br class=""> > +      assert(m->user_data, p->bk->fd == p);<br class=""> > +    }<br class=""> > +    else  /* markers are always of size SIZE_T_SIZE */<br class=""> > +      assert(m->user_data, sz == SIZE_T_SIZE);<br class=""> > +  }<br class=""> > +}<br class=""> > +<br class=""> > +/* Check properties of malloced chunks at the point they are malloced */<br class=""> > +static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {<br class=""> > +  if (mem != 0) {<br class=""> > +    mchunkptr p = mem2chunk(mem);<br class=""> > +    size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);<br class=""> > +    do_check_inuse_chunk(m, p);<br class=""> > +    assert(m->user_data, (sz & CHUNK_ALIGN_MASK) == 0);<br class=""> > +    assert(m->user_data, sz >= MIN_CHUNK_SIZE);<br class=""> > +    assert(m->user_data, sz >= s);<br class=""> > +    /* size is less than MIN_CHUNK_SIZE more than request */<br class=""> > +    assert(m->user_data, sz < (s + MIN_CHUNK_SIZE));<br class=""> > +  }<br class=""> > +}<br class=""> > +<br class=""> > +/* Check a tree and its subtrees.  */<br class=""> > +static void do_check_tree(mstate m, tchunkptr t) {<br class=""> > +  tchunkptr head = 0;<br class=""> > +  tchunkptr u = t;<br class=""> > +  bindex_t tindex = t->index;<br class=""> > +  size_t tsize = chunksize(t);<br class=""> > +  bindex_t idx;<br class=""> > +  compute_tree_index(tsize, idx);<br class=""> > +  assert(m->user_data, tindex == idx);<br class=""> > +  assert(m->user_data, tsize >= MIN_LARGE_SIZE);<br class=""> > +  assert(m->user_data, tsize >= minsize_for_tree_index(idx));<br class=""> > +  assert(m->user_data, (idx == NTREEBINS-1) || (tsize <<br class=""> > minsize_for_tree_index((idx+1))));<br class=""> > +<br class=""> > +  do { /* traverse through chain of same-sized nodes */<br class=""> > +    do_check_any_chunk(m, ((mchunkptr)u));<br class=""> > +    assert(m->user_data, u->index == tindex);<br class=""> > +    assert(m->user_data, chunksize(u) == tsize);<br class=""> > +    assert(m->user_data, !cinuse(u));<br class=""> > +    assert(m->user_data, !next_pinuse(u));<br class=""> > +    assert(m->user_data, u->fd->bk == u);<br class=""> > +    assert(m->user_data, u->bk->fd == u);<br class=""> > +    if (u->parent == 0) {<br class=""> > +      assert(m->user_data, u->child[0] == 0);<br class=""> > +      assert(m->user_data, u->child[1] == 0);<br class=""> > +    }<br class=""> > +    else {<br class=""> > +      assert(m->user_data, head == 0); /* only one node on chain has parent<br class=""> > */<br class=""> > +      head = u;<br class=""> > +      assert(m->user_data, u->parent != u);<br class=""> > +      assert(m->user_data, u->parent->child[0] == u ||<br class=""> > +             u->parent->child[1] == u ||<br class=""> > +             *((tbinptr*)(u->parent)) == u);<br class=""> > +      if (u->child[0] != 0) {<br class=""> > +        assert(m->user_data, u->child[0]->parent == u);<br class=""> > +        assert(m->user_data, u->child[0] != u);<br class=""> > +        do_check_tree(m, u->child[0]);<br class=""> > +      }<br class=""> > +      if (u->child[1] != 0) {<br class=""> > +        assert(m->user_data, u->child[1]->parent == u);<br class=""> > +        assert(m->user_data, u->child[1] != u);<br class=""> > +        do_check_tree(m, u->child[1]);<br class=""> > +      }<br class=""> > +      if (u->child[0] != 0 && u->child[1] != 0) {<br class=""> > +        assert(m->user_data, chunksize(u->child[0]) <<br class=""> > chunksize(u->child[1]));<br class=""> > +      }<br class=""> > +    }<br class=""> > +    u = u->fd;<br class=""> > +  } while (u != t);<br class=""> > +  assert(m->user_data, head != 0);<br class=""> > +}<br class=""> > +<br class=""> > +/*  Check all the chunks in a treebin.  */<br class=""> > +static void do_check_treebin(mstate m, bindex_t i) {<br class=""> > +  tbinptr* tb = treebin_at(m, i);<br class=""> > +  tchunkptr t = *tb;<br class=""> > +  int empty = (m->treemap & (1U << i)) == 0;<br class=""> > +  if (t == 0)<br class=""> > +    assert(m->user_data, empty);<br class=""> > +  if (!empty)<br class=""> > +    do_check_tree(m, t);<br class=""> > +}<br class=""> > +<br class=""> > +/*  Check all the chunks in a smallbin.  */<br class=""> > +static void do_check_smallbin(mstate m, bindex_t i) {<br class=""> > +  sbinptr b = smallbin_at(m, i);<br class=""> > +  mchunkptr p = b->bk;<br class=""> > +  unsigned int empty = (m->smallmap & (1U << i)) == 0;<br class=""> > +  if (p == b)<br class=""> > +    assert(m->user_data, empty);<br class=""> > +  if (!empty) {<br class=""> > +    for (; p != b; p = p->bk) {<br class=""> > +      size_t size = chunksize(p);<br class=""> > +      mchunkptr q;<br class=""> > +      /* each chunk claims to be free */<br class=""> > +      do_check_free_chunk(m, p);<br class=""> > +      /* chunk belongs in bin */<br class=""> > +      assert(m->user_data, small_index(size) == i);<br class=""> > +      assert(m->user_data, p->bk == b || chunksize(p->bk) == chunksize(p));<br class=""> > +      /* chunk is followed by an inuse chunk */<br class=""> > +      q = next_chunk(p);<br class=""> > +      if (q->head != FENCEPOST_HEAD)<br class=""> > +        do_check_inuse_chunk(m, q);<br class=""> > +    }<br class=""> > +  }<br class=""> > +}<br class=""> > +<br class=""> > +/* Find x in a bin. Used in other check functions. */<br class=""> > +static int bin_find(mstate m, mchunkptr x) {<br class=""> > +  size_t size = chunksize(x);<br class=""> > +  if (is_small(size)) {<br class=""> > +    bindex_t sidx = small_index(size);<br class=""> > +    sbinptr b = smallbin_at(m, sidx);<br class=""> > +    if (smallmap_is_marked(m, sidx)) {<br class=""> > +      mchunkptr p = b;<br class=""> > +      do {<br class=""> > +        if (p == x)<br class=""> > +          return 1;<br class=""> > +      } while ((p = p->fd) != b);<br class=""> > +    }<br class=""> > +  }<br class=""> > +  else {<br class=""> > +    bindex_t tidx;<br class=""> > +    compute_tree_index(size, tidx);<br class=""> > +    if (treemap_is_marked(m, tidx)) {<br class=""> > +      tchunkptr t = *treebin_at(m, tidx);<br class=""> > +      size_t sizebits = size << leftshift_for_tree_index(tidx);<br class=""> > +      while (t != 0 && chunksize(t) != size) {<br class=""> > +        t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];<br class=""> > +        sizebits <<= 1;<br class=""> > +      }<br class=""> > +      if (t != 0) {<br class=""> > +        tchunkptr u = t;<br class=""> > +        do {<br class=""> > +          if (u == (tchunkptr)x)<br class=""> > +            return 1;<br class=""> > +        } while ((u = u->fd) != t);<br class=""> > +      }<br class=""> > +    }<br class=""> > +  }<br class=""> > +  return 0;<br class=""> > +}<br class=""> > +<br class=""> > +/* Traverse each chunk and check it; return total */<br class=""> > +static size_t traverse_and_check(mstate m) {<br class=""> > +  size_t sum = 0;<br class=""> > +  if (is_initialized(m)) {<br class=""> > +    msegmentptr s = &m->seg;<br class=""> > +    sum += m->topsize + TOP_FOOT_SIZE;<br class=""> > +    while (s != 0) {<br class=""> > +      mchunkptr q = align_as_chunk(s->base);<br class=""> > +      mchunkptr lastq = 0;<br class=""> > +      assert(m->user_data, pinuse(q));<br class=""> > +      while (segment_holds(s, q) &&<br class=""> > +             q != m->top && q->head != FENCEPOST_HEAD) {<br class=""> > +        sum += chunksize(q);<br class=""> > +        if (cinuse(q)) {<br class=""> > +          assert(m->user_data, !bin_find(m, q));<br class=""> > +          do_check_inuse_chunk(m, q);<br class=""> > +        }<br class=""> > +        else {<br class=""> > +          assert(m->user_data, q == m->dv || bin_find(m, q));<br class=""> > +          assert(m->user_data, lastq == 0 || cinuse(lastq)); /* Not 2<br class=""> > consecutive free */<br class=""> > +          do_check_free_chunk(m, q);<br class=""> > +        }<br class=""> > +        lastq = q;<br class=""> > +        q = next_chunk(q);<br class=""> > +      }<br class=""> > +      s = s->next;<br class=""> > +    }<br class=""> > +  }<br class=""> > +  return sum;<br class=""> > +}<br class=""> > +<br class=""> > +/* Check all properties of malloc_state. */<br class=""> > +static void do_check_malloc_state(mstate m) {<br class=""> > +  bindex_t i;<br class=""> > +  size_t total;<br class=""> > +  /* check bins */<br class=""> > +  for (i = 0; i < NSMALLBINS; ++i)<br class=""> > +    do_check_smallbin(m, i);<br class=""> > +  for (i = 0; i < NTREEBINS; ++i)<br class=""> > +    do_check_treebin(m, i);<br class=""> > +<br class=""> > +  if (m->dvsize != 0) { /* check dv chunk */<br class=""> > +    do_check_any_chunk(m, m->dv);<br class=""> > +    assert(m->user_data, m->dvsize == chunksize(m->dv));<br class=""> > +    assert(m->user_data, m->dvsize >= MIN_CHUNK_SIZE);<br class=""> > +    assert(m->user_data, bin_find(m, m->dv) == 0);<br class=""> > +  }<br class=""> > +<br class=""> > +  if (m->top != 0) {   /* check top chunk */<br class=""> > +    do_check_top_chunk(m, m->top);<br class=""> > +    assert(m->user_data, m->topsize == chunksize(m->top));<br class=""> > +    assert(m->user_data, m->topsize > 0);<br class=""> > +    assert(m->user_data, bin_find(m, m->top) == 0);<br class=""> > +  }<br class=""> > +<br class=""> > +  total = traverse_and_check(m);<br class=""> > +  assert(m->user_data, total <= m->footprint);<br class=""> > +  assert(m->user_data, m->footprint <= m->max_footprint);<br class=""> > +}<br class=""> > +#endif /* DEBUG */<br class=""> > +<br class=""> > +/* ----------------------------- statistics ------------------------------<br class=""> > */<br class=""> > +<br class=""> > +#if !NO_MALLINFO<br class=""> > +static struct mallinfo internal_mallinfo(mstate m) {<br class=""> > +  struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };<br class=""> > +  if (!PREACTION(m)) {<br class=""> > +    check_malloc_state(m);<br class=""> > +    if (is_initialized(m)) {<br class=""> > +      size_t nfree = SIZE_T_ONE; /* top always free */<br class=""> > +      size_t mfree = m->topsize + TOP_FOOT_SIZE;<br class=""> > +      size_t sum = mfree;<br class=""> > +      msegmentptr s = &m->seg;<br class=""> > +      while (s != 0) {<br class=""> > +        mchunkptr q = align_as_chunk(s->base);<br class=""> > +        while (segment_holds(s, q) &&<br class=""> > +               q != m->top && q->head != FENCEPOST_HEAD) {<br class=""> > +          size_t sz = chunksize(q);<br class=""> > +          sum += sz;<br class=""> > +          if (!cinuse(q)) {<br class=""> > +            mfree += sz;<br class=""> > +            ++nfree;<br class=""> > +          }<br class=""> > +          q = next_chunk(q);<br class=""> > +        }<br class=""> > +        s = s->next;<br class=""> > +      }<br class=""> > +<br class=""> > +      nm.arena    = sum;<br class=""> > +      nm.ordblks  = nfree;<br class=""> > +      nm.hblkhd   = m->footprint - sum;<br class=""> > +      nm.usmblks  = m->max_footprint;<br class=""> > +      nm.uordblks = m->footprint - mfree;<br class=""> > +      nm.fordblks = mfree;<br class=""> > +      nm.keepcost = m->topsize;<br class=""> > +    }<br class=""> > +<br class=""> > +    POSTACTION(m);<br class=""> > +  }<br class=""> > +  return nm;<br class=""> > +}<br class=""> > +#endif /* !NO_MALLINFO */<br class=""> > +<br class=""> > +static void internal_malloc_stats(mstate m) {<br class=""> > +  if (!PREACTION(m)) {<br class=""> > +    size_t maxfp = 0;<br class=""> > +    size_t fp = 0;<br class=""> > +    size_t used = 0;<br class=""> > +    check_malloc_state(m);<br class=""> > +    if (is_initialized(m)) {<br class=""> > +      msegmentptr s = &m->seg;<br class=""> > +      maxfp = m->max_footprint;<br class=""> > +      fp = m->footprint;<br class=""> > +      used = fp - (m->topsize + TOP_FOOT_SIZE);<br class=""> > +<br class=""> > +      while (s != 0) {<br class=""> > +        mchunkptr q = align_as_chunk(s->base);<br class=""> > +        while (segment_holds(s, q) &&<br class=""> > +               q != m->top && q->head != FENCEPOST_HEAD) {<br class=""> > +          if (!cinuse(q))<br class=""> > +            used -= chunksize(q);<br class=""> > +          q = next_chunk(q);<br class=""> > +        }<br class=""> > +        s = s->next;<br class=""> > +      }<br class=""> > +    }<br class=""> > +<br class=""> > +    PRINT((m->user_data, "max system bytes = %10lu\n", (unsigned<br class=""> > long)(maxfp)));<br class=""> > +    PRINT((m->user_data, "system bytes     = %10lu\n", (unsigned<br class=""> > long)(fp)));<br class=""> > +    PRINT((m->user_data, "in use bytes     = %10lu\n", (unsigned<br class=""> > long)(used)));<br class=""> > +<br class=""> > +    POSTACTION(m);<br class=""> > +  }<br class=""> > +}<br class=""> > +<br class=""> > +/* ----------------------- Operations on smallbins -----------------------<br class=""> > */<br class=""> > +<br class=""> > +/*<br class=""> > +  Various forms of linking and unlinking are defined as macros.  Even<br class=""> > +  the ones for trees, which are very long but have very short typical<br class=""> > +  paths.  This is ugly but reduces reliance on inlining support of<br class=""> > +  compilers.<br class=""> > +*/<br class=""> > +<br class=""> > +/* Link a free chunk into a smallbin  */<br class=""> > +#define insert_small_chunk(M, P, S) {\<br class=""> > +  bindex_t I  = small_index(S);\<br class=""> > +  mchunkptr B = smallbin_at(M, I);\<br class=""> > +  mchunkptr F = B;\<br class=""> > +  assert((M)->user_data, S >= MIN_CHUNK_SIZE);\<br class=""> > +  if (!smallmap_is_marked(M, I))\<br class=""> > +    mark_smallmap(M, I);\<br class=""> > +  else if (RTCHECK(ok_address(M, B->fd)))\<br class=""> > +    F = B->fd;\<br class=""> > +  else {\<br class=""> > +    CORRUPTION_ERROR_ACTION(M);\<br class=""> > +  }\<br class=""> > +  B->fd = P;\<br class=""> > +  F->bk = P;\<br class=""> > +  P->fd = F;\<br class=""> > +  P->bk = B;\<br class=""> > +}<br class=""> > +<br class=""> > +/* Unlink a chunk from a smallbin  */<br class=""> > +#define unlink_small_chunk(M, P, S) {\<br class=""> > +  mchunkptr F = P->fd;\<br class=""> > +  mchunkptr B = P->bk;\<br class=""> > +  bindex_t I = small_index(S);\<br class=""> > +  assert((M)->user_data, P != B);\<br class=""> > +  assert((M)->user_data, P != F);\<br class=""> > +  assert((M)->user_data, chunksize(P) == small_index2size(I));\<br class=""> > +  if (F == B)\<br class=""> > +    clear_smallmap(M, I);\<br class=""> > +  else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\<br class=""> > +                   (B == smallbin_at(M,I) || ok_address(M, B)))) {\<br class=""> > +    F->bk = B;\<br class=""> > +    B->fd = F;\<br class=""> > +  }\<br class=""> > +  else {\<br class=""> > +    CORRUPTION_ERROR_ACTION(M);\<br class=""> > +  }\<br class=""> > +}<br class=""> > +<br class=""> > +/* Unlink the first chunk from a smallbin */<br class=""> > +#define unlink_first_small_chunk(M, B, P, I) {\<br class=""> > +  mchunkptr F = P->fd;\<br class=""> > +  assert((M)->user_data, P != B);\<br class=""> > +  assert((M)->user_data, P != F);\<br class=""> > +  assert((M)->user_data, chunksize(P) == small_index2size(I));\<br class=""> > +  if (B == F)\<br class=""> > +    clear_smallmap(M, I);\<br class=""> > +  else if (RTCHECK(ok_address(M, F))) {\<br class=""> > +    B->fd = F;\<br class=""> > +    F->bk = B;\<br class=""> > +  }\<br class=""> > +  else {\<br class=""> > +    CORRUPTION_ERROR_ACTION(M);\<br class=""> > +  }\<br class=""> > +}<br class=""> > +<br class=""> > +/* Replace dv node, binning the old one */<br class=""> > +/* Used only when dvsize known to be small */<br class=""> > +#define replace_dv(M, P, S) {\<br class=""> > +  size_t DVS = M->dvsize;\<br class=""> > +  if (DVS != 0) {\<br class=""> > +    mchunkptr DV = M->dv;\<br class=""> > +    assert((M)->user_data, is_small(DVS));\<br class=""> > +    insert_small_chunk(M, DV, DVS);\<br class=""> > +  }\<br class=""> > +  M->dvsize = S;\<br class=""> > +  M->dv = P;\<br class=""> > +}<br class=""> > +<br class=""> > +<br class=""> > +/* ------------------------- Operations on trees -------------------------<br class=""> > */<br class=""> > +<br class=""> > +/* Insert chunk into tree */<br class=""> > +#define insert_large_chunk(M, X, S) {\<br class=""> > +  tbinptr* H;\<br class=""> > +  bindex_t I;\<br class=""> > +  compute_tree_index(S, I);\<br class=""> > +  H = treebin_at(M, I);\<br class=""> > +  X->index = I;\<br class=""> > +  X->child[0] = X->child[1] = 0;\<br class=""> > +  if (!treemap_is_marked(M, I)) {\<br class=""> > +    mark_treemap(M, I);\<br class=""> > +    *H = X;\<br class=""> > +    X->parent = (tchunkptr)H;\<br class=""> > +    X->fd = X->bk = X;\<br class=""> > +  }\<br class=""> > +  else {\<br class=""> > +    tchunkptr T = *H;\<br class=""> > +    size_t K = S << leftshift_for_tree_index(I);\<br class=""> > +    for (;;) {\<br class=""> > +      if (chunksize(T) != S) {\<br class=""> > +        tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\<br class=""> > +        K <<= 1;\<br class=""> > +        if (*C != 0)\<br class=""> > +          T = *C;\<br class=""> > +        else if (RTCHECK(ok_address(M, C))) {\<br class=""> > +          *C = X;\<br class=""> > +          X->parent = T;\<br class=""> > +          X->fd = X->bk = X;\<br class=""> > +          break;\<br class=""> > +        }\<br class=""> > +        else {\<br class=""> > +          CORRUPTION_ERROR_ACTION(M);\<br class=""> > +          break;\<br class=""> > +        }\<br class=""> > +      }\<br class=""> > +      else {\<br class=""> > +        tchunkptr F = T->fd;\<br class=""> > +        if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\<br class=""> > +          T->fd = F->bk = X;\<br class=""> > +          X->fd = F;\<br class=""> > +          X->bk = T;\<br class=""> > +          X->parent = 0;\<br class=""> > +          break;\<br class=""> > +        }\<br class=""> > +        else {\<br class=""> > +          CORRUPTION_ERROR_ACTION(M);\<br class=""> > +          break;\<br class=""> > +        }\<br class=""> > +      }\<br class=""> > +    }\<br class=""> > +  }\<br class=""> > +}<br class=""> > +<br class=""> > +/*<br class=""> > +  Unlink steps:<br class=""> > +<br class=""> > +  1. If x is a chained node, unlink it from its same-sized fd/bk links<br class=""> > +     and choose its bk node as its replacement.<br class=""> > +  2. If x was the last node of its size, but not a leaf node, it must<br class=""> > +     be replaced with a leaf node (not merely one with an open left or<br class=""> > +     right), to make sure that lefts and rights of descendents<br class=""> > +     correspond properly to bit masks.  We use the rightmost descendent<br class=""> > +     of x.  We could use any other leaf, but this is easy to locate and<br class=""> > +     tends to counteract removal of leftmosts elsewhere, and so keeps<br class=""> > +     paths shorter than minimally guaranteed.  This doesn't loop much<br class=""> > +     because on average a node in a tree is near the bottom.<br class=""> > +  3. If x is the base of a chain (i.e., has parent links) relink<br class=""> > +     x's parent and children to x's replacement (or null if none).<br class=""> > +*/<br class=""> > +<br class=""> > +#define unlink_large_chunk(M, X) {\<br class=""> > +  tchunkptr XP = X->parent;\<br class=""> > +  tchunkptr R;\<br class=""> > +  if (X->bk != X) {\<br class=""> > +    tchunkptr F = X->fd;\<br class=""> > +    R = X->bk;\<br class=""> > +    if (RTCHECK(ok_address(M, F))) {\<br class=""> > +      F->bk = R;\<br class=""> > +      R->fd = F;\<br class=""> > +    }\<br class=""> > +    else {\<br class=""> > +      CORRUPTION_ERROR_ACTION(M);\<br class=""> > +    }\<br class=""> > +  }\<br class=""> > +  else {\<br class=""> > +    tchunkptr* RP;\<br class=""> > +    if (((R = *(RP = &(X->child[1]))) != 0) ||\<br class=""> > +        ((R = *(RP = &(X->child[0]))) != 0)) {\<br class=""> > +      tchunkptr* CP;\<br class=""> > +      while ((*(CP = &(R->child[1])) != 0) ||\<br class=""> > +             (*(CP = &(R->child[0])) != 0)) {\<br class=""> > +        R = *(RP = CP);\<br class=""> > +      }\<br class=""> > +      if (RTCHECK(ok_address(M, RP)))\<br class=""> > +        *RP = 0;\<br class=""> > +      else {\<br class=""> > +        CORRUPTION_ERROR_ACTION(M);\<br class=""> > +      }\<br class=""> > +    }\<br class=""> > +  }\<br class=""> > +  if (XP != 0) {\<br class=""> > +    tbinptr* H = treebin_at(M, X->index);\<br class=""> > +    if (X == *H) {\<br class=""> > +      if ((*H = R) == 0) \<br class=""> > +        clear_treemap(M, X->index);\<br class=""> > +    }\<br class=""> > +    else if (RTCHECK(ok_address(M, XP))) {\<br class=""> > +      if (XP->child[0] == X) \<br class=""> > +        XP->child[0] = R;\<br class=""> > +      else \<br class=""> > +        XP->child[1] = R;\<br class=""> > +    }\<br class=""> > +    else\<br class=""> > +      CORRUPTION_ERROR_ACTION(M);\<br class=""> > +    if (R != 0) {\<br class=""> > +      if (RTCHECK(ok_address(M, R))) {\<br class=""> > +        tchunkptr C0, C1;\<br class=""> > +        R->parent = XP;\<br class=""> > +        if ((C0 = X->child[0]) != 0) {\<br class=""> > +          if (RTCHECK(ok_address(M, C0))) {\<br class=""> > +            R->child[0] = C0;\<br class=""> > +            C0->parent = R;\<br class=""> > +          }\<br class=""> > +          else\<br class=""> > +            CORRUPTION_ERROR_ACTION(M);\<br class=""> > +        }\<br class=""> > +        if ((C1 = X->child[1]) != 0) {\<br class=""> > +          if (RTCHECK(ok_address(M, C1))) {\<br class=""> > +            R->child[1] = C1;\<br class=""> > +            C1->parent = R;\<br class=""> > +          }\<br class=""> > +          else\<br class=""> > +            CORRUPTION_ERROR_ACTION(M);\<br class=""> > +        }\<br class=""> > +      }\<br class=""> > +      else\<br class=""> > +        CORRUPTION_ERROR_ACTION(M);\<br class=""> > +    }\<br class=""> > +  }\<br class=""> > +}<br class=""> > +<br class=""> > +/* Relays to large vs small bin operations */<br class=""> > +<br class=""> > +#define insert_chunk(M, P, S)\<br class=""> > +  if (is_small(S)) insert_small_chunk(M, P, S)\<br class=""> > +  else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }<br class=""> > +<br class=""> > +#define unlink_chunk(M, P, S)\<br class=""> > +  if (is_small(S)) unlink_small_chunk(M, P, S)\<br class=""> > +  else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }<br class=""> > +<br class=""> > +<br class=""> > +/* Relays to internal calls to malloc/free from realloc, memalign etc */<br class=""> > +<br class=""> > +#define internal_malloc(m, b) mspace_malloc(m, b)<br class=""> > +#define internal_free(m, mem) mspace_free(m,mem);<br class=""> > +<br class=""> > +<br class=""> > +/* -------------------------- mspace management --------------------------<br class=""> > */<br class=""> > +<br class=""> > +/* Initialize top chunk and its size */<br class=""> > +static void init_top(mstate m, mchunkptr p, size_t psize) {<br class=""> > +  /* Ensure alignment */<br class=""> > +  size_t offset = align_offset(chunk2mem(p));<br class=""> > +  p = (mchunkptr)((char*)p + offset);<br class=""> > +  psize -= offset;<br class=""> > +<br class=""> > +  m->top = p;<br class=""> > +  m->topsize = psize;<br class=""> > +  p->head = psize | PINUSE_BIT;<br class=""> > +  /* set size of fake trailing chunk holding overhead space only once */<br class=""> > +  chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;<br class=""> > +}<br class=""> > +<br class=""> > +/* Initialize bins for a new mstate that is otherwise zeroed out */<br class=""> > +static void init_bins(mstate m) {<br class=""> > +  /* Establish circular links for smallbins */<br class=""> > +  bindex_t i;<br class=""> > +  for (i = 0; i < NSMALLBINS; ++i) {<br class=""> > +    sbinptr bin = smallbin_at(m,i);<br class=""> > +    bin->fd = bin->bk = bin;<br class=""> > +  }<br class=""> > +}<br class=""> > +<br class=""> > +#if PROCEED_ON_ERROR<br class=""> > +<br class=""> > +/* default corruption action */<br class=""> > +static void reset_on_error(mstate m) {<br class=""> > +  int i;<br class=""> > +  ++malloc_corruption_error_count;<br class=""> > +  /* Reinitialize fields to forget about all memory */<br class=""> > +  m->smallbins = m->treebins = 0;<br class=""> > +  m->dvsize = m->topsize = 0;<br class=""> > +  m->seg.base = 0;<br class=""> > +  m->seg.size = 0;<br class=""> > +  m->seg.next = 0;<br class=""> > +  m->top = m->dv = 0;<br class=""> > +  for (i = 0; i < NTREEBINS; ++i)<br class=""> > +    *treebin_at(m, i) = 0;<br class=""> > +  init_bins(m);<br class=""> > +}<br class=""> > +#endif /* PROCEED_ON_ERROR */<br class=""> > +<br class=""> > +/* Allocate chunk and prepend remainder with chunk in successor base. */<br class=""> > +static void* prepend_alloc(mstate m, char* newbase, char* oldbase,<br class=""> > +                           size_t nb) {<br class=""> > +  mchunkptr p = align_as_chunk(newbase);<br class=""> > +  mchunkptr oldfirst = align_as_chunk(oldbase);<br class=""> > +  size_t psize = (char*)oldfirst - (char*)p;<br class=""> > +  mchunkptr q = chunk_plus_offset(p, nb);<br class=""> > +  size_t qsize = psize - nb;<br class=""> > +  set_size_and_pinuse_of_inuse_chunk(m, p, nb);<br class=""> > +<br class=""> > +  assert(m->user_data, (char*)oldfirst > (char*)q);<br class=""> > +  assert(m->user_data, pinuse(oldfirst));<br class=""> > +  assert(m->user_data, qsize >= MIN_CHUNK_SIZE);<br class=""> > +<br class=""> > +  /* consolidate remainder with first chunk of old base */<br class=""> > +  if (oldfirst == m->top) {<br class=""> > +    size_t tsize = m->topsize += qsize;<br class=""> > +    m->top = q;<br class=""> > +    q->head = tsize | PINUSE_BIT;<br class=""> > +    check_top_chunk(m, q);<br class=""> > +  }<br class=""> > +  else if (oldfirst == m->dv) {<br class=""> > +    size_t dsize = m->dvsize += qsize;<br class=""> > +    m->dv = q;<br class=""> > +    set_size_and_pinuse_of_free_chunk(q, dsize);<br class=""> > +  }<br class=""> > +  else {<br class=""> > +    if (!cinuse(oldfirst)) {<br class=""> > +      size_t nsize = chunksize(oldfirst);<br class=""> > +      unlink_chunk(m, oldfirst, nsize);<br class=""> > +      oldfirst = chunk_plus_offset(oldfirst, nsize);<br class=""> > +      qsize += nsize;<br class=""> > +    }<br class=""> > +    set_free_with_pinuse(q, qsize, oldfirst);<br class=""> > +    insert_chunk(m, q, qsize);<br class=""> > +    check_free_chunk(m, q);<br class=""> > +  }<br class=""> > +<br class=""> > +  check_malloced_chunk(m, chunk2mem(p), nb);<br class=""> > +  return chunk2mem(p);<br class=""> > +}<br class=""> > +<br class=""> > +/* -------------------------- System allocation --------------------------<br class=""> > */<br class=""> > +<br class=""> > +/* Get memory from system using MORECORE or MMAP */<br class=""> > +static void* sys_alloc(mstate m, size_t nb) {<br class=""> > +  MALLOC_FAILURE_ACTION;<br class=""> > +  return 0;<br class=""> > +}<br class=""> > +<br class=""> > +/* ---------------------------- malloc support ---------------------------<br class=""> > */<br class=""> > +<br class=""> > +/* allocate a large request from the best fitting chunk in a treebin */<br class=""> > +static void* tmalloc_large(mstate m, size_t nb) {<br class=""> > +  tchunkptr v = 0;<br class=""> > +  size_t rsize = -nb; /* Unsigned negation */<br class=""> > +  tchunkptr t;<br class=""> > +  bindex_t idx;<br class=""> > +  compute_tree_index(nb, idx);<br class=""> > +<br class=""> > +  if ((t = *treebin_at(m, idx)) != 0) {<br class=""> > +    /* Traverse tree for this bin looking for node with size == nb */<br class=""> > +    size_t sizebits = nb << leftshift_for_tree_index(idx);<br class=""> > +    tchunkptr rst = 0;  /* The deepest untaken right subtree */<br class=""> > +    for (;;) {<br class=""> > +      tchunkptr rt;<br class=""> > +      size_t trem = chunksize(t) - nb;<br class=""> > +      if (trem < rsize) {<br class=""> > +        v = t;<br class=""> > +        if ((rsize = trem) == 0)<br class=""> > +          break;<br class=""> > +      }<br class=""> > +      rt = t->child[1];<br class=""> > +      t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];<br class=""> > +      if (rt != 0 && rt != t)<br class=""> > +        rst = rt;<br class=""> > +      if (t == 0) {<br class=""> > +        t = rst; /* set t to least subtree holding sizes > nb */<br class=""> > +        break;<br class=""> > +      }<br class=""> > +      sizebits <<= 1;<br class=""> > +    }<br class=""> > +  }<br class=""> > +<br class=""> > +  if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */<br class=""> > +    binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;<br class=""> > +    if (leftbits != 0) {<br class=""> > +      bindex_t i;<br class=""> > +      binmap_t leastbit = least_bit(leftbits);<br class=""> > +      compute_bit2idx(leastbit, i);<br class=""> > +      t = *treebin_at(m, i);<br class=""> > +    }<br class=""> > +  }<br class=""> > +<br class=""> > +  while (t != 0) { /* find smallest of tree or subtree */<br class=""> > +    size_t trem = chunksize(t) - nb;<br class=""> > +    if (trem < rsize) {<br class=""> > +      rsize = trem;<br class=""> > +      v = t;<br class=""> > +    }<br class=""> > +    t = leftmost_child(t);<br class=""> > +  }<br class=""> > +<br class=""> > +  /*  If dv is a better fit, return 0 so malloc will use it */<br class=""> > +  if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {<br class=""> > +    if (RTCHECK(ok_address(m, v))) { /* split */<br class=""> > +      mchunkptr r = chunk_plus_offset(v, nb);<br class=""> > +      assert(m->user_data, chunksize(v) == rsize + nb);<br class=""> > +      if (RTCHECK(ok_next(v, r))) {<br class=""> > +        unlink_large_chunk(m, v);<br class=""> > +        if (rsize < MIN_CHUNK_SIZE)<br class=""> > +          set_inuse_and_pinuse(m, v, (rsize + nb));<br class=""> > +        else {<br class=""> > +          set_size_and_pinuse_of_inuse_chunk(m, v, nb);<br class=""> > +          set_size_and_pinuse_of_free_chunk(r, rsize);<br class=""> > +          insert_chunk(m, r, rsize);<br class=""> > +        }<br class=""> > +        return chunk2mem(v);<br class=""> > +      }<br class=""> > +    }<br class=""> > +    CORRUPTION_ERROR_ACTION(m);<br class=""> > +  }<br class=""> > +  return 0;<br class=""> > +}<br class=""> > +<br class=""> > +/* allocate a small request from the best fitting chunk in a treebin */<br class=""> > +static void* tmalloc_small(mstate m, size_t nb) {<br class=""> > +  tchunkptr t, v;<br class=""> > +  size_t rsize;<br class=""> > +  bindex_t i;<br class=""> > +  binmap_t leastbit = least_bit(m->treemap);<br class=""> > +  compute_bit2idx(leastbit, i);<br class=""> > +<br class=""> > +  v = t = *treebin_at(m, i);<br class=""> > +  rsize = chunksize(t) - nb;<br class=""> > +<br class=""> > +  while ((t = leftmost_child(t)) != 0) {<br class=""> > +    size_t trem = chunksize(t) - nb;<br class=""> > +    if (trem < rsize) {<br class=""> > +      rsize = trem;<br class=""> > +      v = t;<br class=""> > +    }<br class=""> > +  }<br class=""> > +<br class=""> > +  if (RTCHECK(ok_address(m, v))) {<br class=""> > +    mchunkptr r = chunk_plus_offset(v, nb);<br class=""> > +    assert(m->user_data, chunksize(v) == rsize + nb);<br class=""> > +    if (RTCHECK(ok_next(v, r))) {<br class=""> > +      unlink_large_chunk(m, v);<br class=""> > +      if (rsize < MIN_CHUNK_SIZE)<br class=""> > +        set_inuse_and_pinuse(m, v, (rsize + nb));<br class=""> > +      else {<br class=""> > +        set_size_and_pinuse_of_inuse_chunk(m, v, nb);<br class=""> > +        set_size_and_pinuse_of_free_chunk(r, rsize);<br class=""> > +        replace_dv(m, r, rsize);<br class=""> > +      }<br class=""> > +      return chunk2mem(v);<br class=""> > +    }<br class=""> > +  }<br class=""> > +<br class=""> > +  CORRUPTION_ERROR_ACTION(m);<br class=""> > +  return 0;<br class=""> > +}<br class=""> > +<br class=""> > +/* --------------------------- realloc support ---------------------------<br class=""> > */<br class=""> > +<br class=""> > +static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {<br class=""> > +  if (bytes >= MAX_REQUEST) {<br class=""> > +    MALLOC_FAILURE_ACTION;<br class=""> > +    return 0;<br class=""> > +  }<br class=""> > +  if (!PREACTION(m)) {<br class=""> > +    mchunkptr oldp = mem2chunk(oldmem);<br class=""> > +    size_t oldsize = chunksize(oldp);<br class=""> > +    mchunkptr next = chunk_plus_offset(oldp, oldsize);<br class=""> > +    mchunkptr newp = 0;<br class=""> > +    void* extra = 0;<br class=""> > +<br class=""> > +    /* Try to either shrink or extend into top. Else malloc-copy-free */<br class=""> > +<br class=""> > +    if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&<br class=""> > +                ok_next(oldp, next) && ok_pinuse(next))) {<br class=""> > +      size_t nb = request2size(bytes);<br class=""> > +      if (oldsize >= nb) { /* already big enough */<br class=""> > +        size_t rsize = oldsize - nb;<br class=""> > +        newp = oldp;<br class=""> > +        if (rsize >= MIN_CHUNK_SIZE) {<br class=""> > +          mchunkptr remainder = chunk_plus_offset(newp, nb);<br class=""> > +          set_inuse(m, newp, nb);<br class=""> > +          set_inuse(m, remainder, rsize);<br class=""> > +          extra = chunk2mem(remainder);<br class=""> > +        }<br class=""> > +      }<br class=""> > +      else if (next == m->top && oldsize + m->topsize > nb) {<br class=""> > +        /* Expand into top */<br class=""> > +        size_t newsize = oldsize + m->topsize;<br class=""> > +        size_t newtopsize = newsize - nb;<br class=""> > +        mchunkptr newtop = chunk_plus_offset(oldp, nb);<br class=""> > +        set_inuse(m, oldp, nb);<br class=""> > +        newtop->head = newtopsize |PINUSE_BIT;<br class=""> > +        m->top = newtop;<br class=""> > +        m->topsize = newtopsize;<br class=""> > +        newp = oldp;<br class=""> > +      }<br class=""> > +    }<br class=""> > +    else {<br class=""> > +      USAGE_ERROR_ACTION(m, oldmem);<br class=""> > +      POSTACTION(m);<br class=""> > +      return 0;<br class=""> > +    }<br class=""> > +<br class=""> > +    POSTACTION(m);<br class=""> > +<br class=""> > +    if (newp != 0) {<br class=""> > +      if (extra != 0) {<br class=""> > +        internal_free(m, extra);<br class=""> > +      }<br class=""> > +      check_inuse_chunk(m, newp);<br class=""> > +      return chunk2mem(newp);<br class=""> > +    }<br class=""> > +    else {<br class=""> > +      void* newmem = internal_malloc(m, bytes);<br class=""> > +      if (newmem != 0) {<br class=""> > +        size_t oc = oldsize - overhead_for(oldp);<br class=""> > +        MEMCPY(newmem, oldmem, (oc < bytes)? oc : bytes);<br class=""> > +        internal_free(m, oldmem);<br class=""> > +      }<br class=""> > +      return newmem;<br class=""> > +    }<br class=""> > +  }<br class=""> > +  return 0;<br class=""> > +}<br class=""> > +<br class=""> > +/* --------------------------- memalign support --------------------------<br class=""> > */<br class=""> > +<br class=""> > +static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {<br class=""> > +  if (alignment <= MALLOC_ALIGNMENT)    /* Can just use malloc */<br class=""> > +    return internal_malloc(m, bytes);<br class=""> > +  if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size<br class=""> > */<br class=""> > +    alignment = MIN_CHUNK_SIZE;<br class=""> > +  if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */<br class=""> > +    size_t a = MALLOC_ALIGNMENT << 1;<br class=""> > +    while (a < alignment) a <<= 1;<br class=""> > +    alignment = a;<br class=""> > +  }<br class=""> > +<br class=""> > +  if (bytes >= MAX_REQUEST - alignment) {<br class=""> > +    if (m != 0)  { /* Test isn't needed but avoids compiler warning */<br class=""> > +      MALLOC_FAILURE_ACTION;<br class=""> > +    }<br class=""> > +  }<br class=""> > +  else {<br class=""> > +    size_t nb = request2size(bytes);<br class=""> > +    size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;<br class=""> > +    char* mem = (char*)internal_malloc(m, req);<br class=""> > +    if (mem != 0) {<br class=""> > +      void* leader = 0;<br class=""> > +      void* trailer = 0;<br class=""> > +      mchunkptr p = mem2chunk(mem);<br class=""> > +<br class=""> > +      if (PREACTION(m)) return 0;<br class=""> > +      if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */<br class=""> > +        /*<br class=""> > +          Find an aligned spot inside chunk.  Since we need to give<br class=""> > +          back leading space in a chunk of at least MIN_CHUNK_SIZE, if<br class=""> > +          the first calculation places us at a spot with less than<br class=""> > +          MIN_CHUNK_SIZE leader, we can move to the next aligned spot.<br class=""> > +          We've allocated enough total room so that this is always<br class=""> > +          possible.<br class=""> > +        */<br class=""> > +        char* br = (char*)mem2chunk((size_t)(((size_t)(mem +<br class=""> > +                                                       alignment -<br class=""> > +                                                       SIZE_T_ONE)) &<br class=""> > +                                             -alignment));<br class=""> > +        char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?<br class=""> > +          br : br+alignment;<br class=""> > +        mchunkptr newp = (mchunkptr)pos;<br class=""> > +        size_t leadsize = pos - (char*)(p);<br class=""> > +        size_t newsize = chunksize(p) - leadsize;<br class=""> > +<br class=""> > +        /* Otherwise, give back leader, use the rest */<br class=""> > +        set_inuse(m, newp, newsize);<br class=""> > +        set_inuse(m, p, leadsize);<br class=""> > +        leader = chunk2mem(p);<br class=""> > +<br class=""> > +        p = newp;<br class=""> > +      }<br class=""> > +<br class=""> > +      assert(m->user_data, chunksize(p) >= nb);<br class=""> > +      assert(m->user_data, (((size_t)(chunk2mem(p))) % alignment) == 0);<br class=""> > +      check_inuse_chunk(m, p);<br class=""> > +      POSTACTION(m);<br class=""> > +      if (leader != 0) {<br class=""> > +        internal_free(m, leader);<br class=""> > +      }<br class=""> > +      if (trailer != 0) {<br class=""> > +        internal_free(m, trailer);<br class=""> > +      }<br class=""> > +      return chunk2mem(p);<br class=""> > +    }<br class=""> > +  }<br class=""> > +  return 0;<br class=""> > +}<br class=""> > +<br class=""> > +/* ----------------------------- user mspaces ----------------------------<br class=""> > */<br class=""> > +<br class=""> > +static mstate init_user_mstate(char* tbase, size_t tsize, void *user_data) {<br class=""> > +  size_t msize = pad_request(sizeof(struct malloc_state));<br class=""> > +  mchunkptr mn;<br class=""> > +  mchunkptr msp = align_as_chunk(tbase);<br class=""> > +  mstate m = (mstate)(chunk2mem(msp));<br class=""> > +  MEMCLEAR(m, msize);<br class=""> > +  INITIAL_LOCK(&m->mutex);<br class=""> > +  msp->head = (msize|PINUSE_BIT|CINUSE_BIT);<br class=""> > +  m->seg.base = m->least_addr = tbase;<br class=""> > +  m->seg.size = m->footprint = m->max_footprint = tsize;<br class=""> > +  m->magic = mparams.magic;<br class=""> > +  m->mflags = mparams.default_mflags;<br class=""> > +  m->user_data = user_data;<br class=""> > +  init_bins(m);<br class=""> > +  mn = next_chunk(mem2chunk(m));<br class=""> > +  init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);<br class=""> > +  check_top_chunk(m, m->top);<br class=""> > +  return m;<br class=""> > +}<br class=""> > +<br class=""> > +mspace create_mspace_with_base(void* base, size_t capacity, int locked, void<br class=""> > *user_data) {<br class=""> > +  mstate m = 0;<br class=""> > +  size_t msize = pad_request(sizeof(struct malloc_state));<br class=""> > +  init_mparams(); /* Ensure pagesize etc initialized */<br class=""> > +<br class=""> > +  if (capacity > msize + TOP_FOOT_SIZE &&<br class=""> > +      capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {<br class=""> > +    m = init_user_mstate((char*)base, capacity, user_data);<br class=""> > +    set_lock(m, locked);<br class=""> > +  }<br class=""> > +  return (mspace)m;<br class=""> > +}<br class=""> > +<br class=""> > +/*<br class=""> > +  mspace versions of routines are near-clones of the global<br class=""> > +  versions. This is not so nice but better than the alternatives.<br class=""> > +*/<br class=""> > +<br class=""> > +<br class=""> > +void* mspace_malloc(mspace msp, size_t bytes) {<br class=""> > +  mstate ms = (mstate)msp;<br class=""> > +  if (!ok_magic(ms)) {<br class=""> > +    USAGE_ERROR_ACTION(ms,ms);<br class=""> > +    return 0;<br class=""> > +  }<br class=""> > +  if (!PREACTION(ms)) {<br class=""> > +    void* mem;<br class=""> > +    size_t nb;<br class=""> > +    if (bytes <= MAX_SMALL_REQUEST) {<br class=""> > +      bindex_t idx;<br class=""> > +      binmap_t smallbits;<br class=""> > +      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);<br class=""> > +      idx = small_index(nb);<br class=""> > +      smallbits = ms->smallmap >> idx;<br class=""> > +<br class=""> > +      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */<br class=""> > +        mchunkptr b, p;<br class=""> > +        idx += ~smallbits & 1;       /* Uses next bin if idx empty */<br class=""> > +        b = smallbin_at(ms, idx);<br class=""> > +        p = b->fd;<br class=""> > +        assert(ms->user_data, chunksize(p) == small_index2size(idx));<br class=""> > +        unlink_first_small_chunk(ms, b, p, idx);<br class=""> > +        set_inuse_and_pinuse(ms, p, small_index2size(idx));<br class=""> > +        mem = chunk2mem(p);<br class=""> > +        check_malloced_chunk(ms, mem, nb);<br class=""> > +        goto postaction;<br class=""> > +      }<br class=""> > +<br class=""> > +      else if (nb > ms->dvsize) {<br class=""> > +        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */<br class=""> > +          mchunkptr b, p, r;<br class=""> > +          size_t rsize;<br class=""> > +          bindex_t i;<br class=""> > +          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));<br class=""> > +          binmap_t leastbit = least_bit(leftbits);<br class=""> > +          compute_bit2idx(leastbit, i);<br class=""> > +          b = smallbin_at(ms, i);<br class=""> > +          p = b->fd;<br class=""> > +          assert(ms->user_data, chunksize(p) == small_index2size(i));<br class=""> > +          unlink_first_small_chunk(ms, b, p, i);<br class=""> > +          rsize = small_index2size(i) - nb;<br class=""> > +          /* Fit here cannot be remainderless if 4byte sizes */<br class=""> > +          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)<br class=""> > +            set_inuse_and_pinuse(ms, p, small_index2size(i));<br class=""> > +          else {<br class=""> > +            set_size_and_pinuse_of_inuse_chunk(ms, p, nb);<br class=""> > +            r = chunk_plus_offset(p, nb);<br class=""> > +            set_size_and_pinuse_of_free_chunk(r, rsize);<br class=""> > +            replace_dv(ms, r, rsize);<br class=""> > +          }<br class=""> > +          mem = chunk2mem(p);<br class=""> > +          check_malloced_chunk(ms, mem, nb);<br class=""> > +          goto postaction;<br class=""> > +        }<br class=""> > +<br class=""> > +        else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {<br class=""> > +          check_malloced_chunk(ms, mem, nb);<br class=""> > +          goto postaction;<br class=""> > +        }<br class=""> > +      }<br class=""> > +    }<br class=""> > +    else if (bytes >= MAX_REQUEST)<br class=""> > +      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc)<br class=""> > */<br class=""> > +    else {<br class=""> > +      nb = pad_request(bytes);<br class=""> > +      if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {<br class=""> > +        check_malloced_chunk(ms, mem, nb);<br class=""> > +        goto postaction;<br class=""> > +      }<br class=""> > +    }<br class=""> > +<br class=""> > +    if (nb <= ms->dvsize) {<br class=""> > +      size_t rsize = ms->dvsize - nb;<br class=""> > +      mchunkptr p = ms->dv;<br class=""> > +      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */<br class=""> > +        mchunkptr r = ms->dv = chunk_plus_offset(p, nb);<br class=""> > +        ms->dvsize = rsize;<br class=""> > +        set_size_and_pinuse_of_free_chunk(r, rsize);<br class=""> > +        set_size_and_pinuse_of_inuse_chunk(ms, p, nb);<br class=""> > +      }<br class=""> > +      else { /* exhaust dv */<br class=""> > +        size_t dvs = ms->dvsize;<br class=""> > +        ms->dvsize = 0;<br class=""> > +        ms->dv = 0;<br class=""> > +        set_inuse_and_pinuse(ms, p, dvs);<br class=""> > +      }<br class=""> > +      mem = chunk2mem(p);<br class=""> > +      check_malloced_chunk(ms, mem, nb);<br class=""> > +      goto postaction;<br class=""> > +    }<br class=""> > +<br class=""> > +    else if (nb < ms->topsize) { /* Split top */<br class=""> > +      size_t rsize = ms->topsize -= nb;<br class=""> > +      mchunkptr p = ms->top;<br class=""> > +      mchunkptr r = ms->top = chunk_plus_offset(p, nb);<br class=""> > +      r->head = rsize | PINUSE_BIT;<br class=""> > +      set_size_and_pinuse_of_inuse_chunk(ms, p, nb);<br class=""> > +      mem = chunk2mem(p);<br class=""> > +      check_top_chunk(ms, ms->top);<br class=""> > +      check_malloced_chunk(ms, mem, nb);<br class=""> > +      goto postaction;<br class=""> > +    }<br class=""> > +<br class=""> > +    mem = sys_alloc(ms, nb);<br class=""> > +<br class=""> > +  postaction:<br class=""> > +    POSTACTION(ms);<br class=""> > +    return mem;<br class=""> > +  }<br class=""> > +<br class=""> > +  return 0;<br class=""> > +}<br class=""> > +<br class=""> > +void mspace_free(mspace msp, void* mem) {<br class=""> > +  if (mem != 0) {<br class=""> > +    mchunkptr p  = mem2chunk(mem);<br class=""> > +#if FOOTERS<br class=""> > +    mstate fm = get_mstate_for(p);<br class=""> > +#else /* FOOTERS */<br class=""> > +    mstate fm = (mstate)msp;<br class=""> > +#endif /* FOOTERS */<br class=""> > +    if (!ok_magic(fm)) {<br class=""> > +      USAGE_ERROR_ACTION(fm, p);<br class=""> > +      return;<br class=""> > +    }<br class=""> > +    if (!PREACTION(fm)) {<br class=""> > +      check_inuse_chunk(fm, p);<br class=""> > +      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {<br class=""> > +        size_t psize = chunksize(p);<br class=""> > +        mchunkptr next = chunk_plus_offset(p, psize);<br class=""> > +        if (!pinuse(p)) {<br class=""> > +          size_t prevsize = p->prev_foot;<br class=""> > +<br class=""> > +          mchunkptr prev = chunk_minus_offset(p, prevsize);<br class=""> > +          psize += prevsize;<br class=""> > +          p = prev;<br class=""> > +          if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */<br class=""> > +            if (p != fm->dv) {<br class=""> > +              unlink_chunk(fm, p, prevsize);<br class=""> > +            }<br class=""> > +            else if ((next->head & INUSE_BITS) == INUSE_BITS) {<br class=""> > +              fm->dvsize = psize;<br class=""> > +              set_free_with_pinuse(p, psize, next);<br class=""> > +              goto postaction;<br class=""> > +            }<br class=""> > +          }<br class=""> > +          else<br class=""> > +            goto erroraction;<br class=""> > +        }<br class=""> > +<br class=""> > +        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {<br class=""> > +          if (!cinuse(next)) {  /* consolidate forward */<br class=""> > +            if (next == fm->top) {<br class=""> > +              size_t tsize = fm->topsize += psize;<br class=""> > +              fm->top = p;<br class=""> > +              p->head = tsize | PINUSE_BIT;<br class=""> > +              if (p == fm->dv) {<br class=""> > +                fm->dv = 0;<br class=""> > +                fm->dvsize = 0;<br class=""> > +              }<br class=""> > +              goto postaction;<br class=""> > +            }<br class=""> > +            else if (next == fm->dv) {<br class=""> > +              size_t dsize = fm->dvsize += psize;<br class=""> > +              fm->dv = p;<br class=""> > +              set_size_and_pinuse_of_free_chunk(p, dsize);<br class=""> > +              goto postaction;<br class=""> > +            }<br class=""> > +            else {<br class=""> > +              size_t nsize = chunksize(next);<br class=""> > +              psize += nsize;<br class=""> > +              unlink_chunk(fm, next, nsize);<br class=""> > +              set_size_and_pinuse_of_free_chunk(p, psize);<br class=""> > +              if (p == fm->dv) {<br class=""> > +                fm->dvsize = psize;<br class=""> > +                goto postaction;<br class=""> > +              }<br class=""> > +            }<br class=""> > +          }<br class=""> > +          else<br class=""> > +            set_free_with_pinuse(p, psize, next);<br class=""> > +          insert_chunk(fm, p, psize);<br class=""> > +          check_free_chunk(fm, p);<br class=""> > +          goto postaction;<br class=""> > +        }<br class=""> > +      }<br class=""> > +    erroraction:<br class=""> > +      USAGE_ERROR_ACTION(fm, p);<br class=""> > +    postaction:<br class=""> > +      POSTACTION(fm);<br class=""> > +    }<br class=""> > +  }<br class=""> > +}<br class=""> > +<br class=""> > +void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {<br class=""> > +  void* mem;<br class=""> > +  size_t req = 0;<br class=""> > +  mstate ms = (mstate)msp;<br class=""> > +  if (!ok_magic(ms)) {<br class=""> > +    USAGE_ERROR_ACTION(ms,ms);<br class=""> > +    return 0;<br class=""> > +  }<br class=""> > +  if (n_elements != 0) {<br class=""> > +    req = n_elements * elem_size;<br class=""> > +    if (((n_elements | elem_size) & ~(size_t)0xffff) &&<br class=""> > +        (req / n_elements != elem_size))<br class=""> > +      req = MAX_SIZE_T; /* force downstream failure on overflow */<br class=""> > +  }<br class=""> > +  mem = internal_malloc(ms, req);<br class=""> > +  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))<br class=""> > +    MEMCLEAR(mem, req);<br class=""> > +  return mem;<br class=""> > +}<br class=""> > +<br class=""> > +void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {<br class=""> > +  if (oldmem == 0)<br class=""> > +    return mspace_malloc(msp, bytes);<br class=""> > +#ifdef REALLOC_ZERO_BYTES_FREES<br class=""> > +  if (bytes == 0) {<br class=""> > +    mspace_free(msp, oldmem);<br class=""> > +    return 0;<br class=""> > +  }<br class=""> > +#endif /* REALLOC_ZERO_BYTES_FREES */<br class=""> > +  else {<br class=""> > +#if FOOTERS<br class=""> > +    mchunkptr p  = mem2chunk(oldmem);<br class=""> > +    mstate ms = get_mstate_for(p);<br class=""> > +#else /* FOOTERS */<br class=""> > +    mstate ms = (mstate)msp;<br class=""> > +#endif /* FOOTERS */<br class=""> > +    if (!ok_magic(ms)) {<br class=""> > +      USAGE_ERROR_ACTION(ms,ms);<br class=""> > +      return 0;<br class=""> > +    }<br class=""> > +    return internal_realloc(ms, oldmem, bytes);<br class=""> > +  }<br class=""> > +}<br class=""> > +<br class=""> > +void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {<br class=""> > +  mstate ms = (mstate)msp;<br class=""> > +  if (!ok_magic(ms)) {<br class=""> > +    USAGE_ERROR_ACTION(ms,ms);<br class=""> > +    return 0;<br class=""> > +  }<br class=""> > +  return internal_memalign(ms, alignment, bytes);<br class=""> > +}<br class=""> > +<br class=""> > +void mspace_malloc_stats(mspace msp) {<br class=""> > +  mstate ms = (mstate)msp;<br class=""> > +  if (ok_magic(ms)) {<br class=""> > +    internal_malloc_stats(ms);<br class=""> > +  }<br class=""> > +  else {<br class=""> > +    USAGE_ERROR_ACTION(ms,ms);<br class=""> > +  }<br class=""> > +}<br class=""> > +<br class=""> > +size_t mspace_footprint(mspace msp) {<br class=""> > +  size_t result;<br class=""> > +  mstate ms = (mstate)msp;<br class=""> > +  if (ok_magic(ms)) {<br class=""> > +    result = ms->footprint;<br class=""> > +  } else {<br class=""> > +    USAGE_ERROR_ACTION(ms,ms);<br class=""> > +  }<br class=""> > +  return result;<br class=""> > +}<br class=""> > +<br class=""> > +<br class=""> > +size_t mspace_max_footprint(mspace msp) {<br class=""> > +  size_t result;<br class=""> > +  mstate ms = (mstate)msp;<br class=""> > +  if (ok_magic(ms)) {<br class=""> > +    result = ms->max_footprint;<br class=""> > +  } else {<br class=""> > +    USAGE_ERROR_ACTION(ms,ms);<br class=""> > +  }<br class=""> > +  return result;<br class=""> > +}<br class=""> > +<br class=""> > +<br class=""> > +#if !NO_MALLINFO<br class=""> > +struct mallinfo mspace_mallinfo(mspace msp) {<br class=""> > +  mstate ms = (mstate)msp;<br class=""> > +  if (!ok_magic(ms)) {<br class=""> > +    USAGE_ERROR_ACTION(ms,ms);<br class=""> > +  }<br class=""> > +  return internal_mallinfo(ms);<br class=""> > +}<br class=""> > +#endif /* NO_MALLINFO */<br class=""> > +<br class=""> > +int mspace_mallopt(int param_number, int value) {<br class=""> > +  return change_mparam(param_number, value);<br class=""> > +}<br class=""> > +<br class=""> > diff --git a/qxldod/qxldod.vcxproj b/qxldod/qxldod.vcxproj<br class=""> > index 749ba1b..f4d279b 100755<br class=""> > --- a/qxldod/qxldod.vcxproj<br class=""> > +++ b/qxldod/qxldod.vcxproj<br class=""> > @@ -279,7 +279,7 @@<br class=""> >    <ItemGroup><br class=""> >      <ClCompile Include="BaseObject.cpp" /><br class=""> >      <ClCompile Include="driver.cpp" /><br class=""> > -    <ClCompile Include="mspace.c" /><br class=""> > +    <ClCompile Include="mspace.cpp" /><br class=""> >      <ClCompile Include="QxlDod.cpp" /><br class=""> >    </ItemGroup><br class=""> >    <ItemGroup><br class=""> > diff --git a/qxldod/qxldod.vcxproj.filters b/qxldod/qxldod.vcxproj.filters<br class=""> > index bb9daa9..b0a8103 100755<br class=""> > --- a/qxldod/qxldod.vcxproj.filters<br class=""> > +++ b/qxldod/qxldod.vcxproj.filters<br class=""> > @@ -42,7 +42,7 @@<br class=""> >      <ClCompile Include="QxlDod.cpp"><br class=""> >        <Filter>Source Files</Filter><br class=""> >      </ClCompile><br class=""> > -    <ClCompile Include="mspace.c"><br class=""> > +    <ClCompile Include="mspace.cpp"><br class=""> >        <Filter>Source Files</Filter><br class=""> >      </ClCompile><br class=""> >    </ItemGroup><br class=""><br class=""></blockquote></div><br class=""><br clear="all" class=""><div class=""><br class=""></div>-- <br class=""><div class=""><div dir="ltr" class=""><div class=""><div dir="ltr" class=""><div class=""><div dir="ltr" class=""><span style="color: #0b5394; font-family: times new roman,serif; font-size: large;" data-mce-style="color: #0b5394; font-family: times new roman,serif; font-size: large;" face="times new roman, serif" size="4" class="">Respectfully,<br class=""></span><div style="font-size:12.8px;color:rgb(136,136,136)" data-mce-style="font-size: 12.8px; color: #888888;" class=""><span style="color: #0b5394; font-family: times new roman,serif; font-size: large;" data-mce-style="color: #0b5394; font-family: times new roman,serif; font-size: large;" face="times new roman, serif" size="4" class=""><b class=""><i class="">Sameeh Jubran</i></b></span></div><div style="font-size:12.8px;color:rgb(136,136,136)" data-mce-style="font-size: 12.8px; color: #888888;" class=""><i style="color:rgb(7,55,99);font-family:"times new roman",serif;font-size:large" data-mce-style="color: #073763; font-family: 'times new roman',serif; font-size: large;" class=""><span style="line-height:15px" data-mce-style="line-height: 15px;" class=""><a href="https://il.linkedin.com/pub/sameeh-jubran/87/747/a8a" title="View public profile" name="m_7126241177016800315_UNIQUE_ID_SafeHtmlFilter_UNIQUE_ID_SafeHtmlFilter_UNIQUE_ID_SafeHtmlFilter_UNIQUE_ID_SafeHtmlFilter_14e2c1de96f8c195_UNIQUE_ID_SafeHtmlFilter_SafeHtmlFilter_SafeHtmlFilter_webProfileURL" style="color:rgb(17,85,204);margin:0px;padding:0px;border-width:0px;outline:none;vertical-align:baseline;text-decoration:none" target="_blank" data-mce-href="https://il.linkedin.com/pub/sameeh-jubran/87/747/a8a" data-mce-style="color: #1155cc; margin: 0px; padding: 0px; border-width: 0px; outline: none; vertical-align: baseline; text-decoration: none;" class="">Linkedin</a></span></i><br class=""></div><div style="font-size:12.8px;color:rgb(136,136,136)" data-mce-style="font-size: 12.8px; color: #888888;" class=""><span style="color: #073763; font-family: times new roman,serif; font-size: large;" data-mce-style="color: #073763; font-family: times new roman,serif; font-size: large;" face="times new roman, serif" size="4" class=""><i class="">Junior Software Engineer @ <a href="http://www.daynix.com/" target="_blank" data-mce-href="http://www.daynix.com" class="">Daynix</a>.</i></span></div></div></div></div></div></div></div></div></div></blockquote><div class=""><br class=""></div></div></div></div></blockquote></div><br class=""></body></html>