16661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
26661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  This is a version (aka dlmalloc) of malloc/free/realloc written by
36661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Doug Lea and released to the public domain, as explained at
46661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  http://creativecommons.org/publicdomain/zero/1.0/ Send questions,
56661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  comments, complaints, performance data, etc to dl@cs.oswego.edu
66661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
76661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao* Version 2.8.6 Wed Aug 29 06:57:58 2012  Doug Lea
86661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   Note: There may be an updated version of this malloc obtainable at
96661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao           ftp://gee.cs.oswego.edu/pub/misc/malloc.c
106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         Check before installing!
116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao* Quickstart
136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  This library is all in one file to simplify the most common usage:
156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ftp it, compile it (-O3), and link it into another program. All of
166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the compile-time options default to reasonable values for use on
176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  most platforms.  You might later want to step through various
186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  compile-time and dynamic tuning options.
196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  For convenience, an include file for code using this malloc is at:
216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.6.h
226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  You don't really need this .h file unless you call functions not
236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  defined in your system include files.  The .h file contains only the
246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  excerpts from this file needed for using this malloc on ANSI C/C++
256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  systems, so long as you haven't changed compile-time options about
266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  naming and tuning parameters.  If you do, then you can create your
276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  own malloc.h that does include all settings by cutting at the point
286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  indicated below. Note that you may already by default be using a C
296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  library containing a malloc that is based on some version of this
306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc (for example in linux). You might still want to use the one
316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  in this file to customize settings or to avoid overheads associated
326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  with library versions.
336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao* Vital statistics:
356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Supported pointer/size_t representation:       4 or 8 bytes
376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       size_t MUST be an unsigned type of the same width as
386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       pointers. (If you are using an ancient system that declares
396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       size_t as a signed type, or need it to be a different width
406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       than pointers, you can use a previous release of this malloc
416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       (e.g. 2.7.2) supporting these.)
426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Alignment:                                     8 bytes (minimum)
446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       This suffices for nearly all current machines and C compilers.
456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       However, you can define MALLOC_ALIGNMENT to be wider than this
466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       if necessary (up to 128bytes), at the expense of using more space.
476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Minimum overhead per allocated chunk:   4 or  8 bytes (if 4byte sizes)
496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                          8 or 16 bytes (if 8byte sizes)
506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       Each malloced chunk has a hidden word of overhead holding size
516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       and status information, and additional cross-check word
526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       if FOOTERS is defined.
536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Minimum allocated size: 4-byte ptrs:  16 bytes    (including overhead)
556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                          8-byte ptrs:  32 bytes    (including overhead)
566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       Even a request for zero bytes (i.e., malloc(0)) returns a
586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       pointer to something of the minimum allocatable size.
596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       The maximum overhead wastage (i.e., number of extra bytes
606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       allocated than were requested in malloc) is less than or equal
616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       to the minimum size, except for requests >= mmap_threshold that
626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       are serviced via mmap(), where the worst case wastage is about
636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       32 bytes plus the remainder from a system page (the minimal
646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       mmap unit); typically 4096 or 8192 bytes.
656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Security: static-safe; optionally more or less
676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       The "security" of malloc refers to the ability of malicious
686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       code to accentuate the effects of errors (for example, freeing
696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       space that is not currently malloc'ed or overwriting past the
706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       ends of chunks) in code that calls malloc.  This malloc
716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       guarantees not to modify any memory locations below the base of
726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       heap, i.e., static variables, even in the presence of usage
736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       errors.  The routines additionally detect most improper frees
746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       and reallocs.  All this holds as long as the static bookkeeping
756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       for malloc itself is not corrupted by some other means.  This
766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       is only one aspect of security -- these checks do not, and
776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       cannot, detect all possible programming errors.
786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       If FOOTERS is defined nonzero, then each allocated chunk
806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       carries an additional check word to verify that it was malloced
816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       from its space.  These check words are the same within each
826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       execution of a program using malloc, but differ across
836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       executions, so externally crafted fake chunks cannot be
846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       freed. This improves security by rejecting frees/reallocs that
856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       could corrupt heap memory, in addition to the checks preventing
866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       writes to statics that are always on.  This may further improve
876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       security at the expense of time and space overhead.  (Note that
886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       FOOTERS may also be worth using with MSPACES.)
896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       By default detected errors cause the program to abort (calling
916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       "abort()"). You can override this to instead proceed past
926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       errors by defining PROCEED_ON_ERROR.  In this case, a bad free
936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       has no effect, and a malloc that encounters a bad address
946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       caused by user overwrites will ignore the bad address by
956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       dropping pointers and indices to all known memory. This may
966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       be appropriate for programs that should continue if at all
976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       possible in the face of programming errors, although they may
986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       run out of memory because dropped memory is never reclaimed.
996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       If you don't like either of these options, you can define
1016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
1026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       else. And if if you are sure that your program using malloc has
1036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       no errors or vulnerabilities, you can define INSECURE to 1,
1046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       which might (or might not) provide a small performance improvement.
1056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       It is also possible to limit the maximum total allocatable
1076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       space, using malloc_set_footprint_limit. This is not
1086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       designed as a security feature in itself (calls to set limits
1096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       are not screened or privileged), but may be useful as one
1106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       aspect of a secure implementation.
1116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Thread-safety: NOT thread-safe unless USE_LOCKS defined non-zero
1136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       When USE_LOCKS is defined, each public call to malloc, free,
1146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       etc is surrounded with a lock. By default, this uses a plain
1156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       pthread mutex, win32 critical section, or a spin-lock if if
1166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       available for the platform and not disabled by setting
1176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       USE_SPIN_LOCKS=0.  However, if USE_RECURSIVE_LOCKS is defined,
1186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       recursive versions are used instead (which are not required for
1196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       base functionality but may be needed in layered extensions).
1206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       Using a global lock is not especially fast, and can be a major
1216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       bottleneck.  It is designed only to provide minimal protection
1226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       in concurrent environments, and to provide a basis for
1236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       extensions.  If you are using malloc in a concurrent program,
1246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       consider instead using nedmalloc
1256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       (http://www.nedprod.com/programs/portable/nedmalloc/) or
1266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       ptmalloc (See http://www.malloc.de), which are derived from
1276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       versions of this malloc.
1286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
1306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       This malloc can use unix sbrk or any emulation (invoked using
1316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       the CALL_MORECORE macro) and/or mmap/munmap or any emulation
1326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
1336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       memory.  On most unix systems, it tends to work best if both
1346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       MORECORE and MMAP are enabled.  On Win32, it uses emulations
1356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       based on VirtualAlloc. It also uses common C library functions
1366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       like memset.
1376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Compliance: I believe it is compliant with the Single Unix Specification
1396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
1406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       others as well.
1416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao* Overview of algorithms
1436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  This is not the fastest, most space-conserving, most portable, or
1456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  most tunable malloc ever written. However it is among the fastest
1466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  while also being among the most space-conserving, portable and
1476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tunable.  Consistent balance across these factors results in a good
1486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  general-purpose allocator for malloc-intensive programs.
1496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  In most ways, this malloc is a best-fit allocator. Generally, it
1516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  chooses the best-fitting existing chunk for a request, with ties
1526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  broken in approximately least-recently-used order. (This strategy
1536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  normally maintains low fragmentation.) However, for requests less
1546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  than 256bytes, it deviates from best-fit when there is not an
1556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  exactly fitting available chunk by preferring to use space adjacent
1566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  to that used for the previous small request, as well as by breaking
1576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ties in approximately most-recently-used order. (These enhance
1586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  locality of series of small allocations.)  And for very large requests
1596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (>= 256Kb by default), it relies on system memory mapping
1606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  facilities, if supported.  (This helps avoid carrying around and
1616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  possibly fragmenting memory used only for large chunks.)
1626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  All operations (except malloc_stats and mallinfo) have execution
1646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  times that are bounded by a constant factor of the number of bits in
1656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  a size_t, not counting any clearing in calloc or copying in realloc,
1666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  or actions surrounding MORECORE and MMAP that have times
1676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  proportional to the number of non-contiguous regions returned by
1686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  system allocation routines, which is often just 1. In real-time
1696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  applications, you can optionally suppress segment traversals using
1706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  NO_SEGMENT_TRAVERSAL, which assures bounded execution even when
1716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  system allocators return non-contiguous spaces, at the typical
1726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  expense of carrying around more memory and increased fragmentation.
1736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The implementation is not very modular and seriously overuses
1756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  macros. Perhaps someday all C compilers will do as good a job
1766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  inlining modular code as can now be done by brute-force expansion,
1776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  but now, enough of them seem not to.
1786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Some compilers issue a lot of warnings about code that is
1806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  dead/unreachable only on some platforms, and also about intentional
1816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  uses of negation on unsigned types. All known cases of each can be
1826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ignored.
1836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  For a longer but out of date high-level description, see
1856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     http://gee.cs.oswego.edu/dl/html/malloc.html
1866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao* MSPACES
1886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If MSPACES is defined, then in addition to malloc, free, etc.,
1896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  this file also defines mspace_malloc, mspace_free, etc. These
1906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  are versions of malloc routines that take an "mspace" argument
1916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  obtained using create_mspace, to control all internal bookkeeping.
1926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If ONLY_MSPACES is defined, only these versions are compiled.
1936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  So if you would like to use this allocator for only some allocations,
1946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  and your system malloc for others, you can compile with
1956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ONLY_MSPACES and then do something like...
1966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    static mspace mymspace = create_mspace(0,0); // for example
1976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define mymalloc(bytes)  mspace_malloc(mymspace, bytes)
1986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
1996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (Note: If you only need one instance of an mspace, you can instead
2006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  use "USE_DL_PREFIX" to relabel the global malloc.)
2016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  You can similarly create thread-local allocators by storing
2036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspaces as thread-locals. For example:
2046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    static __thread mspace tlms = 0;
2056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    void*  tlmalloc(size_t bytes) {
2066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (tlms == 0) tlms = create_mspace(0, 0);
2076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return mspace_malloc(tlms, bytes);
2086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
2096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    void  tlfree(void* mem) { mspace_free(tlms, mem); }
2106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Unless FOOTERS is defined, each mspace is completely independent.
2126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  You cannot allocate from one and free to another (although
2136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  conformance is only weakly checked, so usage errors are not always
2146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  caught). If FOOTERS is defined, then each chunk carries around a tag
2156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  indicating its originating mspace, and frees are directed to their
2166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  originating spaces. Normally, this requires use of locks.
2176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao -------------------------  Compile-time options ---------------------------
2196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoBe careful in setting #define values for numerical constants of type
2216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t. On some systems, literal values are not automatically extended
2226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoto size_t precision unless they are explicitly casted. You can also
2236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaouse the symbolic values MAX_SIZE_T, SIZE_T_ONE, etc below.
2246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoWIN32                    default: defined if _WIN32 defined
2266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Defining WIN32 sets up defaults for MS environment and compilers.
2276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Otherwise defaults are for unix. Beware that there seem to be some
2286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  cases where this malloc might not be a pure drop-in replacement for
2296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Win32 malloc: Random-looking failures from Win32 GDI API's (eg;
2306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  SetDIBits()) may be due to bugs in some video driver implementations
2316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  when pixel buffers are malloc()ed, and the region spans more than
2326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  one VirtualAlloc()ed region. Because dlmalloc uses a small (64Kb)
2336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  default granularity, pixel buffers may straddle virtual allocation
2346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  regions more often than when using the Microsoft allocator.  You can
2356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  avoid this by using VirtualAlloc() and VirtualFree() for all pixel
2366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  buffers rather than using malloc().  If this is not possible,
2376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  recompile this malloc with a larger DEFAULT_GRANULARITY. Note:
2386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  in cases where MSC and gcc (cygwin) are known to differ on WIN32,
2396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  conditions use _MSC_VER to distinguish them.
2406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT       default: extern
2426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Defines how public APIs are declared. If you want to export via a
2436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Windows DLL, you might define this as
2446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define DLMALLOC_EXPORT extern  __declspec(dllexport)
2456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If you want a POSIX ELF shared object, you might use
2466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define DLMALLOC_EXPORT extern __attribute__((visibility("default")))
2476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoMALLOC_ALIGNMENT         default: (size_t)(2 * sizeof(void *))
2496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Controls the minimum alignment for malloc'ed chunks.  It must be a
2506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  power of two and at least 8, even on machines for which smaller
2516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  alignments would suffice. It may be defined as larger than this
2526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  though. Note however that code and data structures are optimized for
2536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the case of 8-byte alignment.
2546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoMSPACES                  default: 0 (false)
2566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If true, compile in support for independent allocation spaces.
2576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  This is only supported if HAVE_MMAP is true.
2586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoONLY_MSPACES             default: 0 (false)
2606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If true, only compile in mspace versions, not regular versions.
2616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoUSE_LOCKS                default: 0 (false)
2636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Causes each call to each public routine to be surrounded with
2646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  pthread or WIN32 mutex lock/unlock. (If set true, this can be
2656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  overridden on a per-mspace basis for mspace versions.) If set to a
2666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  non-zero value other than 1, locks are used, but their
2676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  implementation is left out, so lock functions must be supplied manually,
2686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  as described below.
2696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoUSE_SPIN_LOCKS           default: 1 iff USE_LOCKS and spin locks available
2716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If true, uses custom spin locks for locking. This is currently
2726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  supported only gcc >= 4.1, older gccs on x86 platforms, and recent
2736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MS compilers.  Otherwise, posix locks or win32 critical sections are
2746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  used.
2756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoUSE_RECURSIVE_LOCKS      default: not defined
2776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If defined nonzero, uses recursive (aka reentrant) locks, otherwise
2786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  uses plain mutexes. This is not required for malloc proper, but may
2796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  be needed for layered allocators such as nedmalloc.
2806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoLOCK_AT_FORK            default: not defined
2826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If defined nonzero, performs pthread_atfork upon initialization
2836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  to initialize child lock while holding parent lock. The implementation
2846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assumes that pthread locks (not custom locks) are being used. In other
2856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  cases, you may need to customize the implementation.
2866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoFOOTERS                  default: 0
2886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If true, provide extra checking and dispatching by placing
2896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  information in the footers of allocated chunks. This adds
2906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  space and time overhead.
2916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoINSECURE                 default: 0
2936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If true, omit checks for usage errors and heap space overwrites.
2946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
2956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoUSE_DL_PREFIX            default: NOT defined
2966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Causes compiler to prefix all public routines with the string 'dl'.
2976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  This can be useful when you only want to use this malloc in one part
2986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  of a program, using your regular system malloc elsewhere.
2996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoMALLOC_INSPECT_ALL       default: NOT defined
3016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If defined, compiles malloc_inspect_all and mspace_inspect_all, that
3026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  perform traversal of all heap space.  Unless access to these
3036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  functions is otherwise restricted, you probably do not want to
3046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  include them in secure implementations.
3056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoABORT                    default: defined as abort()
3076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Defines how to abort on failed checks.  On most systems, a failed
3086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  check cannot die with an "assert" or even print an informative
3096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  message, because the underlying print routines in turn call malloc,
3106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  which will fail again.  Generally, the best policy is to simply call
3116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  abort(). It's not very useful to do more than this because many
3126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  errors due to overwriting will show up as address faults (null, odd
3136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  addresses etc) rather than malloc-triggered checks, so will also
3146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  abort.  Also, most compilers know that abort() does not return, so
3156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  can better optimize code conditionally calling it.
3166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoPROCEED_ON_ERROR           default: defined as 0 (false)
3186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Controls whether detected bad addresses cause them to bypassed
3196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  rather than aborting. If set, detected bad arguments to free and
3206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  realloc are ignored. And all bookkeeping information is zeroed out
3216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  upon a detected overwrite of freed heap space, thus losing the
3226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ability to ever return it from malloc again, but enabling the
3236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  application to proceed. If PROCEED_ON_ERROR is defined, the
3246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  static variable malloc_corruption_error_count is compiled in
3256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  and can be examined to see if errors have occurred. This option
3266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  generates slower code than the default abort policy.
3276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDEBUG                    default: NOT defined
3296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The DEBUG setting is mainly intended for people trying to modify
3306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  this code or diagnose problems when porting to new platforms.
3316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  However, it may also be able to better isolate user errors than just
3326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  using runtime checks.  The assertions in the check routines spell
3336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  out in more detail the assumptions and invariants underlying the
3346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  algorithms.  The checking is fairly extensive, and will slow down
3356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  execution noticeably. Calling malloc_stats or mallinfo with DEBUG
3366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  set will attempt to check every non-mmapped allocated and free chunk
3376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  in the course of computing the summaries.
3386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoABORT_ON_ASSERT_FAILURE   default: defined as 1 (true)
3406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Debugging assertion failures can be nearly impossible if your
3416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  version of the assert macro causes malloc to be called, which will
3426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  lead to a cascade of further failures, blowing the runtime stack.
3436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),
3446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  which will usually make debugging easier.
3456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoMALLOC_FAILURE_ACTION     default: sets errno to ENOMEM, or no-op on win32
3476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The action to take before "return 0" when malloc fails to be able to
3486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return memory because there is none available.
3496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoHAVE_MORECORE             default: 1 (true) unless win32 or ONLY_MSPACES
3516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  True if this system supports sbrk or an emulation of it.
3526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoMORECORE                  default: sbrk
3546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The name of the sbrk-style system routine to call to obtain more
3556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  memory.  See below for guidance on writing custom MORECORE
3566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  functions. The type of the argument to sbrk/MORECORE varies across
3576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  systems.  It cannot be size_t, because it supports negative
3586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  arguments, so it is normally the signed type of the same width as
3596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t (sometimes declared as "intptr_t").  It doesn't much matter
3606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  though. Internally, we only call it with arguments less than half
3616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the max value of a size_t, which should work across all reasonable
3626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  possibilities, although sometimes generating compiler warnings.
3636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoMORECORE_CONTIGUOUS       default: 1 (true) if HAVE_MORECORE
3656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If true, take advantage of fact that consecutive calls to MORECORE
3666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  with positive arguments always return contiguous increasing
3676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  addresses.  This is true of unix sbrk. It does not hurt too much to
3686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  set it true anyway, since malloc copes with non-contiguities.
3696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Setting it false when definitely non-contiguous saves time
3706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  and possibly wasted space it would take to discover this though.
3716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoMORECORE_CANNOT_TRIM      default: NOT defined
3736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  True if MORECORE cannot release space back to the system when given
3746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  negative arguments. This is generally necessary only if you are
3756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  using a hand-crafted MORECORE function that cannot handle negative
3766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  arguments.
3776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoNO_SEGMENT_TRAVERSAL       default: 0
3796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If non-zero, suppresses traversals of memory segments
3806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  returned by either MORECORE or CALL_MMAP. This disables
3816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  merging of segments that are contiguous, and selectively
3826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  releasing them to the OS if unused, but bounds execution times.
3836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoHAVE_MMAP                 default: 1 (true)
3856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  True if this system supports mmap or an emulation of it.  If so, and
3866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  HAVE_MORECORE is not true, MMAP is used for all system
3876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  allocation. If set and HAVE_MORECORE is true as well, MMAP is
3886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  primarily used to directly allocate very large blocks. It is also
3896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  used as a backup strategy in cases where MORECORE fails to provide
3906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  space from system. Note: A single call to MUNMAP is assumed to be
3916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  able to unmap memory that may have be allocated using multiple calls
3926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  to MMAP, so long as they are adjacent.
3936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoHAVE_MREMAP               default: 1 on linux, else 0
3956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If true realloc() uses mremap() to re-allocate large blocks and
3966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  extend or shrink allocation spaces.
3976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
3986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoMMAP_CLEARS               default: 1 except on WINCE.
3996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  True if mmap clears memory so calloc doesn't need to. This is true
4006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for standard unix mmap using /dev/zero and on WIN32 except for WINCE.
4016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
4026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoUSE_BUILTIN_FFS            default: 0 (i.e., not used)
4036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Causes malloc to use the builtin ffs() function to compute indices.
4046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Some compilers may recognize and intrinsify ffs to be faster than the
4056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  supplied C version. Also, the case of x86 using gcc is special-cased
4066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  to an asm instruction, so is already as fast as it can be, and so
4076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  this setting has no effect. Similarly for Win32 under recent MS compilers.
4086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (On most x86s, the asm version is only slightly faster than the C version.)
4096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
4106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaomalloc_getpagesize         default: derive from system includes, or 4096.
4116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The system page size. To the extent possible, this malloc manages
4126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  memory from the system in page-size units.  This may be (and
4136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  usually is) a function rather than a constant. This is ignored
4146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if WIN32, where page size is determined using getSystemInfo during
4156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  initialization.
4166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
4176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoUSE_DEV_RANDOM             default: 0 (i.e., not used)
4186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Causes malloc to use /dev/random to initialize secure magic seed for
4196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  stamping footers. Otherwise, the current time is used.
4206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
4216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoNO_MALLINFO                default: 0
4226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If defined, don't compile "mallinfo". This can be a simple way
4236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  of dealing with mismatches between system declarations and
4246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  those in this file.
4256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
4266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoMALLINFO_FIELD_TYPE        default: size_t
4276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The type of the fields in the mallinfo struct. This was originally
4286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  defined as "int" in SVID etc, but is more usefully defined as
4296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t. The value is used only if  HAVE_USR_INCLUDE_MALLOC_H is not set
4306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
4316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoNO_MALLOC_STATS            default: 0
4326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If defined, don't compile "malloc_stats". This avoids calls to
4336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  fprintf and bringing in stdio dependencies you might not want.
4346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
4356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoREALLOC_ZERO_BYTES_FREES    default: not defined
4366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  This should be set if a call to realloc with zero bytes should
4376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  be the same as a call to free. Some people think it should. Otherwise,
4386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  since this malloc returns a unique pointer for malloc(0), so does
4396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  realloc(p, 0).
4406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
4416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoLACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H
4426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoLACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H,  LACKS_ERRNO_H
4436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoLACKS_STDLIB_H LACKS_SCHED_H LACKS_TIME_H  default: NOT defined unless on WIN32
4446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Define these if your system does not have these header files.
4456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  You might need to manually insert some of the declarations they provide.
4466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
4476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDEFAULT_GRANULARITY        default: page size if MORECORE_CONTIGUOUS,
4486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                system_info.dwAllocationGranularity in WIN32,
4496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                otherwise 64K.
4506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      Also settable using mallopt(M_GRANULARITY, x)
4516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The unit for allocating and deallocating memory from the system.  On
4526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  most systems with contiguous MORECORE, there is no reason to
4536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  make this more than a page. However, systems with MMAP tend to
4546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  either require or encourage larger granularities.  You can increase
4556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  this value to prevent system allocation functions to be called so
4566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  often, especially if they are slow.  The value must be at least one
4576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  page and must be a power of two.  Setting to 0 causes initialization
4586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  to either page size or win32 region size.  (Note: In previous
4596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  versions of malloc, the equivalent of this option was called
4606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  "TOP_PAD")
4616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
4626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDEFAULT_TRIM_THRESHOLD    default: 2MB
4636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      Also settable using mallopt(M_TRIM_THRESHOLD, x)
4646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The maximum amount of unused top-most memory to keep before
4656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  releasing via malloc_trim in free().  Automatic trimming is mainly
4666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  useful in long-lived programs using contiguous MORECORE.  Because
4676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  trimming via sbrk can be slow on some systems, and can sometimes be
4686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  wasteful (in cases where programs immediately afterward allocate
4696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  more large chunks) the value should be high enough so that your
4706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  overall system performance would improve by releasing this much
4716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  memory.  As a rough guide, you might set to a value close to the
4726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  average size of a process (program) running on your system.
4736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Releasing this much memory would allow such a process to run in
4746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  memory.  Generally, it is worth tuning trim thresholds when a
4756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  program undergoes phases where several large chunks are allocated
4766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  and released in ways that can reuse each other's storage, perhaps
4776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mixed with phases where there are no such chunks at all. The trim
4786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  value must be greater than page size to have any useful effect.  To
4796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  disable trimming completely, you can set to MAX_SIZE_T. Note that the trick
4806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  some people use of mallocing a huge space and then freeing it at
4816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  program startup, in an attempt to reserve system memory, doesn't
4826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  have the intended effect under automatic trimming, since that memory
4836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  will immediately be returned to the system.
4846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
4856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDEFAULT_MMAP_THRESHOLD       default: 256K
4866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      Also settable using mallopt(M_MMAP_THRESHOLD, x)
4876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The request size threshold for using MMAP to directly service a
4886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  request. Requests of at least this size that cannot be allocated
4896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  using already-existing space will be serviced via mmap.  (If enough
4906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  normal freed space already exists it is used instead.)  Using mmap
4916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  segregates relatively large chunks of memory so that they can be
4926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  individually obtained and released from the host system. A request
4936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  serviced through mmap is never reused by any other request (at least
4946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  not directly; the system may just so happen to remap successive
4956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  requests to the same locations).  Segregating space in this way has
4966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the benefits that: Mmapped space can always be individually released
4976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  back to the system, which helps keep the system level memory demands
4986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  of a long-lived program low.  Also, mapped memory doesn't become
4996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  `locked' between other chunks, as can happen with normally allocated
5006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  chunks, which means that even trimming via malloc_trim would not
5016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  release them.  However, it has the disadvantage that the space
5026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  cannot be reclaimed, consolidated, and then used to service later
5036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  requests, as happens with normal chunks.  The advantages of mmap
5046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  nearly always outweigh disadvantages for "large" chunks, but the
5056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  value of "large" may vary across systems.  The default is an
5066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  empirically derived value that works well in most systems. You can
5076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  disable mmap by setting to MAX_SIZE_T.
5086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
5096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoMAX_RELEASE_CHECK_RATE   default: 4095 unless not HAVE_MMAP
5106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The number of consolidated frees between checks to release
5116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  unused segments when freeing. When using non-contiguous segments,
5126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  especially with multiple mspaces, checking only for topmost space
5136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  doesn't always suffice to trigger trimming. To compensate for this,
5146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  free() will, with a period of MAX_RELEASE_CHECK_RATE (or the
5156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  current number of segments, if greater) try to release unused
5166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  segments to the OS when freeing chunks that result in
5176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  consolidation. The best value for this parameter is a compromise
5186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  between slowing down frees with relatively costly checks that
5196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  rarely trigger versus holding on to unused memory. To effectively
5206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  disable, set to MAX_SIZE_T. This may lead to a very slight speed
5216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  improvement at the expense of carrying around more memory.
5226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
5236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
5246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Version identifier to allow people to support multiple versions */
5256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef DLMALLOC_VERSION
5266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DLMALLOC_VERSION 20806
5276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* DLMALLOC_VERSION */
5286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
5296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef DLMALLOC_EXPORT
5306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DLMALLOC_EXPORT extern
5316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
5326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
5336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef WIN32
5346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef _WIN32
5356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define WIN32 1
5366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* _WIN32 */
5376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef _WIN32_WCE
5386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define LACKS_FCNTL_H
5396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define WIN32 1
5406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* _WIN32_WCE */
5416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* WIN32 */
5426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef WIN32
5436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define WIN32_LEAN_AND_MEAN
5446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <windows.h>
5456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <tchar.h>
5466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define HAVE_MMAP 1
5476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define HAVE_MORECORE 0
5486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define LACKS_UNISTD_H
5496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define LACKS_SYS_PARAM_H
5506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define LACKS_SYS_MMAN_H
5516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define LACKS_STRING_H
5526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define LACKS_STRINGS_H
5536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define LACKS_SYS_TYPES_H
5546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define LACKS_ERRNO_H
5556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define LACKS_SCHED_H
5566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MALLOC_FAILURE_ACTION
5576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MALLOC_FAILURE_ACTION
5586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MALLOC_FAILURE_ACTION */
5596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MMAP_CLEARS
5606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef _WIN32_WCE /* WINCE reportedly does not clear */
5616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MMAP_CLEARS 0
5626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else
5636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MMAP_CLEARS 1
5646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* _WIN32_WCE */
5656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /*MMAP_CLEARS */
5666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* WIN32 */
5676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
5686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if defined(DARWIN) || defined(_DARWIN)
5696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
5706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef HAVE_MORECORE
5716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define HAVE_MORECORE 0
5726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define HAVE_MMAP 1
5736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* OSX allocators provide 16 byte alignment */
5746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MALLOC_ALIGNMENT
5756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MALLOC_ALIGNMENT ((size_t)16U)
5766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
5776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* HAVE_MORECORE */
5786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* DARWIN */
5796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
5806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef LACKS_SYS_TYPES_H
5816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <sys/types.h>  /* For size_t */
5826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* LACKS_SYS_TYPES_H */
5836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
5846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* The maximum possible size_t value has all bits set */
5856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MAX_SIZE_T           (~(size_t)0)
5866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
5876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef USE_LOCKS /* ensure true if spin or recursive locks set */
5886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define USE_LOCKS  ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \
5896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                    (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0))
5906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_LOCKS */
5916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
5926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */
5936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if ((defined(__GNUC__) &&                                              \
5946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) ||      \
5956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       defined(__i386__) || defined(__x86_64__))) ||                    \
5966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     (defined(_MSC_VER) && _MSC_VER>=1310))
5976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef USE_SPIN_LOCKS
5986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define USE_SPIN_LOCKS 1
5996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_SPIN_LOCKS */
6006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif USE_SPIN_LOCKS
6016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#error "USE_SPIN_LOCKS defined without implementation"
6026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* ... locks available... */
6036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif !defined(USE_SPIN_LOCKS)
6046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define USE_SPIN_LOCKS 0
6056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_LOCKS */
6066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
6076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef ONLY_MSPACES
6086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ONLY_MSPACES 0
6096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* ONLY_MSPACES */
6106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MSPACES
6116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if ONLY_MSPACES
6126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MSPACES 1
6136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else   /* ONLY_MSPACES */
6146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MSPACES 0
6156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* ONLY_MSPACES */
6166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* MSPACES */
6176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MALLOC_ALIGNMENT
6186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *)))
6196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* MALLOC_ALIGNMENT */
6206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef FOOTERS
6216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define FOOTERS 0
6226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* FOOTERS */
6236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef ABORT
6246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ABORT  abort()
6256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* ABORT */
6266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef ABORT_ON_ASSERT_FAILURE
6276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ABORT_ON_ASSERT_FAILURE 1
6286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* ABORT_ON_ASSERT_FAILURE */
6296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef PROCEED_ON_ERROR
6306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define PROCEED_ON_ERROR 0
6316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* PROCEED_ON_ERROR */
6326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
6336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef INSECURE
6346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define INSECURE 0
6356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* INSECURE */
6366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MALLOC_INSPECT_ALL
6376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MALLOC_INSPECT_ALL 0
6386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* MALLOC_INSPECT_ALL */
6396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef HAVE_MMAP
6406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define HAVE_MMAP 1
6416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* HAVE_MMAP */
6426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MMAP_CLEARS
6436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MMAP_CLEARS 1
6446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* MMAP_CLEARS */
6456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef HAVE_MREMAP
6466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef linux
6476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define HAVE_MREMAP 1
6486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define _GNU_SOURCE /* Turns on mremap() definition */
6496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else   /* linux */
6506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define HAVE_MREMAP 0
6516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* linux */
6526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* HAVE_MREMAP */
6536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MALLOC_FAILURE_ACTION
6546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MALLOC_FAILURE_ACTION  errno = ENOMEM;
6556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* MALLOC_FAILURE_ACTION */
6566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef HAVE_MORECORE
6576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if ONLY_MSPACES
6586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define HAVE_MORECORE 0
6596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else   /* ONLY_MSPACES */
6606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define HAVE_MORECORE 1
6616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* ONLY_MSPACES */
6626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* HAVE_MORECORE */
6636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !HAVE_MORECORE
6646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MORECORE_CONTIGUOUS 0
6656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else   /* !HAVE_MORECORE */
6666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MORECORE_DEFAULT sbrk
6676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MORECORE_CONTIGUOUS
6686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MORECORE_CONTIGUOUS 1
6696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* MORECORE_CONTIGUOUS */
6706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* HAVE_MORECORE */
6716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef DEFAULT_GRANULARITY
6726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if (MORECORE_CONTIGUOUS || defined(WIN32))
6736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DEFAULT_GRANULARITY (0)  /* 0 means to compute in init_mparams */
6746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else   /* MORECORE_CONTIGUOUS */
6756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
6766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* MORECORE_CONTIGUOUS */
6776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* DEFAULT_GRANULARITY */
6786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef DEFAULT_TRIM_THRESHOLD
6796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MORECORE_CANNOT_TRIM
6806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
6816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else   /* MORECORE_CANNOT_TRIM */
6826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
6836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* MORECORE_CANNOT_TRIM */
6846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* DEFAULT_TRIM_THRESHOLD */
6856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef DEFAULT_MMAP_THRESHOLD
6866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if HAVE_MMAP
6876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
6886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else   /* HAVE_MMAP */
6896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
6906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* HAVE_MMAP */
6916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* DEFAULT_MMAP_THRESHOLD */
6926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MAX_RELEASE_CHECK_RATE
6936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if HAVE_MMAP
6946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MAX_RELEASE_CHECK_RATE 4095
6956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else
6966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MAX_RELEASE_CHECK_RATE MAX_SIZE_T
6976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* HAVE_MMAP */
6986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MAX_RELEASE_CHECK_RATE */
6996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef USE_BUILTIN_FFS
7006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define USE_BUILTIN_FFS 0
7016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* USE_BUILTIN_FFS */
7026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef USE_DEV_RANDOM
7036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define USE_DEV_RANDOM 0
7046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* USE_DEV_RANDOM */
7056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef NO_MALLINFO
7066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define NO_MALLINFO 0
7076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* NO_MALLINFO */
7086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MALLINFO_FIELD_TYPE
7096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MALLINFO_FIELD_TYPE size_t
7106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* MALLINFO_FIELD_TYPE */
7116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef NO_MALLOC_STATS
7126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define NO_MALLOC_STATS 0
7136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* NO_MALLOC_STATS */
7146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef NO_SEGMENT_TRAVERSAL
7156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define NO_SEGMENT_TRAVERSAL 0
7166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* NO_SEGMENT_TRAVERSAL */
7176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
7186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
7196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mallopt tuning options.  SVID/XPG defines four standard parameter
7206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  numbers for mallopt, normally defined in malloc.h.  None of these
7216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  are used in this malloc, so setting them has no effect. But this
7226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc does support the following options.
7236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
7246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
7256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define M_TRIM_THRESHOLD     (-1)
7266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define M_GRANULARITY        (-2)
7276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define M_MMAP_THRESHOLD     (-3)
7286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
7296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ------------------------ Mallinfo declarations ------------------------ */
7306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
7316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !NO_MALLINFO
7326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
7336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  This version of malloc supports the standard SVID/XPG mallinfo
7346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  routine that returns a struct containing usage properties and
7356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  statistics. It should work on any system that has a
7366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /usr/include/malloc.h defining struct mallinfo.  The main
7376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  declaration needed is the mallinfo struct that is returned (by-copy)
7386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  by mallinfo().  The malloinfo struct contains a bunch of fields that
7396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  are not even meaningful in this version of malloc.  These fields are
7406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  are instead filled by mallinfo() with other numbers that might be of
7416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  interest.
7426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
7436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
7446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /usr/include/malloc.h file that includes a declaration of struct
7456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mallinfo.  If so, it is included; else a compliant version is
7466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  declared below.  These must be precisely the same for mallinfo() to
7476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  work.  The original SVID version of this struct, defined on most
7486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  systems with mallinfo, declares all fields as ints. But some others
7496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  define as unsigned long. If your system defines the fields using a
7506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  type of different width than listed here, you MUST #include your
7516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  system version and #define HAVE_USR_INCLUDE_MALLOC_H.
7526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
7536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
7546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* #define HAVE_USR_INCLUDE_MALLOC_H */
7556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
7566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef HAVE_USR_INCLUDE_MALLOC_H
7576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include "/usr/include/malloc.h"
7586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* HAVE_USR_INCLUDE_MALLOC_H */
7596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef STRUCT_MALLINFO_DECLARED
7606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* HP-UX (and others?) redefines mallinfo unless _STRUCT_MALLINFO is defined */
7616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define _STRUCT_MALLINFO
7626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define STRUCT_MALLINFO_DECLARED 1
7636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostruct mallinfo {
7646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MALLINFO_FIELD_TYPE arena;    /* non-mmapped space allocated from system */
7656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MALLINFO_FIELD_TYPE ordblks;  /* number of free chunks */
7666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MALLINFO_FIELD_TYPE smblks;   /* always 0 */
7676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MALLINFO_FIELD_TYPE hblks;    /* always 0 */
7686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MALLINFO_FIELD_TYPE hblkhd;   /* space in mmapped regions */
7696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MALLINFO_FIELD_TYPE usmblks;  /* maximum total allocated space */
7706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MALLINFO_FIELD_TYPE fsmblks;  /* always 0 */
7716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
7726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MALLINFO_FIELD_TYPE fordblks; /* total free space */
7736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
7746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao};
7756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* STRUCT_MALLINFO_DECLARED */
7766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* HAVE_USR_INCLUDE_MALLOC_H */
7776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* NO_MALLINFO */
7786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
7796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
7806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Try to persuade compilers to inline. The most critical functions for
7816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  inlining are defined as macros, so these aren't used for them.
7826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
7836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
7846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef FORCEINLINE
7856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  #if defined(__GNUC__)
7866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define FORCEINLINE __inline __attribute__ ((always_inline))
7876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  #elif defined(_MSC_VER)
7886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define FORCEINLINE __forceinline
7896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  #endif
7906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
7916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef NOINLINE
7926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  #if defined(__GNUC__)
7936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define NOINLINE __attribute__ ((noinline))
7946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  #elif defined(_MSC_VER)
7956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define NOINLINE __declspec(noinline)
7966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  #else
7976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define NOINLINE
7986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  #endif
7996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
8006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef __cplusplus
8026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoextern "C" {
8036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef FORCEINLINE
8046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao #define FORCEINLINE inline
8056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
8066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* __cplusplus */
8076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef FORCEINLINE
8086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao #define FORCEINLINE
8096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
8106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !ONLY_MSPACES
8126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ------------------- Declarations of public routines ------------------- */
8146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef USE_DL_PREFIX
8166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlcalloc               calloc
8176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlfree                 free
8186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmalloc               malloc
8196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmemalign             memalign
8206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlposix_memalign       posix_memalign
8216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlrealloc              realloc
8226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlrealloc_in_place     realloc_in_place
8236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlvalloc               valloc
8246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlpvalloc              pvalloc
8256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmallinfo             mallinfo
8266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmallopt              mallopt
8276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmalloc_trim          malloc_trim
8286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmalloc_stats         malloc_stats
8296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmalloc_usable_size   malloc_usable_size
8306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmalloc_footprint     malloc_footprint
8316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmalloc_max_footprint malloc_max_footprint
8326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmalloc_footprint_limit malloc_footprint_limit
8336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmalloc_set_footprint_limit malloc_set_footprint_limit
8346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlmalloc_inspect_all   malloc_inspect_all
8356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlindependent_calloc   independent_calloc
8366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlindependent_comalloc independent_comalloc
8376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define dlbulk_free            bulk_free
8386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_DL_PREFIX */
8396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
8416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc(size_t n)
8426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Returns a pointer to a newly allocated chunk of at least n bytes, or
8436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  null if no space is available, in which case errno is set to ENOMEM
8446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  on ANSI C systems.
8456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If n is zero, malloc returns a minimum-sized chunk. (The minimum
8476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
8486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  systems.)  Note that size_t is an unsigned type, so calls with
8496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  arguments that would be negative if signed are interpreted as
8506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  requests for huge amounts of space, which will often fail. The
8516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  maximum supported value of n differs across systems, but is in all
8526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  cases less than the maximum representable value of a size_t.
8536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
8546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void* dlmalloc(size_t);
8556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
8576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  free(void* p)
8586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Releases the chunk of memory pointed to by p, that had been previously
8596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  allocated using malloc or a related routine such as realloc.
8606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  It has no effect if p is null. If p was not malloced or already
8616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  freed, free(p) will by default cause the current program to abort.
8626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
8636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void  dlfree(void*);
8646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
8666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  calloc(size_t n_elements, size_t element_size);
8676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Returns a pointer to n_elements * element_size bytes, with all locations
8686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  set to zero.
8696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
8706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void* dlcalloc(size_t, size_t);
8716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
8736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  realloc(void* p, size_t n)
8746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Returns a pointer to a chunk of size n that contains the same data
8756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  as does chunk p up to the minimum of (n, p's size) bytes, or null
8766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if no space is available.
8776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The returned pointer may or may not be the same as p. The algorithm
8796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  prefers extending p in most cases when possible, otherwise it
8806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  employs the equivalent of a malloc-copy-free sequence.
8816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If p is null, realloc is equivalent to malloc.
8836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If space is not available, realloc returns null, errno is set (if on
8856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ANSI) and p is NOT freed.
8866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if n is for fewer bytes than already held by p, the newly unused
8886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  space is lopped off and freed if possible.  realloc with a size
8896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  argument of zero (re)allocates a minimum-sized chunk.
8906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The old unix realloc convention of allowing the last-free'd chunk
8926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  to be used as an argument to realloc is not supported.
8936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
8946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void* dlrealloc(void*, size_t);
8956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
8966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
8976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  realloc_in_place(void* p, size_t n)
8986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Resizes the space allocated for p to size n, only if this can be
8996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  done without moving p (i.e., only if there is adjacent space
9006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  available if n is greater than p's current allocated size, or n is
9016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  less than or equal to p's size). This may be used instead of plain
9026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  realloc if an alternative allocation strategy is needed upon failure
9036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  to expand space; for example, reallocation of a buffer that must be
9046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  memory-aligned or cleared. You can use realloc_in_place to trigger
9056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  these alternatives only when needed.
9066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Returns p if successful; otherwise null.
9086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
9096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void* dlrealloc_in_place(void*, size_t);
9106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
9126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  memalign(size_t alignment, size_t n);
9136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Returns a pointer to a newly allocated chunk of n bytes, aligned
9146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  in accord with the alignment argument.
9156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The alignment argument should be a power of two. If the argument is
9176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  not a power of two, the nearest greater power is used.
9186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  8-byte alignment is guaranteed by normal malloc calls, so don't
9196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bother calling memalign with an argument of 8 or less.
9206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Overreliance on memalign is a sure way to fragment space.
9226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
9236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void* dlmemalign(size_t, size_t);
9246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
9266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int posix_memalign(void** pp, size_t alignment, size_t n);
9276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Allocates a chunk of n bytes, aligned in accord with the alignment
9286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  argument. Differs from memalign only in that it (1) assigns the
9296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  allocated memory to *pp rather than returning it, (2) fails and
9306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  returns EINVAL if the alignment is not a power of two (3) fails and
9316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  returns ENOMEM if memory cannot be allocated.
9326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
9336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT int dlposix_memalign(void**, size_t, size_t);
9346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
9366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  valloc(size_t n);
9376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Equivalent to memalign(pagesize, n), where pagesize is the page
9386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size of the system. If the pagesize is unknown, 4096 is used.
9396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
9406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void* dlvalloc(size_t);
9416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
9436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mallopt(int parameter_number, int parameter_value)
9446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Sets tunable parameters The format is to provide a
9456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (parameter-number, parameter-value) pair.  mallopt then sets the
9466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  corresponding parameter to the argument value if it can (i.e., so
9476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  long as the value is meaningful), and returns 1 if successful else
9486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  0.  To workaround the fact that mallopt is specified to use int,
9496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  not size_t parameters, the value -1 is specially treated as the
9506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  maximum unsigned size_t value.
9516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  SVID/XPG/ANSI defines four standard param numbers for mallopt,
9536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  normally defined in malloc.h.  None of these are use in this malloc,
9546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  so setting them has no effect. But this malloc also supports other
9556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  options in mallopt. See below for details.  Briefly, supported
9566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  parameters are as follows (listed defaults are for "typical"
9576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  configurations).
9586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Symbol            param #  default    allowed param values
9606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  M_TRIM_THRESHOLD     -1   2*1024*1024   any   (-1 disables)
9616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  M_GRANULARITY        -2     page size   any power of 2 >= page size
9626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  M_MMAP_THRESHOLD     -3      256*1024   any   (or 0 if no MMAP support)
9636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
9646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT int dlmallopt(int, int);
9656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
9676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_footprint();
9686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Returns the number of bytes obtained from the system.  The total
9696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  number of bytes allocated by malloc, realloc etc., is less than this
9706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  value. Unlike mallinfo, this function returns only a precomputed
9716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  result, so can be called frequently to monitor memory consumption.
9726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Even if locks are otherwise defined, this function does not use them,
9736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  so results might not be up to date.
9746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
9756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT size_t dlmalloc_footprint(void);
9766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
9786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_max_footprint();
9796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Returns the maximum number of bytes obtained from the system. This
9806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  value will be greater than current footprint if deallocated space
9816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  has been reclaimed by the system. The peak number of bytes allocated
9826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  by malloc, realloc etc., is less than this value. Unlike mallinfo,
9836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  this function returns only a precomputed result, so can be called
9846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  frequently to monitor memory consumption.  Even if locks are
9856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  otherwise defined, this function does not use them, so results might
9866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  not be up to date.
9876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
9886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT size_t dlmalloc_max_footprint(void);
9896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
9906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
9916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_footprint_limit();
9926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Returns the number of bytes that the heap is allowed to obtain from
9936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the system, returning the last value returned by
9946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_set_footprint_limit, or the maximum size_t value if
9956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  never set. The returned value reflects a permission. There is no
9966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  guarantee that this number of bytes can actually be obtained from
9976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the system.
9986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
9996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT size_t dlmalloc_footprint_limit();
10006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
10026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_set_footprint_limit();
10036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Sets the maximum number of bytes to obtain from the system, causing
10046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  failure returns from malloc and related functions upon attempts to
10056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  exceed this value. The argument value may be subject to page
10066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  rounding to an enforceable limit; this actual value is returned.
10076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Using an argument of the maximum possible size_t effectively
10086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  disables checks. If the argument is less than or equal to the
10096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  current malloc_footprint, then all future allocations that require
10106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  additional system memory will fail. However, invocation cannot
10116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  retroactively deallocate existing used memory.
10126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
10136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT size_t dlmalloc_set_footprint_limit(size_t bytes);
10146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if MALLOC_INSPECT_ALL
10166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
10176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_inspect_all(void(*handler)(void *start,
10186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                    void *end,
10196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                    size_t used_bytes,
10206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                    void* callback_arg),
10216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                      void* arg);
10226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Traverses the heap and calls the given handler for each managed
10236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  region, skipping all bytes that are (or may be) used for bookkeeping
10246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  purposes.  Traversal does not include include chunks that have been
10256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  directly memory mapped. Each reported region begins at the start
10266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  address, and continues up to but not including the end address.  The
10276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  first used_bytes of the region contain allocated data. If
10286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  used_bytes is zero, the region is unallocated. The handler is
10296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  invoked with the given callback argument. If locks are defined, they
10306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  are held during the entire traversal. It is a bad idea to invoke
10316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  other malloc functions from within the handler.
10326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  For example, to count the number of in-use chunks with size greater
10346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  than 1000, you could write:
10356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  static int count = 0;
10366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void count_chunks(void* start, void* end, size_t used, void* arg) {
10376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (used >= 1000) ++count;
10386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
10396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  then:
10406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    malloc_inspect_all(count_chunks, NULL);
10416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_inspect_all is compiled only if MALLOC_INSPECT_ALL is defined.
10436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
10446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*),
10456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                           void* arg);
10466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MALLOC_INSPECT_ALL */
10486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !NO_MALLINFO
10506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
10516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mallinfo()
10526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Returns (by copy) a struct containing various summary statistics:
10536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  arena:     current total non-mmapped bytes allocated from system
10556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ordblks:   the number of free chunks
10566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  smblks:    always zero.
10576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  hblks:     current number of mmapped regions
10586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  hblkhd:    total bytes held in mmapped regions
10596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  usmblks:   the maximum total allocated space. This will be greater
10606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                than current total if trimming has occurred.
10616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  fsmblks:   always zero
10626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  uordblks:  current total allocated space (normal or mmapped)
10636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  fordblks:  total free space
10646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  keepcost:  the maximum number of bytes that could ideally be released
10656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao               back to system via malloc_trim. ("ideally" means that
10666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao               it ignores page restrictions etc.)
10676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Because these fields are ints, but internal bookkeeping may
10696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  be kept as longs, the reported values may wrap around zero and
10706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  thus be inaccurate.
10716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
10726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT struct mallinfo dlmallinfo(void);
10736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* NO_MALLINFO */
10746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
10766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
10776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  independent_calloc is similar to calloc, but instead of returning a
10796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  single cleared space, it returns an array of pointers to n_elements
10806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  independent elements that can hold contents of size elem_size, each
10816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  of which starts out cleared, and can be independently freed,
10826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  realloc'ed etc. The elements are guaranteed to be adjacently
10836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  allocated (this is not guaranteed to occur with multiple callocs or
10846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mallocs), which may also improve cache locality in some
10856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  applications.
10866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The "chunks" argument is optional (i.e., may be null, which is
10886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  probably the most typical usage). If it is null, the returned array
10896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  is itself dynamically allocated and should also be freed when it is
10906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  no longer needed. Otherwise, the chunks array must be of at least
10916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  n_elements in length. It is filled in with the pointers to the
10926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  chunks.
10936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  In either case, independent_calloc returns this pointer array, or
10956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  null if the allocation failed.  If n_elements is zero and "chunks"
10966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  is null, it returns a chunk representing an array with zero elements
10976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (which should be freed if not wanted).
10986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
10996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Each element must be freed when it is no longer needed. This can be
11006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  done all at once using bulk_free.
11016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  independent_calloc simplifies and speeds up implementations of many
11036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  kinds of pools.  It may also be useful when constructing large data
11046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  structures that initially have a fixed number of fixed-sized nodes,
11056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  but the number is not known at compile time, and some of the nodes
11066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  may later need to be freed. For example:
11076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct Node { int item; struct Node* next; };
11096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct Node* build_list() {
11116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    struct Node** pool;
11126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    int n = read_number_of_nodes_needed();
11136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (n <= 0) return 0;
11146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
11156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (pool == 0) die();
11166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    // organize into a linked list...
11176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    struct Node* first = pool[0];
11186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    for (i = 0; i < n-1; ++i)
11196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      pool[i]->next = pool[i+1];
11206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    free(pool);     // Can now free the array (or not, if it is needed later)
11216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return first;
11226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
11236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
11246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void** dlindependent_calloc(size_t, size_t, void**);
11256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
11276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
11286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  independent_comalloc allocates, all at once, a set of n_elements
11306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  chunks with sizes indicated in the "sizes" array.    It returns
11316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  an array of pointers to these elements, each of which can be
11326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  independently freed, realloc'ed etc. The elements are guaranteed to
11336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  be adjacently allocated (this is not guaranteed to occur with
11346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  multiple callocs or mallocs), which may also improve cache locality
11356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  in some applications.
11366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The "chunks" argument is optional (i.e., may be null). If it is null
11386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the returned array is itself dynamically allocated and should also
11396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  be freed when it is no longer needed. Otherwise, the chunks array
11406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  must be of at least n_elements in length. It is filled in with the
11416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  pointers to the chunks.
11426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  In either case, independent_comalloc returns this pointer array, or
11446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  null if the allocation failed.  If n_elements is zero and chunks is
11456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  null, it returns a chunk representing an array with zero elements
11466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (which should be freed if not wanted).
11476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Each element must be freed when it is no longer needed. This can be
11496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  done all at once using bulk_free.
11506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  independent_comallac differs from independent_calloc in that each
11526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  element may have a different size, and also that it does not
11536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  automatically clear elements.
11546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  independent_comalloc can be used to speed up allocation in cases
11566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  where several structs or objects must always be allocated at the
11576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  same time.  For example:
11586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct Head { ... }
11606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct Foot { ... }
11616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void send_message(char* msg) {
11636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    int msglen = strlen(msg);
11646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
11656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    void* chunks[3];
11666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (independent_comalloc(3, sizes, chunks) == 0)
11676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      die();
11686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    struct Head* head = (struct Head*)(chunks[0]);
11696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    char*        body = (char*)(chunks[1]);
11706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    struct Foot* foot = (struct Foot*)(chunks[2]);
11716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    // ...
11726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
11736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  In general though, independent_comalloc is worth using only for
11756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  larger values of n_elements. For small values, you probably won't
11766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  detect enough difference from series of malloc calls to bother.
11776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Overuse of independent_comalloc can increase overall memory usage,
11796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  since it cannot reuse existing noncontiguous small chunks that
11806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  might be available for some of the elements.
11816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
11826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void** dlindependent_comalloc(size_t, size_t*, void**);
11836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
11856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bulk_free(void* array[], size_t n_elements)
11866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Frees and clears (sets to null) each non-null pointer in the given
11876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  array.  This is likely to be faster than freeing them one-by-one.
11886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If footers are used, pointers that have been allocated in different
11896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspaces are not freed or cleared, and the count of all such pointers
11906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  is returned.  For large arrays of pointers with poor locality, it
11916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  may be worthwhile to sort this array before calling bulk_free.
11926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
11936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT size_t  dlbulk_free(void**, size_t n_elements);
11946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
11956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
11966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  pvalloc(size_t n);
11976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Equivalent to valloc(minimum-page-that-holds(n)), that is,
11986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  round up n to nearest pagesize.
11996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao */
12006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void*  dlpvalloc(size_t);
12016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
12036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_trim(size_t pad);
12046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If possible, gives memory back to the system (via negative arguments
12066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  to sbrk) if there is unused memory at the `high' end of the malloc
12076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  pool or in unused MMAP segments. You can call this after freeing
12086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  large blocks of memory to potentially reduce the system-level memory
12096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  requirements of a program. However, it cannot guarantee to reduce
12106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  memory. Under some allocation patterns, some large free blocks of
12116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  memory will be locked between two used chunks, so they cannot be
12126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  given back to the system.
12136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The `pad' argument to malloc_trim represents the amount of free
12156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  trailing space to leave untrimmed. If this argument is zero, only
12166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the minimum amount of memory to maintain internal data structures
12176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  will be left. Non-zero arguments can be supplied to maintain enough
12186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  trailing space to service future expected allocations without having
12196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  to re-obtain memory from the system.
12206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Malloc_trim returns 1 if it actually released any memory, else 0.
12226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
12236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT int  dlmalloc_trim(size_t);
12246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
12266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_stats();
12276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Prints on stderr the amount of space obtained from the system (both
12286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  via sbrk and mmap), the maximum amount (which may be more than
12296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  current if malloc_trim and/or munmap got called), and the current
12306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  number of bytes allocated via malloc (or realloc, etc) but not yet
12316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  freed. Note that this is the number of bytes allocated, not the
12326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  number requested. It will be larger than the number requested
12336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  because of alignment and bookkeeping overhead. Because it includes
12346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  alignment wastage as being in use, this figure may be greater than
12356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  zero even when no user-level chunks are allocated.
12366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The reported current and maximum system memory can be inaccurate if
12386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  a program makes other calls to system memory allocation functions
12396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (normally sbrk) outside of malloc.
12406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_stats prints only the most commonly interesting statistics.
12426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  More information can be obtained by calling mallinfo.
12436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
12446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void  dlmalloc_stats(void);
12456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
12476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_usable_size(void* p);
12486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Returns the number of bytes you can actually use in
12506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  an allocated chunk, which may be more than you requested (although
12516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  often not) due to alignment and minimum size constraints.
12526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  You can use this many bytes without worrying about
12536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  overwriting other allocated objects. This is not a particularly great
12546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  programming practice. malloc_usable_size can be more useful in
12556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  debugging and assertions, for example:
12566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  p = malloc(n);
12586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(malloc_usable_size(p) >= 256);
12596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
12606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* BEGIN android-changed: added const */
12616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t dlmalloc_usable_size(const void*);
12626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* END android-change */
12636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* ONLY_MSPACES */
12656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if MSPACES
12676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
12696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace is an opaque type representing an independent
12706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  region of space that supports mspace_malloc, etc.
12716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
12726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef void* mspace;
12736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
12756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  create_mspace creates and returns a new independent space with the
12766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  given initial capacity, or, if 0, the default granularity size.  It
12776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  returns null if there is no system memory available to create the
12786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  space.  If argument locked is non-zero, the space uses a separate
12796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  lock to control access. The capacity of the space will grow
12806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  dynamically as needed to service mspace_malloc requests.  You can
12816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  control the sizes of incremental increases of this space by
12826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  compiling with a different DEFAULT_GRANULARITY or dynamically
12836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  setting with mallopt(M_GRANULARITY, value).
12846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
12856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT mspace create_mspace(size_t capacity, int locked);
12866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
12886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  destroy_mspace destroys the given space, and attempts to return all
12896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  of its memory back to the system, returning the total number of
12906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bytes freed. After destruction, the results of access to all memory
12916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  used by the space become undefined.
12926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
12936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT size_t destroy_mspace(mspace msp);
12946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
12956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
12966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  create_mspace_with_base uses the memory supplied as the initial base
12976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
12986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  space is used for bookkeeping, so the capacity must be at least this
12996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  large. (Otherwise 0 is returned.) When this initial space is
13006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  exhausted, additional memory will be obtained from the system.
13016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Destroying this space will deallocate all additionally allocated
13026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  space (if possible) but not the initial base.
13036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT mspace create_mspace_with_base(void* base, size_t capacity, int locked);
13056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_track_large_chunks controls whether requests for large chunks
13086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  are allocated in their own untracked mmapped regions, separate from
13096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  others in this mspace. By default large chunks are not tracked,
13106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  which reduces fragmentation. However, such chunks are not
13116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  necessarily released to the system upon destroy_mspace.  Enabling
13126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tracking by setting to true may increase fragmentation, but avoids
13136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  leakage when relying on destroy_mspace to release all memory
13146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  allocated using this space.  The function returns the previous
13156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  setting.
13166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT int mspace_track_large_chunks(mspace msp, int enable);
13186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_malloc behaves as malloc, but operates within
13226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the given space.
13236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void* mspace_malloc(mspace msp, size_t bytes);
13256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_free behaves as free, but operates within
13286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the given space.
13296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If compiled with FOOTERS==1, mspace_free is not actually needed.
13316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  free may be called instead of mspace_free because freed chunks from
13326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  any space are handled by their originating spaces.
13336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void mspace_free(mspace msp, void* mem);
13356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_realloc behaves as realloc, but operates within
13386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the given space.
13396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If compiled with FOOTERS==1, mspace_realloc is not actually
13416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  needed.  realloc may be called instead of mspace_realloc because
13426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  realloced chunks from any space are handled by their originating
13436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  spaces.
13446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void* mspace_realloc(mspace msp, void* mem, size_t newsize);
13466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_calloc behaves as calloc, but operates within
13496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the given space.
13506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
13526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_memalign behaves as memalign, but operates within
13556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the given space.
13566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
13586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_independent_calloc behaves as independent_calloc, but
13616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  operates within the given space.
13626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void** mspace_independent_calloc(mspace msp, size_t n_elements,
13646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                 size_t elem_size, void* chunks[]);
13656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_independent_comalloc behaves as independent_comalloc, but
13686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  operates within the given space.
13696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void** mspace_independent_comalloc(mspace msp, size_t n_elements,
13716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                   size_t sizes[], void* chunks[]);
13726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_footprint() returns the number of bytes obtained from the
13756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  system for this space.
13766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT size_t mspace_footprint(mspace msp);
13786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_max_footprint() returns the peak number of bytes obtained from the
13816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  system for this space.
13826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT size_t mspace_max_footprint(mspace msp);
13846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !NO_MALLINFO
13876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_mallinfo behaves as mallinfo, but reports properties of
13896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the given space.
13906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT struct mallinfo mspace_mallinfo(mspace msp);
13926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* NO_MALLINFO */
13936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
13956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_usable_size(void* p) behaves the same as malloc_usable_size;
13966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
13976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT size_t mspace_usable_size(const void* mem);
13986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
13996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
14006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_malloc_stats behaves as malloc_stats, but reports
14016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  properties of the given space.
14026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
14036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT void mspace_malloc_stats(mspace msp);
14046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
14056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
14066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace_trim behaves as malloc_trim, but
14076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  operates within the given space.
14086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
14096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT int mspace_trim(mspace msp, size_t pad);
14106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
14116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
14126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  An alias for mallopt.
14136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
14146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoDLMALLOC_EXPORT int mspace_mallopt(int, int);
14156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
14166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MSPACES */
14176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
14186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef __cplusplus
14196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}  /* end of extern "C" */
14206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* __cplusplus */
14216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
14226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
14236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ========================================================================
14246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  To make a fully customizable malloc.h header file, cut everything
14256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  above this line, put into file malloc.h, edit to suit, and #include it
14266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  on the next line, as well as in programs that use this malloc.
14276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ========================================================================
14286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
14296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
14306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* #include "malloc.h" */
14316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
14326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*------------------------------ internal #includes ---------------------- */
14336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
14346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef _MSC_VER
14356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#pragma warning( disable : 4146 ) /* no "unsigned" warnings */
14366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* _MSC_VER */
14376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !NO_MALLOC_STATS
14386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <stdio.h>       /* for printing in malloc_stats */
14396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* NO_MALLOC_STATS */
14406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef LACKS_ERRNO_H
14416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <errno.h>       /* for MALLOC_FAILURE_ACTION */
14426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* LACKS_ERRNO_H */
14436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef DEBUG
14446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if ABORT_ON_ASSERT_FAILURE
14456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#undef assert
14466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define assert(x) if(!(x)) ABORT
14476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* ABORT_ON_ASSERT_FAILURE */
14486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <assert.h>
14496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* ABORT_ON_ASSERT_FAILURE */
14506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else  /* DEBUG */
14516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef assert
14526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define assert(x)
14536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
14546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DEBUG 0
14556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* DEBUG */
14566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !defined(WIN32) && !defined(LACKS_TIME_H)
14576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <time.h>        /* for magic initialization */
14586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* WIN32 */
14596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef LACKS_STDLIB_H
14606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <stdlib.h>      /* for abort() */
14616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* LACKS_STDLIB_H */
14626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef LACKS_STRING_H
14636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <string.h>      /* for memset etc */
14646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* LACKS_STRING_H */
14656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if USE_BUILTIN_FFS
14666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef LACKS_STRINGS_H
14676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <strings.h>     /* for ffs */
14686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* LACKS_STRINGS_H */
14696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_BUILTIN_FFS */
14706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if HAVE_MMAP
14716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef LACKS_SYS_MMAN_H
14726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */
14736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if (defined(linux) && !defined(__USE_GNU))
14746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define __USE_GNU 1
14756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <sys/mman.h>    /* for mmap */
14766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#undef __USE_GNU
14776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else
14786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <sys/mman.h>    /* for mmap */
14796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* linux */
14806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* LACKS_SYS_MMAN_H */
14816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef LACKS_FCNTL_H
14826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <fcntl.h>
14836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* LACKS_FCNTL_H */
14846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* HAVE_MMAP */
14856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef LACKS_UNISTD_H
14866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <unistd.h>     /* for sbrk, sysconf */
14876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* LACKS_UNISTD_H */
14886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
14896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoextern void*     sbrk(ptrdiff_t);
14906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* FreeBSD etc */
14916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* LACKS_UNISTD_H */
14926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
14936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Declarations for locking */
14946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if USE_LOCKS
14956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef WIN32
14966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if defined (__SVR4) && defined (__sun)  /* solaris */
14976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <thread.h>
14986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif !defined(LACKS_SCHED_H)
14996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <sched.h>
15006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* solaris or LACKS_SCHED_H */
15016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0) || !USE_SPIN_LOCKS
15026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#include <pthread.h>
15036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_RECURSIVE_LOCKS ... */
15046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif defined(_MSC_VER)
15056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef _M_AMD64
15066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* These are already defined on AMD64 builds */
15076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef __cplusplus
15086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoextern "C" {
15096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* __cplusplus */
15106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoLONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp);
15116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoLONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value);
15126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef __cplusplus
15136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
15146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* __cplusplus */
15156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* _M_AMD64 */
15166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#pragma intrinsic (_InterlockedCompareExchange)
15176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#pragma intrinsic (_InterlockedExchange)
15186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define interlockedcompareexchange _InterlockedCompareExchange
15196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define interlockedexchange _InterlockedExchange
15206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif defined(WIN32) && defined(__GNUC__)
15216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
15226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define interlockedexchange __sync_lock_test_and_set
15236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* Win32 */
15246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* USE_LOCKS */
15256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_LOCKS */
15266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
15276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef LOCK_AT_FORK
15286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define LOCK_AT_FORK 0
15296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
15306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
15316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Declarations for bit scanning on win32 */
15326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if defined(_MSC_VER) && _MSC_VER>=1300
15336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef BitScanForward /* Try to avoid pulling in WinNT.h */
15346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef __cplusplus
15356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoextern "C" {
15366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* __cplusplus */
15376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaounsigned char _BitScanForward(unsigned long *index, unsigned long mask);
15386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaounsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
15396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef __cplusplus
15406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
15416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* __cplusplus */
15426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
15436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define BitScanForward _BitScanForward
15446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define BitScanReverse _BitScanReverse
15456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#pragma intrinsic(_BitScanForward)
15466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#pragma intrinsic(_BitScanReverse)
15476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* BitScanForward */
15486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* defined(_MSC_VER) && _MSC_VER>=1300 */
15496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
15506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef WIN32
15516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef malloc_getpagesize
15526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
15536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#    ifndef _SC_PAGE_SIZE
15546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#      define _SC_PAGE_SIZE _SC_PAGESIZE
15556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#    endif
15566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#  endif
15576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#  ifdef _SC_PAGE_SIZE
15586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
15596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#  else
15606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
15616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       extern size_t getpagesize();
15626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#      define malloc_getpagesize getpagesize()
15636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#    else
15646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#      ifdef WIN32 /* use supplied emulation of getpagesize */
15656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#        define malloc_getpagesize getpagesize()
15666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#      else
15676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#        ifndef LACKS_SYS_PARAM_H
15686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#          include <sys/param.h>
15696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#        endif
15706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#        ifdef EXEC_PAGESIZE
15716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#          define malloc_getpagesize EXEC_PAGESIZE
15726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#        else
15736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#          ifdef NBPG
15746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#            ifndef CLSIZE
15756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#              define malloc_getpagesize NBPG
15766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#            else
15776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#              define malloc_getpagesize (NBPG * CLSIZE)
15786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#            endif
15796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#          else
15806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#            ifdef NBPC
15816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#              define malloc_getpagesize NBPC
15826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#            else
15836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#              ifdef PAGESIZE
15846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#                define malloc_getpagesize PAGESIZE
15856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#              else /* just guess */
15866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#                define malloc_getpagesize ((size_t)4096U)
15876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#              endif
15886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#            endif
15896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#          endif
15906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#        endif
15916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#      endif
15926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#    endif
15936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#  endif
15946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
15956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
15966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
15976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ------------------- size_t and alignment properties -------------------- */
15986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
15996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* The byte and bit size of a size_t */
16006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SIZE_T_SIZE         (sizeof(size_t))
16016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SIZE_T_BITSIZE      (sizeof(size_t) << 3)
16026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Some constants coerced to size_t */
16046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Annoying but necessary to avoid errors on some platforms */
16056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SIZE_T_ZERO         ((size_t)0)
16066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SIZE_T_ONE          ((size_t)1)
16076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SIZE_T_TWO          ((size_t)2)
16086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SIZE_T_FOUR         ((size_t)4)
16096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define TWO_SIZE_T_SIZES    (SIZE_T_SIZE<<1)
16106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define FOUR_SIZE_T_SIZES   (SIZE_T_SIZE<<2)
16116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SIX_SIZE_T_SIZES    (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
16126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define HALF_MAX_SIZE_T     (MAX_SIZE_T / 2U)
16136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* The bit mask value corresponding to MALLOC_ALIGNMENT */
16156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CHUNK_ALIGN_MASK    (MALLOC_ALIGNMENT - SIZE_T_ONE)
16166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* True if address a has acceptable alignment */
16186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define is_aligned(A)       (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
16196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* the number of bytes to offset an address to align it */
16216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define align_offset(A)\
16226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
16236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
16246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -------------------------- MMAP preliminaries ------------------------- */
16266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
16286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
16296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   checks to fail so compiler optimizer can delete code rather than
16306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   using so many "#if"s.
16316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
16326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* MORECORE and MMAP must return MFAIL on failure */
16356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MFAIL                ((void*)(MAX_SIZE_T))
16366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CMFAIL               ((char*)(MFAIL)) /* defined for convenience */
16376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if HAVE_MMAP
16396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef WIN32
16416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MUNMAP_DEFAULT(a, s)  munmap((a), (s))
16426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MMAP_PROT            (PROT_READ|PROT_WRITE)
16436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
16446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MAP_ANONYMOUS        MAP_ANON
16456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MAP_ANON */
16466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef MAP_ANONYMOUS
16476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MMAP_FLAGS           (MAP_PRIVATE|MAP_ANONYMOUS)
16486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MMAP_DEFAULT(s)       mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
16496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* MAP_ANONYMOUS */
16506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
16516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   Nearly all versions of mmap support MAP_ANONYMOUS, so the following
16526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   is unlikely to be needed, but is supplied just in case.
16536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
16546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MMAP_FLAGS           (MAP_PRIVATE)
16556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
16566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \
16576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao           (dev_zero_fd = open("/dev/zero", O_RDWR), \
16586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
16596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
16606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MAP_ANONYMOUS */
16616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s)
16636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* WIN32 */
16656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Win32 MMAP via VirtualAlloc */
16676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic FORCEINLINE void* win32mmap(size_t size) {
16686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
16696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return (ptr != 0)? ptr: MFAIL;
16706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
16716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
16736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic FORCEINLINE void* win32direct_mmap(size_t size) {
16746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
16756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                           PAGE_READWRITE);
16766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return (ptr != 0)? ptr: MFAIL;
16776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
16786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* This function supports releasing coalesed segments */
16806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic FORCEINLINE int win32munmap(void* ptr, size_t size) {
16816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MEMORY_BASIC_INFORMATION minfo;
16826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  char* cptr = (char*)ptr;
16836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  while (size) {
16846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
16856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return -1;
16866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
16876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        minfo.State != MEM_COMMIT || minfo.RegionSize > size)
16886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return -1;
16896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
16906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return -1;
16916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    cptr += minfo.RegionSize;
16926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size -= minfo.RegionSize;
16936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
16946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
16956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
16966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
16976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MMAP_DEFAULT(s)             win32mmap(s)
16986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MUNMAP_DEFAULT(a, s)        win32munmap((a), (s))
16996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DIRECT_MMAP_DEFAULT(s)      win32direct_mmap(s)
17006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* WIN32 */
17016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* HAVE_MMAP */
17026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if HAVE_MREMAP
17046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef WIN32
17056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MREMAP_DEFAULT(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
17066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* WIN32 */
17076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* HAVE_MREMAP */
17086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/**
17106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao * Define CALL_MORECORE
17116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao */
17126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if HAVE_MORECORE
17136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #ifdef MORECORE
17146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        #define CALL_MORECORE(S)    MORECORE(S)
17156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #else  /* MORECORE */
17166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        #define CALL_MORECORE(S)    MORECORE_DEFAULT(S)
17176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #endif /* MORECORE */
17186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else  /* HAVE_MORECORE */
17196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define CALL_MORECORE(S)        MFAIL
17206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* HAVE_MORECORE */
17216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/**
17236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao * Define CALL_MMAP/CALL_MUNMAP/CALL_DIRECT_MMAP
17246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao */
17256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if HAVE_MMAP
17266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define USE_MMAP_BIT            (SIZE_T_ONE)
17276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #ifdef MMAP
17296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        #define CALL_MMAP(s)        MMAP(s)
17306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #else /* MMAP */
17316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        #define CALL_MMAP(s)        MMAP_DEFAULT(s)
17326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #endif /* MMAP */
17336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #ifdef MUNMAP
17346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        #define CALL_MUNMAP(a, s)   MUNMAP((a), (s))
17356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #else /* MUNMAP */
17366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        #define CALL_MUNMAP(a, s)   MUNMAP_DEFAULT((a), (s))
17376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #endif /* MUNMAP */
17386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #ifdef DIRECT_MMAP
17396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s)
17406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #else /* DIRECT_MMAP */
17416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s)
17426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #endif /* DIRECT_MMAP */
17436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else  /* HAVE_MMAP */
17446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define USE_MMAP_BIT            (SIZE_T_ZERO)
17456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define MMAP(s)                 MFAIL
17476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define MUNMAP(a, s)            (-1)
17486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define DIRECT_MMAP(s)          MFAIL
17496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define CALL_DIRECT_MMAP(s)     DIRECT_MMAP(s)
17506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define CALL_MMAP(s)            MMAP(s)
17516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define CALL_MUNMAP(a, s)       MUNMAP((a), (s))
17526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* HAVE_MMAP */
17536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/**
17556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao * Define CALL_MREMAP
17566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao */
17576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if HAVE_MMAP && HAVE_MREMAP
17586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #ifdef MREMAP
17596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv))
17606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #else /* MREMAP */
17616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv))
17626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #endif /* MREMAP */
17636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else  /* HAVE_MMAP && HAVE_MREMAP */
17646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    #define CALL_MREMAP(addr, osz, nsz, mv)     MFAIL
17656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* HAVE_MMAP && HAVE_MREMAP */
17666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* mstate bit set if continguous morecore disabled or failed */
17686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define USE_NONCONTIGUOUS_BIT (4U)
17696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* segment bit set in create_mspace_with_base */
17716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define EXTERN_BIT            (8U)
17726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* --------------------------- Lock preliminaries ------------------------ */
17756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
17776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  When locks are defined, there is one global lock, plus
17786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  one per-mspace lock.
17796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The global lock_ensures that mparams.magic and other unique
17816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mparams values are initialized only once. It also protects
17826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  sequences of calls to MORECORE.  In many cases sys_alloc requires
17836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  two calls, that should not be interleaved with calls by other
17846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  threads.  This does not protect against direct calls to MORECORE
17856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  by other threads not using this lock, so there is still code to
17866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  cope the best we can on interference.
17876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Per-mspace locks surround calls to malloc, free, etc.
17896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  By default, locks are simple non-reentrant mutexes.
17906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Because lock-protected regions generally have bounded times, it is
17926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  OK to use the supplied simple spinlocks. Spinlocks are likely to
17936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  improve performance for lightly contended applications, but worsen
17946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  performance under heavy contention.
17956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
17966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If USE_LOCKS is > 1, the definitions of lock routines here are
17976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bypassed, in which case you will need to define the type MLOCK_T,
17986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  and at least INITIAL_LOCK, DESTROY_LOCK, ACQUIRE_LOCK, RELEASE_LOCK
17996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  and TRY_LOCK.  You must also declare a
18006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    static MLOCK_T malloc_global_mutex = { initialization values };.
18016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
18036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !USE_LOCKS
18056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define USE_LOCK_BIT               (0U)
18066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define INITIAL_LOCK(l)            (0)
18076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DESTROY_LOCK(l)            (0)
18086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ACQUIRE_MALLOC_GLOBAL_LOCK()
18096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define RELEASE_MALLOC_GLOBAL_LOCK()
18106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else
18126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if USE_LOCKS > 1
18136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -----------------------  User-defined locks ------------------------ */
18146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Define your own lock implementation here */
18156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* #define INITIAL_LOCK(lk)  ... */
18166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* #define DESTROY_LOCK(lk)  ... */
18176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* #define ACQUIRE_LOCK(lk)  ... */
18186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* #define RELEASE_LOCK(lk)  ... */
18196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* #define TRY_LOCK(lk) ... */
18206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* static MLOCK_T malloc_global_mutex = ... */
18216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif USE_SPIN_LOCKS
18236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* First, define CAS_LOCK and CLEAR_LOCK on ints */
18256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Note CAS_LOCK defined to return 0 on success */
18266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
18286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CAS_LOCK(sl)     __sync_lock_test_and_set(sl, 1)
18296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CLEAR_LOCK(sl)   __sync_lock_release(sl)
18306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
18326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Custom spin locks for older gcc on x86 */
18336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic FORCEINLINE int x86_cas_lock(int *sl) {
18346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int ret;
18356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int val = 1;
18366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int cmp = 0;
18376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  __asm__ __volatile__  ("lock; cmpxchgl %1, %2"
18386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                         : "=a" (ret)
18396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                         : "r" (val), "m" (*(sl)), "0"(cmp)
18406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                         : "memory", "cc");
18416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return ret;
18426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
18436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic FORCEINLINE void x86_clear_lock(int* sl) {
18456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(*sl != 0);
18466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int prev = 0;
18476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int ret;
18486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  __asm__ __volatile__ ("lock; xchgl %0, %1"
18496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                        : "=r" (ret)
18506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                        : "m" (*(sl)), "0"(prev)
18516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                        : "memory");
18526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
18536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CAS_LOCK(sl)     x86_cas_lock(sl)
18556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CLEAR_LOCK(sl)   x86_clear_lock(sl)
18566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* Win32 MSC */
18586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CAS_LOCK(sl)     interlockedexchange(sl, (LONG)1)
18596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CLEAR_LOCK(sl)   interlockedexchange (sl, (LONG)0)
18606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* ... gcc spins locks ... */
18626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* How to yield for a spin lock */
18646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SPINS_PER_YIELD       63
18656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if defined(_MSC_VER)
18666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SLEEP_EX_DURATION     50 /* delay for yield/sleep */
18676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SPIN_LOCK_YIELD  SleepEx(SLEEP_EX_DURATION, FALSE)
18686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif defined (__SVR4) && defined (__sun) /* solaris */
18696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SPIN_LOCK_YIELD   thr_yield();
18706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif !defined(LACKS_SCHED_H)
18716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SPIN_LOCK_YIELD   sched_yield();
18726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else
18736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SPIN_LOCK_YIELD
18746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* ... yield ... */
18756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !defined(USE_RECURSIVE_LOCKS) || USE_RECURSIVE_LOCKS == 0
18776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Plain spin locks use single word (embedded in malloc_states) */
18786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic int spin_acquire_lock(int *sl) {
18796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int spins = 0;
18806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  while (*(volatile int *)sl != 0 || CAS_LOCK(sl)) {
18816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if ((++spins & SPINS_PER_YIELD) == 0) {
18826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      SPIN_LOCK_YIELD;
18836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
18846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
18856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
18866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
18876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MLOCK_T               int
18896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define TRY_LOCK(sl)          !CAS_LOCK(sl)
18906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define RELEASE_LOCK(sl)      CLEAR_LOCK(sl)
18916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ACQUIRE_LOCK(sl)      (CAS_LOCK(sl)? spin_acquire_lock(sl) : 0)
18926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define INITIAL_LOCK(sl)      (*sl = 0)
18936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DESTROY_LOCK(sl)      (0)
18946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic MLOCK_T malloc_global_mutex = 0;
18956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
18966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* USE_RECURSIVE_LOCKS */
18976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* types for lock owners */
18986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef WIN32
18996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define THREAD_ID_T           DWORD
19006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CURRENT_THREAD        GetCurrentThreadId()
19016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define EQ_OWNER(X,Y)         ((X) == (Y))
19026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else
19036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
19046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Note: the following assume that pthread_t is a type that can be
19056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  initialized to (casted) zero. If this is not the case, you will need to
19066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  somehow redefine these or not use spin locks.
19076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
19086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define THREAD_ID_T           pthread_t
19096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CURRENT_THREAD        pthread_self()
19106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define EQ_OWNER(X,Y)         pthread_equal(X, Y)
19116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
19126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
19136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostruct malloc_recursive_lock {
19146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int sl;
19156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  unsigned int c;
19166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  THREAD_ID_T threadid;
19176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao};
19186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
19196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MLOCK_T  struct malloc_recursive_lock
19206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic MLOCK_T malloc_global_mutex = { 0, 0, (THREAD_ID_T)0};
19216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
19226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic FORCEINLINE void recursive_release_lock(MLOCK_T *lk) {
19236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(lk->sl != 0);
19246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (--lk->c == 0) {
19256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    CLEAR_LOCK(&lk->sl);
19266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
19276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
19286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
19296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic FORCEINLINE int recursive_acquire_lock(MLOCK_T *lk) {
19306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  THREAD_ID_T mythreadid = CURRENT_THREAD;
19316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int spins = 0;
19326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for (;;) {
19336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (*((volatile int *)(&lk->sl)) == 0) {
19346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (!CAS_LOCK(&lk->sl)) {
19356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        lk->threadid = mythreadid;
19366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        lk->c = 1;
19376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        return 0;
19386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
19396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
19406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (EQ_OWNER(lk->threadid, mythreadid)) {
19416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      ++lk->c;
19426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return 0;
19436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
19446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if ((++spins & SPINS_PER_YIELD) == 0) {
19456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      SPIN_LOCK_YIELD;
19466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
19476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
19486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
19496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
19506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic FORCEINLINE int recursive_try_lock(MLOCK_T *lk) {
19516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  THREAD_ID_T mythreadid = CURRENT_THREAD;
19526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (*((volatile int *)(&lk->sl)) == 0) {
19536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!CAS_LOCK(&lk->sl)) {
19546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      lk->threadid = mythreadid;
19556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      lk->c = 1;
19566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return 1;
19576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
19586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
19596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (EQ_OWNER(lk->threadid, mythreadid)) {
19606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    ++lk->c;
19616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 1;
19626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
19636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
19646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
19656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
19666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define RELEASE_LOCK(lk)      recursive_release_lock(lk)
19676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define TRY_LOCK(lk)          recursive_try_lock(lk)
19686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ACQUIRE_LOCK(lk)      recursive_acquire_lock(lk)
19696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define INITIAL_LOCK(lk)      ((lk)->threadid = (THREAD_ID_T)0, (lk)->sl = 0, (lk)->c = 0)
19706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DESTROY_LOCK(lk)      (0)
19716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_RECURSIVE_LOCKS */
19726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
19736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif defined(WIN32) /* Win32 critical sections */
19746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MLOCK_T               CRITICAL_SECTION
19756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ACQUIRE_LOCK(lk)      (EnterCriticalSection(lk), 0)
19766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define RELEASE_LOCK(lk)      LeaveCriticalSection(lk)
19776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define TRY_LOCK(lk)          TryEnterCriticalSection(lk)
19786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define INITIAL_LOCK(lk)      (!InitializeCriticalSectionAndSpinCount((lk), 0x80000000|4000))
19796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DESTROY_LOCK(lk)      (DeleteCriticalSection(lk), 0)
19806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define NEED_GLOBAL_LOCK_INIT
19816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
19826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic MLOCK_T malloc_global_mutex;
19836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic volatile LONG malloc_global_mutex_status;
19846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
19856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Use spin loop to initialize global lock */
19866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void init_malloc_global_mutex() {
19876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for (;;) {
19886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    long stat = malloc_global_mutex_status;
19896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (stat > 0)
19906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return;
19916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* transition to < 0 while initializing, then to > 0) */
19926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (stat == 0 &&
19936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        interlockedcompareexchange(&malloc_global_mutex_status, (LONG)-1, (LONG)0) == 0) {
19946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      InitializeCriticalSection(&malloc_global_mutex);
19956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      interlockedexchange(&malloc_global_mutex_status, (LONG)1);
19966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return;
19976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
19986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    SleepEx(0, FALSE);
19996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
20006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
20016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* pthreads-based locks */
20036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MLOCK_T               pthread_mutex_t
20046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ACQUIRE_LOCK(lk)      pthread_mutex_lock(lk)
20056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define RELEASE_LOCK(lk)      pthread_mutex_unlock(lk)
20066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define TRY_LOCK(lk)          (!pthread_mutex_trylock(lk))
20076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define INITIAL_LOCK(lk)      pthread_init_lock(lk)
20086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define DESTROY_LOCK(lk)      pthread_mutex_destroy(lk)
20096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 && defined(linux) && !defined(PTHREAD_MUTEX_RECURSIVE)
20116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Cope with old-style linux recursive lock initialization by adding */
20126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* skipped internal declaration from pthread.h */
20136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoextern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr,
20146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                              int __kind));
20156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
20166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y)
20176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_RECURSIVE_LOCKS ... */
20186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER;
20206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic int pthread_init_lock (MLOCK_T *lk) {
20226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  pthread_mutexattr_t attr;
20236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (pthread_mutexattr_init(&attr)) return 1;
20246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0
20256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1;
20266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
20276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (pthread_mutex_init(lk, &attr)) return 1;
20286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (pthread_mutexattr_destroy(&attr)) return 1;
20296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
20306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
20316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* ... lock types ... */
20336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Common code for all lock types */
20356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define USE_LOCK_BIT               (2U)
20366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef ACQUIRE_MALLOC_GLOBAL_LOCK
20386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ACQUIRE_MALLOC_GLOBAL_LOCK()  ACQUIRE_LOCK(&malloc_global_mutex);
20396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
20406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef RELEASE_MALLOC_GLOBAL_LOCK
20426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define RELEASE_MALLOC_GLOBAL_LOCK()  RELEASE_LOCK(&malloc_global_mutex);
20436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
20446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_LOCKS */
20466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -----------------------  Chunk representations ------------------------ */
20486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
20506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (The following includes lightly edited explanations by Colin Plumb.)
20516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The malloc_chunk declaration below is misleading (but accurate and
20536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  necessary).  It declares a "view" into memory allowing access to
20546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  necessary fields at known offsets from a given base.
20556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Chunks of memory are maintained using a `boundary tag' method as
20576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  originally described by Knuth.  (See the paper by Paul Wilson
20586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
20596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  techniques.)  Sizes of free chunks are stored both in the front of
20606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  each chunk and at the end.  This makes consolidating fragmented
20616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  chunks into bigger chunks fast.  The head fields also hold bits
20626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  representing whether chunks are free or in use.
20636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Here are some pictures to make it clearer.  They are "exploded" to
20656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  show that the state of a chunk can be thought of as extending from
20666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the high 31 bits of the head field of its header through the
20676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  prev_foot and PINUSE_BIT bit of the following chunk header.
20686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  A chunk that's in use looks like:
20706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao           | Size of previous chunk (if P = 0)                             |
20736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
20756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         | Size of this chunk                                         1| +-+
20766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         |                                                               |
20786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         +-                                                             -+
20796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         |                                                               |
20806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         +-                                                             -+
20816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         |                                                               :
20826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         +-      size - sizeof(size_t) available payload bytes          -+
20836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         :                                                               |
20846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao chunk-> +-                                                             -+
20856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         |                                                               |
20866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
20886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       | Size of next chunk (may or may not be in use)               | +-+
20896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    And if it's free, it looks like this:
20926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
20936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   chunk-> +-                                                             -+
20946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao           | User payload (must be in use, or we would have merged!)       |
20956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
20976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         | Size of this chunk                                         0| +-+
20986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         | Next pointer                                                  |
21006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         | Prev pointer                                                  |
21026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         |                                                               :
21046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         +-      size - sizeof(struct chunk) unused bytes               -+
21056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         :                                                               |
21066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         | Size of this chunk                                            |
21086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
21106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       | Size of next chunk (must be in use, or we would have merged)| +-+
21116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       |                                                               :
21136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       +- User payload                                                -+
21146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       :                                                               |
21156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                                                     |0|
21176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                                                     +-+
21186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Note that since we always merge adjacent free chunks, the chunks
21196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  adjacent to a free chunk must be in use.
21206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Given a pointer to a chunk (which can be derived trivially from the
21226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  payload pointer) we can, in O(1) time, find out whether the adjacent
21236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  chunks are free, and if so, unlink them from the lists that they
21246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  are on and merge them with the current chunk.
21256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Chunks always begin on even word boundaries, so the mem portion
21276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (which is returned to the user) is also on an even word boundary, and
21286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  thus at least double-word aligned.
21296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
21316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  chunk size (which is always a multiple of two words), is an in-use
21326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bit for the *previous* chunk.  If that bit is *clear*, then the
21336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  word before the current chunk size contains the previous chunk
21346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size, and can be used to find the front of the previous chunk.
21356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The very first chunk allocated always has this bit set, preventing
21366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  access to non-existent (or non-owned) memory. If pinuse is set for
21376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  any given chunk, then you CANNOT determine the size of the
21386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  previous chunk, and might even get a memory addressing fault when
21396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  trying to do so.
21406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
21426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the chunk size redundantly records whether the current chunk is
21436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  inuse (unless the chunk is mmapped). This redundancy enables usage
21446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  checks within free and realloc, and reduces indirection when freeing
21456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  and consolidating chunks.
21466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Each freshly allocated chunk must have both cinuse and pinuse set.
21486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  That is, each allocated chunk borders either a previously allocated
21496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  and still in-use chunk, or the base of its memory arena. This is
21506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensured by making all allocations from the `lowest' part of any
21516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  found chunk.  Further, no free chunk physically borders another one,
21526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  so each free chunk is known to be preceded and followed by either
21536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  inuse chunks or the ends of memory.
21546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Note that the `foot' of the current chunk is actually represented
21566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  as the prev_foot of the NEXT chunk. This makes it easier to
21576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  deal with alignments etc but can be very confusing when trying
21586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  to extend or adapt this code.
21596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The exceptions to all this are
21616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     1. The special chunk `top' is the top-most available chunk (i.e.,
21636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        the one bordering the end of available memory). It is treated
21646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        specially.  Top is never included in any bin, is used only if
21656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        no other chunk is available, and is released back to the
21666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        system if it is very large (see M_TRIM_THRESHOLD).  In effect,
21676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        the top chunk is treated as larger (and thus less well
21686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        fitting) than any other available chunk.  The top chunk
21696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        doesn't update its trailing size field since there is no next
21706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        contiguous chunk that would have to index off it. However,
21716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        space is still allocated for it (TOP_FOOT_SIZE) to enable
21726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        separation or merging when space is extended.
21736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     3. Chunks allocated via mmap, have both cinuse and pinuse bits
21756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        cleared in their head fields.  Because they are allocated
21766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        one-by-one, each must carry its own prev_foot field, which is
21776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        also used to hold the offset this chunk has within its mmapped
21786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        region, which is needed to preserve alignment. Each mmapped
21796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        chunk is trailed by the first two fields of a fake next-chunk
21806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        for sake of usage checks.
21816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
21836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostruct malloc_chunk {
21856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t               prev_foot;  /* Size of previous chunk (if free).  */
21866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t               head;       /* Size and inuse bits. */
21876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct malloc_chunk* fd;         /* double links -- used only if free. */
21886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct malloc_chunk* bk;
21896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao};
21906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef struct malloc_chunk  mchunk;
21926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef struct malloc_chunk* mchunkptr;
21936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */
21946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef unsigned int bindex_t;         /* Described below */
21956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef unsigned int binmap_t;         /* Described below */
21966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef unsigned int flag_t;           /* The type of various bit flag sets */
21976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
21986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ------------------- Chunks sizes and alignments ----------------------- */
21996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MCHUNK_SIZE         (sizeof(mchunk))
22016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if FOOTERS
22036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CHUNK_OVERHEAD      (TWO_SIZE_T_SIZES)
22046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* FOOTERS */
22056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CHUNK_OVERHEAD      (SIZE_T_SIZE)
22066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* FOOTERS */
22076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* MMapped chunks need a second word of overhead ... */
22096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
22106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ... and additional padding for fake next-chunk at foot */
22116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MMAP_FOOT_PAD       (FOUR_SIZE_T_SIZES)
22126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* The smallest size we can malloc is an aligned minimal chunk */
22146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MIN_CHUNK_SIZE\
22156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
22166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* conversion from malloc headers to user pointers, and back */
22186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define chunk2mem(p)        ((void*)((char*)(p)       + TWO_SIZE_T_SIZES))
22196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define mem2chunk(mem)      ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
22206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* chunk associated with aligned address A */
22216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define align_as_chunk(A)   (mchunkptr)((A) + align_offset(chunk2mem(A)))
22226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Bounds on request (not chunk) sizes. */
22246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MAX_REQUEST         ((-MIN_CHUNK_SIZE) << 2)
22256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MIN_REQUEST         (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
22266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* pad request bytes into a usable size */
22286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define pad_request(req) \
22296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
22306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* pad request, checking for minimum (but not maximum) */
22326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define request2size(req) \
22336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
22346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ------------------ Operations on head and foot fields ----------------- */
22376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
22396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The head field of a chunk is or'ed with PINUSE_BIT when previous
22406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
22416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  use, unless mmapped, in which case both bits are cleared.
22426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  FLAG4_BIT is not used by this malloc, but might be useful in extensions.
22446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
22456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define PINUSE_BIT          (SIZE_T_ONE)
22476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CINUSE_BIT          (SIZE_T_TWO)
22486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define FLAG4_BIT           (SIZE_T_FOUR)
22496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define INUSE_BITS          (PINUSE_BIT|CINUSE_BIT)
22506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define FLAG_BITS           (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT)
22516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Head value for fenceposts */
22536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define FENCEPOST_HEAD      (INUSE_BITS|SIZE_T_SIZE)
22546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* extraction of fields from head words */
22566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define cinuse(p)           ((p)->head & CINUSE_BIT)
22576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define pinuse(p)           ((p)->head & PINUSE_BIT)
22586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define flag4inuse(p)       ((p)->head & FLAG4_BIT)
22596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define is_inuse(p)         (((p)->head & INUSE_BITS) != PINUSE_BIT)
22606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define is_mmapped(p)       (((p)->head & INUSE_BITS) == 0)
22616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define chunksize(p)        ((p)->head & ~(FLAG_BITS))
22636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define clear_pinuse(p)     ((p)->head &= ~PINUSE_BIT)
22656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define set_flag4(p)        ((p)->head |= FLAG4_BIT)
22666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define clear_flag4(p)      ((p)->head &= ~FLAG4_BIT)
22676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Treat space at ptr +/- offset as a chunk */
22696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define chunk_plus_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
22706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
22716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Ptr to next or previous physical malloc_chunk. */
22736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS)))
22746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
22756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* extract next chunk's pinuse bit */
22776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define next_pinuse(p)  ((next_chunk(p)->head) & PINUSE_BIT)
22786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Get/set size at footer */
22806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define get_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot)
22816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define set_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
22826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Set size, pinuse bit, and foot */
22846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define set_size_and_pinuse_of_free_chunk(p, s)\
22856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
22866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Set size, pinuse bit, foot, and clear next pinuse */
22886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define set_free_with_pinuse(p, s, n)\
22896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
22906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Get the internal overhead associated with chunk p */
22926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define overhead_for(p)\
22936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
22946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
22956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Return true if malloced space is not necessarily cleared */
22966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if MMAP_CLEARS
22976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define calloc_must_clear(p) (!is_mmapped(p))
22986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* MMAP_CLEARS */
22996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define calloc_must_clear(p) (1)
23006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MMAP_CLEARS */
23016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ---------------------- Overlaid data structures ----------------------- */
23036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
23056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  When chunks are not in use, they are treated as nodes of either
23066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  lists or trees.
23076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  "Small"  chunks are stored in circular doubly-linked lists, and look
23096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  like this:
23106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             Size of previous chunk                            |
23136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    `head:' |             Size of chunk, in bytes                         |P|
23156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             Forward pointer to next chunk in list             |
23176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             Back pointer to previous chunk in list            |
23196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             Unused space (may be 0 bytes long)                .
23216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            .                                                               .
23226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            .                                                               |
23236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaonextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    `foot:' |             Size of chunk, in bytes                           |
23256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Larger chunks are kept in a form of bitwise digital trees (aka
23286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tries) keyed on chunksizes.  Because malloc_tree_chunks are only for
23296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  free chunks greater than 256 bytes, their size doesn't impose any
23306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  constraints on user chunk sizes.  Each node looks like:
23316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             Size of previous chunk                            |
23346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    `head:' |             Size of chunk, in bytes                         |P|
23366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             Forward pointer to next chunk of same size        |
23386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             Back pointer to previous chunk of same size       |
23406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             Pointer to left child (child[0])                  |
23426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             Pointer to right child (child[1])                 |
23446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             Pointer to parent                                 |
23466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             bin index of this chunk                           |
23486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            |             Unused space                                      .
23506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            .                                                               |
23516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaonextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    `foot:' |             Size of chunk, in bytes                           |
23536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Each tree holding treenodes is a tree of unique chunk sizes.  Chunks
23566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  of the same size are arranged in a circularly-linked list, with only
23576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the oldest chunk (the next to be used, in our FIFO ordering)
23586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  actually in the tree.  (Tree members are distinguished by a non-null
23596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  parent pointer.)  If a chunk with the same size an an existing node
23606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  is inserted, it is linked off the existing node using pointers that
23616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  work in the same way as fd/bk pointers of small chunks.
23626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Each tree contains a power of 2 sized range of chunk sizes (the
23646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  smallest is 0x100 <= x < 0x180), which is is divided in half at each
23656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tree level, with the chunks in the smaller half of the range (0x100
23666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  <= x < 0x140 for the top nose) in the left subtree and the larger
23676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  half (0x140 <= x < 0x180) in the right subtree.  This is, of course,
23686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  done by inspecting individual bits.
23696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Using these rules, each node's left subtree contains all smaller
23716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  sizes than its right subtree.  However, the node at the root of each
23726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  subtree has no particular ordering relationship to either.  (The
23736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  dividing line between the subtree sizes is based on trie relation.)
23746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  If we remove the last chunk of a given size from the interior of the
23756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tree, we need to replace it with a leaf node.  The tree ordering
23766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  rules permit a node to be replaced by any leaf below it.
23776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The smallest chunk in a tree (a common operation in a best-fit
23796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  allocator) can be found by walking a path to the leftmost leaf in
23806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the tree.  Unlike a usual binary tree, where we follow left child
23816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  pointers until we reach a null, here we follow the right child
23826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  pointer any time the left one is null, until we reach a leaf with
23836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  both child pointers null. The smallest chunk in the tree will be
23846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  somewhere along that path.
23856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The worst case number of steps to add, find, or remove a node is
23876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bounded by the number of bits differentiating chunks within
23886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bins. Under current bin calculations, this ranges from 6 up to 21
23896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
23906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  is of course much better.
23916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
23926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
23936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostruct malloc_tree_chunk {
23946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* The first four fields must be compatible with malloc_chunk */
23956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t                    prev_foot;
23966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t                    head;
23976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct malloc_tree_chunk* fd;
23986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct malloc_tree_chunk* bk;
23996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct malloc_tree_chunk* child[2];
24016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct malloc_tree_chunk* parent;
24026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bindex_t                  index;
24036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao};
24046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef struct malloc_tree_chunk  tchunk;
24066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef struct malloc_tree_chunk* tchunkptr;
24076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
24086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* A little helper macro for trees */
24106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
24116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ----------------------------- Segments -------------------------------- */
24136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
24156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Each malloc space may include non-contiguous segments, held in a
24166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  list headed by an embedded malloc_segment record representing the
24176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  top-most space. Segments also include flags holding properties of
24186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the space. Large chunks that are directly allocated by mmap are not
24196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  included in this list. They are instead independently created and
24206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  destroyed without otherwise keeping track of them.
24216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Segment management mainly comes into play for spaces allocated by
24236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MMAP.  Any call to MMAP might or might not return memory that is
24246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  adjacent to an existing segment.  MORECORE normally contiguously
24256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  extends the current space, so this space is almost always adjacent,
24266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  which is simpler and faster to deal with. (This is why MORECORE is
24276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  used preferentially to MMAP when both are available -- see
24286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  sys_alloc.)  When allocating using MMAP, we don't use any of the
24296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  hinting mechanisms (inconsistently) supported in various
24306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  implementations of unix mmap, or distinguish reserving from
24316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  committing memory. Instead, we just ask for space, and exploit
24326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  contiguity when we get it.  It is probably possible to do
24336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  better than this on some systems, but no general scheme seems
24346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  to be significantly better.
24356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Management entails a simpler variant of the consolidation scheme
24376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  used for chunks to reduce fragmentation -- new adjacent memory is
24386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  normally prepended or appended to an existing segment. However,
24396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  there are limitations compared to chunk consolidation that mostly
24406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  reflect the fact that segment processing is relatively infrequent
24416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (occurring only when getting memory from system) and that we
24426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  don't expect to have huge numbers of segments:
24436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  * Segments are not indexed, so traversal requires linear scans.  (It
24456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    would be possible to index these, but is not worth the extra
24466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    overhead and complexity for most programs on most platforms.)
24476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  * New segments are only appended to old ones when holding top-most
24486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    memory; if they cannot be prepended to others, they are held in
24496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    different segments.
24506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Except for the top-most segment of an mstate, each segment record
24526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  is kept at the tail of its segment. Segments are added by pushing
24536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  segment records onto the list headed by &mstate.seg for the
24546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  containing mstate.
24556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Segment flags control allocation/merge/deallocation policies:
24576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  * If EXTERN_BIT set, then we did not allocate this segment,
24586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    and so should not try to deallocate or merge with others.
24596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    (This currently holds only for the initial segment passed
24606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    into create_mspace_with_base.)
24616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  * If USE_MMAP_BIT set, the segment may be merged with
24626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    other surrounding mmapped segments and trimmed/de-allocated
24636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    using munmap.
24646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  * If neither bit is set, then the segment was obtained using
24656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    MORECORE so can be merged with surrounding MORECORE'd segments
24666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    and deallocated/trimmed using MORECORE with negative arguments.
24676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
24686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostruct malloc_segment {
24706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  char*        base;             /* base address */
24716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t       size;             /* allocated size */
24726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct malloc_segment* next;   /* ptr to next segment */
24736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  flag_t       sflags;           /* mmap and extern flag */
24746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao};
24756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define is_mmapped_segment(S)  ((S)->sflags & USE_MMAP_BIT)
24776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define is_extern_segment(S)   ((S)->sflags & EXTERN_BIT)
24786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef struct malloc_segment  msegment;
24806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef struct malloc_segment* msegmentptr;
24816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ---------------------------- malloc_state ----------------------------- */
24836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
24856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   A malloc_state holds all of the bookkeeping for a space.
24866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   The main fields are:
24876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Top
24896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    The topmost chunk of the currently active segment. Its size is
24906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    cached in topsize.  The actual size of topmost space is
24916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    topsize+TOP_FOOT_SIZE, which includes space reserved for adding
24926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    fenceposts and segment records if necessary when getting more
24936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    space from the system.  The size at which to autotrim top is
24946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    cached from mparams in trim_check, except that it is disabled if
24956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    an autotrim fails.
24966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
24976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Designated victim (dv)
24986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    This is the preferred chunk for servicing small requests that
24996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    don't have exact fits.  It is normally the chunk split off most
25006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    recently to service another small request.  Its size is cached in
25016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    dvsize. The link fields of this chunk are not maintained since it
25026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    is not kept in a bin.
25036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  SmallBins
25056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    An array of bin headers for free chunks.  These bins hold chunks
25066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
25076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    chunks of all the same size, spaced 8 bytes apart.  To simplify
25086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    use in double-linked lists, each bin header acts as a malloc_chunk
25096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    pointing to the real first node, if it exists (else pointing to
25106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    itself).  This avoids special-casing for headers.  But to avoid
25116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    waste, we allocate only the fd/bk pointers of bins, and then use
25126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    repositioning tricks to treat these as the fields of a chunk.
25136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  TreeBins
25156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    Treebins are pointers to the roots of trees holding a range of
25166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    sizes. There are 2 equally spaced treebins for each power of two
25176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
25186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    larger.
25196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Bin maps
25216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    There is one bit map for small bins ("smallmap") and one for
25226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    treebins ("treemap).  Each bin sets its bit when non-empty, and
25236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    clears the bit when empty.  Bit operations are then used to avoid
25246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    bin-by-bin searching -- nearly all "search" is done without ever
25256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    looking at bins that won't be selected.  The bit maps
25266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    conservatively use 32 bits per map word, even if on 64bit system.
25276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    For a good description of some of the bit-based techniques used
25286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    here, see Henry S. Warren Jr's book "Hacker's Delight" (and
25296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    supplement at http://hackersdelight.org/). Many of these are
25306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    intended to reduce the branchiness of paths through malloc etc, as
25316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    well as to reduce the number of memory locations read or written.
25326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Segments
25346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    A list of segments headed by an embedded malloc_segment record
25356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    representing the initial space.
25366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Address check support
25386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    The least_addr field is the least address ever obtained from
25396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    MORECORE or MMAP. Attempted frees and reallocs of any address less
25406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    than this are trapped (unless INSECURE is defined).
25416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Magic tag
25436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    A cross-check field that should always hold same value as mparams.magic.
25446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Max allowed footprint
25466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    The maximum allowed bytes to allocate from system (zero means no limit)
25476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Flags
25496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    Bits recording whether to use MMAP, locks, or contiguous MORECORE
25506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Statistics
25526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    Each space keeps track of current and maximum system memory
25536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    obtained via MORECORE or MMAP.
25546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Trim support
25566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    Fields holding the amount of unused topmost memory that should trigger
25576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    trimming, and a counter to force periodic scanning to release unused
25586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    non-topmost segments.
25596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Locking
25616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    If USE_LOCKS is defined, the "mutex" lock is acquired and released
25626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    around every public call using this mspace.
25636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Extension support
25656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    A void* pointer and a size_t field that can be used to help implement
25666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    extensions to this malloc.
25676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
25686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Bin types, widths and sizes */
25706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define NSMALLBINS        (32U)
25716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define NTREEBINS         (32U)
25726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SMALLBIN_SHIFT    (3U)
25736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SMALLBIN_WIDTH    (SIZE_T_ONE << SMALLBIN_SHIFT)
25746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define TREEBIN_SHIFT     (8U)
25756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MIN_LARGE_SIZE    (SIZE_T_ONE << TREEBIN_SHIFT)
25766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MAX_SMALL_SIZE    (MIN_LARGE_SIZE - SIZE_T_ONE)
25776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
25786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
25796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostruct malloc_state {
25806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  binmap_t   smallmap;
25816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  binmap_t   treemap;
25826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t     dvsize;
25836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t     topsize;
25846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  char*      least_addr;
25856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr  dv;
25866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr  top;
25876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t     trim_check;
25886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t     release_checks;
25896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t     magic;
25906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr  smallbins[(NSMALLBINS+1)*2];
25916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tbinptr    treebins[NTREEBINS];
25926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t     footprint;
25936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t     max_footprint;
25946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t     footprint_limit; /* zero means no limit */
25956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  flag_t     mflags;
25966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if USE_LOCKS
25976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MLOCK_T    mutex;     /* locate lock among fields that rarely change */
25986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_LOCKS */
25996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  msegment   seg;
26006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void*      extp;      /* Unused but available for extensions */
26016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t     exts;
26026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao};
26036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaotypedef struct malloc_state*    mstate;
26056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ------------- Global malloc_state and malloc_params ------------------- */
26076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
26096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_params holds global properties, including those that can be
26106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  dynamically set using mallopt. There is a single instance, mparams,
26116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  initialized in init_mparams. Note that the non-zeroness of "magic"
26126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  also serves as an initialization flag.
26136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
26146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostruct malloc_params {
26166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t magic;
26176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t page_size;
26186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t granularity;
26196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t mmap_threshold;
26206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t trim_threshold;
26216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  flag_t default_mflags;
26226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao};
26236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic struct malloc_params mparams;
26256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Ensure mparams initialized */
26276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ensure_initialization() (void)(mparams.magic != 0 || init_mparams())
26286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !ONLY_MSPACES
26306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* The global malloc_state used for all non-"mspace" calls */
26326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic struct malloc_state _gm_;
26336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define gm                 (&_gm_)
26346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define is_global(M)       ((M) == &_gm_)
26356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* !ONLY_MSPACES */
26376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define is_initialized(M)  ((M)->top != 0)
26396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -------------------------- system alloc setup ------------------------- */
26416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Operations on mflags */
26436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define use_lock(M)           ((M)->mflags &   USE_LOCK_BIT)
26456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define enable_lock(M)        ((M)->mflags |=  USE_LOCK_BIT)
26466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if USE_LOCKS
26476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define disable_lock(M)       ((M)->mflags &= ~USE_LOCK_BIT)
26486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else
26496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define disable_lock(M)
26506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
26516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define use_mmap(M)           ((M)->mflags &   USE_MMAP_BIT)
26536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define enable_mmap(M)        ((M)->mflags |=  USE_MMAP_BIT)
26546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if HAVE_MMAP
26556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define disable_mmap(M)       ((M)->mflags &= ~USE_MMAP_BIT)
26566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else
26576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define disable_mmap(M)
26586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
26596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define use_noncontiguous(M)  ((M)->mflags &   USE_NONCONTIGUOUS_BIT)
26616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define disable_contiguous(M) ((M)->mflags |=  USE_NONCONTIGUOUS_BIT)
26626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define set_lock(M,L)\
26646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao ((M)->mflags = (L)?\
26656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((M)->mflags | USE_LOCK_BIT) :\
26666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((M)->mflags & ~USE_LOCK_BIT))
26676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* page-align a size */
26696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define page_align(S)\
26706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE))
26716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* granularity-align a size */
26736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define granularity_align(S)\
26746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (((S) + (mparams.granularity - SIZE_T_ONE))\
26756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   & ~(mparams.granularity - SIZE_T_ONE))
26766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* For mmap, use granularity alignment on windows, else page-align */
26796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef WIN32
26806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define mmap_align(S) granularity_align(S)
26816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else
26826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define mmap_align(S) page_align(S)
26836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
26846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* For sys_alloc, enough padding to ensure can malloc request on success */
26866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT)
26876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define is_page_aligned(S)\
26896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
26906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define is_granularity_aligned(S)\
26916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
26926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*  True if segment S holds address A */
26946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define segment_holds(S, A)\
26956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
26966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
26976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Return segment holding given address */
26986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic msegmentptr segment_holding(mstate m, char* addr) {
26996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  msegmentptr sp = &m->seg;
27006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for (;;) {
27016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (addr >= sp->base && addr < sp->base + sp->size)
27026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return sp;
27036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if ((sp = sp->next) == 0)
27046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return 0;
27056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
27066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
27076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Return true if segment contains a segment link */
27096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic int has_segment_link(mstate m, msegmentptr ss) {
27106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  msegmentptr sp = &m->seg;
27116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for (;;) {
27126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
27136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return 1;
27146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if ((sp = sp->next) == 0)
27156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return 0;
27166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
27176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
27186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef MORECORE_CANNOT_TRIM
27206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define should_trim(M,s)  ((s) > (M)->trim_check)
27216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else  /* MORECORE_CANNOT_TRIM */
27226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define should_trim(M,s)  (0)
27236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MORECORE_CANNOT_TRIM */
27246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
27266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  TOP_FOOT_SIZE is padding at the end of a segment, including space
27276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  that may be needed to place segment records and fenceposts when new
27286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  noncontiguous segments are added.
27296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
27306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define TOP_FOOT_SIZE\
27316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
27326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -------------------------------  Hooks -------------------------------- */
27356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
27376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  PREACTION should be defined to return 0 on success, and nonzero on
27386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  failure. If you are not using locking, you can redefine these to do
27396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  anything you like.
27406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
27416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if USE_LOCKS
27436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define PREACTION(M)  ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
27446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
27456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* USE_LOCKS */
27466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef PREACTION
27486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define PREACTION(M) (0)
27496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* PREACTION */
27506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef POSTACTION
27526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define POSTACTION(M)
27536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif  /* POSTACTION */
27546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_LOCKS */
27566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
27586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
27596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  USAGE_ERROR_ACTION is triggered on detected bad frees and
27606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  reallocs. The argument p is an address that might have triggered the
27616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  fault. It is ignored by the two predefined actions, but might be
27626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  useful in custom actions that try to help diagnose errors.
27636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
27646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if PROCEED_ON_ERROR
27666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* A count of the number of corruption errors causing resets */
27686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoint malloc_corruption_error_count;
27696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* default corruption action */
27716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void reset_on_error(mstate m);
27726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CORRUPTION_ERROR_ACTION(m)  reset_on_error(m)
27746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define USAGE_ERROR_ACTION(m, p)
27756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* PROCEED_ON_ERROR */
27776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef CORRUPTION_ERROR_ACTION
27796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define CORRUPTION_ERROR_ACTION(m) ABORT
27806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* CORRUPTION_ERROR_ACTION */
27816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef USAGE_ERROR_ACTION
27836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define USAGE_ERROR_ACTION(m,p) ABORT
27846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USAGE_ERROR_ACTION */
27856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* PROCEED_ON_ERROR */
27876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -------------------------- Debugging setup ---------------------------- */
27906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if ! DEBUG
27926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
27936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_free_chunk(M,P)
27946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_inuse_chunk(M,P)
27956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_malloced_chunk(M,P,N)
27966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_mmapped_chunk(M,P)
27976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_malloc_state(M)
27986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_top_chunk(M,P)
27996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
28006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* DEBUG */
28016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_free_chunk(M,P)       do_check_free_chunk(M,P)
28026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_inuse_chunk(M,P)      do_check_inuse_chunk(M,P)
28036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_top_chunk(M,P)        do_check_top_chunk(M,P)
28046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
28056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_mmapped_chunk(M,P)    do_check_mmapped_chunk(M,P)
28066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define check_malloc_state(M)       do_check_malloc_state(M)
28076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
28086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void   do_check_any_chunk(mstate m, mchunkptr p);
28096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void   do_check_top_chunk(mstate m, mchunkptr p);
28106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void   do_check_mmapped_chunk(mstate m, mchunkptr p);
28116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void   do_check_inuse_chunk(mstate m, mchunkptr p);
28126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void   do_check_free_chunk(mstate m, mchunkptr p);
28136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void   do_check_malloced_chunk(mstate m, void* mem, size_t s);
28146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void   do_check_tree(mstate m, tchunkptr t);
28156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void   do_check_treebin(mstate m, bindex_t i);
28166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void   do_check_smallbin(mstate m, bindex_t i);
28176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void   do_check_malloc_state(mstate m);
28186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic int    bin_find(mstate m, mchunkptr x);
28196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic size_t traverse_and_check(mstate m);
28206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* DEBUG */
28216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
28226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ---------------------------- Indexing Bins ---------------------------- */
28236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
28246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define is_small(s)         (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
28256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define small_index(s)      (bindex_t)((s)  >> SMALLBIN_SHIFT)
28266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define small_index2size(i) ((i)  << SMALLBIN_SHIFT)
28276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))
28286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
28296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* addressing by index. See above about smallbin repositioning */
28306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* BEGIN android-changed: strict aliasing change: char* cast to void* */
28316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define smallbin_at(M, i)   ((sbinptr)((void*)&((M)->smallbins[(i)<<1])))
28326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* END android-changed */
28336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define treebin_at(M,i)     (&((M)->treebins[i]))
28346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
28356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* assign tree index for size S to variable I. Use x86 asm if possible  */
28366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
28376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define compute_tree_index(S, I)\
28386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao{\
28396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  unsigned int X = S >> TREEBIN_SHIFT;\
28406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (X == 0)\
28416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I = 0;\
28426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (X > 0xFFFF)\
28436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I = NTREEBINS-1;\
28446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {\
28456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    unsigned int K = (unsigned) sizeof(X)*__CHAR_BIT__ - 1 - (unsigned) __builtin_clz(X); \
28466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
28476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
28486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
28496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
28506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif defined (__INTEL_COMPILER)
28516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define compute_tree_index(S, I)\
28526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao{\
28536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t X = S >> TREEBIN_SHIFT;\
28546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (X == 0)\
28556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I = 0;\
28566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (X > 0xFFFF)\
28576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I = NTREEBINS-1;\
28586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {\
28596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    unsigned int K = _bit_scan_reverse (X); \
28606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
28616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
28626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
28636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
28646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif defined(_MSC_VER) && _MSC_VER>=1300
28656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define compute_tree_index(S, I)\
28666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao{\
28676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t X = S >> TREEBIN_SHIFT;\
28686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (X == 0)\
28696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I = 0;\
28706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (X > 0xFFFF)\
28716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I = NTREEBINS-1;\
28726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {\
28736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    unsigned int K;\
28746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    _BitScanReverse((DWORD *) &K, (DWORD) X);\
28756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
28766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
28776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
28786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
28796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* GNUC */
28806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define compute_tree_index(S, I)\
28816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao{\
28826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t X = S >> TREEBIN_SHIFT;\
28836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (X == 0)\
28846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I = 0;\
28856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (X > 0xFFFF)\
28866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I = NTREEBINS-1;\
28876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {\
28886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    unsigned int Y = (unsigned int)X;\
28896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    unsigned int N = ((Y - 0x100) >> 16) & 8;\
28906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
28916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    N += K;\
28926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
28936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    K = 14 - N + ((Y <<= K) >> 15);\
28946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
28956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
28966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
28976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* GNUC */
28986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
28996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Bit representing maximum resolved size in a treebin at i */
29006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define bit_for_tree_index(i) \
29016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
29026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Shift placing maximum resolved bit in a treebin at i as sign bit */
29046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define leftshift_for_tree_index(i) \
29056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   ((i == NTREEBINS-1)? 0 : \
29066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
29076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* The size of the smallest chunk held in bin with index i */
29096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define minsize_for_tree_index(i) \
29106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) |  \
29116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
29126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ------------------------ Operations on bin maps ----------------------- */
29156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* bit corresponding to given index */
29176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define idx2bit(i)              ((binmap_t)(1) << (i))
29186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Mark/Clear bits with given index */
29206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define mark_smallmap(M,i)      ((M)->smallmap |=  idx2bit(i))
29216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define clear_smallmap(M,i)     ((M)->smallmap &= ~idx2bit(i))
29226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define smallmap_is_marked(M,i) ((M)->smallmap &   idx2bit(i))
29236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define mark_treemap(M,i)       ((M)->treemap  |=  idx2bit(i))
29256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define clear_treemap(M,i)      ((M)->treemap  &= ~idx2bit(i))
29266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define treemap_is_marked(M,i)  ((M)->treemap  &   idx2bit(i))
29276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* isolate the least set bit of a bitmap */
29296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define least_bit(x)         ((x) & -(x))
29306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* mask with all bits to left of least bit of x on */
29326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define left_bits(x)         ((x<<1) | -(x<<1))
29336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* mask with all bits to left of or equal to least bit of x on */
29356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define same_or_left_bits(x) ((x) | -(x))
29366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* index corresponding to given bit. Use x86 asm if possible */
29386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
29406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define compute_bit2idx(X, I)\
29416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao{\
29426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  unsigned int J;\
29436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  J = __builtin_ctz(X); \
29446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  I = (bindex_t)J;\
29456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
29466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif defined (__INTEL_COMPILER)
29486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define compute_bit2idx(X, I)\
29496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao{\
29506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  unsigned int J;\
29516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  J = _bit_scan_forward (X); \
29526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  I = (bindex_t)J;\
29536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
29546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif defined(_MSC_VER) && _MSC_VER>=1300
29566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define compute_bit2idx(X, I)\
29576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao{\
29586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  unsigned int J;\
29596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  _BitScanForward((DWORD *) &J, X);\
29606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  I = (bindex_t)J;\
29616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
29626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif USE_BUILTIN_FFS
29646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define compute_bit2idx(X, I) I = ffs(X)-1
29656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else
29676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define compute_bit2idx(X, I)\
29686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao{\
29696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  unsigned int Y = X - 1;\
29706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  unsigned int K = Y >> (16-4) & 16;\
29716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  unsigned int N = K;        Y >>= K;\
29726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  N += K = Y >> (8-3) &  8;  Y >>= K;\
29736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  N += K = Y >> (4-2) &  4;  Y >>= K;\
29746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  N += K = Y >> (2-1) &  2;  Y >>= K;\
29756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  N += K = Y >> (1-0) &  1;  Y >>= K;\
29766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  I = (bindex_t)(N + Y);\
29776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
29786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* GNUC */
29796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ----------------------- Runtime Check Support ------------------------- */
29826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
29846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  For security, the main invariant is that malloc/free/etc never
29856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  writes to a static address other than malloc_state, unless static
29866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc_state itself has been corrupted, which cannot occur via
29876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  malloc (because of these checks). In essence this means that we
29886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  believe all pointers, sizes, maps etc held in malloc_state, but
29896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  check all of those linked or offsetted from other embedded data
29906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  structures.  These checks are interspersed with main code in a way
29916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  that tends to minimize their run-time cost.
29926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
29936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  When FOOTERS is defined, in addition to range checking, we also
29946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  verify footer fields of inuse chunks, which can be used guarantee
29956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  that the mstate controlling malloc/free is intact.  This is a
29966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  streamlined version of the approach described by William Robertson
29976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  et al in "Run-time Detection of Heap-based Overflows" LISA'03
29986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  http://www.usenix.org/events/lisa03/tech/robertson.html The footer
29996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  of an inuse chunk holds the xor of its mstate and a random seed,
30006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  that is checked upon calls to free() and realloc().  This is
30016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (probabalistically) unguessable from outside the program, but can be
30026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  computed by any code successfully malloc'ing any chunk, so does not
30036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  itself provide protection against code that has already broken
30046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  security through some other means.  Unlike Robertson et al, we
30056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  always dynamically check addresses of all offset chunks (previous,
30066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  next, etc). This turns out to be cheaper than relying on hashes.
30076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
30086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !INSECURE
30106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check if address a is at least as high as any from MORECORE or MMAP */
30116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
30126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check if address of next chunk n is higher than base chunk p */
30136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ok_next(p, n)    ((char*)(p) < (char*)(n))
30146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check if p has inuse status */
30156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ok_inuse(p)     is_inuse(p)
30166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check if p has its pinuse bit on */
30176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ok_pinuse(p)     pinuse(p)
30186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* !INSECURE */
30206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ok_address(M, a) (1)
30216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ok_next(b, n)    (1)
30226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ok_inuse(p)      (1)
30236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ok_pinuse(p)     (1)
30246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* !INSECURE */
30256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if (FOOTERS && !INSECURE)
30276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check if (alleged) mstate m has expected magic field */
30286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ok_magic(M)      ((M)->magic == mparams.magic)
30296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else  /* (FOOTERS && !INSECURE) */
30306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define ok_magic(M)      (1)
30316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* (FOOTERS && !INSECURE) */
30326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* In gcc, use __builtin_expect to minimize impact of checks */
30346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !INSECURE
30356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if defined(__GNUC__) && __GNUC__ >= 3
30366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define RTCHECK(e)  __builtin_expect(e, 1)
30376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* GNUC */
30386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define RTCHECK(e)  (e)
30396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* GNUC */
30406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* !INSECURE */
30416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define RTCHECK(e)  (1)
30426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* !INSECURE */
30436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* macros to set up inuse chunks with or without footers */
30456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !FOOTERS
30476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define mark_inuse_foot(M,p,s)
30496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Macros for setting head/foot of non-mmapped chunks */
30516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Set cinuse bit and pinuse bit of next chunk */
30536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define set_inuse(M,p,s)\
30546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
30556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
30566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
30586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define set_inuse_and_pinuse(M,p,s)\
30596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
30606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
30616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Set size, cinuse and pinuse bit of this chunk */
30636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
30646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
30656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* FOOTERS */
30676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Set foot of inuse chunk to be xor of mstate and seed */
30696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define mark_inuse_foot(M,p,s)\
30706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
30716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define get_mstate_for(p)\
30736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((mstate)(((mchunkptr)((char*)(p) +\
30746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    (chunksize(p))))->prev_foot ^ mparams.magic))
30756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define set_inuse(M,p,s)\
30776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
30786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
30796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mark_inuse_foot(M,p,s))
30806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define set_inuse_and_pinuse(M,p,s)\
30826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
30836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
30846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao mark_inuse_foot(M,p,s))
30856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
30876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
30886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mark_inuse_foot(M, p, s))
30896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* !FOOTERS */
30916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ---------------------------- setting mparams -------------------------- */
30936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
30946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if LOCK_AT_FORK
30956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void pre_fork(void)         { ACQUIRE_LOCK(&(gm)->mutex); }
30966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void post_fork_parent(void) { RELEASE_LOCK(&(gm)->mutex); }
30976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void post_fork_child(void)  { INITIAL_LOCK(&(gm)->mutex); }
30986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* LOCK_AT_FORK */
30996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
31006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Initialize mparams */
31016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic int init_mparams(void) {
31026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* BEGIN android-added: move pthread_atfork outside of lock */
31036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int first_run = 0;
31046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* END android-added */
31056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef NEED_GLOBAL_LOCK_INIT
31066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (malloc_global_mutex_status <= 0)
31076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    init_malloc_global_mutex();
31086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
31096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
31106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ACQUIRE_MALLOC_GLOBAL_LOCK();
31116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (mparams.magic == 0) {
31126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t magic;
31136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t psize;
31146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t gsize;
31156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* BEGIN android-added: move pthread_atfork outside of lock */
31166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    first_run = 1;
31176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* END android-added */
31186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
31196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifndef WIN32
31206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    psize = malloc_getpagesize;
31216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize);
31226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* WIN32 */
31236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    {
31246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      SYSTEM_INFO system_info;
31256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      GetSystemInfo(&system_info);
31266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      psize = system_info.dwPageSize;
31276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      gsize = ((DEFAULT_GRANULARITY != 0)?
31286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao               DEFAULT_GRANULARITY : system_info.dwAllocationGranularity);
31296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
31306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* WIN32 */
31316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
31326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* Sanity-check configuration:
31336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       size_t must be unsigned and as wide as pointer type.
31346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       ints must be at least 4 bytes.
31356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       alignment must be at least 8.
31366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       Alignment, min chunk size, and page size must all be powers of 2.
31376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    */
31386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if ((sizeof(size_t) != sizeof(char*)) ||
31396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        (MAX_SIZE_T < MIN_CHUNK_SIZE)  ||
31406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        (sizeof(int) < 4)  ||
31416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        (MALLOC_ALIGNMENT < (size_t)8U) ||
31426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) ||
31436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        ((MCHUNK_SIZE      & (MCHUNK_SIZE-SIZE_T_ONE))      != 0) ||
31446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        ((gsize            & (gsize-SIZE_T_ONE))            != 0) ||
31456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        ((psize            & (psize-SIZE_T_ONE))            != 0))
31466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      ABORT;
31476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mparams.granularity = gsize;
31486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mparams.page_size = psize;
31496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
31506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
31516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if MORECORE_CONTIGUOUS
31526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
31536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else  /* MORECORE_CONTIGUOUS */
31546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
31556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MORECORE_CONTIGUOUS */
31566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
31576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !ONLY_MSPACES
31586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* Set up lock for main malloc area */
31596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    gm->mflags = mparams.default_mflags;
31606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    (void)INITIAL_LOCK(&gm->mutex);
31616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
31626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* BEGIN android-removed: move pthread_atfork outside of lock */
31636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if 0 && LOCK_AT_FORK
31646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    pthread_atfork(&pre_fork, &post_fork_parent, &post_fork_child);
31656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
31666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* END android-removed */
31676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
31686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    {
31696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if USE_DEV_RANDOM
31706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      int fd;
31716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      unsigned char buf[sizeof(size_t)];
31726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* Try to use /dev/urandom, else fall back on using time */
31736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
31746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          read(fd, buf, sizeof(buf)) == sizeof(buf)) {
31756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        magic = *((size_t *) buf);
31766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        close(fd);
31776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
31786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else
31796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* USE_DEV_RANDOM */
31806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef WIN32
31816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U);
31826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#elif defined(LACKS_TIME_H)
31836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      magic = (size_t)&magic ^ (size_t)0x55555555U;
31846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else
31856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      magic = (size_t)(time(0) ^ (size_t)0x55555555U);
31866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
31876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      magic |= (size_t)8U;    /* ensure nonzero */
31886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      magic &= ~(size_t)7U;   /* improve chances of fault for bad values */
31896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* Until memory modes commonly available, use volatile-write */
31906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      (*(volatile size_t *)(&(mparams.magic))) = magic;
31916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
31926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
31936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
31946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  RELEASE_MALLOC_GLOBAL_LOCK();
31956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* BEGIN android-added: move pthread_atfork outside of lock */
31966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (first_run != 0) {
31976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if LOCK_AT_FORK
31986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    pthread_atfork(&pre_fork, &post_fork_parent, &post_fork_child);
31996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
32006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
32016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* END android-added */
32026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 1;
32036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
32046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
32056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* support for mallopt */
32066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic int change_mparam(int param_number, int value) {
32076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t val;
32086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
32096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  val = (value == -1)? MAX_SIZE_T : (size_t)value;
32106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  switch(param_number) {
32116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  case M_TRIM_THRESHOLD:
32126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mparams.trim_threshold = val;
32136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 1;
32146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  case M_GRANULARITY:
32156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
32166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mparams.granularity = val;
32176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return 1;
32186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
32196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else
32206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return 0;
32216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  case M_MMAP_THRESHOLD:
32226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mparams.mmap_threshold = val;
32236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 1;
32246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  default:
32256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 0;
32266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
32276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
32286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
32296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if DEBUG
32306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ------------------------- Debugging Support --------------------------- */
32316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
32326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check properties of any chunk, whether free, inuse, mmapped etc  */
32336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void do_check_any_chunk(mstate m, mchunkptr p) {
32346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
32356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(ok_address(m, p));
32366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
32376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
32386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check properties of top chunk */
32396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void do_check_top_chunk(mstate m, mchunkptr p) {
32406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  msegmentptr sp = segment_holding(m, (char*)p);
32416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t  sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */
32426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(sp != 0);
32436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
32446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(ok_address(m, p));
32456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(sz == m->topsize);
32466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(sz > 0);
32476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
32486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(pinuse(p));
32496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(!pinuse(chunk_plus_offset(p, sz)));
32506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
32516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
32526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check properties of (inuse) mmapped chunks */
32536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void do_check_mmapped_chunk(mstate m, mchunkptr p) {
32546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t  sz = chunksize(p);
32556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD);
32566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(is_mmapped(p));
32576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(use_mmap(m));
32586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
32596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(ok_address(m, p));
32606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(!is_small(sz));
32616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
32626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
32636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
32646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
32656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
32666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check properties of inuse chunks */
32676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void do_check_inuse_chunk(mstate m, mchunkptr p) {
32686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  do_check_any_chunk(m, p);
32696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(is_inuse(p));
32706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(next_pinuse(p));
32716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* If not pinuse and not mmapped, previous chunk has OK offset */
32726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
32736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (is_mmapped(p))
32746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    do_check_mmapped_chunk(m, p);
32756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
32766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
32776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check properties of free chunks */
32786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void do_check_free_chunk(mstate m, mchunkptr p) {
32796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t sz = chunksize(p);
32806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr next = chunk_plus_offset(p, sz);
32816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  do_check_any_chunk(m, p);
32826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(!is_inuse(p));
32836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(!next_pinuse(p));
32846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert (!is_mmapped(p));
32856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (p != m->dv && p != m->top) {
32866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (sz >= MIN_CHUNK_SIZE) {
32876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert((sz & CHUNK_ALIGN_MASK) == 0);
32886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(is_aligned(chunk2mem(p)));
32896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(next->prev_foot == sz);
32906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(pinuse(p));
32916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert (next == m->top || is_inuse(next));
32926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(p->fd->bk == p);
32936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(p->bk->fd == p);
32946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
32956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else  /* markers are always of size SIZE_T_SIZE */
32966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(sz == SIZE_T_SIZE);
32976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
32986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
32996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
33006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check properties of malloced chunks at the point they are malloced */
33016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
33026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (mem != 0) {
33036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr p = mem2chunk(mem);
33046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t sz = p->head & ~INUSE_BITS;
33056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    do_check_inuse_chunk(m, p);
33066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert((sz & CHUNK_ALIGN_MASK) == 0);
33076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(sz >= MIN_CHUNK_SIZE);
33086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(sz >= s);
33096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
33106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
33116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
33126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
33136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
33146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check a tree and its subtrees.  */
33156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void do_check_tree(mstate m, tchunkptr t) {
33166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tchunkptr head = 0;
33176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tchunkptr u = t;
33186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bindex_t tindex = t->index;
33196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t tsize = chunksize(t);
33206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bindex_t idx;
33216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  compute_tree_index(tsize, idx);
33226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(tindex == idx);
33236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(tsize >= MIN_LARGE_SIZE);
33246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(tsize >= minsize_for_tree_index(idx));
33256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
33266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
33276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  do { /* traverse through chain of same-sized nodes */
33286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    do_check_any_chunk(m, ((mchunkptr)u));
33296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(u->index == tindex);
33306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(chunksize(u) == tsize);
33316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(!is_inuse(u));
33326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(!next_pinuse(u));
33336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(u->fd->bk == u);
33346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(u->bk->fd == u);
33356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (u->parent == 0) {
33366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(u->child[0] == 0);
33376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(u->child[1] == 0);
33386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
33396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {
33406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(head == 0); /* only one node on chain has parent */
33416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      head = u;
33426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(u->parent != u);
33436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert (u->parent->child[0] == u ||
33446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              u->parent->child[1] == u ||
33456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              *((tbinptr*)(u->parent)) == u);
33466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (u->child[0] != 0) {
33476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        assert(u->child[0]->parent == u);
33486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        assert(u->child[0] != u);
33496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        do_check_tree(m, u->child[0]);
33506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
33516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (u->child[1] != 0) {
33526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        assert(u->child[1]->parent == u);
33536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        assert(u->child[1] != u);
33546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        do_check_tree(m, u->child[1]);
33556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
33566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (u->child[0] != 0 && u->child[1] != 0) {
33576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        assert(chunksize(u->child[0]) < chunksize(u->child[1]));
33586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
33596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
33606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    u = u->fd;
33616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  } while (u != t);
33626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(head != 0);
33636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
33646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
33656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*  Check all the chunks in a treebin.  */
33666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void do_check_treebin(mstate m, bindex_t i) {
33676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tbinptr* tb = treebin_at(m, i);
33686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tchunkptr t = *tb;
33696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int empty = (m->treemap & (1U << i)) == 0;
33706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (t == 0)
33716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(empty);
33726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!empty)
33736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    do_check_tree(m, t);
33746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
33756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
33766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*  Check all the chunks in a smallbin.  */
33776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void do_check_smallbin(mstate m, bindex_t i) {
33786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  sbinptr b = smallbin_at(m, i);
33796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr p = b->bk;
33806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  unsigned int empty = (m->smallmap & (1U << i)) == 0;
33816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (p == b)
33826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(empty);
33836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!empty) {
33846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    for (; p != b; p = p->bk) {
33856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t size = chunksize(p);
33866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr q;
33876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* each chunk claims to be free */
33886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      do_check_free_chunk(m, p);
33896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* chunk belongs in bin */
33906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(small_index(size) == i);
33916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(p->bk == b || chunksize(p->bk) == chunksize(p));
33926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* chunk is followed by an inuse chunk */
33936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      q = next_chunk(p);
33946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (q->head != FENCEPOST_HEAD)
33956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        do_check_inuse_chunk(m, q);
33966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
33976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
33986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
33996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
34006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Find x in a bin. Used in other check functions. */
34016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic int bin_find(mstate m, mchunkptr x) {
34026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t size = chunksize(x);
34036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (is_small(size)) {
34046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    bindex_t sidx = small_index(size);
34056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    sbinptr b = smallbin_at(m, sidx);
34066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (smallmap_is_marked(m, sidx)) {
34076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr p = b;
34086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      do {
34096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (p == x)
34106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          return 1;
34116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      } while ((p = p->fd) != b);
34126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
34136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
34146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
34156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    bindex_t tidx;
34166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    compute_tree_index(size, tidx);
34176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (treemap_is_marked(m, tidx)) {
34186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      tchunkptr t = *treebin_at(m, tidx);
34196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t sizebits = size << leftshift_for_tree_index(tidx);
34206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      while (t != 0 && chunksize(t) != size) {
34216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
34226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        sizebits <<= 1;
34236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
34246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (t != 0) {
34256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        tchunkptr u = t;
34266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        do {
34276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (u == (tchunkptr)x)
34286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            return 1;
34296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        } while ((u = u->fd) != t);
34306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
34316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
34326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
34336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
34346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
34356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
34366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Traverse each chunk and check it; return total */
34376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic size_t traverse_and_check(mstate m) {
34386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t sum = 0;
34396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (is_initialized(m)) {
34406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    msegmentptr s = &m->seg;
34416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    sum += m->topsize + TOP_FOOT_SIZE;
34426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    while (s != 0) {
34436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr q = align_as_chunk(s->base);
34446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr lastq = 0;
34456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(pinuse(q));
34466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      while (segment_holds(s, q) &&
34476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao             q != m->top && q->head != FENCEPOST_HEAD) {
34486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        sum += chunksize(q);
34496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (is_inuse(q)) {
34506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          assert(!bin_find(m, q));
34516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          do_check_inuse_chunk(m, q);
34526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
34536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else {
34546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          assert(q == m->dv || bin_find(m, q));
34556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */
34566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          do_check_free_chunk(m, q);
34576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
34586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        lastq = q;
34596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        q = next_chunk(q);
34606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
34616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      s = s->next;
34626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
34636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
34646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return sum;
34656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
34666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
34676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
34686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Check all properties of malloc_state. */
34696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void do_check_malloc_state(mstate m) {
34706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bindex_t i;
34716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t total;
34726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* check bins */
34736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for (i = 0; i < NSMALLBINS; ++i)
34746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    do_check_smallbin(m, i);
34756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for (i = 0; i < NTREEBINS; ++i)
34766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    do_check_treebin(m, i);
34776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
34786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (m->dvsize != 0) { /* check dv chunk */
34796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    do_check_any_chunk(m, m->dv);
34806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(m->dvsize == chunksize(m->dv));
34816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(m->dvsize >= MIN_CHUNK_SIZE);
34826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(bin_find(m, m->dv) == 0);
34836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
34846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
34856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (m->top != 0) {   /* check top chunk */
34866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    do_check_top_chunk(m, m->top);
34876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /*assert(m->topsize == chunksize(m->top)); redundant */
34886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(m->topsize > 0);
34896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(bin_find(m, m->top) == 0);
34906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
34916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
34926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  total = traverse_and_check(m);
34936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(total <= m->footprint);
34946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(m->footprint <= m->max_footprint);
34956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
34966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* DEBUG */
34976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
34986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ----------------------------- statistics ------------------------------ */
34996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
35006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !NO_MALLINFO
35016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic struct mallinfo internal_mallinfo(mstate m) {
35026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
35036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
35046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!PREACTION(m)) {
35056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    check_malloc_state(m);
35066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (is_initialized(m)) {
35076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t nfree = SIZE_T_ONE; /* top always free */
35086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t mfree = m->topsize + TOP_FOOT_SIZE;
35096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t sum = mfree;
35106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      msegmentptr s = &m->seg;
35116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      while (s != 0) {
35126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr q = align_as_chunk(s->base);
35136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        while (segment_holds(s, q) &&
35146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao               q != m->top && q->head != FENCEPOST_HEAD) {
35156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          size_t sz = chunksize(q);
35166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          sum += sz;
35176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (!is_inuse(q)) {
35186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            mfree += sz;
35196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            ++nfree;
35206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
35216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          q = next_chunk(q);
35226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
35236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        s = s->next;
35246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
35256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
35266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nm.arena    = sum;
35276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nm.ordblks  = nfree;
35286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nm.hblkhd   = m->footprint - sum;
35296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* BEGIN android-changed: usmblks set to footprint from max_footprint */
35306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nm.usmblks  = m->footprint;
35316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* END android-changed */
35326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nm.uordblks = m->footprint - mfree;
35336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nm.fordblks = mfree;
35346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nm.keepcost = m->topsize;
35356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
35366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
35376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    POSTACTION(m);
35386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
35396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return nm;
35406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
35416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* !NO_MALLINFO */
35426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
35436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !NO_MALLOC_STATS
35446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void internal_malloc_stats(mstate m) {
35456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
35466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!PREACTION(m)) {
35476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t maxfp = 0;
35486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t fp = 0;
35496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t used = 0;
35506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    check_malloc_state(m);
35516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (is_initialized(m)) {
35526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      msegmentptr s = &m->seg;
35536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      maxfp = m->max_footprint;
35546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      fp = m->footprint;
35556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      used = fp - (m->topsize + TOP_FOOT_SIZE);
35566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
35576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      while (s != 0) {
35586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr q = align_as_chunk(s->base);
35596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        while (segment_holds(s, q) &&
35606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao               q != m->top && q->head != FENCEPOST_HEAD) {
35616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (!is_inuse(q))
35626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            used -= chunksize(q);
35636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          q = next_chunk(q);
35646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
35656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        s = s->next;
35666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
35676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
35686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    POSTACTION(m); /* drop lock */
35696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
35706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    fprintf(stderr, "system bytes     = %10lu\n", (unsigned long)(fp));
35716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    fprintf(stderr, "in use bytes     = %10lu\n", (unsigned long)(used));
35726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
35736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
35746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* NO_MALLOC_STATS */
35756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
35766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ----------------------- Operations on smallbins ----------------------- */
35776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
35786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
35796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Various forms of linking and unlinking are defined as macros.  Even
35806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the ones for trees, which are very long but have very short typical
35816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  paths.  This is ugly but reduces reliance on inlining support of
35826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  compilers.
35836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
35846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
35856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Link a free chunk into a smallbin  */
35866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define insert_small_chunk(M, P, S) {\
35876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bindex_t I  = small_index(S);\
35886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr B = smallbin_at(M, I);\
35896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr F = B;\
35906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(S >= MIN_CHUNK_SIZE);\
35916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!smallmap_is_marked(M, I))\
35926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mark_smallmap(M, I);\
35936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (RTCHECK(ok_address(M, B->fd)))\
35946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    F = B->fd;\
35956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {\
35966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    CORRUPTION_ERROR_ACTION(M);\
35976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
35986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  B->fd = P;\
35996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  F->bk = P;\
36006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  P->fd = F;\
36016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  P->bk = B;\
36026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
36036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
36046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Unlink a chunk from a smallbin  */
36056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define unlink_small_chunk(M, P, S) {\
36066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr F = P->fd;\
36076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr B = P->bk;\
36086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bindex_t I = small_index(S);\
36096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(P != B);\
36106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(P != F);\
36116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(chunksize(P) == small_index2size(I));\
36126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (RTCHECK(F == smallbin_at(M,I) || (ok_address(M, F) && F->bk == P))) { \
36136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (B == F) {\
36146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      clear_smallmap(M, I);\
36156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }\
36166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (RTCHECK(B == smallbin_at(M,I) ||\
36176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                     (ok_address(M, B) && B->fd == P))) {\
36186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      F->bk = B;\
36196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      B->fd = F;\
36206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }\
36216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {\
36226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      CORRUPTION_ERROR_ACTION(M);\
36236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }\
36246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
36256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {\
36266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    CORRUPTION_ERROR_ACTION(M);\
36276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
36286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
36296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
36306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Unlink the first chunk from a smallbin */
36316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define unlink_first_small_chunk(M, B, P, I) {\
36326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr F = P->fd;\
36336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(P != B);\
36346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(P != F);\
36356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(chunksize(P) == small_index2size(I));\
36366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (B == F) {\
36376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    clear_smallmap(M, I);\
36386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
36396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (RTCHECK(ok_address(M, F) && F->bk == P)) {\
36406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    F->bk = B;\
36416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    B->fd = F;\
36426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
36436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {\
36446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    CORRUPTION_ERROR_ACTION(M);\
36456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
36466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
36476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
36486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Replace dv node, binning the old one */
36496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Used only when dvsize known to be small */
36506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define replace_dv(M, P, S) {\
36516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t DVS = M->dvsize;\
36526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(is_small(DVS));\
36536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (DVS != 0) {\
36546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr DV = M->dv;\
36556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    insert_small_chunk(M, DV, DVS);\
36566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
36576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  M->dvsize = S;\
36586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  M->dv = P;\
36596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
36606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
36616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ------------------------- Operations on trees ------------------------- */
36626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
36636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Insert chunk into tree */
36646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define insert_large_chunk(M, X, S) {\
36656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tbinptr* H;\
36666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bindex_t I;\
36676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  compute_tree_index(S, I);\
36686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  H = treebin_at(M, I);\
36696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  X->index = I;\
36706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  X->child[0] = X->child[1] = 0;\
36716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!treemap_is_marked(M, I)) {\
36726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mark_treemap(M, I);\
36736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    *H = X;\
36746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    X->parent = (tchunkptr)H;\
36756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    X->fd = X->bk = X;\
36766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
36776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {\
36786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    tchunkptr T = *H;\
36796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t K = S << leftshift_for_tree_index(I);\
36806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    for (;;) {\
36816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (chunksize(T) != S) {\
36826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
36836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        K <<= 1;\
36846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (*C != 0)\
36856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          T = *C;\
36866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else if (RTCHECK(ok_address(M, C))) {\
36876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          *C = X;\
36886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          X->parent = T;\
36896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          X->fd = X->bk = X;\
36906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          break;\
36916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }\
36926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else {\
36936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          CORRUPTION_ERROR_ACTION(M);\
36946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          break;\
36956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }\
36966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }\
36976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else {\
36986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        tchunkptr F = T->fd;\
36996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
37006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          T->fd = F->bk = X;\
37016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          X->fd = F;\
37026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          X->bk = T;\
37036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          X->parent = 0;\
37046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          break;\
37056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }\
37066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else {\
37076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          CORRUPTION_ERROR_ACTION(M);\
37086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          break;\
37096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }\
37106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }\
37116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }\
37126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
37136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
37146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
37156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
37166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Unlink steps:
37176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
37186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  1. If x is a chained node, unlink it from its same-sized fd/bk links
37196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     and choose its bk node as its replacement.
37206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  2. If x was the last node of its size, but not a leaf node, it must
37216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     be replaced with a leaf node (not merely one with an open left or
37226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     right), to make sure that lefts and rights of descendents
37236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     correspond properly to bit masks.  We use the rightmost descendent
37246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     of x.  We could use any other leaf, but this is easy to locate and
37256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     tends to counteract removal of leftmosts elsewhere, and so keeps
37266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     paths shorter than minimally guaranteed.  This doesn't loop much
37276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     because on average a node in a tree is near the bottom.
37286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  3. If x is the base of a chain (i.e., has parent links) relink
37296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     x's parent and children to x's replacement (or null if none).
37306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
37316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
37326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define unlink_large_chunk(M, X) {\
37336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tchunkptr XP = X->parent;\
37346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tchunkptr R;\
37356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (X->bk != X) {\
37366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    tchunkptr F = X->fd;\
37376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    R = X->bk;\
37386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (RTCHECK(ok_address(M, F) && F->bk == X && R->fd == X)) {\
37396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      F->bk = R;\
37406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      R->fd = F;\
37416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }\
37426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {\
37436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      CORRUPTION_ERROR_ACTION(M);\
37446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }\
37456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
37466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {\
37476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    tchunkptr* RP;\
37486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (((R = *(RP = &(X->child[1]))) != 0) ||\
37496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        ((R = *(RP = &(X->child[0]))) != 0)) {\
37506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      tchunkptr* CP;\
37516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      while ((*(CP = &(R->child[1])) != 0) ||\
37526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao             (*(CP = &(R->child[0])) != 0)) {\
37536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        R = *(RP = CP);\
37546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }\
37556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (RTCHECK(ok_address(M, RP)))\
37566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        *RP = 0;\
37576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else {\
37586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        CORRUPTION_ERROR_ACTION(M);\
37596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }\
37606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }\
37616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
37626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (XP != 0) {\
37636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    tbinptr* H = treebin_at(M, X->index);\
37646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (X == *H) {\
37656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if ((*H = R) == 0) \
37666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        clear_treemap(M, X->index);\
37676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }\
37686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (RTCHECK(ok_address(M, XP))) {\
37696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (XP->child[0] == X) \
37706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        XP->child[0] = R;\
37716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else \
37726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        XP->child[1] = R;\
37736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }\
37746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else\
37756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      CORRUPTION_ERROR_ACTION(M);\
37766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (R != 0) {\
37776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (RTCHECK(ok_address(M, R))) {\
37786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        tchunkptr C0, C1;\
37796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        R->parent = XP;\
37806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if ((C0 = X->child[0]) != 0) {\
37816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (RTCHECK(ok_address(M, C0))) {\
37826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            R->child[0] = C0;\
37836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            C0->parent = R;\
37846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }\
37856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else\
37866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            CORRUPTION_ERROR_ACTION(M);\
37876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }\
37886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if ((C1 = X->child[1]) != 0) {\
37896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (RTCHECK(ok_address(M, C1))) {\
37906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            R->child[1] = C1;\
37916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            C1->parent = R;\
37926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }\
37936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else\
37946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            CORRUPTION_ERROR_ACTION(M);\
37956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }\
37966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }\
37976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else\
37986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        CORRUPTION_ERROR_ACTION(M);\
37996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }\
38006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }\
38016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
38026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Relays to large vs small bin operations */
38046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define insert_chunk(M, P, S)\
38066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (is_small(S)) insert_small_chunk(M, P, S)\
38076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
38086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define unlink_chunk(M, P, S)\
38106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (is_small(S)) unlink_small_chunk(M, P, S)\
38116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
38126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Relays to internal calls to malloc/free from realloc, memalign etc */
38156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if ONLY_MSPACES
38176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define internal_malloc(m, b) mspace_malloc(m, b)
38186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define internal_free(m, mem) mspace_free(m,mem);
38196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* ONLY_MSPACES */
38206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if MSPACES
38216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define internal_malloc(m, b)\
38226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ((m == gm)? dlmalloc(b) : mspace_malloc(m, b))
38236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define internal_free(m, mem)\
38246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   if (m == gm) dlfree(mem); else mspace_free(m,mem);
38256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* MSPACES */
38266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define internal_malloc(m, b) dlmalloc(b)
38276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define internal_free(m, mem) dlfree(mem)
38286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MSPACES */
38296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* ONLY_MSPACES */
38306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -----------------------  Direct-mmapping chunks ----------------------- */
38326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
38346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Directly mmapped chunks are set up with an offset to the start of
38356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  the mmapped region stored in the prev_foot field of the chunk. This
38366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  allows reconstruction of the required argument to MUNMAP when freed,
38376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  and also allows adjustment of the returned chunk to meet alignment
38386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  requirements (especially in memalign).
38396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
38406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Malloc using mmap */
38426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void* mmap_alloc(mstate m, size_t nb) {
38436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
38446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (m->footprint_limit != 0) {
38456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t fp = m->footprint + mmsize;
38466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (fp <= m->footprint || fp > m->footprint_limit)
38476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return 0;
38486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
38496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (mmsize > nb) {     /* Check for wrap around 0 */
38506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    char* mm = (char*)(CALL_DIRECT_MMAP(mmsize));
38516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (mm != CMFAIL) {
38526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t offset = align_offset(chunk2mem(mm));
38536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t psize = mmsize - offset - MMAP_FOOT_PAD;
38546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr p = (mchunkptr)(mm + offset);
38556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      p->prev_foot = offset;
38566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      p->head = psize;
38576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mark_inuse_foot(m, p, psize);
38586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
38596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
38606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (m->least_addr == 0 || mm < m->least_addr)
38626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->least_addr = mm;
38636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if ((m->footprint += mmsize) > m->max_footprint)
38646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->max_footprint = m->footprint;
38656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(is_aligned(chunk2mem(p)));
38666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_mmapped_chunk(m, p);
38676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return chunk2mem(p);
38686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
38696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
38706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
38716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
38726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Realloc using mmap */
38746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) {
38756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t oldsize = chunksize(oldp);
38766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (void)flags; /* placate people compiling -Wunused */
38776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (is_small(nb)) /* Can't shrink mmap regions below small size */
38786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 0;
38796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* Keep old chunk if big enough but not too big */
38806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (oldsize >= nb + SIZE_T_SIZE &&
38816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      (oldsize - nb) <= (mparams.granularity << 1))
38826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return oldp;
38836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
38846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t offset = oldp->prev_foot;
38856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
38866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
38876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
38886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                  oldmmsize, newmmsize, flags);
38896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (cp != CMFAIL) {
38906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr newp = (mchunkptr)(cp + offset);
38916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
38926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      newp->head = psize;
38936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mark_inuse_foot(m, newp, psize);
38946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
38956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
38966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
38976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (cp < m->least_addr)
38986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->least_addr = cp;
38996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
39006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->max_footprint = m->footprint;
39016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_mmapped_chunk(m, newp);
39026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return newp;
39036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
39046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
39056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
39066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
39076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -------------------------- mspace management -------------------------- */
39106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Initialize top chunk and its size */
39126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void init_top(mstate m, mchunkptr p, size_t psize) {
39136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* Ensure alignment */
39146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t offset = align_offset(chunk2mem(p));
39156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  p = (mchunkptr)((char*)p + offset);
39166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  psize -= offset;
39176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->top = p;
39196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->topsize = psize;
39206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  p->head = psize | PINUSE_BIT;
39216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* set size of fake trailing chunk holding overhead space only once */
39226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
39236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->trim_check = mparams.trim_threshold; /* reset on each update */
39246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
39256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Initialize bins for a new mstate that is otherwise zeroed out */
39276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void init_bins(mstate m) {
39286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* Establish circular links for smallbins */
39296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bindex_t i;
39306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for (i = 0; i < NSMALLBINS; ++i) {
39316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    sbinptr bin = smallbin_at(m,i);
39326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    bin->fd = bin->bk = bin;
39336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
39346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
39356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if PROCEED_ON_ERROR
39376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* default corruption action */
39396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void reset_on_error(mstate m) {
39406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int i;
39416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ++malloc_corruption_error_count;
39426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* Reinitialize fields to forget about all memory */
39436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->smallmap = m->treemap = 0;
39446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->dvsize = m->topsize = 0;
39456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->seg.base = 0;
39466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->seg.size = 0;
39476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->seg.next = 0;
39486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->top = m->dv = 0;
39496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for (i = 0; i < NTREEBINS; ++i)
39506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    *treebin_at(m, i) = 0;
39516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  init_bins(m);
39526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
39536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* PROCEED_ON_ERROR */
39546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Allocate chunk and prepend remainder with chunk in successor base. */
39566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void* prepend_alloc(mstate m, char* newbase, char* oldbase,
39576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                           size_t nb) {
39586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr p = align_as_chunk(newbase);
39596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr oldfirst = align_as_chunk(oldbase);
39606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t psize = (char*)oldfirst - (char*)p;
39616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr q = chunk_plus_offset(p, nb);
39626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t qsize = psize - nb;
39636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  set_size_and_pinuse_of_inuse_chunk(m, p, nb);
39646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert((char*)oldfirst > (char*)q);
39666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(pinuse(oldfirst));
39676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(qsize >= MIN_CHUNK_SIZE);
39686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* consolidate remainder with first chunk of old base */
39706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (oldfirst == m->top) {
39716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t tsize = m->topsize += qsize;
39726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    m->top = q;
39736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    q->head = tsize | PINUSE_BIT;
39746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    check_top_chunk(m, q);
39756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
39766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (oldfirst == m->dv) {
39776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t dsize = m->dvsize += qsize;
39786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    m->dv = q;
39796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    set_size_and_pinuse_of_free_chunk(q, dsize);
39806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
39816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
39826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!is_inuse(oldfirst)) {
39836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t nsize = chunksize(oldfirst);
39846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      unlink_chunk(m, oldfirst, nsize);
39856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      oldfirst = chunk_plus_offset(oldfirst, nsize);
39866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      qsize += nsize;
39876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
39886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    set_free_with_pinuse(q, qsize, oldfirst);
39896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    insert_chunk(m, q, qsize);
39906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    check_free_chunk(m, q);
39916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
39926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  check_malloced_chunk(m, chunk2mem(p), nb);
39946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return chunk2mem(p);
39956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
39966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
39976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Add a segment to hold a new noncontiguous region */
39986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
39996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* Determine locations and sizes of segment, fenceposts, old top */
40006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  char* old_top = (char*)m->top;
40016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  msegmentptr oldsp = segment_holding(m, old_top);
40026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  char* old_end = oldsp->base + oldsp->size;
40036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t ssize = pad_request(sizeof(struct malloc_segment));
40046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
40056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t offset = align_offset(chunk2mem(rawsp));
40066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  char* asp = rawsp + offset;
40076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
40086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr sp = (mchunkptr)csp;
40096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  msegmentptr ss = (msegmentptr)(chunk2mem(sp));
40106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr tnext = chunk_plus_offset(sp, ssize);
40116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr p = tnext;
40126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int nfences = 0;
40136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
40146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* reset top to new space */
40156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
40166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
40176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* Set up segment record */
40186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(is_aligned(ss));
40196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
40206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  *ss = m->seg; /* Push current record */
40216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->seg.base = tbase;
40226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->seg.size = tsize;
40236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->seg.sflags = mmapped;
40246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->seg.next = ss;
40256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
40266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* Insert trailing fenceposts */
40276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for (;;) {
40286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
40296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    p->head = FENCEPOST_HEAD;
40306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    ++nfences;
40316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if ((char*)(&(nextp->head)) < old_end)
40326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      p = nextp;
40336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else
40346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      break;
40356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
40366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(nfences >= 2);
40376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
40386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* Insert the rest of old top into a bin as an ordinary free chunk */
40396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (csp != old_top) {
40406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr q = (mchunkptr)old_top;
40416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t psize = csp - old_top;
40426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr tn = chunk_plus_offset(q, psize);
40436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    set_free_with_pinuse(q, psize, tn);
40446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    insert_chunk(m, q, psize);
40456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
40466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
40476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  check_top_chunk(m, m->top);
40486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
40496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
40506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -------------------------- System allocation -------------------------- */
40516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
40526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Get memory from system using MORECORE or MMAP */
40536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void* sys_alloc(mstate m, size_t nb) {
40546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  char* tbase = CMFAIL;
40556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t tsize = 0;
40566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  flag_t mmap_flag = 0;
40576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t asize; /* allocation size */
40586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
40596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
40606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
40616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* Directly map large chunks, but only if already initialized */
40626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) {
40636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    void* mem = mmap_alloc(m, nb);
40646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (mem != 0)
40656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return mem;
40666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
40676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
40686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  asize = granularity_align(nb + SYS_ALLOC_PADDING);
40696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (asize <= nb) {
40706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* BEGIN android-added: set errno */
40716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    MALLOC_FAILURE_ACTION;
40726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* END android-added */
40736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 0; /* wraparound */
40746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
40756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (m->footprint_limit != 0) {
40766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t fp = m->footprint + asize;
40776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (fp <= m->footprint || fp > m->footprint_limit) {
40786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* BEGIN android-added: set errno */
40796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      MALLOC_FAILURE_ACTION;
40806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* END android-added */
40816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return 0;
40826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
40836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
40846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
40856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /*
40866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    Try getting memory in any of three ways (in most-preferred to
40876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    least-preferred order):
40886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    1. A call to MORECORE that can normally contiguously extend memory.
40896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
40906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       or main space is mmapped or a previous contiguous call failed)
40916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    2. A call to MMAP new space (disabled if not HAVE_MMAP).
40926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       Note that under the default settings, if MORECORE is unable to
40936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       fulfill a request, and HAVE_MMAP is true, then mmap is
40946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       used as a noncontiguous system allocator. This is a useful backup
40956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       strategy for systems with holes in address spaces -- in this case
40966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       sbrk cannot contiguously expand the heap, but mmap may be able to
40976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       find space.
40986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    3. A call to MORECORE that cannot usually contiguously extend memory.
40996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       (disabled if not HAVE_MORECORE)
41006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
41016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   In all cases, we need to request enough bytes from system to ensure
41026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   we can malloc nb bytes upon success, so pad with enough space for
41036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   top_foot, plus alignment-pad to make sure we don't lose bytes if
41046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   not on boundary, and round this up to a granularity unit.
41056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  */
41066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
41076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
41086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    char* br = CMFAIL;
41096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t ssize = asize; /* sbrk call size */
41106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
41116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    ACQUIRE_MALLOC_GLOBAL_LOCK();
41126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
41136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (ss == 0) {  /* First time through or recovery */
41146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      char* base = (char*)CALL_MORECORE(0);
41156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (base != CMFAIL) {
41166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t fp;
41176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        /* Adjust to end on a page boundary */
41186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (!is_page_aligned(base))
41196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          ssize += (page_align((size_t)base) - (size_t)base);
41206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        fp = m->footprint + ssize; /* recheck limits */
41216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (ssize > nb && ssize < HALF_MAX_SIZE_T &&
41226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            (m->footprint_limit == 0 ||
41236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao             (fp > m->footprint && fp <= m->footprint_limit)) &&
41246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            (br = (char*)(CALL_MORECORE(ssize))) == base) {
41256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          tbase = base;
41266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          tsize = ssize;
41276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
41286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
41296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
41306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {
41316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* Subtract out existing available top space from MORECORE request. */
41326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      ssize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING);
41336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* Use mem here only if it did continuously extend old space */
41346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (ssize < HALF_MAX_SIZE_T &&
41356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          (br = (char*)(CALL_MORECORE(ssize))) == ss->base+ss->size) {
41366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        tbase = br;
41376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        tsize = ssize;
41386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
41396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
41406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
41416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (tbase == CMFAIL) {    /* Cope with partial failure */
41426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (br != CMFAIL) {    /* Try to use/extend the space we did get */
41436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (ssize < HALF_MAX_SIZE_T &&
41446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            ssize < nb + SYS_ALLOC_PADDING) {
41456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - ssize);
41466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (esize < HALF_MAX_SIZE_T) {
41476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            char* end = (char*)CALL_MORECORE(esize);
41486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            if (end != CMFAIL)
41496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              ssize += esize;
41506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            else {            /* Can't use; try to release */
41516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              (void) CALL_MORECORE(-ssize);
41526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              br = CMFAIL;
41536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            }
41546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
41556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
41566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
41576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (br != CMFAIL) {    /* Use the space we did get */
41586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        tbase = br;
41596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        tsize = ssize;
41606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
41616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else
41626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        disable_contiguous(m); /* Don't try contiguous path in the future */
41636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
41646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
41656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    RELEASE_MALLOC_GLOBAL_LOCK();
41666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
41676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
41686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (HAVE_MMAP && tbase == CMFAIL) {  /* Try MMAP */
41696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    char* mp = (char*)(CALL_MMAP(asize));
41706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (mp != CMFAIL) {
41716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      tbase = mp;
41726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      tsize = asize;
41736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mmap_flag = USE_MMAP_BIT;
41746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
41756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
41766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
41776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
41786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (asize < HALF_MAX_SIZE_T) {
41796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      char* br = CMFAIL;
41806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      char* end = CMFAIL;
41816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      ACQUIRE_MALLOC_GLOBAL_LOCK();
41826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      br = (char*)(CALL_MORECORE(asize));
41836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      end = (char*)(CALL_MORECORE(0));
41846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      RELEASE_MALLOC_GLOBAL_LOCK();
41856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (br != CMFAIL && end != CMFAIL && br < end) {
41866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t ssize = end - br;
41876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (ssize > nb + TOP_FOOT_SIZE) {
41886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          tbase = br;
41896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          tsize = ssize;
41906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
41916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
41926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
41936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
41946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
41956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (tbase != CMFAIL) {
41966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
41976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if ((m->footprint += tsize) > m->max_footprint)
41986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      m->max_footprint = m->footprint;
41996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
42006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!is_initialized(m)) { /* first-time initialization */
42016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (m->least_addr == 0 || tbase < m->least_addr)
42026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->least_addr = tbase;
42036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      m->seg.base = tbase;
42046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      m->seg.size = tsize;
42056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      m->seg.sflags = mmap_flag;
42066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      m->magic = mparams.magic;
42076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      m->release_checks = MAX_RELEASE_CHECK_RATE;
42086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      init_bins(m);
42096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !ONLY_MSPACES
42106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (is_global(m))
42116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
42126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else
42136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
42146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      {
42156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        /* Offset top by embedded malloc_state */
42166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr mn = next_chunk(mem2chunk(m));
42176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
42186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
42196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
42206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
42216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {
42226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* Try to merge with an existing segment */
42236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      msegmentptr sp = &m->seg;
42246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* Only consider most recent segment if traversal suppressed */
42256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      while (sp != 0 && tbase != sp->base + sp->size)
42266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
42276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (sp != 0 &&
42286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          !is_extern_segment(sp) &&
42296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          (sp->sflags & USE_MMAP_BIT) == mmap_flag &&
42306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          segment_holds(sp, m->top)) { /* append */
42316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        sp->size += tsize;
42326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        init_top(m, m->top, m->topsize + tsize);
42336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
42346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else {
42356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (tbase < m->least_addr)
42366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          m->least_addr = tbase;
42376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        sp = &m->seg;
42386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        while (sp != 0 && sp->base != tbase + tsize)
42396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
42406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (sp != 0 &&
42416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            !is_extern_segment(sp) &&
42426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            (sp->sflags & USE_MMAP_BIT) == mmap_flag) {
42436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          char* oldbase = sp->base;
42446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          sp->base = tbase;
42456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          sp->size += tsize;
42466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          return prepend_alloc(m, tbase, oldbase, nb);
42476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
42486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else
42496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          add_segment(m, tbase, tsize, mmap_flag);
42506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
42516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
42526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
42536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (nb < m->topsize) { /* Allocate from new or extended top space */
42546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t rsize = m->topsize -= nb;
42556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr p = m->top;
42566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr r = m->top = chunk_plus_offset(p, nb);
42576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      r->head = rsize | PINUSE_BIT;
42586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      set_size_and_pinuse_of_inuse_chunk(m, p, nb);
42596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_top_chunk(m, m->top);
42606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_malloced_chunk(m, chunk2mem(p), nb);
42616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return chunk2mem(p);
42626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
42636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
42646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
42656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  MALLOC_FAILURE_ACTION;
42666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
42676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
42686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
42696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -----------------------  system deallocation -------------------------- */
42706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
42716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Unmap and unlink any mmapped segments that don't contain used chunks */
42726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic size_t release_unused_segments(mstate m) {
42736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t released = 0;
42746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int nsegs = 0;
42756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  msegmentptr pred = &m->seg;
42766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  msegmentptr sp = pred->next;
42776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  while (sp != 0) {
42786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    char* base = sp->base;
42796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t size = sp->size;
42806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    msegmentptr next = sp->next;
42816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    ++nsegs;
42826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
42836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr p = align_as_chunk(base);
42846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t psize = chunksize(p);
42856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* Can unmap if first chunk holds entire segment and not pinned */
42866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
42876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        tchunkptr tp = (tchunkptr)p;
42886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        assert(segment_holds(sp, (char*)sp));
42896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (p == m->dv) {
42906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          m->dv = 0;
42916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          m->dvsize = 0;
42926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
42936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else {
42946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          unlink_large_chunk(m, tp);
42956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
42966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (CALL_MUNMAP(base, size) == 0) {
42976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          released += size;
42986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          m->footprint -= size;
42996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          /* unlink obsoleted record */
43006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          sp = pred;
43016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          sp->next = next;
43026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
43036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else { /* back out if cannot unmap */
43046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          insert_large_chunk(m, tp, psize);
43056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
43066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
43076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
43086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */
43096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      break;
43106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    pred = sp;
43116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    sp = next;
43126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
43136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* Reset check counter */
43146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->release_checks = (((size_t) nsegs > (size_t) MAX_RELEASE_CHECK_RATE)?
43156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                       (size_t) nsegs : (size_t) MAX_RELEASE_CHECK_RATE);
43166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return released;
43176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
43186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
43196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic int sys_trim(mstate m, size_t pad) {
43206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t released = 0;
43216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
43226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (pad < MAX_REQUEST && is_initialized(m)) {
43236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
43246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
43256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (m->topsize > pad) {
43266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* Shrink top space in granularity-size units, keeping at least one */
43276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t unit = mparams.granularity;
43286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
43296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                      SIZE_T_ONE) * unit;
43306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      msegmentptr sp = segment_holding(m, (char*)m->top);
43316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
43326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (!is_extern_segment(sp)) {
43336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (is_mmapped_segment(sp)) {
43346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (HAVE_MMAP &&
43356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              sp->size >= extra &&
43366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              !has_segment_link(m, sp)) { /* can't shrink if pinned */
43376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            size_t newsize = sp->size - extra;
43386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            (void)newsize; /* placate people compiling -Wunused-variable */
43396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            /* Prefer mremap, fall back to munmap */
43406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
43416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
43426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              released = extra;
43436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            }
43446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
43456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
43466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else if (HAVE_MORECORE) {
43476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
43486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
43496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          ACQUIRE_MALLOC_GLOBAL_LOCK();
43506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          {
43516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            /* Make sure end of memory is where we last set it. */
43526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            char* old_br = (char*)(CALL_MORECORE(0));
43536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            if (old_br == sp->base + sp->size) {
43546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              char* rel_br = (char*)(CALL_MORECORE(-extra));
43556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              char* new_br = (char*)(CALL_MORECORE(0));
43566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              if (rel_br != CMFAIL && new_br < old_br)
43576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                released = old_br - new_br;
43586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            }
43596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
43606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          RELEASE_MALLOC_GLOBAL_LOCK();
43616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
43626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
43636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
43646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (released != 0) {
43656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        sp->size -= released;
43666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->footprint -= released;
43676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        init_top(m, m->top, m->topsize - released);
43686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        check_top_chunk(m, m->top);
43696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
43706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
43716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
43726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* Unmap any unused mmapped segments */
43736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (HAVE_MMAP)
43746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      released += release_unused_segments(m);
43756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
43766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* On failure, disable autotrim to avoid repeated failed future calls */
43776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (released == 0 && m->topsize > m->trim_check)
43786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      m->trim_check = MAX_SIZE_T;
43796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
43806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
43816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return (released != 0)? 1 : 0;
43826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
43836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
43846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Consolidate and bin a chunk. Differs from exported versions
43856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   of free mainly in that the chunk need not be marked as inuse.
43866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
43876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void dispose_chunk(mstate m, mchunkptr p, size_t psize) {
43886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr next = chunk_plus_offset(p, psize);
43896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!pinuse(p)) {
43906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr prev;
43916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t prevsize = p->prev_foot;
43926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (is_mmapped(p)) {
43936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      psize += prevsize + MMAP_FOOT_PAD;
43946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
43956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->footprint -= psize;
43966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return;
43976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
43986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    prev = chunk_minus_offset(p, prevsize);
43996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    psize += prevsize;
44006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    p = prev;
44016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (RTCHECK(ok_address(m, prev))) { /* consolidate backward */
44026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (p != m->dv) {
44036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        unlink_chunk(m, p, prevsize);
44046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
44056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else if ((next->head & INUSE_BITS) == INUSE_BITS) {
44066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->dvsize = psize;
44076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_free_with_pinuse(p, psize, next);
44086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        return;
44096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
44106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
44116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {
44126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      CORRUPTION_ERROR_ACTION(m);
44136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return;
44146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
44156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
44166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (RTCHECK(ok_address(m, next))) {
44176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!cinuse(next)) {  /* consolidate forward */
44186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (next == m->top) {
44196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t tsize = m->topsize += psize;
44206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->top = p;
44216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        p->head = tsize | PINUSE_BIT;
44226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (p == m->dv) {
44236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          m->dv = 0;
44246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          m->dvsize = 0;
44256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
44266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        return;
44276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
44286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else if (next == m->dv) {
44296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t dsize = m->dvsize += psize;
44306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->dv = p;
44316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_size_and_pinuse_of_free_chunk(p, dsize);
44326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        return;
44336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
44346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else {
44356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t nsize = chunksize(next);
44366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        psize += nsize;
44376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        unlink_chunk(m, next, nsize);
44386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_size_and_pinuse_of_free_chunk(p, psize);
44396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (p == m->dv) {
44406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          m->dvsize = psize;
44416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          return;
44426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
44436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
44446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
44456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {
44466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      set_free_with_pinuse(p, psize, next);
44476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
44486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    insert_chunk(m, p, psize);
44496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
44506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
44516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    CORRUPTION_ERROR_ACTION(m);
44526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
44536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
44546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
44556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ---------------------------- malloc --------------------------- */
44566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
44576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* allocate a large request from the best fitting chunk in a treebin */
44586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void* tmalloc_large(mstate m, size_t nb) {
44596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tchunkptr v = 0;
44606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t rsize = -nb; /* Unsigned negation */
44616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tchunkptr t;
44626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bindex_t idx;
44636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  compute_tree_index(nb, idx);
44646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if ((t = *treebin_at(m, idx)) != 0) {
44656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* Traverse tree for this bin looking for node with size == nb */
44666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t sizebits = nb << leftshift_for_tree_index(idx);
44676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    tchunkptr rst = 0;  /* The deepest untaken right subtree */
44686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    for (;;) {
44696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      tchunkptr rt;
44706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t trem = chunksize(t) - nb;
44716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (trem < rsize) {
44726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        v = t;
44736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if ((rsize = trem) == 0)
44746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          break;
44756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
44766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      rt = t->child[1];
44776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
44786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (rt != 0 && rt != t)
44796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        rst = rt;
44806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (t == 0) {
44816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        t = rst; /* set t to least subtree holding sizes > nb */
44826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        break;
44836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
44846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      sizebits <<= 1;
44856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
44866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
44876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
44886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
44896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (leftbits != 0) {
44906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      bindex_t i;
44916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      binmap_t leastbit = least_bit(leftbits);
44926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      compute_bit2idx(leastbit, i);
44936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      t = *treebin_at(m, i);
44946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
44956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
44966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
44976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  while (t != 0) { /* find smallest of tree or subtree */
44986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t trem = chunksize(t) - nb;
44996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (trem < rsize) {
45006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      rsize = trem;
45016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      v = t;
45026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
45036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    t = leftmost_child(t);
45046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
45056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
45066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /*  If dv is a better fit, return 0 so malloc will use it */
45076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
45086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (RTCHECK(ok_address(m, v))) { /* split */
45096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr r = chunk_plus_offset(v, nb);
45106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(chunksize(v) == rsize + nb);
45116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (RTCHECK(ok_next(v, r))) {
45126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        unlink_large_chunk(m, v);
45136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (rsize < MIN_CHUNK_SIZE)
45146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_inuse_and_pinuse(m, v, (rsize + nb));
45156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else {
45166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_size_and_pinuse_of_inuse_chunk(m, v, nb);
45176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_size_and_pinuse_of_free_chunk(r, rsize);
45186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          insert_chunk(m, r, rsize);
45196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
45206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        return chunk2mem(v);
45216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
45226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
45236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    CORRUPTION_ERROR_ACTION(m);
45246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
45256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
45266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
45276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
45286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* allocate a small request from the best fitting chunk in a treebin */
45296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void* tmalloc_small(mstate m, size_t nb) {
45306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  tchunkptr t, v;
45316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t rsize;
45326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  bindex_t i;
45336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  binmap_t leastbit = least_bit(m->treemap);
45346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  compute_bit2idx(leastbit, i);
45356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  v = t = *treebin_at(m, i);
45366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  rsize = chunksize(t) - nb;
45376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
45386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  while ((t = leftmost_child(t)) != 0) {
45396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t trem = chunksize(t) - nb;
45406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (trem < rsize) {
45416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      rsize = trem;
45426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      v = t;
45436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
45446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
45456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
45466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (RTCHECK(ok_address(m, v))) {
45476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr r = chunk_plus_offset(v, nb);
45486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    assert(chunksize(v) == rsize + nb);
45496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (RTCHECK(ok_next(v, r))) {
45506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      unlink_large_chunk(m, v);
45516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (rsize < MIN_CHUNK_SIZE)
45526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_inuse_and_pinuse(m, v, (rsize + nb));
45536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else {
45546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_size_and_pinuse_of_inuse_chunk(m, v, nb);
45556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_size_and_pinuse_of_free_chunk(r, rsize);
45566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        replace_dv(m, r, rsize);
45576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
45586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return chunk2mem(v);
45596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
45606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
45616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
45626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  CORRUPTION_ERROR_ACTION(m);
45636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
45646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
45656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
45666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !ONLY_MSPACES
45676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
45686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* dlmalloc(size_t bytes) {
45696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /*
45706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     Basic algorithm:
45716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     If a small request (< 256 bytes minus per-chunk overhead):
45726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       1. If one exists, use a remainderless chunk in associated smallbin.
45736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          (Remainderless means that there are too few excess bytes to
45746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          represent as a chunk.)
45756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       2. If it is big enough, use the dv chunk, which is normally the
45766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          chunk adjacent to the one used for the most recent small request.
45776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       3. If one exists, split the smallest available chunk in a bin,
45786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          saving remainder in dv.
45796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       4. If it is big enough, use the top chunk.
45806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       5. If available, get memory from system and use it
45816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     Otherwise, for a large request:
45826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       1. Find the smallest available binned chunk that fits, and use it
45836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if it is better fitting than dv chunk, splitting if necessary.
45846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       2. If better fitting than any binned chunk, use the dv chunk.
45856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       3. If it is big enough, use the top chunk.
45866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       4. If request size >= mmap threshold, try to directly mmap this chunk.
45876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao       5. If available, get memory from system and use it
45886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
45896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     The ugly goto's here ensure that postaction occurs along all paths.
45906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  */
45916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
45926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if USE_LOCKS
45936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization(); /* initialize in sys_alloc if not using locks */
45946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
45956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
45966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!PREACTION(gm)) {
45976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    void* mem;
45986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t nb;
45996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (bytes <= MAX_SMALL_REQUEST) {
46006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      bindex_t idx;
46016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      binmap_t smallbits;
46026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
46036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      idx = small_index(nb);
46046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      smallbits = gm->smallmap >> idx;
46056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
46066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
46076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr b, p;
46086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
46096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        b = smallbin_at(gm, idx);
46106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        p = b->fd;
46116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        assert(chunksize(p) == small_index2size(idx));
46126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        unlink_first_small_chunk(gm, b, p, idx);
46136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_inuse_and_pinuse(gm, p, small_index2size(idx));
46146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mem = chunk2mem(p);
46156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        check_malloced_chunk(gm, mem, nb);
46166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        goto postaction;
46176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
46186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
46196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else if (nb > gm->dvsize) {
46206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
46216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mchunkptr b, p, r;
46226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          size_t rsize;
46236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          bindex_t i;
46246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
46256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          binmap_t leastbit = least_bit(leftbits);
46266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          compute_bit2idx(leastbit, i);
46276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          b = smallbin_at(gm, i);
46286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          p = b->fd;
46296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          assert(chunksize(p) == small_index2size(i));
46306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          unlink_first_small_chunk(gm, b, p, i);
46316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          rsize = small_index2size(i) - nb;
46326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          /* Fit here cannot be remainderless if 4byte sizes */
46336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
46346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            set_inuse_and_pinuse(gm, p, small_index2size(i));
46356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else {
46366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
46376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            r = chunk_plus_offset(p, nb);
46386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            set_size_and_pinuse_of_free_chunk(r, rsize);
46396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            replace_dv(gm, r, rsize);
46406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
46416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mem = chunk2mem(p);
46426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          check_malloced_chunk(gm, mem, nb);
46436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          goto postaction;
46446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
46456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
46466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
46476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          check_malloced_chunk(gm, mem, nb);
46486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          goto postaction;
46496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
46506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
46516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
46526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (bytes >= MAX_REQUEST)
46536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
46546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {
46556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nb = pad_request(bytes);
46566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
46576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        check_malloced_chunk(gm, mem, nb);
46586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        goto postaction;
46596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
46606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
46616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
46626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (nb <= gm->dvsize) {
46636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t rsize = gm->dvsize - nb;
46646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr p = gm->dv;
46656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
46666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
46676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        gm->dvsize = rsize;
46686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_size_and_pinuse_of_free_chunk(r, rsize);
46696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
46706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
46716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else { /* exhaust dv */
46726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t dvs = gm->dvsize;
46736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        gm->dvsize = 0;
46746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        gm->dv = 0;
46756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_inuse_and_pinuse(gm, p, dvs);
46766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
46776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mem = chunk2mem(p);
46786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_malloced_chunk(gm, mem, nb);
46796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      goto postaction;
46806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
46816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
46826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (nb < gm->topsize) { /* Split top */
46836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t rsize = gm->topsize -= nb;
46846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr p = gm->top;
46856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr r = gm->top = chunk_plus_offset(p, nb);
46866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      r->head = rsize | PINUSE_BIT;
46876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
46886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mem = chunk2mem(p);
46896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_top_chunk(gm, gm->top);
46906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_malloced_chunk(gm, mem, nb);
46916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      goto postaction;
46926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
46936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
46946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mem = sys_alloc(gm, nb);
46956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
46966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  postaction:
46976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    POSTACTION(gm);
46986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return mem;
46996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
47006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
47016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
47026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
47036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
47046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ---------------------------- free --------------------------- */
47056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
47066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid dlfree(void* mem) {
47076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /*
47086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     Consolidate freed chunks with preceeding or succeeding bordering
47096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     free chunks, if they exist, and then place in a bin.  Intermixed
47106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     with special cases for top, dv, mmapped chunks, and usage errors.
47116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  */
47126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
47136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (mem != 0) {
47146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr p  = mem2chunk(mem);
47156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if FOOTERS
47166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mstate fm = get_mstate_for(p);
47176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!ok_magic(fm)) {
47186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      USAGE_ERROR_ACTION(fm, p);
47196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return;
47206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
47216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* FOOTERS */
47226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#define fm gm
47236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* FOOTERS */
47246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!PREACTION(fm)) {
47256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_inuse_chunk(fm, p);
47266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) {
47276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t psize = chunksize(p);
47286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr next = chunk_plus_offset(p, psize);
47296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (!pinuse(p)) {
47306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          size_t prevsize = p->prev_foot;
47316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (is_mmapped(p)) {
47326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            psize += prevsize + MMAP_FOOT_PAD;
47336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
47346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              fm->footprint -= psize;
47356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            goto postaction;
47366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
47376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else {
47386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            mchunkptr prev = chunk_minus_offset(p, prevsize);
47396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            psize += prevsize;
47406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            p = prev;
47416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
47426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              if (p != fm->dv) {
47436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                unlink_chunk(fm, p, prevsize);
47446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              }
47456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
47466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                fm->dvsize = psize;
47476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                set_free_with_pinuse(p, psize, next);
47486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                goto postaction;
47496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              }
47506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            }
47516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            else
47526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              goto erroraction;
47536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
47546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
47556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
47566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
47576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (!cinuse(next)) {  /* consolidate forward */
47586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            if (next == fm->top) {
47596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              size_t tsize = fm->topsize += psize;
47606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              fm->top = p;
47616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              p->head = tsize | PINUSE_BIT;
47626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              if (p == fm->dv) {
47636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                fm->dv = 0;
47646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                fm->dvsize = 0;
47656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              }
47666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              if (should_trim(fm, tsize))
47676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                sys_trim(fm, 0);
47686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              goto postaction;
47696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            }
47706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            else if (next == fm->dv) {
47716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              size_t dsize = fm->dvsize += psize;
47726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              fm->dv = p;
47736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              set_size_and_pinuse_of_free_chunk(p, dsize);
47746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              goto postaction;
47756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            }
47766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            else {
47776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              size_t nsize = chunksize(next);
47786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              psize += nsize;
47796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              unlink_chunk(fm, next, nsize);
47806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              set_size_and_pinuse_of_free_chunk(p, psize);
47816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              if (p == fm->dv) {
47826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                fm->dvsize = psize;
47836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                goto postaction;
47846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              }
47856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            }
47866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
47876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else
47886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            set_free_with_pinuse(p, psize, next);
47896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
47906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (is_small(psize)) {
47916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            insert_small_chunk(fm, p, psize);
47926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            check_free_chunk(fm, p);
47936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
47946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else {
47956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            tchunkptr tp = (tchunkptr)p;
47966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            insert_large_chunk(fm, tp, psize);
47976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            check_free_chunk(fm, p);
47986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            if (--fm->release_checks == 0)
47996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              release_unused_segments(fm);
48006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
48016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          goto postaction;
48026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
48036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
48046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    erroraction:
48056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      USAGE_ERROR_ACTION(fm, p);
48066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    postaction:
48076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      POSTACTION(fm);
48086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
48096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
48106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !FOOTERS
48116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#undef fm
48126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* FOOTERS */
48136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
48146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
48156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* dlcalloc(size_t n_elements, size_t elem_size) {
48166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void* mem;
48176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t req = 0;
48186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (n_elements != 0) {
48196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    req = n_elements * elem_size;
48206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
48216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        (req / n_elements != elem_size))
48226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      req = MAX_SIZE_T; /* force downstream failure on overflow */
48236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
48246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mem = dlmalloc(req);
48256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (mem != 0) {
48266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr p = mem2chunk(mem);
48276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (calloc_must_clear(p)) {
48286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* Make sure to clear all of the buffer, not just the requested size. */
48296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      memset(mem, 0, chunksize(p) - overhead_for(p));
48306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
48316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
48326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return mem;
48336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
48346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
48356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* !ONLY_MSPACES */
48366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
48376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ------------ Internal support for realloc, memalign, etc -------------- */
48386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
48396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Try to realloc; only in-place unless can_move true */
48406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb,
48416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                   int can_move) {
48426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr newp = 0;
48436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t oldsize = chunksize(p);
48446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr next = chunk_plus_offset(p, oldsize);
48456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (RTCHECK(ok_address(m, p) && ok_inuse(p) &&
48466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              ok_next(p, next) && ok_pinuse(next))) {
48476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (is_mmapped(p)) {
48486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      newp = mmap_resize(m, p, nb, can_move);
48496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
48506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (oldsize >= nb) {             /* already big enough */
48516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t rsize = oldsize - nb;
48526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (rsize >= MIN_CHUNK_SIZE) {      /* split off remainder */
48536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr r = chunk_plus_offset(p, nb);
48546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_inuse(m, p, nb);
48556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_inuse(m, r, rsize);
48566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        dispose_chunk(m, r, rsize);
48576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
48586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      newp = p;
48596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
48606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (next == m->top) {  /* extend into top */
48616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (oldsize + m->topsize > nb) {
48626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t newsize = oldsize + m->topsize;
48636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t newtopsize = newsize - nb;
48646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr newtop = chunk_plus_offset(p, nb);
48656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_inuse(m, p, nb);
48666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        newtop->head = newtopsize |PINUSE_BIT;
48676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->top = newtop;
48686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        m->topsize = newtopsize;
48696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        newp = p;
48706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
48716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
48726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (next == m->dv) { /* extend into dv */
48736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t dvs = m->dvsize;
48746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (oldsize + dvs >= nb) {
48756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t dsize = oldsize + dvs - nb;
48766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (dsize >= MIN_CHUNK_SIZE) {
48776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mchunkptr r = chunk_plus_offset(p, nb);
48786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mchunkptr n = chunk_plus_offset(r, dsize);
48796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_inuse(m, p, nb);
48806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_size_and_pinuse_of_free_chunk(r, dsize);
48816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          clear_pinuse(n);
48826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          m->dvsize = dsize;
48836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          m->dv = r;
48846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
48856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else { /* exhaust dv */
48866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          size_t newsize = oldsize + dvs;
48876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_inuse(m, p, newsize);
48886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          m->dvsize = 0;
48896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          m->dv = 0;
48906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
48916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        newp = p;
48926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
48936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
48946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (!cinuse(next)) { /* extend into next free chunk */
48956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t nextsize = chunksize(next);
48966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (oldsize + nextsize >= nb) {
48976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t rsize = oldsize + nextsize - nb;
48986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        unlink_chunk(m, next, nextsize);
48996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (rsize < MIN_CHUNK_SIZE) {
49006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          size_t newsize = oldsize + nextsize;
49016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_inuse(m, p, newsize);
49026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
49036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else {
49046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mchunkptr r = chunk_plus_offset(p, nb);
49056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_inuse(m, p, nb);
49066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_inuse(m, r, rsize);
49076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          dispose_chunk(m, r, rsize);
49086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
49096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        newp = p;
49106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
49116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
49126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
49136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
49146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(m, chunk2mem(p));
49156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
49166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return newp;
49176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
49186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
49196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
49206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void* mem = 0;
49216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
49226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    alignment = MIN_CHUNK_SIZE;
49236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
49246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t a = MALLOC_ALIGNMENT << 1;
49256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    while (a < alignment) a <<= 1;
49266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    alignment = a;
49276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
49286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (bytes >= MAX_REQUEST - alignment) {
49296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (m != 0)  { /* Test isn't needed but avoids compiler warning */
49306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      MALLOC_FAILURE_ACTION;
49316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
49326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
49336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
49346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t nb = request2size(bytes);
49356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
49366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mem = internal_malloc(m, req);
49376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (mem != 0) {
49386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr p = mem2chunk(mem);
49396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (PREACTION(m))
49406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        return 0;
49416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */
49426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        /*
49436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          Find an aligned spot inside chunk.  Since we need to give
49446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          back leading space in a chunk of at least MIN_CHUNK_SIZE, if
49456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          the first calculation places us at a spot with less than
49466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
49476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          We've allocated enough total room so that this is always
49486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          possible.
49496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        */
49506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        char* br = (char*)mem2chunk((size_t)(((size_t)((char*)mem + alignment -
49516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                                       SIZE_T_ONE)) &
49526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                             -alignment));
49536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
49546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          br : br+alignment;
49556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr newp = (mchunkptr)pos;
49566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t leadsize = pos - (char*)(p);
49576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t newsize = chunksize(p) - leadsize;
49586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
49596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
49606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          newp->prev_foot = p->prev_foot + leadsize;
49616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          newp->head = newsize;
49626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
49636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else { /* Otherwise, give back leader, use the rest */
49646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_inuse(m, newp, newsize);
49656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_inuse(m, p, leadsize);
49666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          dispose_chunk(m, p, leadsize);
49676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
49686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        p = newp;
49696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
49706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
49716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      /* Give back spare room at the end */
49726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (!is_mmapped(p)) {
49736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t size = chunksize(p);
49746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (size > nb + MIN_CHUNK_SIZE) {
49756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          size_t remainder_size = size - nb;
49766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mchunkptr remainder = chunk_plus_offset(p, nb);
49776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_inuse(m, p, nb);
49786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          set_inuse(m, remainder, remainder_size);
49796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          dispose_chunk(m, remainder, remainder_size);
49806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
49816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
49826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
49836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mem = chunk2mem(p);
49846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert (chunksize(p) >= nb);
49856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(((size_t)mem & (alignment - 1)) == 0);
49866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_inuse_chunk(m, p);
49876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      POSTACTION(m);
49886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
49896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
49906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return mem;
49916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
49926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
49936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
49946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Common support for independent_X routines, handling
49956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    all of the combinations that can result.
49966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  The opts arg has:
49976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    bit 0 set if all elements are same size (using sizes[0])
49986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    bit 1 set if elements should be zeroed
49996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
50006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void** ialloc(mstate m,
50016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                     size_t n_elements,
50026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                     size_t* sizes,
50036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                     int opts,
50046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                     void* chunks[]) {
50056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
50066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t    element_size;   /* chunksize of each element, if all same */
50076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t    contents_size;  /* total size of elements */
50086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t    array_size;     /* request size of pointer array */
50096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void*     mem;            /* malloced aggregate space */
50106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr p;              /* corresponding chunk */
50116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t    remainder_size; /* remaining bytes while splitting */
50126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void**    marray;         /* either "chunks" or malloced ptr array */
50136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr array_chunk;    /* chunk for malloced ptr array */
50146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  flag_t    was_enabled;    /* to disable mmap */
50156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t    size;
50166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t    i;
50176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
50186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
50196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* compute array length, if needed */
50206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (chunks != 0) {
50216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (n_elements == 0)
50226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return chunks; /* nothing to do */
50236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    marray = chunks;
50246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    array_size = 0;
50256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
50266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
50276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* if empty req, must still return chunk representing empty array */
50286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (n_elements == 0)
50296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return (void**)internal_malloc(m, 0);
50306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    marray = 0;
50316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    array_size = request2size(n_elements * (sizeof(void*)));
50326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
50336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
50346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* compute total element size */
50356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (opts & 0x1) { /* all-same-size */
50366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    element_size = request2size(*sizes);
50376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    contents_size = n_elements * element_size;
50386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
50396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else { /* add up all the sizes */
50406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    element_size = 0;
50416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    contents_size = 0;
50426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    for (i = 0; i != n_elements; ++i)
50436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      contents_size += request2size(sizes[i]);
50446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
50456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
50466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size = contents_size + array_size;
50476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
50486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /*
50496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     Allocate the aggregate chunk.  First disable direct-mmapping so
50506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     malloc won't use it, since we would not be able to later
50516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao     free/realloc space internal to a segregated mmap region.
50526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  */
50536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  was_enabled = use_mmap(m);
50546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  disable_mmap(m);
50556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mem = internal_malloc(m, size - CHUNK_OVERHEAD);
50566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (was_enabled)
50576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    enable_mmap(m);
50586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (mem == 0)
50596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 0;
50606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
50616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (PREACTION(m)) return 0;
50626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  p = mem2chunk(mem);
50636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  remainder_size = chunksize(p);
50646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
50656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  assert(!is_mmapped(p));
50666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
50676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (opts & 0x2) {       /* optionally clear the elements */
50686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
50696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
50706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
50716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* If not provided, allocate the pointer array as final part of chunk */
50726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (marray == 0) {
50736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t  array_chunk_size;
50746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    array_chunk = chunk_plus_offset(p, contents_size);
50756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    array_chunk_size = remainder_size - contents_size;
50766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    marray = (void**) (chunk2mem(array_chunk));
50776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
50786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    remainder_size = contents_size;
50796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
50806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
50816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  /* split out elements */
50826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for (i = 0; ; ++i) {
50836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    marray[i] = chunk2mem(p);
50846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (i != n_elements-1) {
50856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (element_size != 0)
50866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size = element_size;
50876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else
50886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size = request2size(sizes[i]);
50896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      remainder_size -= size;
50906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      set_size_and_pinuse_of_inuse_chunk(m, p, size);
50916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      p = chunk_plus_offset(p, size);
50926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
50936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else { /* the final element absorbs any overallocation slop */
50946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
50956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      break;
50966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
50976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
50986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
50996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if DEBUG
51006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (marray != chunks) {
51016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    /* final element must have exactly exhausted chunk */
51026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (element_size != 0) {
51036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(remainder_size == element_size);
51046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
51056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {
51066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      assert(remainder_size == request2size(sizes[i]));
51076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
51086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    check_inuse_chunk(m, mem2chunk(marray));
51096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
51106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  for (i = 0; i != n_elements; ++i)
51116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    check_inuse_chunk(m, mem2chunk(marray[i]));
51126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
51136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* DEBUG */
51146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
51156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  POSTACTION(m);
51166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return marray;
51176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
51186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
51196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Try to free all pointers in the given array.
51206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   Note: this could be made faster, by delaying consolidation,
51216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   at the price of disabling some user integrity checks, We
51226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   still optimize some consolidations by combining adjacent
51236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   chunks before freeing, which will occur often if allocated
51246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao   with ialloc or the array is sorted.
51256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
51266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic size_t internal_bulk_free(mstate m, void* array[], size_t nelem) {
51276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t unfreed = 0;
51286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!PREACTION(m)) {
51296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    void** a;
51306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    void** fence = &(array[nelem]);
51316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    for (a = array; a != fence; ++a) {
51326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      void* mem = *a;
51336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (mem != 0) {
51346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr p = mem2chunk(mem);
51356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t psize = chunksize(p);
51366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if FOOTERS
51376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (get_mstate_for(p) != m) {
51386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          ++unfreed;
51396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          continue;
51406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
51416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif
51426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        check_inuse_chunk(m, p);
51436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        *a = 0;
51446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (RTCHECK(ok_address(m, p) && ok_inuse(p))) {
51456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          void ** b = a + 1; /* try to merge with next chunk */
51466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mchunkptr next = next_chunk(p);
51476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (b != fence && *b == chunk2mem(next)) {
51486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            size_t newsize = chunksize(next) + psize;
51496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            set_inuse(m, p, newsize);
51506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            *b = chunk2mem(p);
51516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
51526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else
51536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            dispose_chunk(m, p, psize);
51546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
51556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else {
51566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          CORRUPTION_ERROR_ACTION(m);
51576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          break;
51586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
51596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
51606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
51616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (should_trim(m, m->topsize))
51626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      sys_trim(m, 0);
51636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    POSTACTION(m);
51646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
51656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return unfreed;
51666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
51676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
51686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* Traversal */
51696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if MALLOC_INSPECT_ALL
51706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic void internal_inspect_all(mstate m,
51716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                 void(*handler)(void *start,
51726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                                void *end,
51736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                                size_t used_bytes,
51746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                                void* callback_arg),
51756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                 void* arg) {
51766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (is_initialized(m)) {
51776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr top = m->top;
51786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    msegmentptr s;
51796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    for (s = &m->seg; s != 0; s = s->next) {
51806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr q = align_as_chunk(s->base);
51816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      while (segment_holds(s, q) && q->head != FENCEPOST_HEAD) {
51826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr next = next_chunk(q);
51836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t sz = chunksize(q);
51846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t used;
51856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        void* start;
51866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (is_inuse(q)) {
51876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          used = sz - CHUNK_OVERHEAD; /* must not be mmapped */
51886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          start = chunk2mem(q);
51896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
51906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else {
51916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          used = 0;
51926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (is_small(sz)) {     /* offset by possible bookkeeping */
51936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            start = (void*)((char*)q + sizeof(struct malloc_chunk));
51946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
51956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else {
51966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            start = (void*)((char*)q + sizeof(struct malloc_tree_chunk));
51976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
51986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
51996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (start < (void*)next)  /* skip if all space is bookkeeping */
52006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          handler(start, next, used, arg);
52016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (q == top)
52026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          break;
52036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        q = next;
52046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
52056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
52066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
52076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
52086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MALLOC_INSPECT_ALL */
52096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
52106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ------------------ Exported realloc, memalign, etc -------------------- */
52116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
52126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !ONLY_MSPACES
52136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
52146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* dlrealloc(void* oldmem, size_t bytes) {
52156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void* mem = 0;
52166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (oldmem == 0) {
52176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mem = dlmalloc(bytes);
52186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
52196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (bytes >= MAX_REQUEST) {
52206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    MALLOC_FAILURE_ACTION;
52216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
52226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef REALLOC_ZERO_BYTES_FREES
52236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (bytes == 0) {
52246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    dlfree(oldmem);
52256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
52266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* REALLOC_ZERO_BYTES_FREES */
52276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
52286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t nb = request2size(bytes);
52296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr oldp = mem2chunk(oldmem);
52306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if ! FOOTERS
52316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mstate m = gm;
52326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* FOOTERS */
52336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mstate m = get_mstate_for(oldp);
52346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!ok_magic(m)) {
52356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      USAGE_ERROR_ACTION(m, oldmem);
52366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return 0;
52376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
52386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* FOOTERS */
52396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!PREACTION(m)) {
52406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1);
52416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      POSTACTION(m);
52426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (newp != 0) {
52436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        check_inuse_chunk(m, newp);
52446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mem = chunk2mem(newp);
52456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
52466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else {
52476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mem = internal_malloc(m, bytes);
52486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (mem != 0) {
52496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          size_t oc = chunksize(oldp) - overhead_for(oldp);
52506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          memcpy(mem, oldmem, (oc < bytes)? oc : bytes);
52516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          internal_free(m, oldmem);
52526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
52536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
52546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
52556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
52566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return mem;
52576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
52586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
52596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* dlrealloc_in_place(void* oldmem, size_t bytes) {
52606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void* mem = 0;
52616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (oldmem != 0) {
52626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (bytes >= MAX_REQUEST) {
52636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      MALLOC_FAILURE_ACTION;
52646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
52656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {
52666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t nb = request2size(bytes);
52676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr oldp = mem2chunk(oldmem);
52686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if ! FOOTERS
52696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mstate m = gm;
52706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* FOOTERS */
52716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mstate m = get_mstate_for(oldp);
52726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (!ok_magic(m)) {
52736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        USAGE_ERROR_ACTION(m, oldmem);
52746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        return 0;
52756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
52766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* FOOTERS */
52776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (!PREACTION(m)) {
52786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0);
52796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        POSTACTION(m);
52806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (newp == oldp) {
52816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          check_inuse_chunk(m, newp);
52826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mem = oldmem;
52836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
52846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
52856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
52866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
52876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return mem;
52886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
52896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
52906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* dlmemalign(size_t alignment, size_t bytes) {
52916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (alignment <= MALLOC_ALIGNMENT) {
52926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return dlmalloc(bytes);
52936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
52946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return internal_memalign(gm, alignment, bytes);
52956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
52966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
52976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoint dlposix_memalign(void** pp, size_t alignment, size_t bytes) {
52986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void* mem = 0;
52996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (alignment == MALLOC_ALIGNMENT)
53006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mem = dlmalloc(bytes);
53016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
53026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t d = alignment / sizeof(void*);
53036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t r = alignment % sizeof(void*);
53046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (r != 0 || d == 0 || (d & (d-SIZE_T_ONE)) != 0)
53056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return EINVAL;
53066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (bytes <= MAX_REQUEST - alignment) {
53076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (alignment <  MIN_CHUNK_SIZE)
53086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        alignment = MIN_CHUNK_SIZE;
53096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mem = internal_memalign(gm, alignment, bytes);
53106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
53116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
53126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (mem == 0)
53136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return ENOMEM;
53146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
53156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    *pp = mem;
53166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 0;
53176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
53186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
53196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
53206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* dlvalloc(size_t bytes) {
53216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t pagesz;
53226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
53236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  pagesz = mparams.page_size;
53246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return dlmemalign(pagesz, bytes);
53256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
53266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
53276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* BEGIN android-changed: added overflow check */
53286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* dlpvalloc(size_t bytes) {
53296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t pagesz;
53306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t size;
53316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
53326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  pagesz = mparams.page_size;
53336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size = (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE);
53346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (size < bytes) {
53356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return NULL;
53366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
53376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return dlmemalign(pagesz, size);
53386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
53396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* END android-change */
53406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
53416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid** dlindependent_calloc(size_t n_elements, size_t elem_size,
53426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                            void* chunks[]) {
53436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t sz = elem_size; /* serves as 1-element array */
53446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return ialloc(gm, n_elements, &sz, 3, chunks);
53456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
53466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
53476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid** dlindependent_comalloc(size_t n_elements, size_t sizes[],
53486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                              void* chunks[]) {
53496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return ialloc(gm, n_elements, sizes, 0, chunks);
53506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
53516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
53526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t dlbulk_free(void* array[], size_t nelem) {
53536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return internal_bulk_free(gm, array, nelem);
53546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
53556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
53566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if MALLOC_INSPECT_ALL
53576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid dlmalloc_inspect_all(void(*handler)(void *start,
53586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                         void *end,
53596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                         size_t used_bytes,
53606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                         void* callback_arg),
53616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                          void* arg) {
53626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
53636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!PREACTION(gm)) {
53646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    internal_inspect_all(gm, handler, arg);
53656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    POSTACTION(gm);
53666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
53676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
53686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MALLOC_INSPECT_ALL */
53696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
53706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoint dlmalloc_trim(size_t pad) {
53716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int result = 0;
53726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
53736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!PREACTION(gm)) {
53746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    result = sys_trim(gm, pad);
53756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    POSTACTION(gm);
53766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
53776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return result;
53786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
53796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
53806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t dlmalloc_footprint(void) {
53816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return gm->footprint;
53826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
53836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
53846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t dlmalloc_max_footprint(void) {
53856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return gm->max_footprint;
53866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
53876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
53886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t dlmalloc_footprint_limit(void) {
53896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t maf = gm->footprint_limit;
53906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return maf == 0 ? MAX_SIZE_T : maf;
53916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
53926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
53936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t dlmalloc_set_footprint_limit(size_t bytes) {
53946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t result;  /* invert sense of 0 */
53956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (bytes == 0)
53966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    result = granularity_align(1); /* Use minimal size */
53976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (bytes == MAX_SIZE_T)
53986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    result = 0;                    /* disable */
53996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else
54006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    result = granularity_align(bytes);
54016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return gm->footprint_limit = result;
54026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
54036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
54046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !NO_MALLINFO
54056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostruct mallinfo dlmallinfo(void) {
54066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return internal_mallinfo(gm);
54076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
54086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* NO_MALLINFO */
54096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
54106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !NO_MALLOC_STATS
54116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid dlmalloc_stats() {
54126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  internal_malloc_stats(gm);
54136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
54146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* NO_MALLOC_STATS */
54156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
54166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoint dlmallopt(int param_number, int value) {
54176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return change_mparam(param_number, value);
54186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
54196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
54206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* BEGIN android-changed: added const */
54216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t dlmalloc_usable_size(const void* mem) {
54226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* END android-change */
54236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (mem != 0) {
54246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr p = mem2chunk(mem);
54256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (is_inuse(p))
54266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return chunksize(p) - overhead_for(p);
54276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
54286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
54296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
54306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
54316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* !ONLY_MSPACES */
54326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
54336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* ----------------------------- user mspaces ---------------------------- */
54346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
54356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if MSPACES
54366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
54376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostatic mstate init_user_mstate(char* tbase, size_t tsize) {
54386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t msize = pad_request(sizeof(struct malloc_state));
54396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr mn;
54406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mchunkptr msp = align_as_chunk(tbase);
54416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate m = (mstate)(chunk2mem(msp));
54426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  memset(m, 0, msize);
54436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  (void)INITIAL_LOCK(&m->mutex);
54446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  msp->head = (msize|INUSE_BITS);
54456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->seg.base = m->least_addr = tbase;
54466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->seg.size = m->footprint = m->max_footprint = tsize;
54476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->magic = mparams.magic;
54486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->release_checks = MAX_RELEASE_CHECK_RATE;
54496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->mflags = mparams.default_mflags;
54506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->extp = 0;
54516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  m->exts = 0;
54526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  disable_contiguous(m);
54536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  init_bins(m);
54546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mn = next_chunk(mem2chunk(m));
54556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
54566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  check_top_chunk(m, m->top);
54576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return m;
54586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
54596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
54606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaomspace create_mspace(size_t capacity, int locked) {
54616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate m = 0;
54626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t msize;
54636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
54646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  msize = pad_request(sizeof(struct malloc_state));
54656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
54666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t rs = ((capacity == 0)? mparams.granularity :
54676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                 (capacity + TOP_FOOT_SIZE + msize));
54686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t tsize = granularity_align(rs);
54696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    char* tbase = (char*)(CALL_MMAP(tsize));
54706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (tbase != CMFAIL) {
54716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      m = init_user_mstate(tbase, tsize);
54726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      m->seg.sflags = USE_MMAP_BIT;
54736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      set_lock(m, locked);
54746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
54756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
54766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return (mspace)m;
54776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
54786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
54796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaomspace create_mspace_with_base(void* base, size_t capacity, int locked) {
54806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate m = 0;
54816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t msize;
54826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  ensure_initialization();
54836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  msize = pad_request(sizeof(struct malloc_state));
54846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (capacity > msize + TOP_FOOT_SIZE &&
54856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
54866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    m = init_user_mstate((char*)base, capacity);
54876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    m->seg.sflags = EXTERN_BIT;
54886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    set_lock(m, locked);
54896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
54906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return (mspace)m;
54916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
54926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
54936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoint mspace_track_large_chunks(mspace msp, int enable) {
54946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int ret = 0;
54956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
54966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!PREACTION(ms)) {
54976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!use_mmap(ms)) {
54986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      ret = 1;
54996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
55006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!enable) {
55016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      enable_mmap(ms);
55026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    } else {
55036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      disable_mmap(ms);
55046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
55056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    POSTACTION(ms);
55066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
55076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return ret;
55086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
55096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
55106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t destroy_mspace(mspace msp) {
55116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t freed = 0;
55126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
55136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (ok_magic(ms)) {
55146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    msegmentptr sp = &ms->seg;
55156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */
55166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    while (sp != 0) {
55176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      char* base = sp->base;
55186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t size = sp->size;
55196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      flag_t flag = sp->sflags;
55206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      (void)base; /* placate people compiling -Wunused-variable */
55216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      sp = sp->next;
55226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) &&
55236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          CALL_MUNMAP(base, size) == 0)
55246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        freed += size;
55256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
55266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
55276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
55286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
55296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
55306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return freed;
55316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
55326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
55336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
55346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mspace versions of routines are near-clones of the global
55356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  versions. This is not so nice but better than the alternatives.
55366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
55376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
55386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* mspace_malloc(mspace msp, size_t bytes) {
55396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
55406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!ok_magic(ms)) {
55416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
55426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 0;
55436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
55446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!PREACTION(ms)) {
55456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    void* mem;
55466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t nb;
55476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (bytes <= MAX_SMALL_REQUEST) {
55486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      bindex_t idx;
55496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      binmap_t smallbits;
55506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
55516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      idx = small_index(nb);
55526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      smallbits = ms->smallmap >> idx;
55536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
55546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
55556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr b, p;
55566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
55576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        b = smallbin_at(ms, idx);
55586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        p = b->fd;
55596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        assert(chunksize(p) == small_index2size(idx));
55606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        unlink_first_small_chunk(ms, b, p, idx);
55616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_inuse_and_pinuse(ms, p, small_index2size(idx));
55626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mem = chunk2mem(p);
55636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        check_malloced_chunk(ms, mem, nb);
55646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        goto postaction;
55656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
55666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
55676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else if (nb > ms->dvsize) {
55686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
55696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mchunkptr b, p, r;
55706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          size_t rsize;
55716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          bindex_t i;
55726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
55736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          binmap_t leastbit = least_bit(leftbits);
55746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          compute_bit2idx(leastbit, i);
55756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          b = smallbin_at(ms, i);
55766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          p = b->fd;
55776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          assert(chunksize(p) == small_index2size(i));
55786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          unlink_first_small_chunk(ms, b, p, i);
55796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          rsize = small_index2size(i) - nb;
55806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          /* Fit here cannot be remainderless if 4byte sizes */
55816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
55826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            set_inuse_and_pinuse(ms, p, small_index2size(i));
55836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else {
55846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
55856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            r = chunk_plus_offset(p, nb);
55866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            set_size_and_pinuse_of_free_chunk(r, rsize);
55876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            replace_dv(ms, r, rsize);
55886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
55896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mem = chunk2mem(p);
55906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          check_malloced_chunk(ms, mem, nb);
55916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          goto postaction;
55926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
55936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
55946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
55956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          check_malloced_chunk(ms, mem, nb);
55966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          goto postaction;
55976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
55986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
55996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
56006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (bytes >= MAX_REQUEST)
56016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
56026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {
56036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nb = pad_request(bytes);
56046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
56056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        check_malloced_chunk(ms, mem, nb);
56066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        goto postaction;
56076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
56086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
56096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
56106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (nb <= ms->dvsize) {
56116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t rsize = ms->dvsize - nb;
56126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr p = ms->dv;
56136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
56146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
56156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        ms->dvsize = rsize;
56166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_size_and_pinuse_of_free_chunk(r, rsize);
56176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
56186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
56196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else { /* exhaust dv */
56206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t dvs = ms->dvsize;
56216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        ms->dvsize = 0;
56226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        ms->dv = 0;
56236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        set_inuse_and_pinuse(ms, p, dvs);
56246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
56256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mem = chunk2mem(p);
56266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_malloced_chunk(ms, mem, nb);
56276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      goto postaction;
56286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
56296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
56306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (nb < ms->topsize) { /* Split top */
56316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t rsize = ms->topsize -= nb;
56326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr p = ms->top;
56336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr r = ms->top = chunk_plus_offset(p, nb);
56346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      r->head = rsize | PINUSE_BIT;
56356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
56366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mem = chunk2mem(p);
56376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_top_chunk(ms, ms->top);
56386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_malloced_chunk(ms, mem, nb);
56396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      goto postaction;
56406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
56416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
56426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mem = sys_alloc(ms, nb);
56436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
56446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  postaction:
56456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    POSTACTION(ms);
56466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return mem;
56476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
56486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
56496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
56506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
56516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
56526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid mspace_free(mspace msp, void* mem) {
56536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (mem != 0) {
56546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr p  = mem2chunk(mem);
56556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if FOOTERS
56566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mstate fm = get_mstate_for(p);
56576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    (void)msp; /* placate people compiling -Wunused */
56586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* FOOTERS */
56596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mstate fm = (mstate)msp;
56606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* FOOTERS */
56616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!ok_magic(fm)) {
56626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      USAGE_ERROR_ACTION(fm, p);
56636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return;
56646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
56656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!PREACTION(fm)) {
56666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      check_inuse_chunk(fm, p);
56676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) {
56686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        size_t psize = chunksize(p);
56696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr next = chunk_plus_offset(p, psize);
56706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (!pinuse(p)) {
56716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          size_t prevsize = p->prev_foot;
56726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (is_mmapped(p)) {
56736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            psize += prevsize + MMAP_FOOT_PAD;
56746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
56756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              fm->footprint -= psize;
56766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            goto postaction;
56776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
56786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else {
56796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            mchunkptr prev = chunk_minus_offset(p, prevsize);
56806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            psize += prevsize;
56816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            p = prev;
56826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
56836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              if (p != fm->dv) {
56846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                unlink_chunk(fm, p, prevsize);
56856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              }
56866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
56876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                fm->dvsize = psize;
56886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                set_free_with_pinuse(p, psize, next);
56896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                goto postaction;
56906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              }
56916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            }
56926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            else
56936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              goto erroraction;
56946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
56956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
56966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
56976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
56986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (!cinuse(next)) {  /* consolidate forward */
56996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            if (next == fm->top) {
57006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              size_t tsize = fm->topsize += psize;
57016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              fm->top = p;
57026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              p->head = tsize | PINUSE_BIT;
57036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              if (p == fm->dv) {
57046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                fm->dv = 0;
57056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                fm->dvsize = 0;
57066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              }
57076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              if (should_trim(fm, tsize))
57086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                sys_trim(fm, 0);
57096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              goto postaction;
57106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            }
57116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            else if (next == fm->dv) {
57126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              size_t dsize = fm->dvsize += psize;
57136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              fm->dv = p;
57146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              set_size_and_pinuse_of_free_chunk(p, dsize);
57156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              goto postaction;
57166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            }
57176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            else {
57186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              size_t nsize = chunksize(next);
57196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              psize += nsize;
57206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              unlink_chunk(fm, next, nsize);
57216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              set_size_and_pinuse_of_free_chunk(p, psize);
57226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              if (p == fm->dv) {
57236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                fm->dvsize = psize;
57246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                goto postaction;
57256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              }
57266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            }
57276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
57286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else
57296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            set_free_with_pinuse(p, psize, next);
57306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
57316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          if (is_small(psize)) {
57326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            insert_small_chunk(fm, p, psize);
57336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            check_free_chunk(fm, p);
57346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
57356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          else {
57366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            tchunkptr tp = (tchunkptr)p;
57376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            insert_large_chunk(fm, tp, psize);
57386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            check_free_chunk(fm, p);
57396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao            if (--fm->release_checks == 0)
57406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao              release_unused_segments(fm);
57416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          }
57426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          goto postaction;
57436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
57446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
57456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    erroraction:
57466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      USAGE_ERROR_ACTION(fm, p);
57476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    postaction:
57486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      POSTACTION(fm);
57496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
57506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
57516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
57526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
57536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
57546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void* mem;
57556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t req = 0;
57566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
57576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!ok_magic(ms)) {
57586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
57596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 0;
57606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
57616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (n_elements != 0) {
57626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    req = n_elements * elem_size;
57636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
57646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        (req / n_elements != elem_size))
57656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      req = MAX_SIZE_T; /* force downstream failure on overflow */
57666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
57676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mem = internal_malloc(ms, req);
57686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
57696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    memset(mem, 0, req);
57706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return mem;
57716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
57726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
57736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
57746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void* mem = 0;
57756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (oldmem == 0) {
57766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mem = mspace_malloc(msp, bytes);
57776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
57786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (bytes >= MAX_REQUEST) {
57796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    MALLOC_FAILURE_ACTION;
57806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
57816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#ifdef REALLOC_ZERO_BYTES_FREES
57826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else if (bytes == 0) {
57836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mspace_free(msp, oldmem);
57846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
57856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* REALLOC_ZERO_BYTES_FREES */
57866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
57876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t nb = request2size(bytes);
57886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr oldp = mem2chunk(oldmem);
57896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if ! FOOTERS
57906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mstate m = (mstate)msp;
57916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* FOOTERS */
57926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mstate m = get_mstate_for(oldp);
57936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!ok_magic(m)) {
57946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      USAGE_ERROR_ACTION(m, oldmem);
57956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return 0;
57966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
57976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* FOOTERS */
57986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!PREACTION(m)) {
57996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1);
58006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      POSTACTION(m);
58016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (newp != 0) {
58026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        check_inuse_chunk(m, newp);
58036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mem = chunk2mem(newp);
58046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
58056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      else {
58066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mem = mspace_malloc(m, bytes);
58076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (mem != 0) {
58086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          size_t oc = chunksize(oldp) - overhead_for(oldp);
58096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          memcpy(mem, oldmem, (oc < bytes)? oc : bytes);
58106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mspace_free(m, oldmem);
58116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
58126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
58136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
58146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
58156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return mem;
58166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
58176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
58186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* mspace_realloc_in_place(mspace msp, void* oldmem, size_t bytes) {
58196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void* mem = 0;
58206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (oldmem != 0) {
58216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (bytes >= MAX_REQUEST) {
58226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      MALLOC_FAILURE_ACTION;
58236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
58246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else {
58256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      size_t nb = request2size(bytes);
58266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mchunkptr oldp = mem2chunk(oldmem);
58276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if ! FOOTERS
58286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mstate m = (mstate)msp;
58296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#else /* FOOTERS */
58306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      mstate m = get_mstate_for(oldp);
58316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      (void)msp; /* placate people compiling -Wunused */
58326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (!ok_magic(m)) {
58336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        USAGE_ERROR_ACTION(m, oldmem);
58346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        return 0;
58356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
58366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* FOOTERS */
58376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (!PREACTION(m)) {
58386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0);
58396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        POSTACTION(m);
58406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        if (newp == oldp) {
58416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          check_inuse_chunk(m, newp);
58426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          mem = oldmem;
58436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        }
58446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
58456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
58466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
58476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return mem;
58486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
58496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
58506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
58516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
58526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!ok_magic(ms)) {
58536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
58546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 0;
58556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
58566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (alignment <= MALLOC_ALIGNMENT)
58576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return mspace_malloc(msp, bytes);
58586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return internal_memalign(ms, alignment, bytes);
58596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
58606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
58616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid** mspace_independent_calloc(mspace msp, size_t n_elements,
58626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                 size_t elem_size, void* chunks[]) {
58636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t sz = elem_size; /* serves as 1-element array */
58646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
58656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!ok_magic(ms)) {
58666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
58676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 0;
58686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
58696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return ialloc(ms, n_elements, &sz, 3, chunks);
58706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
58716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
58726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid** mspace_independent_comalloc(mspace msp, size_t n_elements,
58736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                   size_t sizes[], void* chunks[]) {
58746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
58756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!ok_magic(ms)) {
58766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
58776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    return 0;
58786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
58796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return ialloc(ms, n_elements, sizes, 0, chunks);
58806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
58816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
58826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t mspace_bulk_free(mspace msp, void* array[], size_t nelem) {
58836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return internal_bulk_free((mstate)msp, array, nelem);
58846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
58856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
58866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if MALLOC_INSPECT_ALL
58876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid mspace_inspect_all(mspace msp,
58886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                        void(*handler)(void *start,
58896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                       void *end,
58906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                       size_t used_bytes,
58916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                                       void* callback_arg),
58926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao                        void* arg) {
58936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
58946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (ok_magic(ms)) {
58956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!PREACTION(ms)) {
58966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      internal_inspect_all(ms, handler, arg);
58976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      POSTACTION(ms);
58986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
58996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
59016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
59026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
59046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MALLOC_INSPECT_ALL */
59056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
59066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoint mspace_trim(mspace msp, size_t pad) {
59076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  int result = 0;
59086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
59096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (ok_magic(ms)) {
59106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (!PREACTION(ms)) {
59116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      result = sys_trim(ms, pad);
59126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      POSTACTION(ms);
59136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
59146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
59166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
59176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return result;
59196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
59206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
59216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !NO_MALLOC_STATS
59226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaovoid mspace_malloc_stats(mspace msp) {
59236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
59246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (ok_magic(ms)) {
59256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    internal_malloc_stats(ms);
59266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
59286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
59296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
59316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* NO_MALLOC_STATS */
59326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
59336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t mspace_footprint(mspace msp) {
59346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t result = 0;
59356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
59366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (ok_magic(ms)) {
59376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    result = ms->footprint;
59386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
59406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
59416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return result;
59436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
59446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
59456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t mspace_max_footprint(mspace msp) {
59466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t result = 0;
59476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
59486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (ok_magic(ms)) {
59496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    result = ms->max_footprint;
59506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
59526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
59536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return result;
59556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
59566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
59576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t mspace_footprint_limit(mspace msp) {
59586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t result = 0;
59596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
59606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (ok_magic(ms)) {
59616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    size_t maf = ms->footprint_limit;
59626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    result = (maf == 0) ? MAX_SIZE_T : maf;
59636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
59656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
59666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return result;
59686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
59696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
59706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t mspace_set_footprint_limit(mspace msp, size_t bytes) {
59716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  size_t result = 0;
59726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
59736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (ok_magic(ms)) {
59746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (bytes == 0)
59756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      result = granularity_align(1); /* Use minimal size */
59766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (bytes == MAX_SIZE_T)
59776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      result = 0;                    /* disable */
59786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else
59796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      result = granularity_align(bytes);
59806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    ms->footprint_limit = result;
59816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  else {
59836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
59846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return result;
59866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
59876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
59886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#if !NO_MALLINFO
59896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaostruct mallinfo mspace_mallinfo(mspace msp) {
59906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  mstate ms = (mstate)msp;
59916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (!ok_magic(ms)) {
59926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    USAGE_ERROR_ACTION(ms,ms);
59936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
59946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return internal_mallinfo(ms);
59956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
59966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* NO_MALLINFO */
59976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
59986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaosize_t mspace_usable_size(const void* mem) {
59996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  if (mem != 0) {
60006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    mchunkptr p = mem2chunk(mem);
60016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (is_inuse(p))
60026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return chunksize(p) - overhead_for(p);
60036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
60046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return 0;
60056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
60066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gaoint mspace_mallopt(int param_number, int value) {
60086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  return change_mparam(param_number, value);
60096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao}
60106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao#endif /* MSPACES */
60126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -------------------- Alternative MORECORE functions ------------------- */
60156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/*
60176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  Guidelines for creating a custom version of MORECORE:
60186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  * For best performance, MORECORE should allocate in multiples of pagesize.
60206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  * MORECORE may allocate more memory than requested. (Or even less,
60216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      but this will usually result in a malloc failure.)
60226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  * MORECORE must not allocate memory when given argument zero, but
60236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      instead return one past the end address of memory from previous
60246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      nonzero call.
60256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  * For best performance, consecutive calls to MORECORE with positive
60266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      arguments should return increasing addresses, indicating that
60276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      space has been contiguously extended.
60286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  * Even though consecutive calls to MORECORE need not return contiguous
60296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      addresses, it must be OK for malloc'ed chunks to span multiple
60306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      regions in those cases where they do happen to be contiguous.
60316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  * MORECORE need not handle negative arguments -- it may instead
60326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      just return MFAIL when given negative arguments.
60336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      Negative arguments are always multiples of pagesize. MORECORE
60346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      must not misinterpret negative args as large positive unsigned
60356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      args. You can suppress all such calls from even occurring by defining
60366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      MORECORE_CANNOT_TRIM,
60376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  As an example alternative MORECORE, here is a custom allocator
60396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  kindly contributed for pre-OSX macOS.  It uses virtually but not
60406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  necessarily physically contiguous non-paged memory (locked in,
60416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  present and won't get swapped out).  You can use it by uncommenting
60426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  this section, adding some #includes, and setting up the appropriate
60436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  defines above:
60446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      #define MORECORE osMoreCore
60466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  There is also a shutdown routine that should somehow be called for
60486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  cleanup upon program exit.
60496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  #define MAX_POOL_ENTRIES 100
60516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  #define MINIMUM_MORECORE_SIZE  (64 * 1024U)
60526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  static int next_os_pool;
60536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void *our_os_pools[MAX_POOL_ENTRIES];
60546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void *osMoreCore(int size)
60566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  {
60576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    void *ptr = 0;
60586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    static void *sbrk_top = 0;
60596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    if (size > 0)
60616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    {
60626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (size < MINIMUM_MORECORE_SIZE)
60636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         size = MINIMUM_MORECORE_SIZE;
60646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (CurrentExecutionLevel() == kTaskLevel)
60656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
60666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (ptr == 0)
60676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      {
60686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        return (void *) MFAIL;
60696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
60706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      // save ptrs so they can be freed during cleanup
60716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      our_os_pools[next_os_pool] = ptr;
60726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      next_os_pool++;
60736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
60746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      sbrk_top = (char *) ptr + size;
60756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return ptr;
60766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
60776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else if (size < 0)
60786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    {
60796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      // we don't currently support shrink behavior
60806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return (void *) MFAIL;
60816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
60826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    else
60836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    {
60846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      return sbrk_top;
60856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    }
60866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
60876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  // cleanup any allocated memory pools
60896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  // called as last thing before shutting down driver
60906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  void osCleanupMem(void)
60926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  {
60936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    void **ptr;
60946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
60956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
60966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      if (*ptr)
60976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      {
60986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         PoolDeallocate(*ptr);
60996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         *ptr = 0;
61006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      }
61016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao  }
61026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
61046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao/* -----------------------------------------------------------------------
61076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh GaoHistory:
61086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    v2.8.6 Wed Aug 29 06:57:58 2012  Doug Lea
61096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * fix bad comparison in dlposix_memalign
61106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * don't reuse adjusted asize in sys_alloc
61116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * add LOCK_AT_FORK -- thanks to Kirill Artamonov for the suggestion
61126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * reduce compiler warnings -- thanks to all who reported/suggested these
61136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    v2.8.5 Sun May 22 10:26:02 2011  Doug Lea  (dl at gee)
61156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Always perform unlink checks unless INSECURE
61166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add posix_memalign.
61176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Improve realloc to expand in more cases; expose realloc_in_place.
61186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        Thanks to Peter Buhr for the suggestion.
61196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add footprint_limit, inspect_all, bulk_free. Thanks
61206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        to Barry Hayes and others for the suggestions.
61216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Internal refactorings to avoid calls while holding locks
61226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Use non-reentrant locks by default. Thanks to Roland McGrath
61236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        for the suggestion.
61246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Small fixes to mspace_destroy, reset_on_error.
61256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Various configuration extensions/changes. Thanks
61266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         to all who contributed these.
61276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.8.4a Thu Apr 28 14:39:43 2011 (dl at gee.cs.oswego.edu)
61296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Update Creative Commons URL
61306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.8.4 Wed May 27 09:56:23 2009  Doug Lea  (dl at gee)
61326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Use zeros instead of prev foot for is_mmapped
61336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add mspace_track_large_chunks; thanks to Jean Brouwers
61346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fix set_inuse in internal_realloc; thanks to Jean Brouwers
61356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fix insufficient sys_alloc padding when using 16byte alignment
61366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fix bad error check in mspace_footprint
61376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Adaptations for ptmalloc; thanks to Wolfram Gloger.
61386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Reentrant spin locks; thanks to Earl Chew and others
61396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Win32 improvements; thanks to Niall Douglas and Earl Chew
61406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options
61416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Extension hook in malloc_state
61426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Various small adjustments to reduce warnings on some compilers
61436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Various configuration extensions/changes for more platforms. Thanks
61446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         to all who contributed these.
61456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.8.3 Thu Sep 22 11:16:32 2005  Doug Lea  (dl at gee)
61476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add max_footprint functions
61486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Ensure all appropriate literals are size_t
61496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fix conditional compilation problem for some #define settings
61506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Avoid concatenating segments with the one provided
61516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        in create_mspace_with_base
61526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Rename some variables to avoid compiler shadowing warnings
61536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Use explicit lock initialization.
61546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Better handling of sbrk interference.
61556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Simplify and fix segment insertion, trimming and mspace_destroy
61566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
61576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Thanks especially to Dennis Flanagan for help on these.
61586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.8.2 Sun Jun 12 16:01:10 2005  Doug Lea  (dl at gee)
61606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fix memalign brace error.
61616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.8.1 Wed Jun  8 16:11:46 2005  Doug Lea  (dl at gee)
61636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fix improper #endif nesting in C++
61646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add explicit casts needed for C++
61656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.8.0 Mon May 30 14:09:02 2005  Doug Lea  (dl at gee)
61676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Use trees for large bins
61686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Support mspaces
61696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Use segments to unify sbrk-based and mmap-based system allocation,
61706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        removing need for emulation on most platforms without sbrk.
61716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Default safety checks
61726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Optional footer checks. Thanks to William Robertson for the idea.
61736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Internal code refactoring
61746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Incorporate suggestions and platform-specific changes.
61756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
61766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        Aaron Bachmann,  Emery Berger, and others.
61776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Speed up non-fastbin processing enough to remove fastbins.
61786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Remove useless cfree() to avoid conflicts with other apps.
61796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Remove internal memcpy, memset. Compilers handle builtins better.
61806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Remove some options that no one ever used and rename others.
61816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
61836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fix malloc_state bitmap array misdeclaration
61846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.7.1 Thu Jul 25 10:58:03 2002  Doug Lea  (dl at gee)
61866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Allow tuning of FIRST_SORTED_BIN_SIZE
61876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
61886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Better detection and support for non-contiguousness of MORECORE.
61896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
61906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Bypass most of malloc if no frees. Thanks To Emery Berger.
61916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fix freeing of old top non-contiguous chunk im sysmalloc.
61926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Raised default trim and map thresholds to 256K.
61936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fix mmap-related #defines. Thanks to Lubos Lunak.
61946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
61956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Branch-free bin calculation
61966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Default trim and mmap thresholds now 256K.
61976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
61986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
61996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Introduce independent_comalloc and independent_calloc.
62006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        Thanks to Michael Pachos for motivation and help.
62016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Make optional .h file available
62026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Allow > 2GB requests on 32bit systems.
62036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
62046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
62056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        and Anonymous.
62066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
62076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        helping test this.)
62086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * memalign: check alignment arg
62096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * realloc: don't try to shift chunks backwards, since this
62106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        leads to  more fragmentation in some programs and doesn't
62116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        seem to help in any others.
62126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Collect all cases in malloc requiring system memory into sysmalloc
62136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Use mmap as backup to sbrk
62146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Place all internal state in malloc_state
62156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Introduce fastbins (although similar to 2.5.1)
62166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Many minor tunings and cosmetic improvements
62176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
62186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
62196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
62206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Include errno.h to support default failure action.
62216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
62226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
62236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * return null for negative arguments
62246661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
62256661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
62266661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          (e.g. WIN32 platforms)
62276661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         * Cleanup header file inclusion for WIN32 platforms
62286661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         * Cleanup code to avoid Microsoft Visual C++ compiler complaints
62296661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
62306661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao           memory allocation routines
62316661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
62326661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
62336661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao           usage of 'assert' in non-WIN32 code
62346661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
62356661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao           avoid infinite loop
62366661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Always call 'fREe()' rather than 'free()'
62376661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
62386661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
62396661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fixed ordering problem with boundary-stamping
62406661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
62416661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
62426661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Added pvalloc, as recommended by H.J. Liu
62436661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Added 64bit pointer support mainly from Wolfram Gloger
62446661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Added anonymously donated WIN32 sbrk emulation
62456661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
62466661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * malloc_extend_top: fix mask error that caused wastage after
62476661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        foreign sbrks
62486661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add linux mremap support code from HJ Liu
62496661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
62506661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
62516661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Integrated most documentation with the code.
62526661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add support for mmap, with help from
62536661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
62546661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Use last_remainder in more cases.
62556661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Pack bins using idea from  colin@nyx10.cs.du.edu
62566661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Use ordered bins instead of best-fit threshhold
62576661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Eliminate block-local decls to simplify tracing and debugging.
62586661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Support another case of realloc via move into top
62596661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Fix error occuring when initial sbrk_base not word-aligned.
62606661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Rely on page size for units instead of SBRK_UNIT to
62616661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        avoid surprises about sbrk alignment conventions.
62626661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
62636661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        (raymond@es.ele.tue.nl) for the suggestion.
62646661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
62656661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * More precautions for cases where other routines call sbrk,
62666661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
62676661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Added macros etc., allowing use in linux libc from
62686661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        H.J. Lu (hjl@gnu.ai.mit.edu)
62696661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Inverted this history list
62706661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
62716661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
62726661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
62736661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Removed all preallocation code since under current scheme
62746661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        the work required to undo bad preallocations exceeds
62756661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        the work saved in good cases for most test programs.
62766661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * No longer use return list or unconsolidated bins since
62776661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        no scheme using them consistently outperforms those that don't
62786661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        given above changes.
62796661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Use best fit for very large chunks to prevent some worst-cases.
62806661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Added some support for debugging
62816661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
62826661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
62836661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Removed footers when chunks are in use. Thanks to
62846661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        Paul Wilson (wilson@cs.texas.edu) for the suggestion.
62856661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
62866661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
62876661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Added malloc_trim, with help from Wolfram Gloger
62886661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao        (wmglo@Dent.MED.Uni-Muenchen.DE).
62896661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
62906661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
62916661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
62926661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
62936661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * realloc: try to expand in both directions
62946661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * malloc: swap order of clean-bin strategy;
62956661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * realloc: only conditionally expand backwards
62966661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Try not to scavenge used bins
62976661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Use bin counts as a guide to preallocation
62986661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Occasionally bin return list chunks in first scan
62996661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add a few optimizations from colin@nyx10.cs.du.edu
63006661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
63016661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
63026661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * faster bin computation & slightly different binning
63036661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * merged all consolidations to one part of malloc proper
63046661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         (eliminating old malloc_find_space & malloc_clean_bin)
63056661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Scan 2 returns chunks (not just 1)
63066661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Propagate failure in realloc if malloc returns 0
63076661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Add stuff to allow compilation on non-ANSI compilers
63086661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          from kpv@research.att.com
63096661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
63106661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
63116661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * removed potential for odd address access in prev_chunk
63126661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * removed dependency on getpagesize.h
63136661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * misc cosmetics and a bit more internal documentation
63146661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * anticosmetics: mangled names in macros to evade debugger strangeness
63156661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * tested on sparc, hp-700, dec-mips, rs6000
63166661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          with gcc & native cc (hp, dec only) allowing
63176661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao          Detlefs & Zorn comparison study (in SIGPLAN Notices.)
63186661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
63196661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao    Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
63206661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao      * Based loosely on libg++-1.2X malloc. (It retains some of the overall
63216661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao         structure of old version,  but most details differ.)
63226661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao
63236661f3ca66b55d8f5a57b96fec97efaf8f3897a5Josh Gao*/
6324