19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL - Simple DirectMedia Layer
39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Copyright (C) 1997-2012 Sam Lantinga
49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This library is free software; you can redistribute it and/or
69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    modify it under the terms of the GNU Lesser General Public
79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    License as published by the Free Software Foundation; either
89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    version 2.1 of the License, or (at your option) any later version.
99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This library is distributed in the hope that it will be useful,
119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    but WITHOUT ANY WARRANTY; without even the implied warranty of
129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Lesser General Public License for more details.
149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    You should have received a copy of the GNU Lesser General Public
169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    License along with this library; if not, write to the Free Software
179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Sam Lantinga
209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    slouken@libsdl.org
219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_config.h"
239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* This file contains portable memory management functions for SDL */
259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_stdinc.h"
279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef HAVE_MALLOC
299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_SYS_TYPES_H
319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_STDIO_H
329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_STRINGS_H
339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_STRING_H
349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_STDLIB_H
359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ABORT
369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  This is a version (aka dlmalloc) of malloc/free/realloc written by
399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Doug Lea and released to the public domain, as explained at
409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  http://creativecommons.org/licenses/publicdomain.  Send questions,
419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  comments, complaints, performance data, etc to dl@cs.oswego.edu
429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall* Version 2.8.3 Thu Sep 22 11:16:15 2005  Doug Lea  (dl at gee)
449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   Note: There may be an updated version of this malloc obtainable at
469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           ftp://gee.cs.oswego.edu/pub/misc/malloc.c
479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         Check before installing!
489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall* Quickstart
509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  This library is all in one file to simplify the most common usage:
529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ftp it, compile it (-O3), and link it into another program. All of
539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the compile-time options default to reasonable values for use on
549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  most platforms.  You might later want to step through various
559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  compile-time and dynamic tuning options.
569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  For convenience, an include file for code using this malloc is at:
589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h
599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  You don't really need this .h file unless you call functions not
609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  defined in your system include files.  The .h file contains only the
619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  excerpts from this file needed for using this malloc on ANSI C/C++
629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  systems, so long as you haven't changed compile-time options about
639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  naming and tuning parameters.  If you do, then you can create your
649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  own malloc.h that does include all settings by cutting at the point
659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  indicated below. Note that you may already by default be using a C
669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  library containing a malloc that is based on some version of this
679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc (for example in linux). You might still want to use the one
689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  in this file to customize settings or to avoid overheads associated
699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  with library versions.
709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall* Vital statistics:
729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Supported pointer/size_t representation:       4 or 8 bytes
749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       size_t MUST be an unsigned type of the same width as
759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       pointers. (If you are using an ancient system that declares
769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       size_t as a signed type, or need it to be a different width
779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       than pointers, you can use a previous release of this malloc
789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       (e.g. 2.7.2) supporting these.)
799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Alignment:                                     8 bytes (default)
819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       This suffices for nearly all current machines and C compilers.
829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       However, you can define MALLOC_ALIGNMENT to be wider than this
839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       if necessary (up to 128bytes), at the expense of using more space.
849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Minimum overhead per allocated chunk:   4 or  8 bytes (if 4byte sizes)
869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                          8 or 16 bytes (if 8byte sizes)
879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       Each malloced chunk has a hidden word of overhead holding size
889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       and status information, and additional cross-check word
899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       if FOOTERS is defined.
909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Minimum allocated size: 4-byte ptrs:  16 bytes    (including overhead)
929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                          8-byte ptrs:  32 bytes    (including overhead)
939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       Even a request for zero bytes (i.e., malloc(0)) returns a
959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       pointer to something of the minimum allocatable size.
969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       The maximum overhead wastage (i.e., number of extra bytes
979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       allocated than were requested in malloc) is less than or equal
989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       to the minimum size, except for requests >= mmap_threshold that
999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       are serviced via mmap(), where the worst case wastage is about
1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       32 bytes plus the remainder from a system page (the minimal
1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       mmap unit); typically 4096 or 8192 bytes.
1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Security: static-safe; optionally more or less
1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       The "security" of malloc refers to the ability of malicious
1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       code to accentuate the effects of errors (for example, freeing
1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       space that is not currently malloc'ed or overwriting past the
1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       ends of chunks) in code that calls malloc.  This malloc
1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       guarantees not to modify any memory locations below the base of
1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       heap, i.e., static variables, even in the presence of usage
1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       errors.  The routines additionally detect most improper frees
1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       and reallocs.  All this holds as long as the static bookkeeping
1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       for malloc itself is not corrupted by some other means.  This
1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       is only one aspect of security -- these checks do not, and
1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       cannot, detect all possible programming errors.
1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       If FOOTERS is defined nonzero, then each allocated chunk
1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       carries an additional check word to verify that it was malloced
1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       from its space.  These check words are the same within each
1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       execution of a program using malloc, but differ across
1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       executions, so externally crafted fake chunks cannot be
1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       freed. This improves security by rejecting frees/reallocs that
1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       could corrupt heap memory, in addition to the checks preventing
1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       writes to statics that are always on.  This may further improve
1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       security at the expense of time and space overhead.  (Note that
1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       FOOTERS may also be worth using with MSPACES.)
1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       By default detected errors cause the program to abort (calling
1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       "abort()"). You can override this to instead proceed past
1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       errors by defining PROCEED_ON_ERROR.  In this case, a bad free
1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       has no effect, and a malloc that encounters a bad address
1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       caused by user overwrites will ignore the bad address by
1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       dropping pointers and indices to all known memory. This may
1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       be appropriate for programs that should continue if at all
1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       possible in the face of programming errors, although they may
1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       run out of memory because dropped memory is never reclaimed.
1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       If you don't like either of these options, you can define
1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       else. And if if you are sure that your program using malloc has
1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       no errors or vulnerabilities, you can define INSECURE to 1,
1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       which might (or might not) provide a small performance improvement.
1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Thread-safety: NOT thread-safe unless USE_LOCKS defined
1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       When USE_LOCKS is defined, each public call to malloc, free,
1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       etc is surrounded with either a pthread mutex or a win32
1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       spinlock (depending on WIN32). This is not especially fast, and
1479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       can be a major bottleneck.  It is designed only to provide
1489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       minimal protection in concurrent environments, and to provide a
1499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       basis for extensions.  If you are using malloc in a concurrent
1509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       program, consider instead using ptmalloc, which is derived from
1519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       a version of this malloc. (See http://www.malloc.de).
1529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
1549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       This malloc can use unix sbrk or any emulation (invoked using
1559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       the CALL_MORECORE macro) and/or mmap/munmap or any emulation
1569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
1579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       memory.  On most unix systems, it tends to work best if both
1589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       MORECORE and MMAP are enabled.  On Win32, it uses emulations
1599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       based on VirtualAlloc. It also uses common C library functions
1609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       like memset.
1619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Compliance: I believe it is compliant with the Single Unix Specification
1639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
1649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       others as well.
1659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall* Overview of algorithms
1679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  This is not the fastest, most space-conserving, most portable, or
1699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  most tunable malloc ever written. However it is among the fastest
1709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  while also being among the most space-conserving, portable and
1719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tunable.  Consistent balance across these factors results in a good
1729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  general-purpose allocator for malloc-intensive programs.
1739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  In most ways, this malloc is a best-fit allocator. Generally, it
1759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  chooses the best-fitting existing chunk for a request, with ties
1769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  broken in approximately least-recently-used order. (This strategy
1779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  normally maintains low fragmentation.) However, for requests less
1789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  than 256bytes, it deviates from best-fit when there is not an
1799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  exactly fitting available chunk by preferring to use space adjacent
1809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  to that used for the previous small request, as well as by breaking
1819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ties in approximately most-recently-used order. (These enhance
1829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  locality of series of small allocations.)  And for very large requests
1839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (>= 256Kb by default), it relies on system memory mapping
1849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  facilities, if supported.  (This helps avoid carrying around and
1859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  possibly fragmenting memory used only for large chunks.)
1869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  All operations (except malloc_stats and mallinfo) have execution
1889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  times that are bounded by a constant factor of the number of bits in
1899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  a size_t, not counting any clearing in calloc or copying in realloc,
1909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  or actions surrounding MORECORE and MMAP that have times
1919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  proportional to the number of non-contiguous regions returned by
1929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  system allocation routines, which is often just 1.
1939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The implementation is not very modular and seriously overuses
1959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  macros. Perhaps someday all C compilers will do as good a job
1969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  inlining modular code as can now be done by brute-force expansion,
1979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  but now, enough of them seem not to.
1989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Some compilers issue a lot of warnings about code that is
2009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  dead/unreachable only on some platforms, and also about intentional
2019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  uses of negation on unsigned types. All known cases of each can be
2029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ignored.
2039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  For a longer but out of date high-level description, see
2059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     http://gee.cs.oswego.edu/dl/html/malloc.html
2069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall* MSPACES
2089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If MSPACES is defined, then in addition to malloc, free, etc.,
2099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  this file also defines mspace_malloc, mspace_free, etc. These
2109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  are versions of malloc routines that take an "mspace" argument
2119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  obtained using create_mspace, to control all internal bookkeeping.
2129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If ONLY_MSPACES is defined, only these versions are compiled.
2139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  So if you would like to use this allocator for only some allocations,
2149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  and your system malloc for others, you can compile with
2159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ONLY_MSPACES and then do something like...
2169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    static mspace mymspace = create_mspace(0,0); // for example
2179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    #define mymalloc(bytes)  mspace_malloc(mymspace, bytes)
2189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (Note: If you only need one instance of an mspace, you can instead
2209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  use "USE_DL_PREFIX" to relabel the global malloc.)
2219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  You can similarly create thread-local allocators by storing
2239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspaces as thread-locals. For example:
2249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    static __thread mspace tlms = 0;
2259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    void*  tlmalloc(size_t bytes) {
2269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (tlms == 0) tlms = create_mspace(0, 0);
2279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return mspace_malloc(tlms, bytes);
2289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
2299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    void  tlfree(void* mem) { mspace_free(tlms, mem); }
2309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Unless FOOTERS is defined, each mspace is completely independent.
2329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  You cannot allocate from one and free to another (although
2339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  conformance is only weakly checked, so usage errors are not always
2349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  caught). If FOOTERS is defined, then each chunk carries around a tag
2359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  indicating its originating mspace, and frees are directed to their
2369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  originating spaces.
2379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall -------------------------  Compile-time options ---------------------------
2399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallBe careful in setting #define values for numerical constants of type
2419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t. On some systems, literal values are not automatically extended
2429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallto size_t precision unless they are explicitly casted.
2439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallWIN32                    default: defined if _WIN32 defined
2459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Defining WIN32 sets up defaults for MS environment and compilers.
2469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Otherwise defaults are for unix.
2479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallMALLOC_ALIGNMENT         default: (size_t)8
2499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Controls the minimum alignment for malloc'ed chunks.  It must be a
2509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  power of two and at least 8, even on machines for which smaller
2519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  alignments would suffice. It may be defined as larger than this
2529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  though. Note however that code and data structures are optimized for
2539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the case of 8-byte alignment.
2549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallMSPACES                  default: 0 (false)
2569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If true, compile in support for independent allocation spaces.
2579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  This is only supported if HAVE_MMAP is true.
2589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallONLY_MSPACES             default: 0 (false)
2609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If true, only compile in mspace versions, not regular versions.
2619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallUSE_LOCKS                default: 0 (false)
2639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Causes each call to each public routine to be surrounded with
2649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  pthread or WIN32 mutex lock/unlock. (If set true, this can be
2659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  overridden on a per-mspace basis for mspace versions.)
2669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallFOOTERS                  default: 0
2689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If true, provide extra checking and dispatching by placing
2699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  information in the footers of allocated chunks. This adds
2709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  space and time overhead.
2719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallINSECURE                 default: 0
2739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If true, omit checks for usage errors and heap space overwrites.
2749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallUSE_DL_PREFIX            default: NOT defined
2769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Causes compiler to prefix all public routines with the string 'dl'.
2779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  This can be useful when you only want to use this malloc in one part
2789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  of a program, using your regular system malloc elsewhere.
2799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallABORT                    default: defined as abort()
2819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Defines how to abort on failed checks.  On most systems, a failed
2829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  check cannot die with an "assert" or even print an informative
2839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  message, because the underlying print routines in turn call malloc,
2849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  which will fail again.  Generally, the best policy is to simply call
2859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  abort(). It's not very useful to do more than this because many
2869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  errors due to overwriting will show up as address faults (null, odd
2879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  addresses etc) rather than malloc-triggered checks, so will also
2889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  abort.  Also, most compilers know that abort() does not return, so
2899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  can better optimize code conditionally calling it.
2909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallPROCEED_ON_ERROR           default: defined as 0 (false)
2929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Controls whether detected bad addresses cause them to bypassed
2939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  rather than aborting. If set, detected bad arguments to free and
2949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  realloc are ignored. And all bookkeeping information is zeroed out
2959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  upon a detected overwrite of freed heap space, thus losing the
2969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ability to ever return it from malloc again, but enabling the
2979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  application to proceed. If PROCEED_ON_ERROR is defined, the
2989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  static variable malloc_corruption_error_count is compiled in
2999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  and can be examined to see if errors have occurred. This option
3009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  generates slower code than the default abort policy.
3019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallDEBUG                    default: NOT defined
3039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The DEBUG setting is mainly intended for people trying to modify
3049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  this code or diagnose problems when porting to new platforms.
3059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  However, it may also be able to better isolate user errors than just
3069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  using runtime checks.  The assertions in the check routines spell
3079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  out in more detail the assumptions and invariants underlying the
3089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  algorithms.  The checking is fairly extensive, and will slow down
3099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  execution noticeably. Calling malloc_stats or mallinfo with DEBUG
3109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  set will attempt to check every non-mmapped allocated and free chunk
3119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  in the course of computing the summaries.
3129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallABORT_ON_ASSERT_FAILURE   default: defined as 1 (true)
3149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Debugging assertion failures can be nearly impossible if your
3159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  version of the assert macro causes malloc to be called, which will
3169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  lead to a cascade of further failures, blowing the runtime stack.
3179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),
3189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  which will usually make debugging easier.
3199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallMALLOC_FAILURE_ACTION     default: sets errno to ENOMEM, or no-op on win32
3219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The action to take before "return 0" when malloc fails to be able to
3229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return memory because there is none available.
3239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallHAVE_MORECORE             default: 1 (true) unless win32 or ONLY_MSPACES
3259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  True if this system supports sbrk or an emulation of it.
3269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallMORECORE                  default: sbrk
3289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The name of the sbrk-style system routine to call to obtain more
3299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  memory.  See below for guidance on writing custom MORECORE
3309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  functions. The type of the argument to sbrk/MORECORE varies across
3319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  systems.  It cannot be size_t, because it supports negative
3329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  arguments, so it is normally the signed type of the same width as
3339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t (sometimes declared as "intptr_t").  It doesn't much matter
3349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  though. Internally, we only call it with arguments less than half
3359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the max value of a size_t, which should work across all reasonable
3369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  possibilities, although sometimes generating compiler warnings.  See
3379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  near the end of this file for guidelines for creating a custom
3389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  version of MORECORE.
3399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallMORECORE_CONTIGUOUS       default: 1 (true)
3419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If true, take advantage of fact that consecutive calls to MORECORE
3429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  with positive arguments always return contiguous increasing
3439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  addresses.  This is true of unix sbrk. It does not hurt too much to
3449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  set it true anyway, since malloc copes with non-contiguities.
3459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Setting it false when definitely non-contiguous saves time
3469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  and possibly wasted space it would take to discover this though.
3479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallMORECORE_CANNOT_TRIM      default: NOT defined
3499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  True if MORECORE cannot release space back to the system when given
3509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  negative arguments. This is generally necessary only if you are
3519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  using a hand-crafted MORECORE function that cannot handle negative
3529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  arguments.
3539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallHAVE_MMAP                 default: 1 (true)
3559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  True if this system supports mmap or an emulation of it.  If so, and
3569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  HAVE_MORECORE is not true, MMAP is used for all system
3579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  allocation. If set and HAVE_MORECORE is true as well, MMAP is
3589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  primarily used to directly allocate very large blocks. It is also
3599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  used as a backup strategy in cases where MORECORE fails to provide
3609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  space from system. Note: A single call to MUNMAP is assumed to be
3619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  able to unmap memory that may have be allocated using multiple calls
3629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  to MMAP, so long as they are adjacent.
3639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallHAVE_MREMAP               default: 1 on linux, else 0
3659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If true realloc() uses mremap() to re-allocate large blocks and
3669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  extend or shrink allocation spaces.
3679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallMMAP_CLEARS               default: 1 on unix
3699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  True if mmap clears memory so calloc doesn't need to. This is true
3709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  for standard unix mmap using /dev/zero.
3719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallUSE_BUILTIN_FFS            default: 0 (i.e., not used)
3739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Causes malloc to use the builtin ffs() function to compute indices.
3749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Some compilers may recognize and intrinsify ffs to be faster than the
3759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  supplied C version. Also, the case of x86 using gcc is special-cased
3769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  to an asm instruction, so is already as fast as it can be, and so
3779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  this setting has no effect. (On most x86s, the asm version is only
3789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  slightly faster than the C version.)
3799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallmalloc_getpagesize         default: derive from system includes, or 4096.
3819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The system page size. To the extent possible, this malloc manages
3829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  memory from the system in page-size units.  This may be (and
3839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  usually is) a function rather than a constant. This is ignored
3849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if WIN32, where page size is determined using getSystemInfo during
3859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  initialization.
3869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallUSE_DEV_RANDOM             default: 0 (i.e., not used)
3889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Causes malloc to use /dev/random to initialize secure magic seed for
3899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  stamping footers. Otherwise, the current time is used.
3909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallNO_MALLINFO                default: 0
3929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If defined, don't compile "mallinfo". This can be a simple way
3939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  of dealing with mismatches between system declarations and
3949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  those in this file.
3959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallMALLINFO_FIELD_TYPE        default: size_t
3979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The type of the fields in the mallinfo struct. This was originally
3989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  defined as "int" in SVID etc, but is more usefully defined as
3999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t. The value is used only if  HAVE_USR_INCLUDE_MALLOC_H is not set
4009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallREALLOC_ZERO_BYTES_FREES    default: not defined
4029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  This should be set if a call to realloc with zero bytes should
4039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  be the same as a call to free. Some people think it should. Otherwise,
4049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  since this malloc returns a unique pointer for malloc(0), so does
4059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  realloc(p, 0).
4069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallLACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H
4089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallLACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H,  LACKS_ERRNO_H
4099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallLACKS_STDLIB_H                default: NOT defined unless on WIN32
4109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Define these if your system does not have these header files.
4119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  You might need to manually insert some of the declarations they provide.
4129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallDEFAULT_GRANULARITY        default: page size if MORECORE_CONTIGUOUS,
4149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                system_info.dwAllocationGranularity in WIN32,
4159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                otherwise 64K.
4169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      Also settable using mallopt(M_GRANULARITY, x)
4179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The unit for allocating and deallocating memory from the system.  On
4189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  most systems with contiguous MORECORE, there is no reason to
4199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  make this more than a page. However, systems with MMAP tend to
4209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  either require or encourage larger granularities.  You can increase
4219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  this value to prevent system allocation functions to be called so
4229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  often, especially if they are slow.  The value must be at least one
4239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  page and must be a power of two.  Setting to 0 causes initialization
4249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  to either page size or win32 region size.  (Note: In previous
4259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  versions of malloc, the equivalent of this option was called
4269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  "TOP_PAD")
4279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallDEFAULT_TRIM_THRESHOLD    default: 2MB
4299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      Also settable using mallopt(M_TRIM_THRESHOLD, x)
4309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The maximum amount of unused top-most memory to keep before
4319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  releasing via malloc_trim in free().  Automatic trimming is mainly
4329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  useful in long-lived programs using contiguous MORECORE.  Because
4339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  trimming via sbrk can be slow on some systems, and can sometimes be
4349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  wasteful (in cases where programs immediately afterward allocate
4359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  more large chunks) the value should be high enough so that your
4369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  overall system performance would improve by releasing this much
4379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  memory.  As a rough guide, you might set to a value close to the
4389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  average size of a process (program) running on your system.
4399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Releasing this much memory would allow such a process to run in
4409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  memory.  Generally, it is worth tuning trim thresholds when a
4419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  program undergoes phases where several large chunks are allocated
4429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  and released in ways that can reuse each other's storage, perhaps
4439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mixed with phases where there are no such chunks at all. The trim
4449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  value must be greater than page size to have any useful effect.  To
4459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  disable trimming completely, you can set to MAX_SIZE_T. Note that the trick
4469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  some people use of mallocing a huge space and then freeing it at
4479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  program startup, in an attempt to reserve system memory, doesn't
4489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  have the intended effect under automatic trimming, since that memory
4499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  will immediately be returned to the system.
4509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallDEFAULT_MMAP_THRESHOLD       default: 256K
4529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      Also settable using mallopt(M_MMAP_THRESHOLD, x)
4539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The request size threshold for using MMAP to directly service a
4549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  request. Requests of at least this size that cannot be allocated
4559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  using already-existing space will be serviced via mmap.  (If enough
4569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  normal freed space already exists it is used instead.)  Using mmap
4579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  segregates relatively large chunks of memory so that they can be
4589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  individually obtained and released from the host system. A request
4599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  serviced through mmap is never reused by any other request (at least
4609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  not directly; the system may just so happen to remap successive
4619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  requests to the same locations).  Segregating space in this way has
4629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the benefits that: Mmapped space can always be individually released
4639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  back to the system, which helps keep the system level memory demands
4649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  of a long-lived program low.  Also, mapped memory doesn't become
4659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  `locked' between other chunks, as can happen with normally allocated
4669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  chunks, which means that even trimming via malloc_trim would not
4679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  release them.  However, it has the disadvantage that the space
4689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  cannot be reclaimed, consolidated, and then used to service later
4699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  requests, as happens with normal chunks.  The advantages of mmap
4709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  nearly always outweigh disadvantages for "large" chunks, but the
4719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  value of "large" may vary across systems.  The default is an
4729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  empirically derived value that works well in most systems. You can
4739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  disable mmap by setting to MAX_SIZE_T.
4749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
4769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef WIN32
4789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef _WIN32
4799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define WIN32 1
4809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* _WIN32 */
4819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* WIN32 */
4829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef WIN32
4839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define WIN32_LEAN_AND_MEAN
4849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <windows.h>
4859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define HAVE_MMAP 1
4869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define HAVE_MORECORE 0
4879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_UNISTD_H
4889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_SYS_PARAM_H
4899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_SYS_MMAN_H
4909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_STRING_H
4919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_STRINGS_H
4929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_SYS_TYPES_H
4939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_ERRNO_H
4949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LACKS_FCNTL_H
4959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MALLOC_FAILURE_ACTION
4969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */
4979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* WIN32 */
4989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if defined(DARWIN) || defined(_DARWIN)
5009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
5019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef HAVE_MORECORE
5029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define HAVE_MORECORE 0
5039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define HAVE_MMAP 1
5049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* HAVE_MORECORE */
5059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* DARWIN */
5069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LACKS_SYS_TYPES_H
5089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <sys/types.h>  /* For size_t */
5099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* LACKS_SYS_TYPES_H */
5109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* The maximum possible size_t value has all bits set */
5129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MAX_SIZE_T           (~(size_t)0)
5139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef ONLY_MSPACES
5159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ONLY_MSPACES 0
5169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* ONLY_MSPACES */
5179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef MSPACES
5189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if ONLY_MSPACES
5199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MSPACES 1
5209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else   /* ONLY_MSPACES */
5219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MSPACES 0
5229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* ONLY_MSPACES */
5239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* MSPACES */
5249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef MALLOC_ALIGNMENT
5259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MALLOC_ALIGNMENT ((size_t)8U)
5269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* MALLOC_ALIGNMENT */
5279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef FOOTERS
5289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define FOOTERS 0
5299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* FOOTERS */
5309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef ABORT
5319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ABORT  abort()
5329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* ABORT */
5339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef ABORT_ON_ASSERT_FAILURE
5349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ABORT_ON_ASSERT_FAILURE 1
5359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* ABORT_ON_ASSERT_FAILURE */
5369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef PROCEED_ON_ERROR
5379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define PROCEED_ON_ERROR 0
5389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* PROCEED_ON_ERROR */
5399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef USE_LOCKS
5409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define USE_LOCKS 0
5419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* USE_LOCKS */
5429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef INSECURE
5439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define INSECURE 0
5449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* INSECURE */
5459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef HAVE_MMAP
5469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define HAVE_MMAP 1
5479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* HAVE_MMAP */
5489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef MMAP_CLEARS
5499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MMAP_CLEARS 1
5509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* MMAP_CLEARS */
5519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef HAVE_MREMAP
5529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef linux
5539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define HAVE_MREMAP 1
5549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else   /* linux */
5559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define HAVE_MREMAP 0
5569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* linux */
5579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* HAVE_MREMAP */
5589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef MALLOC_FAILURE_ACTION
5599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MALLOC_FAILURE_ACTION  errno = ENOMEM;
5609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* MALLOC_FAILURE_ACTION */
5619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef HAVE_MORECORE
5629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if ONLY_MSPACES
5639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define HAVE_MORECORE 0
5649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else   /* ONLY_MSPACES */
5659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define HAVE_MORECORE 1
5669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* ONLY_MSPACES */
5679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* HAVE_MORECORE */
5689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !HAVE_MORECORE
5699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MORECORE_CONTIGUOUS 0
5709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else   /* !HAVE_MORECORE */
5719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef MORECORE
5729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MORECORE sbrk
5739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* MORECORE */
5749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef MORECORE_CONTIGUOUS
5759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MORECORE_CONTIGUOUS 1
5769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* MORECORE_CONTIGUOUS */
5779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* HAVE_MORECORE */
5789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef DEFAULT_GRANULARITY
5799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if MORECORE_CONTIGUOUS
5809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define DEFAULT_GRANULARITY (0)  /* 0 means to compute in init_mparams */
5819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else   /* MORECORE_CONTIGUOUS */
5829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
5839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* MORECORE_CONTIGUOUS */
5849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* DEFAULT_GRANULARITY */
5859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef DEFAULT_TRIM_THRESHOLD
5869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef MORECORE_CANNOT_TRIM
5879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
5889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else   /* MORECORE_CANNOT_TRIM */
5899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
5909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* MORECORE_CANNOT_TRIM */
5919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* DEFAULT_TRIM_THRESHOLD */
5929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef DEFAULT_MMAP_THRESHOLD
5939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if HAVE_MMAP
5949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
5959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else   /* HAVE_MMAP */
5969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
5979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* HAVE_MMAP */
5989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* DEFAULT_MMAP_THRESHOLD */
5999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef USE_BUILTIN_FFS
6009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define USE_BUILTIN_FFS 0
6019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* USE_BUILTIN_FFS */
6029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef USE_DEV_RANDOM
6039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define USE_DEV_RANDOM 0
6049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* USE_DEV_RANDOM */
6059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef NO_MALLINFO
6069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define NO_MALLINFO 0
6079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* NO_MALLINFO */
6089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef MALLINFO_FIELD_TYPE
6099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MALLINFO_FIELD_TYPE size_t
6109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* MALLINFO_FIELD_TYPE */
6119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define memset	SDL_memset
6139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define memcpy	SDL_memcpy
6149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define malloc	SDL_malloc
6159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define calloc	SDL_calloc
6169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define realloc	SDL_realloc
6179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define free	SDL_free
6189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
6209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mallopt tuning options.  SVID/XPG defines four standard parameter
6219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  numbers for mallopt, normally defined in malloc.h.  None of these
6229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  are used in this malloc, so setting them has no effect. But this
6239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc does support the following options.
6249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
6259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define M_TRIM_THRESHOLD     (-1)
6279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define M_GRANULARITY        (-2)
6289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define M_MMAP_THRESHOLD     (-3)
6299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ------------------------ Mallinfo declarations ------------------------ */
6319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !NO_MALLINFO
6339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
6349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  This version of malloc supports the standard SVID/XPG mallinfo
6359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  routine that returns a struct containing usage properties and
6369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  statistics. It should work on any system that has a
6379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /usr/include/malloc.h defining struct mallinfo.  The main
6389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  declaration needed is the mallinfo struct that is returned (by-copy)
6399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  by mallinfo().  The malloinfo struct contains a bunch of fields that
6409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  are not even meaningful in this version of malloc.  These fields are
6419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  are instead filled by mallinfo() with other numbers that might be of
6429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  interest.
6439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
6459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /usr/include/malloc.h file that includes a declaration of struct
6469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mallinfo.  If so, it is included; else a compliant version is
6479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  declared below.  These must be precisely the same for mallinfo() to
6489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  work.  The original SVID version of this struct, defined on most
6499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  systems with mallinfo, declares all fields as ints. But some others
6509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  define as unsigned long. If your system defines the fields using a
6519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  type of different width than listed here, you MUST #include your
6529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  system version and #define HAVE_USR_INCLUDE_MALLOC_H.
6539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
6549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* #define HAVE_USR_INCLUDE_MALLOC_H */
6569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef HAVE_USR_INCLUDE_MALLOC_H
6589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "/usr/include/malloc.h"
6599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* HAVE_USR_INCLUDE_MALLOC_H */
6609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct mallinfo {
6629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MALLINFO_FIELD_TYPE arena;    /* non-mmapped space allocated from system */
6639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MALLINFO_FIELD_TYPE ordblks;  /* number of free chunks */
6649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MALLINFO_FIELD_TYPE smblks;   /* always 0 */
6659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MALLINFO_FIELD_TYPE hblks;    /* always 0 */
6669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MALLINFO_FIELD_TYPE hblkhd;   /* space in mmapped regions */
6679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MALLINFO_FIELD_TYPE usmblks;  /* maximum total allocated space */
6689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MALLINFO_FIELD_TYPE fsmblks;  /* always 0 */
6699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
6709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MALLINFO_FIELD_TYPE fordblks; /* total free space */
6719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
6729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
6739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* HAVE_USR_INCLUDE_MALLOC_H */
6759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* NO_MALLINFO */
6769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef __cplusplus
6789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallextern "C" {
6799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* __cplusplus */
6809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !ONLY_MSPACES
6829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ------------------- Declarations of public routines ------------------- */
6849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef USE_DL_PREFIX
6869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlcalloc               calloc
6879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlfree                 free
6889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlmalloc               malloc
6899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlmemalign             memalign
6909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlrealloc              realloc
6919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlvalloc               valloc
6929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlpvalloc              pvalloc
6939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlmallinfo             mallinfo
6949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlmallopt              mallopt
6959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlmalloc_trim          malloc_trim
6969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlmalloc_stats         malloc_stats
6979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlmalloc_usable_size   malloc_usable_size
6989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlmalloc_footprint     malloc_footprint
6999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlmalloc_max_footprint malloc_max_footprint
7009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlindependent_calloc   independent_calloc
7019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dlindependent_comalloc independent_comalloc
7029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* USE_DL_PREFIX */
7039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
7069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc(size_t n)
7079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Returns a pointer to a newly allocated chunk of at least n bytes, or
7089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  null if no space is available, in which case errno is set to ENOMEM
7099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  on ANSI C systems.
7109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If n is zero, malloc returns a minimum-sized chunk. (The minimum
7129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
7139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  systems.)  Note that size_t is an unsigned type, so calls with
7149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  arguments that would be negative if signed are interpreted as
7159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  requests for huge amounts of space, which will often fail. The
7169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  maximum supported value of n differs across systems, but is in all
7179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  cases less than the maximum representable value of a size_t.
7189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
7199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* dlmalloc(size_t);
7209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
7229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  free(void* p)
7239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Releases the chunk of memory pointed to by p, that had been previously
7249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  allocated using malloc or a related routine such as realloc.
7259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  It has no effect if p is null. If p was not malloced or already
7269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  freed, free(p) will by default cause the current program to abort.
7279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
7289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid  dlfree(void*);
7299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
7319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  calloc(size_t n_elements, size_t element_size);
7329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Returns a pointer to n_elements * element_size bytes, with all locations
7339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  set to zero.
7349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
7359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* dlcalloc(size_t, size_t);
7369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
7389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  realloc(void* p, size_t n)
7399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Returns a pointer to a chunk of size n that contains the same data
7409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  as does chunk p up to the minimum of (n, p's size) bytes, or null
7419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if no space is available.
7429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The returned pointer may or may not be the same as p. The algorithm
7449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  prefers extending p in most cases when possible, otherwise it
7459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  employs the equivalent of a malloc-copy-free sequence.
7469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If p is null, realloc is equivalent to malloc.
7489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If space is not available, realloc returns null, errno is set (if on
7509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ANSI) and p is NOT freed.
7519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if n is for fewer bytes than already held by p, the newly unused
7539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  space is lopped off and freed if possible.  realloc with a size
7549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  argument of zero (re)allocates a minimum-sized chunk.
7559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The old unix realloc convention of allowing the last-free'd chunk
7579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  to be used as an argument to realloc is not supported.
7589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
7599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* dlrealloc(void*, size_t);
7619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
7639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  memalign(size_t alignment, size_t n);
7649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Returns a pointer to a newly allocated chunk of n bytes, aligned
7659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  in accord with the alignment argument.
7669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The alignment argument should be a power of two. If the argument is
7689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  not a power of two, the nearest greater power is used.
7699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  8-byte alignment is guaranteed by normal malloc calls, so don't
7709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bother calling memalign with an argument of 8 or less.
7719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Overreliance on memalign is a sure way to fragment space.
7739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
7749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* dlmemalign(size_t, size_t);
7759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
7779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  valloc(size_t n);
7789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Equivalent to memalign(pagesize, n), where pagesize is the page
7799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size of the system. If the pagesize is unknown, 4096 is used.
7809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
7819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* dlvalloc(size_t);
7829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
7849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mallopt(int parameter_number, int parameter_value)
7859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Sets tunable parameters The format is to provide a
7869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (parameter-number, parameter-value) pair.  mallopt then sets the
7879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  corresponding parameter to the argument value if it can (i.e., so
7889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  long as the value is meaningful), and returns 1 if successful else
7899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  0.  SVID/XPG/ANSI defines four standard param numbers for mallopt,
7909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  normally defined in malloc.h.  None of these are use in this malloc,
7919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  so setting them has no effect. But this malloc also supports other
7929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  options in mallopt. See below for details.  Briefly, supported
7939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  parameters are as follows (listed defaults are for "typical"
7949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  configurations).
7959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Symbol            param #  default    allowed param values
7979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  M_TRIM_THRESHOLD     -1   2*1024*1024   any   (MAX_SIZE_T disables)
7989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  M_GRANULARITY        -2     page size   any power of 2 >= page size
7999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  M_MMAP_THRESHOLD     -3      256*1024   any   (or 0 if no MMAP support)
8009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
8019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint dlmallopt(int, int);
8029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
8049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc_footprint();
8059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Returns the number of bytes obtained from the system.  The total
8069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  number of bytes allocated by malloc, realloc etc., is less than this
8079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  value. Unlike mallinfo, this function returns only a precomputed
8089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  result, so can be called frequently to monitor memory consumption.
8099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Even if locks are otherwise defined, this function does not use them,
8109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  so results might not be up to date.
8119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
8129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t dlmalloc_footprint(void);
8139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
8159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc_max_footprint();
8169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Returns the maximum number of bytes obtained from the system. This
8179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  value will be greater than current footprint if deallocated space
8189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  has been reclaimed by the system. The peak number of bytes allocated
8199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  by malloc, realloc etc., is less than this value. Unlike mallinfo,
8209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  this function returns only a precomputed result, so can be called
8219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  frequently to monitor memory consumption.  Even if locks are
8229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  otherwise defined, this function does not use them, so results might
8239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  not be up to date.
8249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
8259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t dlmalloc_max_footprint(void);
8269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !NO_MALLINFO
8289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
8299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mallinfo()
8309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Returns (by copy) a struct containing various summary statistics:
8319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  arena:     current total non-mmapped bytes allocated from system
8339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ordblks:   the number of free chunks
8349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  smblks:    always zero.
8359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  hblks:     current number of mmapped regions
8369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  hblkhd:    total bytes held in mmapped regions
8379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  usmblks:   the maximum total allocated space. This will be greater
8389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                than current total if trimming has occurred.
8399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  fsmblks:   always zero
8409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  uordblks:  current total allocated space (normal or mmapped)
8419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  fordblks:  total free space
8429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  keepcost:  the maximum number of bytes that could ideally be released
8439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall               back to system via malloc_trim. ("ideally" means that
8449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall               it ignores page restrictions etc.)
8459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Because these fields are ints, but internal bookkeeping may
8479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  be kept as longs, the reported values may wrap around zero and
8489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  thus be inaccurate.
8499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
8509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct mallinfo dlmallinfo(void);
8519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* NO_MALLINFO */
8529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
8549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
8559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  independent_calloc is similar to calloc, but instead of returning a
8579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  single cleared space, it returns an array of pointers to n_elements
8589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  independent elements that can hold contents of size elem_size, each
8599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  of which starts out cleared, and can be independently freed,
8609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  realloc'ed etc. The elements are guaranteed to be adjacently
8619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  allocated (this is not guaranteed to occur with multiple callocs or
8629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mallocs), which may also improve cache locality in some
8639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  applications.
8649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The "chunks" argument is optional (i.e., may be null, which is
8669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  probably the most typical usage). If it is null, the returned array
8679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  is itself dynamically allocated and should also be freed when it is
8689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  no longer needed. Otherwise, the chunks array must be of at least
8699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  n_elements in length. It is filled in with the pointers to the
8709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  chunks.
8719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  In either case, independent_calloc returns this pointer array, or
8739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  null if the allocation failed.  If n_elements is zero and "chunks"
8749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  is null, it returns a chunk representing an array with zero elements
8759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (which should be freed if not wanted).
8769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Each element must be individually freed when it is no longer
8789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  needed. If you'd like to instead be able to free all at once, you
8799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  should instead use regular calloc and assign pointers into this
8809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  space to represent elements.  (In this case though, you cannot
8819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  independently free elements.)
8829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  independent_calloc simplifies and speeds up implementations of many
8849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  kinds of pools.  It may also be useful when constructing large data
8859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  structures that initially have a fixed number of fixed-sized nodes,
8869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  but the number is not known at compile time, and some of the nodes
8879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  may later need to be freed. For example:
8889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct Node { int item; struct Node* next; };
8909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct Node* build_list() {
8929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    struct Node** pool;
8939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int n = read_number_of_nodes_needed();
8949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (n <= 0) return 0;
8959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
8969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (pool == 0) die();
8979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // organize into a linked list...
8989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    struct Node* first = pool[0];
8999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (i = 0; i < n-1; ++i)
9009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      pool[i]->next = pool[i+1];
9019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    free(pool);     // Can now free the array (or not, if it is needed later)
9029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return first;
9039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
9049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
9059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid** dlindependent_calloc(size_t, size_t, void**);
9069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
9089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
9099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  independent_comalloc allocates, all at once, a set of n_elements
9119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  chunks with sizes indicated in the "sizes" array.    It returns
9129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  an array of pointers to these elements, each of which can be
9139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  independently freed, realloc'ed etc. The elements are guaranteed to
9149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  be adjacently allocated (this is not guaranteed to occur with
9159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  multiple callocs or mallocs), which may also improve cache locality
9169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  in some applications.
9179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The "chunks" argument is optional (i.e., may be null). If it is null
9199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the returned array is itself dynamically allocated and should also
9209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  be freed when it is no longer needed. Otherwise, the chunks array
9219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  must be of at least n_elements in length. It is filled in with the
9229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  pointers to the chunks.
9239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  In either case, independent_comalloc returns this pointer array, or
9259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  null if the allocation failed.  If n_elements is zero and chunks is
9269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  null, it returns a chunk representing an array with zero elements
9279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (which should be freed if not wanted).
9289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Each element must be individually freed when it is no longer
9309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  needed. If you'd like to instead be able to free all at once, you
9319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  should instead use a single regular malloc, and assign pointers at
9329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  particular offsets in the aggregate space. (In this case though, you
9339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  cannot independently free elements.)
9349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  independent_comallac differs from independent_calloc in that each
9369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  element may have a different size, and also that it does not
9379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  automatically clear elements.
9389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  independent_comalloc can be used to speed up allocation in cases
9409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  where several structs or objects must always be allocated at the
9419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  same time.  For example:
9429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct Head { ... }
9449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct Foot { ... }
9459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  void send_message(char* msg) {
9479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int msglen = strlen(msg);
9489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
9499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    void* chunks[3];
9509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (independent_comalloc(3, sizes, chunks) == 0)
9519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      die();
9529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    struct Head* head = (struct Head*)(chunks[0]);
9539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    char*        body = (char*)(chunks[1]);
9549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    struct Foot* foot = (struct Foot*)(chunks[2]);
9559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // ...
9569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
9579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  In general though, independent_comalloc is worth using only for
9599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  larger values of n_elements. For small values, you probably won't
9609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  detect enough difference from series of malloc calls to bother.
9619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Overuse of independent_comalloc can increase overall memory usage,
9639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  since it cannot reuse existing noncontiguous small chunks that
9649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  might be available for some of the elements.
9659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
9669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid** dlindependent_comalloc(size_t, size_t*, void**);
9679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
9709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  pvalloc(size_t n);
9719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Equivalent to valloc(minimum-page-that-holds(n)), that is,
9729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  round up n to nearest pagesize.
9739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
9749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid*  dlpvalloc(size_t);
9759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
9779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc_trim(size_t pad);
9789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If possible, gives memory back to the system (via negative arguments
9809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  to sbrk) if there is unused memory at the `high' end of the malloc
9819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  pool or in unused MMAP segments. You can call this after freeing
9829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  large blocks of memory to potentially reduce the system-level memory
9839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  requirements of a program. However, it cannot guarantee to reduce
9849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  memory. Under some allocation patterns, some large free blocks of
9859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  memory will be locked between two used chunks, so they cannot be
9869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  given back to the system.
9879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The `pad' argument to malloc_trim represents the amount of free
9899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  trailing space to leave untrimmed. If this argument is zero, only
9909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the minimum amount of memory to maintain internal data structures
9919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  will be left. Non-zero arguments can be supplied to maintain enough
9929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  trailing space to service future expected allocations without having
9939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  to re-obtain memory from the system.
9949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Malloc_trim returns 1 if it actually released any memory, else 0.
9969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
9979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint  dlmalloc_trim(size_t);
9989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
10009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc_usable_size(void* p);
10019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Returns the number of bytes you can actually use in
10039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  an allocated chunk, which may be more than you requested (although
10049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  often not) due to alignment and minimum size constraints.
10059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  You can use this many bytes without worrying about
10069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  overwriting other allocated objects. This is not a particularly great
10079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  programming practice. malloc_usable_size can be more useful in
10089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  debugging and assertions, for example:
10099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  p = malloc(n);
10119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(malloc_usable_size(p) >= 256);
10129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
10139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t dlmalloc_usable_size(void*);
10149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
10169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc_stats();
10179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Prints on stderr the amount of space obtained from the system (both
10189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  via sbrk and mmap), the maximum amount (which may be more than
10199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  current if malloc_trim and/or munmap got called), and the current
10209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  number of bytes allocated via malloc (or realloc, etc) but not yet
10219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  freed. Note that this is the number of bytes allocated, not the
10229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  number requested. It will be larger than the number requested
10239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  because of alignment and bookkeeping overhead. Because it includes
10249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  alignment wastage as being in use, this figure may be greater than
10259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  zero even when no user-level chunks are allocated.
10269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The reported current and maximum system memory can be inaccurate if
10289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  a program makes other calls to system memory allocation functions
10299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (normally sbrk) outside of malloc.
10309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc_stats prints only the most commonly interesting statistics.
10329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  More information can be obtained by calling mallinfo.
10339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
10349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid  dlmalloc_stats(void);
10359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* ONLY_MSPACES */
10379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if MSPACES
10399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
10419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace is an opaque type representing an independent
10429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  region of space that supports mspace_malloc, etc.
10439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
10449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef void* mspace;
10459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
10479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  create_mspace creates and returns a new independent space with the
10489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  given initial capacity, or, if 0, the default granularity size.  It
10499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  returns null if there is no system memory available to create the
10509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  space.  If argument locked is non-zero, the space uses a separate
10519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  lock to control access. The capacity of the space will grow
10529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  dynamically as needed to service mspace_malloc requests.  You can
10539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  control the sizes of incremental increases of this space by
10549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  compiling with a different DEFAULT_GRANULARITY or dynamically
10559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  setting with mallopt(M_GRANULARITY, value).
10569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
10579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallmspace create_mspace(size_t capacity, int locked);
10589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
10609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  destroy_mspace destroys the given space, and attempts to return all
10619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  of its memory back to the system, returning the total number of
10629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bytes freed. After destruction, the results of access to all memory
10639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  used by the space become undefined.
10649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
10659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t destroy_mspace(mspace msp);
10669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
10689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  create_mspace_with_base uses the memory supplied as the initial base
10699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
10709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  space is used for bookkeeping, so the capacity must be at least this
10719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  large. (Otherwise 0 is returned.) When this initial space is
10729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  exhausted, additional memory will be obtained from the system.
10739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Destroying this space will deallocate all additionally allocated
10749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  space (if possible) but not the initial base.
10759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
10769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallmspace create_mspace_with_base(void* base, size_t capacity, int locked);
10779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
10799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_malloc behaves as malloc, but operates within
10809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the given space.
10819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
10829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* mspace_malloc(mspace msp, size_t bytes);
10839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
10859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_free behaves as free, but operates within
10869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the given space.
10879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If compiled with FOOTERS==1, mspace_free is not actually needed.
10899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  free may be called instead of mspace_free because freed chunks from
10909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  any space are handled by their originating spaces.
10919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
10929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid mspace_free(mspace msp, void* mem);
10939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
10959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_realloc behaves as realloc, but operates within
10969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the given space.
10979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If compiled with FOOTERS==1, mspace_realloc is not actually
10999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  needed.  realloc may be called instead of mspace_realloc because
11009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  realloced chunks from any space are handled by their originating
11019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  spaces.
11029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* mspace_realloc(mspace msp, void* mem, size_t newsize);
11049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
11069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_calloc behaves as calloc, but operates within
11079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the given space.
11089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
11109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
11129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_memalign behaves as memalign, but operates within
11139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the given space.
11149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
11169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
11189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_independent_calloc behaves as independent_calloc, but
11199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  operates within the given space.
11209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid** mspace_independent_calloc(mspace msp, size_t n_elements,
11229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                 size_t elem_size, void* chunks[]);
11239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
11259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_independent_comalloc behaves as independent_comalloc, but
11269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  operates within the given space.
11279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid** mspace_independent_comalloc(mspace msp, size_t n_elements,
11299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                   size_t sizes[], void* chunks[]);
11309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
11329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_footprint() returns the number of bytes obtained from the
11339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  system for this space.
11349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t mspace_footprint(mspace msp);
11369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
11389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_max_footprint() returns the peak number of bytes obtained from the
11399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  system for this space.
11409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t mspace_max_footprint(mspace msp);
11429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !NO_MALLINFO
11459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
11469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_mallinfo behaves as mallinfo, but reports properties of
11479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the given space.
11489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct mallinfo mspace_mallinfo(mspace msp);
11509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* NO_MALLINFO */
11519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
11539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_malloc_stats behaves as malloc_stats, but reports
11549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  properties of the given space.
11559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid mspace_malloc_stats(mspace msp);
11579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
11599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace_trim behaves as malloc_trim, but
11609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  operates within the given space.
11619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint mspace_trim(mspace msp, size_t pad);
11639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
11659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  An alias for mallopt.
11669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint mspace_mallopt(int, int);
11689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* MSPACES */
11709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef __cplusplus
11729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};  /* end of extern "C" */
11739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* __cplusplus */
11749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
11769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ========================================================================
11779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  To make a fully customizable malloc.h header file, cut everything
11789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  above this line, put into file malloc.h, edit to suit, and #include it
11799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  on the next line, as well as in programs that use this malloc.
11809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ========================================================================
11819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
11829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* #include "malloc.h" */
11849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*------------------------------ internal #includes ---------------------- */
11869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef _MSC_VER
11889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#pragma warning( disable : 4146 ) /* no "unsigned" warnings */
11899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* _MSC_VER */
11909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LACKS_STDIO_H
11929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <stdio.h>       /* for printing in malloc_stats */
11939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
11949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LACKS_ERRNO_H
11969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <errno.h>       /* for MALLOC_FAILURE_ACTION */
11979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* LACKS_ERRNO_H */
11989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if FOOTERS
11999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <time.h>        /* for magic initialization */
12009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* FOOTERS */
12019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LACKS_STDLIB_H
12029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <stdlib.h>      /* for abort() */
12039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* LACKS_STDLIB_H */
12049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef DEBUG
12059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if ABORT_ON_ASSERT_FAILURE
12069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define assert(x) if(!(x)) ABORT
12079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* ABORT_ON_ASSERT_FAILURE */
12089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <assert.h>
12099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* ABORT_ON_ASSERT_FAILURE */
12109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else  /* DEBUG */
12119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define assert(x)
12129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* DEBUG */
12139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LACKS_STRING_H
12149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <string.h>      /* for memset etc */
12159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* LACKS_STRING_H */
12169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if USE_BUILTIN_FFS
12179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LACKS_STRINGS_H
12189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <strings.h>     /* for ffs */
12199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* LACKS_STRINGS_H */
12209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* USE_BUILTIN_FFS */
12219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if HAVE_MMAP
12229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LACKS_SYS_MMAN_H
12239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <sys/mman.h>    /* for mmap */
12249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* LACKS_SYS_MMAN_H */
12259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LACKS_FCNTL_H
12269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <fcntl.h>
12279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* LACKS_FCNTL_H */
12289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* HAVE_MMAP */
12299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if HAVE_MORECORE
12309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LACKS_UNISTD_H
12319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <unistd.h>     /* for sbrk */
12329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* LACKS_UNISTD_H */
12339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
12349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallextern void*     sbrk(ptrdiff_t);
12359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* FreeBSD etc */
12369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* LACKS_UNISTD_H */
12379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* HAVE_MMAP */
12389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef WIN32
12409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef malloc_getpagesize
12419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
12429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#    ifndef _SC_PAGE_SIZE
12439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#      define _SC_PAGE_SIZE _SC_PAGESIZE
12449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#    endif
12459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#  endif
12469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#  ifdef _SC_PAGE_SIZE
12479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
12489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#  else
12499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
12509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       extern size_t getpagesize();
12519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#      define malloc_getpagesize getpagesize()
12529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#    else
12539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#      ifdef WIN32 /* use supplied emulation of getpagesize */
12549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#        define malloc_getpagesize getpagesize()
12559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#      else
12569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#        ifndef LACKS_SYS_PARAM_H
12579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#          include <sys/param.h>
12589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#        endif
12599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#        ifdef EXEC_PAGESIZE
12609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#          define malloc_getpagesize EXEC_PAGESIZE
12619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#        else
12629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#          ifdef NBPG
12639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#            ifndef CLSIZE
12649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#              define malloc_getpagesize NBPG
12659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#            else
12669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#              define malloc_getpagesize (NBPG * CLSIZE)
12679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#            endif
12689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#          else
12699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#            ifdef NBPC
12709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#              define malloc_getpagesize NBPC
12719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#            else
12729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#              ifdef PAGESIZE
12739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#                define malloc_getpagesize PAGESIZE
12749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#              else /* just guess */
12759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#                define malloc_getpagesize ((size_t)4096U)
12769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#              endif
12779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#            endif
12789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#          endif
12799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#        endif
12809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#      endif
12819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#    endif
12829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#  endif
12839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
12849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
12859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ------------------- size_t and alignment properties -------------------- */
12879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* The byte and bit size of a size_t */
12899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define SIZE_T_SIZE         (sizeof(size_t))
12909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define SIZE_T_BITSIZE      (sizeof(size_t) << 3)
12919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Some constants coerced to size_t */
12939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Annoying but necessary to avoid errors on some plaftorms */
12949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define SIZE_T_ZERO         ((size_t)0)
12959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define SIZE_T_ONE          ((size_t)1)
12969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define SIZE_T_TWO          ((size_t)2)
12979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define TWO_SIZE_T_SIZES    (SIZE_T_SIZE<<1)
12989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define FOUR_SIZE_T_SIZES   (SIZE_T_SIZE<<2)
12999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define SIX_SIZE_T_SIZES    (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
13009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define HALF_MAX_SIZE_T     (MAX_SIZE_T / 2U)
13019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* The bit mask value corresponding to MALLOC_ALIGNMENT */
13039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CHUNK_ALIGN_MASK    (MALLOC_ALIGNMENT - SIZE_T_ONE)
13049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* True if address a has acceptable alignment */
13069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define is_aligned(A)       (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
13079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* the number of bytes to offset an address to align it */
13099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define align_offset(A)\
13109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
13119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
13129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -------------------------- MMAP preliminaries ------------------------- */
13149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
13169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
13179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   checks to fail so compiler optimizer can delete code rather than
13189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   using so many "#if"s.
13199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
13209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* MORECORE and MMAP must return MFAIL on failure */
13239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MFAIL                ((void*)(MAX_SIZE_T))
13249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CMFAIL               ((char*)(MFAIL)) /* defined for convenience */
13259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !HAVE_MMAP
13279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define IS_MMAPPED_BIT       (SIZE_T_ZERO)
13289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define USE_MMAP_BIT         (SIZE_T_ZERO)
13299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CALL_MMAP(s)         MFAIL
13309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CALL_MUNMAP(a, s)    (-1)
13319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define DIRECT_MMAP(s)       MFAIL
13329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* HAVE_MMAP */
13349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define IS_MMAPPED_BIT       (SIZE_T_ONE)
13359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define USE_MMAP_BIT         (SIZE_T_ONE)
13369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef WIN32
13389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CALL_MUNMAP(a, s)    munmap((a), (s))
13399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MMAP_PROT            (PROT_READ|PROT_WRITE)
13409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
13419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MAP_ANONYMOUS        MAP_ANON
13429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* MAP_ANON */
13439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef MAP_ANONYMOUS
13449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MMAP_FLAGS           (MAP_PRIVATE|MAP_ANONYMOUS)
13459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CALL_MMAP(s)         mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
13469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* MAP_ANONYMOUS */
13479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
13489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   Nearly all versions of mmap support MAP_ANONYMOUS, so the following
13499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   is unlikely to be needed, but is supplied just in case.
13509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
13519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MMAP_FLAGS           (MAP_PRIVATE)
13529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
13539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
13549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           (dev_zero_fd = open("/dev/zero", O_RDWR), \
13559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
13569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
13579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* MAP_ANONYMOUS */
13589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define DIRECT_MMAP(s)       CALL_MMAP(s)
13609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* WIN32 */
13619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Win32 MMAP via VirtualAlloc */
13639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void* win32mmap(size_t size) {
13649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
13659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return (ptr != 0)? ptr: MFAIL;
13669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
13679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
13699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void* win32direct_mmap(size_t size) {
13709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
13719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                           PAGE_READWRITE);
13729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return (ptr != 0)? ptr: MFAIL;
13739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
13749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* This function supports releasing coalesed segments */
13769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int win32munmap(void* ptr, size_t size) {
13779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MEMORY_BASIC_INFORMATION minfo;
13789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  char* cptr = ptr;
13799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  while (size) {
13809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
13819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return -1;
13829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
13839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        minfo.State != MEM_COMMIT || minfo.RegionSize > size)
13849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return -1;
13859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
13869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return -1;
13879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    cptr += minfo.RegionSize;
13889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size -= minfo.RegionSize;
13899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
13909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
13919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
13929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CALL_MMAP(s)         win32mmap(s)
13949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CALL_MUNMAP(a, s)    win32munmap((a), (s))
13959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define DIRECT_MMAP(s)       win32direct_mmap(s)
13969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* WIN32 */
13979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* HAVE_MMAP */
13989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if HAVE_MMAP && HAVE_MREMAP
14009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
14019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else  /* HAVE_MMAP && HAVE_MREMAP */
14029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
14039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* HAVE_MMAP && HAVE_MREMAP */
14049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if HAVE_MORECORE
14069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CALL_MORECORE(S)     MORECORE(S)
14079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else  /* HAVE_MORECORE */
14089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CALL_MORECORE(S)     MFAIL
14099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* HAVE_MORECORE */
14109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* mstate bit set if continguous morecore disabled or failed */
14129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define USE_NONCONTIGUOUS_BIT (4U)
14139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* segment bit set in create_mspace_with_base */
14159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define EXTERN_BIT            (8U)
14169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* --------------------------- Lock preliminaries ------------------------ */
14199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if USE_LOCKS
14219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
14239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  When locks are defined, there are up to two global locks:
14249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * If HAVE_MORECORE, morecore_mutex protects sequences of calls to
14269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    MORECORE.  In many cases sys_alloc requires two calls, that should
14279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    not be interleaved with calls by other threads.  This does not
14289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    protect against direct calls to MORECORE by other threads not
14299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    using this lock, so there is still code to cope the best we can on
14309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    interference.
14319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * magic_init_mutex ensures that mparams.magic and other
14339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    unique mparams values are initialized only once.
14349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
14359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef WIN32
14379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* By default use posix locks */
14389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <pthread.h>
14399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MLOCK_T pthread_mutex_t
14409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define INITIAL_LOCK(l)      pthread_mutex_init(l, NULL)
14419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ACQUIRE_LOCK(l)      pthread_mutex_lock(l)
14429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RELEASE_LOCK(l)      pthread_mutex_unlock(l)
14439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if HAVE_MORECORE
14459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER;
14469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* HAVE_MORECORE */
14479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER;
14499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* WIN32 */
14519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
14529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   Because lock-protected regions have bounded times, and there
14539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   are no recursive lock calls, we can use simple spinlocks.
14549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
14559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MLOCK_T long
14579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int win32_acquire_lock (MLOCK_T *sl) {
14589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  for (;;) {
14599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef InterlockedCompareExchangePointer
14609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!InterlockedCompareExchange(sl, 1, 0))
14619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return 0;
14629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else  /* Use older void* version */
14639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0))
14649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return 0;
14659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* InterlockedCompareExchangePointer */
14669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Sleep (0);
14679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
14689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
14699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void win32_release_lock (MLOCK_T *sl) {
14719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  InterlockedExchange (sl, 0);
14729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
14739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define INITIAL_LOCK(l)      *(l)=0
14759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ACQUIRE_LOCK(l)      win32_acquire_lock(l)
14769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RELEASE_LOCK(l)      win32_release_lock(l)
14779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if HAVE_MORECORE
14789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic MLOCK_T morecore_mutex;
14799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* HAVE_MORECORE */
14809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic MLOCK_T magic_init_mutex;
14819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* WIN32 */
14829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define USE_LOCK_BIT               (2U)
14849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else  /* USE_LOCKS */
14859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define USE_LOCK_BIT               (0U)
14869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define INITIAL_LOCK(l)
14879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* USE_LOCKS */
14889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if USE_LOCKS && HAVE_MORECORE
14909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ACQUIRE_MORECORE_LOCK()    ACQUIRE_LOCK(&morecore_mutex);
14919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RELEASE_MORECORE_LOCK()    RELEASE_LOCK(&morecore_mutex);
14929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* USE_LOCKS && HAVE_MORECORE */
14939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ACQUIRE_MORECORE_LOCK()
14949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RELEASE_MORECORE_LOCK()
14959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* USE_LOCKS && HAVE_MORECORE */
14969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if USE_LOCKS
14989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ACQUIRE_MAGIC_INIT_LOCK()  ACQUIRE_LOCK(&magic_init_mutex);
14999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RELEASE_MAGIC_INIT_LOCK()  RELEASE_LOCK(&magic_init_mutex);
15009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else  /* USE_LOCKS */
15019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ACQUIRE_MAGIC_INIT_LOCK()
15029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RELEASE_MAGIC_INIT_LOCK()
15039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* USE_LOCKS */
15049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -----------------------  Chunk representations ------------------------ */
15079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
15099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (The following includes lightly edited explanations by Colin Plumb.)
15109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The malloc_chunk declaration below is misleading (but accurate and
15129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  necessary).  It declares a "view" into memory allowing access to
15139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  necessary fields at known offsets from a given base.
15149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Chunks of memory are maintained using a `boundary tag' method as
15169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  originally described by Knuth.  (See the paper by Paul Wilson
15179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
15189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  techniques.)  Sizes of free chunks are stored both in the front of
15199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  each chunk and at the end.  This makes consolidating fragmented
15209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  chunks into bigger chunks fast.  The head fields also hold bits
15219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  representing whether chunks are free or in use.
15229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Here are some pictures to make it clearer.  They are "exploded" to
15249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  show that the state of a chunk can be thought of as extending from
15259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the high 31 bits of the head field of its header through the
15269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  prev_foot and PINUSE_BIT bit of the following chunk header.
15279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  A chunk that's in use looks like:
15299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           | Size of previous chunk (if P = 1)                             |
15329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
15349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         | Size of this chunk                                         1| +-+
15359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         |                                                               |
15379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         +-                                                             -+
15389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         |                                                               |
15399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         +-                                                             -+
15409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         |                                                               :
15419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         +-      size - sizeof(size_t) available payload bytes          -+
15429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         :                                                               |
15439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall chunk-> +-                                                             -+
15449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         |                                                               |
15459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
15479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       | Size of next chunk (may or may not be in use)               | +-+
15489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    And if it's free, it looks like this:
15519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   chunk-> +-                                                             -+
15539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           | User payload (must be in use, or we would have merged!)       |
15549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
15569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         | Size of this chunk                                         0| +-+
15579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         | Next pointer                                                  |
15599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         | Prev pointer                                                  |
15619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         |                                                               :
15639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         +-      size - sizeof(struct chunk) unused bytes               -+
15649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         :                                                               |
15659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         | Size of this chunk                                            |
15679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
15699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       | Size of next chunk (must be in use, or we would have merged)| +-+
15709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       |                                                               :
15729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       +- User payload                                                -+
15739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       :                                                               |
15749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                                                     |0|
15769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                                                     +-+
15779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Note that since we always merge adjacent free chunks, the chunks
15789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  adjacent to a free chunk must be in use.
15799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Given a pointer to a chunk (which can be derived trivially from the
15819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  payload pointer) we can, in O(1) time, find out whether the adjacent
15829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  chunks are free, and if so, unlink them from the lists that they
15839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  are on and merge them with the current chunk.
15849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Chunks always begin on even word boundaries, so the mem portion
15869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (which is returned to the user) is also on an even word boundary, and
15879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  thus at least double-word aligned.
15889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
15909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  chunk size (which is always a multiple of two words), is an in-use
15919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bit for the *previous* chunk.  If that bit is *clear*, then the
15929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  word before the current chunk size contains the previous chunk
15939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size, and can be used to find the front of the previous chunk.
15949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The very first chunk allocated always has this bit set, preventing
15959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  access to non-existent (or non-owned) memory. If pinuse is set for
15969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  any given chunk, then you CANNOT determine the size of the
15979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  previous chunk, and might even get a memory addressing fault when
15989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  trying to do so.
15999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
16019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the chunk size redundantly records whether the current chunk is
16029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  inuse. This redundancy enables usage checks within free and realloc,
16039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  and reduces indirection when freeing and consolidating chunks.
16049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Each freshly allocated chunk must have both cinuse and pinuse set.
16069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  That is, each allocated chunk borders either a previously allocated
16079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  and still in-use chunk, or the base of its memory arena. This is
16089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ensured by making all allocations from the the `lowest' part of any
16099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  found chunk.  Further, no free chunk physically borders another one,
16109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  so each free chunk is known to be preceded and followed by either
16119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  inuse chunks or the ends of memory.
16129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Note that the `foot' of the current chunk is actually represented
16149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  as the prev_foot of the NEXT chunk. This makes it easier to
16159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  deal with alignments etc but can be very confusing when trying
16169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  to extend or adapt this code.
16179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The exceptions to all this are
16199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     1. The special chunk `top' is the top-most available chunk (i.e.,
16219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        the one bordering the end of available memory). It is treated
16229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        specially.  Top is never included in any bin, is used only if
16239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        no other chunk is available, and is released back to the
16249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        system if it is very large (see M_TRIM_THRESHOLD).  In effect,
16259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        the top chunk is treated as larger (and thus less well
16269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        fitting) than any other available chunk.  The top chunk
16279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        doesn't update its trailing size field since there is no next
16289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        contiguous chunk that would have to index off it. However,
16299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        space is still allocated for it (TOP_FOOT_SIZE) to enable
16309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        separation or merging when space is extended.
16319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     3. Chunks allocated via mmap, which have the lowest-order bit
16339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set
16349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        PINUSE_BIT in their head fields.  Because they are allocated
16359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        one-by-one, each must carry its own prev_foot field, which is
16369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        also used to hold the offset this chunk has within its mmapped
16379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        region, which is needed to preserve alignment. Each mmapped
16389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        chunk is trailed by the first two fields of a fake next-chunk
16399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        for sake of usage checks.
16409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
16429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct malloc_chunk {
16449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t               prev_foot;  /* Size of previous chunk (if free).  */
16459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t               head;       /* Size and inuse bits. */
16469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct malloc_chunk* fd;         /* double links -- used only if free. */
16479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct malloc_chunk* bk;
16489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
16499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef struct malloc_chunk  mchunk;
16519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef struct malloc_chunk* mchunkptr;
16529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */
16539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef size_t bindex_t;               /* Described below */
16549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef unsigned int binmap_t;         /* Described below */
16559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef unsigned int flag_t;           /* The type of various bit flag sets */
16569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ------------------- Chunks sizes and alignments ----------------------- */
16589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MCHUNK_SIZE         (sizeof(mchunk))
16609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if FOOTERS
16629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CHUNK_OVERHEAD      (TWO_SIZE_T_SIZES)
16639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* FOOTERS */
16649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CHUNK_OVERHEAD      (SIZE_T_SIZE)
16659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* FOOTERS */
16669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* MMapped chunks need a second word of overhead ... */
16689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
16699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ... and additional padding for fake next-chunk at foot */
16709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MMAP_FOOT_PAD       (FOUR_SIZE_T_SIZES)
16719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* The smallest size we can malloc is an aligned minimal chunk */
16739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MIN_CHUNK_SIZE\
16749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
16759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* conversion from malloc headers to user pointers, and back */
16779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define chunk2mem(p)        ((void*)((char*)(p)       + TWO_SIZE_T_SIZES))
16789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define mem2chunk(mem)      ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
16799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* chunk associated with aligned address A */
16809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define align_as_chunk(A)   (mchunkptr)((A) + align_offset(chunk2mem(A)))
16819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Bounds on request (not chunk) sizes. */
16839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MAX_REQUEST         ((-MIN_CHUNK_SIZE) << 2)
16849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MIN_REQUEST         (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
16859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* pad request bytes into a usable size */
16879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define pad_request(req) \
16889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
16899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* pad request, checking for minimum (but not maximum) */
16919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define request2size(req) \
16929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
16939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ------------------ Operations on head and foot fields ----------------- */
16969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
16989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The head field of a chunk is or'ed with PINUSE_BIT when previous
16999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
17009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  use. If the chunk was obtained with mmap, the prev_foot field has
17019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  IS_MMAPPED_BIT set, otherwise holding the offset of the base of the
17029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mmapped region to the base of the chunk.
17039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
17049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define PINUSE_BIT          (SIZE_T_ONE)
17069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CINUSE_BIT          (SIZE_T_TWO)
17079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define INUSE_BITS          (PINUSE_BIT|CINUSE_BIT)
17089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Head value for fenceposts */
17109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define FENCEPOST_HEAD      (INUSE_BITS|SIZE_T_SIZE)
17119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* extraction of fields from head words */
17139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define cinuse(p)           ((p)->head & CINUSE_BIT)
17149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define pinuse(p)           ((p)->head & PINUSE_BIT)
17159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define chunksize(p)        ((p)->head & ~(INUSE_BITS))
17169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define clear_pinuse(p)     ((p)->head &= ~PINUSE_BIT)
17189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define clear_cinuse(p)     ((p)->head &= ~CINUSE_BIT)
17199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Treat space at ptr +/- offset as a chunk */
17219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define chunk_plus_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
17229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
17239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Ptr to next or previous physical malloc_chunk. */
17259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS)))
17269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
17279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* extract next chunk's pinuse bit */
17299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define next_pinuse(p)  ((next_chunk(p)->head) & PINUSE_BIT)
17309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Get/set size at footer */
17329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define get_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot)
17339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define set_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
17349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Set size, pinuse bit, and foot */
17369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define set_size_and_pinuse_of_free_chunk(p, s)\
17379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
17389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Set size, pinuse bit, foot, and clear next pinuse */
17409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define set_free_with_pinuse(p, s, n)\
17419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
17429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define is_mmapped(p)\
17449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT))
17459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Get the internal overhead associated with chunk p */
17479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define overhead_for(p)\
17489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
17499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Return true if malloced space is not necessarily cleared */
17519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if MMAP_CLEARS
17529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define calloc_must_clear(p) (!is_mmapped(p))
17539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* MMAP_CLEARS */
17549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define calloc_must_clear(p) (1)
17559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* MMAP_CLEARS */
17569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ---------------------- Overlaid data structures ----------------------- */
17589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
17609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  When chunks are not in use, they are treated as nodes of either
17619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  lists or trees.
17629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  "Small"  chunks are stored in circular doubly-linked lists, and look
17649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  like this:
17659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             Size of previous chunk                            |
17689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    `head:' |             Size of chunk, in bytes                         |P|
17709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             Forward pointer to next chunk in list             |
17729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             Back pointer to previous chunk in list            |
17749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             Unused space (may be 0 bytes long)                .
17769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            .                                                               .
17779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            .                                                               |
17789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallnextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    `foot:' |             Size of chunk, in bytes                           |
17809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Larger chunks are kept in a form of bitwise digital trees (aka
17839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tries) keyed on chunksizes.  Because malloc_tree_chunks are only for
17849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  free chunks greater than 256 bytes, their size doesn't impose any
17859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  constraints on user chunk sizes.  Each node looks like:
17869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
17879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             Size of previous chunk                            |
17899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    `head:' |             Size of chunk, in bytes                         |P|
17919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             Forward pointer to next chunk of same size        |
17939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             Back pointer to previous chunk of same size       |
17959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             Pointer to left child (child[0])                  |
17979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             Pointer to right child (child[1])                 |
17999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             Pointer to parent                                 |
18019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             bin index of this chunk                           |
18039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            |             Unused space                                      .
18059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            .                                                               |
18069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallnextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    `foot:' |             Size of chunk, in bytes                           |
18089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Each tree holding treenodes is a tree of unique chunk sizes.  Chunks
18119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  of the same size are arranged in a circularly-linked list, with only
18129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the oldest chunk (the next to be used, in our FIFO ordering)
18139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  actually in the tree.  (Tree members are distinguished by a non-null
18149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  parent pointer.)  If a chunk with the same size an an existing node
18159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  is inserted, it is linked off the existing node using pointers that
18169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  work in the same way as fd/bk pointers of small chunks.
18179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Each tree contains a power of 2 sized range of chunk sizes (the
18199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  smallest is 0x100 <= x < 0x180), which is is divided in half at each
18209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tree level, with the chunks in the smaller half of the range (0x100
18219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  <= x < 0x140 for the top nose) in the left subtree and the larger
18229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  half (0x140 <= x < 0x180) in the right subtree.  This is, of course,
18239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  done by inspecting individual bits.
18249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Using these rules, each node's left subtree contains all smaller
18269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  sizes than its right subtree.  However, the node at the root of each
18279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  subtree has no particular ordering relationship to either.  (The
18289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  dividing line between the subtree sizes is based on trie relation.)
18299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  If we remove the last chunk of a given size from the interior of the
18309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tree, we need to replace it with a leaf node.  The tree ordering
18319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  rules permit a node to be replaced by any leaf below it.
18329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The smallest chunk in a tree (a common operation in a best-fit
18349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  allocator) can be found by walking a path to the leftmost leaf in
18359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the tree.  Unlike a usual binary tree, where we follow left child
18369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  pointers until we reach a null, here we follow the right child
18379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  pointer any time the left one is null, until we reach a leaf with
18389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  both child pointers null. The smallest chunk in the tree will be
18399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  somewhere along that path.
18409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  The worst case number of steps to add, find, or remove a node is
18429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bounded by the number of bits differentiating chunks within
18439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bins. Under current bin calculations, this ranges from 6 up to 21
18449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
18459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  is of course much better.
18469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
18479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct malloc_tree_chunk {
18499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* The first four fields must be compatible with malloc_chunk */
18509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t                    prev_foot;
18519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t                    head;
18529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct malloc_tree_chunk* fd;
18539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct malloc_tree_chunk* bk;
18549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct malloc_tree_chunk* child[2];
18569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct malloc_tree_chunk* parent;
18579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bindex_t                  index;
18589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
18599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef struct malloc_tree_chunk  tchunk;
18619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef struct malloc_tree_chunk* tchunkptr;
18629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
18639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* A little helper macro for trees */
18659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
18669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ----------------------------- Segments -------------------------------- */
18689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
18709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Each malloc space may include non-contiguous segments, held in a
18719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  list headed by an embedded malloc_segment record representing the
18729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  top-most space. Segments also include flags holding properties of
18739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the space. Large chunks that are directly allocated by mmap are not
18749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  included in this list. They are instead independently created and
18759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  destroyed without otherwise keeping track of them.
18769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Segment management mainly comes into play for spaces allocated by
18789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MMAP.  Any call to MMAP might or might not return memory that is
18799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  adjacent to an existing segment.  MORECORE normally contiguously
18809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  extends the current space, so this space is almost always adjacent,
18819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  which is simpler and faster to deal with. (This is why MORECORE is
18829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  used preferentially to MMAP when both are available -- see
18839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  sys_alloc.)  When allocating using MMAP, we don't use any of the
18849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  hinting mechanisms (inconsistently) supported in various
18859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  implementations of unix mmap, or distinguish reserving from
18869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  committing memory. Instead, we just ask for space, and exploit
18879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  contiguity when we get it.  It is probably possible to do
18889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  better than this on some systems, but no general scheme seems
18899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  to be significantly better.
18909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Management entails a simpler variant of the consolidation scheme
18929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  used for chunks to reduce fragmentation -- new adjacent memory is
18939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  normally prepended or appended to an existing segment. However,
18949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  there are limitations compared to chunk consolidation that mostly
18959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  reflect the fact that segment processing is relatively infrequent
18969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (occurring only when getting memory from system) and that we
18979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  don't expect to have huge numbers of segments:
18989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
18999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * Segments are not indexed, so traversal requires linear scans.  (It
19009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    would be possible to index these, but is not worth the extra
19019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    overhead and complexity for most programs on most platforms.)
19029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * New segments are only appended to old ones when holding top-most
19039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    memory; if they cannot be prepended to others, they are held in
19049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    different segments.
19059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Except for the top-most segment of an mstate, each segment record
19079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  is kept at the tail of its segment. Segments are added by pushing
19089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  segment records onto the list headed by &mstate.seg for the
19099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  containing mstate.
19109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Segment flags control allocation/merge/deallocation policies:
19129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * If EXTERN_BIT set, then we did not allocate this segment,
19139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    and so should not try to deallocate or merge with others.
19149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    (This currently holds only for the initial segment passed
19159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    into create_mspace_with_base.)
19169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * If IS_MMAPPED_BIT set, the segment may be merged with
19179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    other surrounding mmapped segments and trimmed/de-allocated
19189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    using munmap.
19199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * If neither bit is set, then the segment was obtained using
19209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    MORECORE so can be merged with surrounding MORECORE'd segments
19219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    and deallocated/trimmed using MORECORE with negative arguments.
19229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
19239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct malloc_segment {
19259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  char*        base;             /* base address */
19269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t       size;             /* allocated size */
19279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct malloc_segment* next;   /* ptr to next segment */
19289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  flag_t       sflags;           /* mmap and extern flag */
19299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
19309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define is_mmapped_segment(S)  ((S)->sflags & IS_MMAPPED_BIT)
19329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define is_extern_segment(S)   ((S)->sflags & EXTERN_BIT)
19339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef struct malloc_segment  msegment;
19359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef struct malloc_segment* msegmentptr;
19369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ---------------------------- malloc_state ----------------------------- */
19389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
19409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   A malloc_state holds all of the bookkeeping for a space.
19419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   The main fields are:
19429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Top
19449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    The topmost chunk of the currently active segment. Its size is
19459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    cached in topsize.  The actual size of topmost space is
19469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    topsize+TOP_FOOT_SIZE, which includes space reserved for adding
19479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    fenceposts and segment records if necessary when getting more
19489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    space from the system.  The size at which to autotrim top is
19499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    cached from mparams in trim_check, except that it is disabled if
19509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    an autotrim fails.
19519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Designated victim (dv)
19539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This is the preferred chunk for servicing small requests that
19549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    don't have exact fits.  It is normally the chunk split off most
19559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    recently to service another small request.  Its size is cached in
19569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    dvsize. The link fields of this chunk are not maintained since it
19579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    is not kept in a bin.
19589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  SmallBins
19609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    An array of bin headers for free chunks.  These bins hold chunks
19619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
19629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    chunks of all the same size, spaced 8 bytes apart.  To simplify
19639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    use in double-linked lists, each bin header acts as a malloc_chunk
19649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    pointing to the real first node, if it exists (else pointing to
19659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    itself).  This avoids special-casing for headers.  But to avoid
19669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    waste, we allocate only the fd/bk pointers of bins, and then use
19679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    repositioning tricks to treat these as the fields of a chunk.
19689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  TreeBins
19709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Treebins are pointers to the roots of trees holding a range of
19719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    sizes. There are 2 equally spaced treebins for each power of two
19729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
19739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    larger.
19749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Bin maps
19769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    There is one bit map for small bins ("smallmap") and one for
19779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    treebins ("treemap).  Each bin sets its bit when non-empty, and
19789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    clears the bit when empty.  Bit operations are then used to avoid
19799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    bin-by-bin searching -- nearly all "search" is done without ever
19809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    looking at bins that won't be selected.  The bit maps
19819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    conservatively use 32 bits per map word, even if on 64bit system.
19829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    For a good description of some of the bit-based techniques used
19839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    here, see Henry S. Warren Jr's book "Hacker's Delight" (and
19849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    supplement at http://hackersdelight.org/). Many of these are
19859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    intended to reduce the branchiness of paths through malloc etc, as
19869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    well as to reduce the number of memory locations read or written.
19879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Segments
19899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    A list of segments headed by an embedded malloc_segment record
19909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    representing the initial space.
19919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Address check support
19939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    The least_addr field is the least address ever obtained from
19949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    MORECORE or MMAP. Attempted frees and reallocs of any address less
19959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    than this are trapped (unless INSECURE is defined).
19969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
19979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Magic tag
19989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    A cross-check field that should always hold same value as mparams.magic.
19999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Flags
20019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Bits recording whether to use MMAP, locks, or contiguous MORECORE
20029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Statistics
20049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Each space keeps track of current and maximum system memory
20059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    obtained via MORECORE or MMAP.
20069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Locking
20089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    If USE_LOCKS is defined, the "mutex" lock is acquired and released
20099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    around every public call using this mspace.
20109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
20119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Bin types, widths and sizes */
20139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define NSMALLBINS        (32U)
20149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define NTREEBINS         (32U)
20159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define SMALLBIN_SHIFT    (3U)
20169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define SMALLBIN_WIDTH    (SIZE_T_ONE << SMALLBIN_SHIFT)
20179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define TREEBIN_SHIFT     (8U)
20189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MIN_LARGE_SIZE    (SIZE_T_ONE << TREEBIN_SHIFT)
20199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MAX_SMALL_SIZE    (MIN_LARGE_SIZE - SIZE_T_ONE)
20209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
20219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct malloc_state {
20239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  binmap_t   smallmap;
20249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  binmap_t   treemap;
20259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t     dvsize;
20269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t     topsize;
20279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  char*      least_addr;
20289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr  dv;
20299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr  top;
20309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t     trim_check;
20319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t     magic;
20329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr  smallbins[(NSMALLBINS+1)*2];
20339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tbinptr    treebins[NTREEBINS];
20349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t     footprint;
20359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t     max_footprint;
20369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  flag_t     mflags;
20379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if USE_LOCKS
20389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MLOCK_T    mutex;     /* locate lock among fields that rarely change */
20399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* USE_LOCKS */
20409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  msegment   seg;
20419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
20429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef struct malloc_state*    mstate;
20449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ------------- Global malloc_state and malloc_params ------------------- */
20469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
20489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc_params holds global properties, including those that can be
20499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  dynamically set using mallopt. There is a single instance, mparams,
20509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  initialized in init_mparams.
20519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
20529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct malloc_params {
20549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t magic;
20559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t page_size;
20569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t granularity;
20579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t mmap_threshold;
20589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t trim_threshold;
20599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  flag_t default_mflags;
20609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
20619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic struct malloc_params mparams;
20639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* The global malloc_state used for all non-"mspace" calls */
20659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic struct malloc_state _gm_;
20669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define gm                 (&_gm_)
20679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define is_global(M)       ((M) == &_gm_)
20689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define is_initialized(M)  ((M)->top != 0)
20699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -------------------------- system alloc setup ------------------------- */
20719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Operations on mflags */
20739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define use_lock(M)           ((M)->mflags &   USE_LOCK_BIT)
20759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define enable_lock(M)        ((M)->mflags |=  USE_LOCK_BIT)
20769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define disable_lock(M)       ((M)->mflags &= ~USE_LOCK_BIT)
20779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define use_mmap(M)           ((M)->mflags &   USE_MMAP_BIT)
20799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define enable_mmap(M)        ((M)->mflags |=  USE_MMAP_BIT)
20809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define disable_mmap(M)       ((M)->mflags &= ~USE_MMAP_BIT)
20819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define use_noncontiguous(M)  ((M)->mflags &   USE_NONCONTIGUOUS_BIT)
20839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define disable_contiguous(M) ((M)->mflags |=  USE_NONCONTIGUOUS_BIT)
20849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define set_lock(M,L)\
20869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall ((M)->mflags = (L)?\
20879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((M)->mflags | USE_LOCK_BIT) :\
20889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((M)->mflags & ~USE_LOCK_BIT))
20899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* page-align a size */
20919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define page_align(S)\
20929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))
20939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* granularity-align a size */
20959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define granularity_align(S)\
20969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))
20979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
20989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define is_page_aligned(S)\
20999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
21009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define is_granularity_aligned(S)\
21019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
21029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*  True if segment S holds address A */
21049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define segment_holds(S, A)\
21059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
21069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Return segment holding given address */
21089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic msegmentptr segment_holding(mstate m, char* addr) {
21099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  msegmentptr sp = &m->seg;
21109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  for (;;) {
21119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (addr >= sp->base && addr < sp->base + sp->size)
21129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return sp;
21139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ((sp = sp->next) == 0)
21149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return 0;
21159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
21169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
21179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Return true if segment contains a segment link */
21199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int has_segment_link(mstate m, msegmentptr ss) {
21209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  msegmentptr sp = &m->seg;
21219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  for (;;) {
21229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
21239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return 1;
21249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ((sp = sp->next) == 0)
21259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return 0;
21269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
21279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
21289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef MORECORE_CANNOT_TRIM
21309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define should_trim(M,s)  ((s) > (M)->trim_check)
21319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else  /* MORECORE_CANNOT_TRIM */
21329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define should_trim(M,s)  (0)
21339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* MORECORE_CANNOT_TRIM */
21349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
21369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  TOP_FOOT_SIZE is padding at the end of a segment, including space
21379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  that may be needed to place segment records and fenceposts when new
21389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  noncontiguous segments are added.
21399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
21409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define TOP_FOOT_SIZE\
21419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
21429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -------------------------------  Hooks -------------------------------- */
21459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
21479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  PREACTION should be defined to return 0 on success, and nonzero on
21489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  failure. If you are not using locking, you can redefine these to do
21499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  anything you like.
21509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
21519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if USE_LOCKS
21539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Ensure locks are initialized */
21559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())
21569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define PREACTION(M)  ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
21589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
21599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* USE_LOCKS */
21609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef PREACTION
21629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define PREACTION(M) (0)
21639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* PREACTION */
21649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef POSTACTION
21669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define POSTACTION(M)
21679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif  /* POSTACTION */
21689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* USE_LOCKS */
21709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
21729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
21739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  USAGE_ERROR_ACTION is triggered on detected bad frees and
21749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  reallocs. The argument p is an address that might have triggered the
21759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  fault. It is ignored by the two predefined actions, but might be
21769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  useful in custom actions that try to help diagnose errors.
21779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
21789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if PROCEED_ON_ERROR
21809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* A count of the number of corruption errors causing resets */
21829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint malloc_corruption_error_count;
21839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* default corruption action */
21859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void reset_on_error(mstate m);
21869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CORRUPTION_ERROR_ACTION(m)  reset_on_error(m)
21889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define USAGE_ERROR_ACTION(m, p)
21899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* PROCEED_ON_ERROR */
21919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef CORRUPTION_ERROR_ACTION
21939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define CORRUPTION_ERROR_ACTION(m) ABORT
21949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* CORRUPTION_ERROR_ACTION */
21959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
21969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef USAGE_ERROR_ACTION
21979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define USAGE_ERROR_ACTION(m,p) ABORT
21989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* USAGE_ERROR_ACTION */
21999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* PROCEED_ON_ERROR */
22019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -------------------------- Debugging setup ---------------------------- */
22039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if ! DEBUG
22059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_free_chunk(M,P)
22079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_inuse_chunk(M,P)
22089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_malloced_chunk(M,P,N)
22099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_mmapped_chunk(M,P)
22109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_malloc_state(M)
22119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_top_chunk(M,P)
22129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* DEBUG */
22149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_free_chunk(M,P)       do_check_free_chunk(M,P)
22159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_inuse_chunk(M,P)      do_check_inuse_chunk(M,P)
22169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_top_chunk(M,P)        do_check_top_chunk(M,P)
22179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
22189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_mmapped_chunk(M,P)    do_check_mmapped_chunk(M,P)
22199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define check_malloc_state(M)       do_check_malloc_state(M)
22209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void   do_check_any_chunk(mstate m, mchunkptr p);
22229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void   do_check_top_chunk(mstate m, mchunkptr p);
22239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void   do_check_mmapped_chunk(mstate m, mchunkptr p);
22249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void   do_check_inuse_chunk(mstate m, mchunkptr p);
22259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void   do_check_free_chunk(mstate m, mchunkptr p);
22269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void   do_check_malloced_chunk(mstate m, void* mem, size_t s);
22279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void   do_check_tree(mstate m, tchunkptr t);
22289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void   do_check_treebin(mstate m, bindex_t i);
22299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void   do_check_smallbin(mstate m, bindex_t i);
22309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void   do_check_malloc_state(mstate m);
22319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int    bin_find(mstate m, mchunkptr x);
22329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic size_t traverse_and_check(mstate m);
22339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* DEBUG */
22349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ---------------------------- Indexing Bins ---------------------------- */
22369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define is_small(s)         (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
22389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define small_index(s)      ((s)  >> SMALLBIN_SHIFT)
22399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define small_index2size(i) ((i)  << SMALLBIN_SHIFT)
22409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))
22419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* addressing by index. See above about smallbin repositioning */
22439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
22449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define treebin_at(M,i)     (&((M)->treebins[i]))
22459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* assign tree index for size S to variable I */
22479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if defined(__GNUC__) && defined(i386)
22489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define compute_tree_index(S, I)\
22499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{\
22509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t X = S >> TREEBIN_SHIFT;\
22519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (X == 0)\
22529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    I = 0;\
22539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else if (X > 0xFFFF)\
22549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    I = NTREEBINS-1;\
22559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {\
22569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    unsigned int K;\
22579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm"  (X));\
22589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
22599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
22609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
22619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* GNUC */
22629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define compute_tree_index(S, I)\
22639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{\
22649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t X = S >> TREEBIN_SHIFT;\
22659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (X == 0)\
22669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    I = 0;\
22679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else if (X > 0xFFFF)\
22689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    I = NTREEBINS-1;\
22699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {\
22709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    unsigned int Y = (unsigned int)X;\
22719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    unsigned int N = ((Y - 0x100) >> 16) & 8;\
22729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
22739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    N += K;\
22749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
22759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    K = 14 - N + ((Y <<= K) >> 15);\
22769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
22779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
22789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
22799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* GNUC */
22809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Bit representing maximum resolved size in a treebin at i */
22829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define bit_for_tree_index(i) \
22839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
22849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Shift placing maximum resolved bit in a treebin at i as sign bit */
22869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define leftshift_for_tree_index(i) \
22879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   ((i == NTREEBINS-1)? 0 : \
22889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
22899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* The size of the smallest chunk held in bin with index i */
22919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define minsize_for_tree_index(i) \
22929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) |  \
22939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
22949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ------------------------ Operations on bin maps ----------------------- */
22979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
22989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* bit corresponding to given index */
22999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define idx2bit(i)              ((binmap_t)(1) << (i))
23009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Mark/Clear bits with given index */
23029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define mark_smallmap(M,i)      ((M)->smallmap |=  idx2bit(i))
23039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define clear_smallmap(M,i)     ((M)->smallmap &= ~idx2bit(i))
23049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define smallmap_is_marked(M,i) ((M)->smallmap &   idx2bit(i))
23059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define mark_treemap(M,i)       ((M)->treemap  |=  idx2bit(i))
23079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define clear_treemap(M,i)      ((M)->treemap  &= ~idx2bit(i))
23089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define treemap_is_marked(M,i)  ((M)->treemap  &   idx2bit(i))
23099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* index corresponding to given bit */
23119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if defined(__GNUC__) && defined(i386)
23139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define compute_bit2idx(X, I)\
23149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{\
23159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  unsigned int J;\
23169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\
23179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  I = (bindex_t)J;\
23189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
23199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* GNUC */
23219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if  USE_BUILTIN_FFS
23229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define compute_bit2idx(X, I) I = ffs(X)-1
23239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* USE_BUILTIN_FFS */
23259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define compute_bit2idx(X, I)\
23269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{\
23279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  unsigned int Y = X - 1;\
23289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  unsigned int K = Y >> (16-4) & 16;\
23299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  unsigned int N = K;        Y >>= K;\
23309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  N += K = Y >> (8-3) &  8;  Y >>= K;\
23319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  N += K = Y >> (4-2) &  4;  Y >>= K;\
23329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  N += K = Y >> (2-1) &  2;  Y >>= K;\
23339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  N += K = Y >> (1-0) &  1;  Y >>= K;\
23349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  I = (bindex_t)(N + Y);\
23359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
23369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* USE_BUILTIN_FFS */
23379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* GNUC */
23389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* isolate the least set bit of a bitmap */
23409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define least_bit(x)         ((x) & -(x))
23419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* mask with all bits to left of least bit of x on */
23439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define left_bits(x)         ((x<<1) | -(x<<1))
23449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* mask with all bits to left of or equal to least bit of x on */
23469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define same_or_left_bits(x) ((x) | -(x))
23479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ----------------------- Runtime Check Support ------------------------- */
23509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
23529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  For security, the main invariant is that malloc/free/etc never
23539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  writes to a static address other than malloc_state, unless static
23549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc_state itself has been corrupted, which cannot occur via
23559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  malloc (because of these checks). In essence this means that we
23569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  believe all pointers, sizes, maps etc held in malloc_state, but
23579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  check all of those linked or offsetted from other embedded data
23589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  structures.  These checks are interspersed with main code in a way
23599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  that tends to minimize their run-time cost.
23609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  When FOOTERS is defined, in addition to range checking, we also
23629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  verify footer fields of inuse chunks, which can be used guarantee
23639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  that the mstate controlling malloc/free is intact.  This is a
23649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  streamlined version of the approach described by William Robertson
23659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  et al in "Run-time Detection of Heap-based Overflows" LISA'03
23669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  http://www.usenix.org/events/lisa03/tech/robertson.html The footer
23679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  of an inuse chunk holds the xor of its mstate and a random seed,
23689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  that is checked upon calls to free() and realloc().  This is
23699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (probablistically) unguessable from outside the program, but can be
23709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  computed by any code successfully malloc'ing any chunk, so does not
23719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  itself provide protection against code that has already broken
23729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  security through some other means.  Unlike Robertson et al, we
23739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  always dynamically check addresses of all offset chunks (previous,
23749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  next, etc). This turns out to be cheaper than relying on hashes.
23759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
23769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !INSECURE
23789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check if address a is at least as high as any from MORECORE or MMAP */
23799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
23809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check if address of next chunk n is higher than base chunk p */
23819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ok_next(p, n)    ((char*)(p) < (char*)(n))
23829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check if p has its cinuse bit on */
23839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ok_cinuse(p)     cinuse(p)
23849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check if p has its pinuse bit on */
23859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ok_pinuse(p)     pinuse(p)
23869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* !INSECURE */
23889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ok_address(M, a) (1)
23899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ok_next(b, n)    (1)
23909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ok_cinuse(p)     (1)
23919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ok_pinuse(p)     (1)
23929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* !INSECURE */
23939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
23949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (FOOTERS && !INSECURE)
23959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check if (alleged) mstate m has expected magic field */
23969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ok_magic(M)      ((M)->magic == mparams.magic)
23979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else  /* (FOOTERS && !INSECURE) */
23989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ok_magic(M)      (1)
23999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* (FOOTERS && !INSECURE) */
24009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* In gcc, use __builtin_expect to minimize impact of checks */
24039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !INSECURE
24049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if defined(__GNUC__) && __GNUC__ >= 3
24059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RTCHECK(e)  __builtin_expect(e, 1)
24069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* GNUC */
24079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RTCHECK(e)  (e)
24089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* GNUC */
24099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* !INSECURE */
24109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RTCHECK(e)  (1)
24119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* !INSECURE */
24129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* macros to set up inuse chunks with or without footers */
24149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !FOOTERS
24169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define mark_inuse_foot(M,p,s)
24189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Set cinuse bit and pinuse bit of next chunk */
24209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define set_inuse(M,p,s)\
24219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
24229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
24239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
24259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define set_inuse_and_pinuse(M,p,s)\
24269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
24279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
24289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Set size, cinuse and pinuse bit of this chunk */
24309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
24319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
24329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* FOOTERS */
24349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Set foot of inuse chunk to be xor of mstate and seed */
24369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define mark_inuse_foot(M,p,s)\
24379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
24389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define get_mstate_for(p)\
24409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((mstate)(((mchunkptr)((char*)(p) +\
24419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    (chunksize(p))))->prev_foot ^ mparams.magic))
24429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define set_inuse(M,p,s)\
24449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
24459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
24469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mark_inuse_foot(M,p,s))
24479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define set_inuse_and_pinuse(M,p,s)\
24499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
24509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
24519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall mark_inuse_foot(M,p,s))
24529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
24549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
24559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mark_inuse_foot(M, p, s))
24569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* !FOOTERS */
24589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ---------------------------- setting mparams -------------------------- */
24609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Initialize mparams */
24629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int init_mparams(void) {
24639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (mparams.page_size == 0) {
24649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t s;
24659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
24679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
24689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if MORECORE_CONTIGUOUS
24699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
24709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else  /* MORECORE_CONTIGUOUS */
24719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
24729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* MORECORE_CONTIGUOUS */
24739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (FOOTERS && !INSECURE)
24759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
24769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if USE_DEV_RANDOM
24779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      int fd;
24789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      unsigned char buf[sizeof(size_t)];
24799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      /* Try to use /dev/urandom, else fall back on using time */
24809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
24819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          read(fd, buf, sizeof(buf)) == sizeof(buf)) {
24829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        s = *((size_t *) buf);
24839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        close(fd);
24849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
24859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else
24869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* USE_DEV_RANDOM */
24879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        s = (size_t)(time(0) ^ (size_t)0x55555555U);
24889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      s |= (size_t)8U;    /* ensure nonzero */
24909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      s &= ~(size_t)7U;   /* improve chances of fault for bad values */
24919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
24929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
24939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* (FOOTERS && !INSECURE) */
24949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    s = (size_t)0x58585858U;
24959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* (FOOTERS && !INSECURE) */
24969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    ACQUIRE_MAGIC_INIT_LOCK();
24979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (mparams.magic == 0) {
24989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mparams.magic = s;
24999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      /* Set up lock for main malloc area */
25009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      INITIAL_LOCK(&gm->mutex);
25019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      gm->mflags = mparams.default_mflags;
25029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
25039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    RELEASE_MAGIC_INIT_LOCK();
25049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
25059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef WIN32
25069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mparams.page_size = malloc_getpagesize;
25079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
25089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                           DEFAULT_GRANULARITY : mparams.page_size);
25099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* WIN32 */
25109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
25119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      SYSTEM_INFO system_info;
25129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      GetSystemInfo(&system_info);
25139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mparams.page_size = system_info.dwPageSize;
25149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mparams.granularity = system_info.dwAllocationGranularity;
25159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
25169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* WIN32 */
25179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
25189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Sanity-check configuration:
25199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       size_t must be unsigned and as wide as pointer type.
25209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       ints must be at least 4 bytes.
25219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       alignment must be at least 8.
25229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       Alignment, min chunk size, and page size must all be powers of 2.
25239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    */
25249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ((sizeof(size_t) != sizeof(char*)) ||
25259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        (MAX_SIZE_T < MIN_CHUNK_SIZE)  ||
25269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        (sizeof(int) < 4)  ||
25279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        (MALLOC_ALIGNMENT < (size_t)8U) ||
25289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ((MALLOC_ALIGNMENT    & (MALLOC_ALIGNMENT-SIZE_T_ONE))    != 0) ||
25299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ((MCHUNK_SIZE         & (MCHUNK_SIZE-SIZE_T_ONE))         != 0) ||
25309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||
25319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ((mparams.page_size   & (mparams.page_size-SIZE_T_ONE))   != 0))
25329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      ABORT;
25339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
25349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
25359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
25369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
25379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* support for mallopt */
25389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int change_mparam(int param_number, int value) {
25399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t val = (size_t)value;
25409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  init_mparams();
25419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  switch(param_number) {
25429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  case M_TRIM_THRESHOLD:
25439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mparams.trim_threshold = val;
25449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 1;
25459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  case M_GRANULARITY:
25469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
25479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mparams.granularity = val;
25489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return 1;
25499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
25509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else
25519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return 0;
25529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  case M_MMAP_THRESHOLD:
25539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mparams.mmap_threshold = val;
25549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 1;
25559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  default:
25569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
25579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
25589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
25599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
25609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if DEBUG
25619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ------------------------- Debugging Support --------------------------- */
25629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
25639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check properties of any chunk, whether free, inuse, mmapped etc  */
25649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void do_check_any_chunk(mstate m, mchunkptr p) {
25659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
25669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(ok_address(m, p));
25679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
25689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
25699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check properties of top chunk */
25709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void do_check_top_chunk(mstate m, mchunkptr p) {
25719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  msegmentptr sp = segment_holding(m, (char*)p);
25729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t  sz = chunksize(p);
25739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(sp != 0);
25749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
25759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(ok_address(m, p));
25769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(sz == m->topsize);
25779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(sz > 0);
25789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
25799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(pinuse(p));
25809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(!next_pinuse(p));
25819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
25829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
25839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check properties of (inuse) mmapped chunks */
25849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void do_check_mmapped_chunk(mstate m, mchunkptr p) {
25859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t  sz = chunksize(p);
25869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD);
25879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(is_mmapped(p));
25889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(use_mmap(m));
25899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
25909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(ok_address(m, p));
25919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(!is_small(sz));
25929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
25939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
25949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
25959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
25969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
25979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check properties of inuse chunks */
25989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void do_check_inuse_chunk(mstate m, mchunkptr p) {
25999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  do_check_any_chunk(m, p);
26009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(cinuse(p));
26019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(next_pinuse(p));
26029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* If not pinuse and not mmapped, previous chunk has OK offset */
26039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
26049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (is_mmapped(p))
26059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    do_check_mmapped_chunk(m, p);
26069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
26079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
26089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check properties of free chunks */
26099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void do_check_free_chunk(mstate m, mchunkptr p) {
26109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
26119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr next = chunk_plus_offset(p, sz);
26129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  do_check_any_chunk(m, p);
26139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(!cinuse(p));
26149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(!next_pinuse(p));
26159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert (!is_mmapped(p));
26169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (p != m->dv && p != m->top) {
26179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (sz >= MIN_CHUNK_SIZE) {
26189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert((sz & CHUNK_ALIGN_MASK) == 0);
26199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(is_aligned(chunk2mem(p)));
26209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(next->prev_foot == sz);
26219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(pinuse(p));
26229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert (next == m->top || cinuse(next));
26239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(p->fd->bk == p);
26249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(p->bk->fd == p);
26259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
26269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else  /* markers are always of size SIZE_T_SIZE */
26279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(sz == SIZE_T_SIZE);
26289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
26299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
26309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
26319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check properties of malloced chunks at the point they are malloced */
26329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
26339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (mem != 0) {
26349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr p = mem2chunk(mem);
26359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
26369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    do_check_inuse_chunk(m, p);
26379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert((sz & CHUNK_ALIGN_MASK) == 0);
26389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(sz >= MIN_CHUNK_SIZE);
26399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(sz >= s);
26409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
26419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
26429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
26439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
26449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
26459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check a tree and its subtrees.  */
26469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void do_check_tree(mstate m, tchunkptr t) {
26479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tchunkptr head = 0;
26489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tchunkptr u = t;
26499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bindex_t tindex = t->index;
26509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t tsize = chunksize(t);
26519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bindex_t idx;
26529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  compute_tree_index(tsize, idx);
26539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(tindex == idx);
26549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(tsize >= MIN_LARGE_SIZE);
26559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(tsize >= minsize_for_tree_index(idx));
26569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
26579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
26589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  do { /* traverse through chain of same-sized nodes */
26599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    do_check_any_chunk(m, ((mchunkptr)u));
26609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(u->index == tindex);
26619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(chunksize(u) == tsize);
26629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(!cinuse(u));
26639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(!next_pinuse(u));
26649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(u->fd->bk == u);
26659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(u->bk->fd == u);
26669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (u->parent == 0) {
26679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(u->child[0] == 0);
26689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(u->child[1] == 0);
26699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
26709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
26719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(head == 0); /* only one node on chain has parent */
26729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      head = u;
26739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(u->parent != u);
26749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert (u->parent->child[0] == u ||
26759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              u->parent->child[1] == u ||
26769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              *((tbinptr*)(u->parent)) == u);
26779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (u->child[0] != 0) {
26789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        assert(u->child[0]->parent == u);
26799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        assert(u->child[0] != u);
26809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        do_check_tree(m, u->child[0]);
26819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
26829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (u->child[1] != 0) {
26839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        assert(u->child[1]->parent == u);
26849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        assert(u->child[1] != u);
26859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        do_check_tree(m, u->child[1]);
26869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
26879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (u->child[0] != 0 && u->child[1] != 0) {
26889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        assert(chunksize(u->child[0]) < chunksize(u->child[1]));
26899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
26909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
26919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    u = u->fd;
26929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  } while (u != t);
26939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(head != 0);
26949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
26959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
26969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*  Check all the chunks in a treebin.  */
26979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void do_check_treebin(mstate m, bindex_t i) {
26989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tbinptr* tb = treebin_at(m, i);
26999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tchunkptr t = *tb;
27009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  int empty = (m->treemap & (1U << i)) == 0;
27019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (t == 0)
27029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(empty);
27039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!empty)
27049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    do_check_tree(m, t);
27059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
27069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
27079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*  Check all the chunks in a smallbin.  */
27089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void do_check_smallbin(mstate m, bindex_t i) {
27099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  sbinptr b = smallbin_at(m, i);
27109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr p = b->bk;
27119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  unsigned int empty = (m->smallmap & (1U << i)) == 0;
27129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (p == b)
27139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(empty);
27149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!empty) {
27159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (; p != b; p = p->bk) {
27169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t size = chunksize(p);
27179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr q;
27189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      /* each chunk claims to be free */
27199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      do_check_free_chunk(m, p);
27209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      /* chunk belongs in bin */
27219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(small_index(size) == i);
27229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(p->bk == b || chunksize(p->bk) == chunksize(p));
27239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      /* chunk is followed by an inuse chunk */
27249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      q = next_chunk(p);
27259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (q->head != FENCEPOST_HEAD)
27269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        do_check_inuse_chunk(m, q);
27279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
27289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
27299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
27309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
27319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Find x in a bin. Used in other check functions. */
27329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int bin_find(mstate m, mchunkptr x) {
27339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t size = chunksize(x);
27349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (is_small(size)) {
27359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    bindex_t sidx = small_index(size);
27369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    sbinptr b = smallbin_at(m, sidx);
27379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (smallmap_is_marked(m, sidx)) {
27389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr p = b;
27399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      do {
27409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (p == x)
27419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          return 1;
27429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      } while ((p = p->fd) != b);
27439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
27449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
27459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {
27469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    bindex_t tidx;
27479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    compute_tree_index(size, tidx);
27489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (treemap_is_marked(m, tidx)) {
27499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      tchunkptr t = *treebin_at(m, tidx);
27509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t sizebits = size << leftshift_for_tree_index(tidx);
27519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      while (t != 0 && chunksize(t) != size) {
27529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
27539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        sizebits <<= 1;
27549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
27559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (t != 0) {
27569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        tchunkptr u = t;
27579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        do {
27589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (u == (tchunkptr)x)
27599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            return 1;
27609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        } while ((u = u->fd) != t);
27619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
27629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
27639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
27649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
27659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
27669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
27679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Traverse each chunk and check it; return total */
27689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic size_t traverse_and_check(mstate m) {
27699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t sum = 0;
27709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (is_initialized(m)) {
27719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    msegmentptr s = &m->seg;
27729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    sum += m->topsize + TOP_FOOT_SIZE;
27739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    while (s != 0) {
27749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr q = align_as_chunk(s->base);
27759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr lastq = 0;
27769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(pinuse(q));
27779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      while (segment_holds(s, q) &&
27789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall             q != m->top && q->head != FENCEPOST_HEAD) {
27799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        sum += chunksize(q);
27809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (cinuse(q)) {
27819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          assert(!bin_find(m, q));
27829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          do_check_inuse_chunk(m, q);
27839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
27849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else {
27859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          assert(q == m->dv || bin_find(m, q));
27869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */
27879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          do_check_free_chunk(m, q);
27889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
27899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        lastq = q;
27909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        q = next_chunk(q);
27919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
27929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      s = s->next;
27939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
27949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
27959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return sum;
27969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
27979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
27989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Check all properties of malloc_state. */
27999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void do_check_malloc_state(mstate m) {
28009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bindex_t i;
28019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t total;
28029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* check bins */
28039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  for (i = 0; i < NSMALLBINS; ++i)
28049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    do_check_smallbin(m, i);
28059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  for (i = 0; i < NTREEBINS; ++i)
28069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    do_check_treebin(m, i);
28079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
28089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (m->dvsize != 0) { /* check dv chunk */
28099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    do_check_any_chunk(m, m->dv);
28109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(m->dvsize == chunksize(m->dv));
28119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(m->dvsize >= MIN_CHUNK_SIZE);
28129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(bin_find(m, m->dv) == 0);
28139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
28149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
28159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (m->top != 0) {   /* check top chunk */
28169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    do_check_top_chunk(m, m->top);
28179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(m->topsize == chunksize(m->top));
28189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(m->topsize > 0);
28199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(bin_find(m, m->top) == 0);
28209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
28219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
28229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  total = traverse_and_check(m);
28239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(total <= m->footprint);
28249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(m->footprint <= m->max_footprint);
28259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
28269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* DEBUG */
28279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
28289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ----------------------------- statistics ------------------------------ */
28299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
28309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !NO_MALLINFO
28319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic struct mallinfo internal_mallinfo(mstate m) {
28329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
28339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!PREACTION(m)) {
28349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    check_malloc_state(m);
28359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (is_initialized(m)) {
28369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t nfree = SIZE_T_ONE; /* top always free */
28379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t mfree = m->topsize + TOP_FOOT_SIZE;
28389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t sum = mfree;
28399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      msegmentptr s = &m->seg;
28409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      while (s != 0) {
28419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mchunkptr q = align_as_chunk(s->base);
28429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        while (segment_holds(s, q) &&
28439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall               q != m->top && q->head != FENCEPOST_HEAD) {
28449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          size_t sz = chunksize(q);
28459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          sum += sz;
28469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (!cinuse(q)) {
28479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            mfree += sz;
28489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            ++nfree;
28499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
28509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          q = next_chunk(q);
28519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
28529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        s = s->next;
28539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
28549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
28559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nm.arena    = sum;
28569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nm.ordblks  = nfree;
28579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nm.hblkhd   = m->footprint - sum;
28589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nm.usmblks  = m->max_footprint;
28599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nm.uordblks = m->footprint - mfree;
28609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nm.fordblks = mfree;
28619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nm.keepcost = m->topsize;
28629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
28639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
28649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    POSTACTION(m);
28659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
28669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return nm;
28679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
28689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* !NO_MALLINFO */
28699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
28709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void internal_malloc_stats(mstate m) {
28719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!PREACTION(m)) {
28729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t maxfp = 0;
28739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t fp = 0;
28749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t used = 0;
28759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    check_malloc_state(m);
28769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (is_initialized(m)) {
28779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      msegmentptr s = &m->seg;
28789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      maxfp = m->max_footprint;
28799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      fp = m->footprint;
28809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      used = fp - (m->topsize + TOP_FOOT_SIZE);
28819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
28829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      while (s != 0) {
28839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mchunkptr q = align_as_chunk(s->base);
28849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        while (segment_holds(s, q) &&
28859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall               q != m->top && q->head != FENCEPOST_HEAD) {
28869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (!cinuse(q))
28879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            used -= chunksize(q);
28889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          q = next_chunk(q);
28899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
28909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        s = s->next;
28919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
28929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
28939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
28949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LACKS_STDIO_H
28959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
28969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    fprintf(stderr, "system bytes     = %10lu\n", (unsigned long)(fp));
28979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    fprintf(stderr, "in use bytes     = %10lu\n", (unsigned long)(used));
28989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
28999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
29009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    POSTACTION(m);
29019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
29029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
29039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
29049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ----------------------- Operations on smallbins ----------------------- */
29059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
29069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
29079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Various forms of linking and unlinking are defined as macros.  Even
29089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the ones for trees, which are very long but have very short typical
29099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  paths.  This is ugly but reduces reliance on inlining support of
29109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  compilers.
29119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
29129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
29139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Link a free chunk into a smallbin  */
29149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define insert_small_chunk(M, P, S) {\
29159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bindex_t I  = small_index(S);\
29169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr B = smallbin_at(M, I);\
29179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr F = B;\
29189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(S >= MIN_CHUNK_SIZE);\
29199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!smallmap_is_marked(M, I))\
29209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mark_smallmap(M, I);\
29219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else if (RTCHECK(ok_address(M, B->fd)))\
29229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    F = B->fd;\
29239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {\
29249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CORRUPTION_ERROR_ACTION(M);\
29259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
29269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  B->fd = P;\
29279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  F->bk = P;\
29289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  P->fd = F;\
29299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  P->bk = B;\
29309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
29319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
29329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Unlink a chunk from a smallbin  */
29339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define unlink_small_chunk(M, P, S) {\
29349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr F = P->fd;\
29359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr B = P->bk;\
29369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bindex_t I = small_index(S);\
29379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(P != B);\
29389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(P != F);\
29399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(chunksize(P) == small_index2size(I));\
29409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (F == B)\
29419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    clear_smallmap(M, I);\
29429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
29439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                   (B == smallbin_at(M,I) || ok_address(M, B)))) {\
29449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    F->bk = B;\
29459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    B->fd = F;\
29469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
29479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {\
29489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CORRUPTION_ERROR_ACTION(M);\
29499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
29509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
29519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
29529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Unlink the first chunk from a smallbin */
29539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define unlink_first_small_chunk(M, B, P, I) {\
29549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr F = P->fd;\
29559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(P != B);\
29569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(P != F);\
29579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(chunksize(P) == small_index2size(I));\
29589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (B == F)\
29599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    clear_smallmap(M, I);\
29609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else if (RTCHECK(ok_address(M, F))) {\
29619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    B->fd = F;\
29629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    F->bk = B;\
29639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
29649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {\
29659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CORRUPTION_ERROR_ACTION(M);\
29669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
29679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
29689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
29699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Replace dv node, binning the old one */
29709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Used only when dvsize known to be small */
29719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define replace_dv(M, P, S) {\
29729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t DVS = M->dvsize;\
29739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (DVS != 0) {\
29749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr DV = M->dv;\
29759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(is_small(DVS));\
29769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    insert_small_chunk(M, DV, DVS);\
29779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
29789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  M->dvsize = S;\
29799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  M->dv = P;\
29809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
29819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
29829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ------------------------- Operations on trees ------------------------- */
29839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
29849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Insert chunk into tree */
29859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define insert_large_chunk(M, X, S) {\
29869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tbinptr* H;\
29879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bindex_t I;\
29889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  compute_tree_index(S, I);\
29899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  H = treebin_at(M, I);\
29909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  X->index = I;\
29919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  X->child[0] = X->child[1] = 0;\
29929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!treemap_is_marked(M, I)) {\
29939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mark_treemap(M, I);\
29949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    *H = X;\
29959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    X->parent = (tchunkptr)H;\
29969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    X->fd = X->bk = X;\
29979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
29989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {\
29999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    tchunkptr T = *H;\
30009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t K = S << leftshift_for_tree_index(I);\
30019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (;;) {\
30029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (chunksize(T) != S) {\
30039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
30049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        K <<= 1;\
30059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (*C != 0)\
30069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          T = *C;\
30079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else if (RTCHECK(ok_address(M, C))) {\
30089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          *C = X;\
30099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          X->parent = T;\
30109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          X->fd = X->bk = X;\
30119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          break;\
30129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }\
30139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else {\
30149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          CORRUPTION_ERROR_ACTION(M);\
30159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          break;\
30169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }\
30179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }\
30189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else {\
30199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        tchunkptr F = T->fd;\
30209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
30219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          T->fd = F->bk = X;\
30229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          X->fd = F;\
30239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          X->bk = T;\
30249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          X->parent = 0;\
30259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          break;\
30269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }\
30279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else {\
30289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          CORRUPTION_ERROR_ACTION(M);\
30299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          break;\
30309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }\
30319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }\
30329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }\
30339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
30349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
30359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
30369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
30379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Unlink steps:
30389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
30399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  1. If x is a chained node, unlink it from its same-sized fd/bk links
30409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     and choose its bk node as its replacement.
30419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  2. If x was the last node of its size, but not a leaf node, it must
30429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     be replaced with a leaf node (not merely one with an open left or
30439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     right), to make sure that lefts and rights of descendents
30449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     correspond properly to bit masks.  We use the rightmost descendent
30459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     of x.  We could use any other leaf, but this is easy to locate and
30469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     tends to counteract removal of leftmosts elsewhere, and so keeps
30479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     paths shorter than minimally guaranteed.  This doesn't loop much
30489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     because on average a node in a tree is near the bottom.
30499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  3. If x is the base of a chain (i.e., has parent links) relink
30509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     x's parent and children to x's replacement (or null if none).
30519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
30529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
30539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define unlink_large_chunk(M, X) {\
30549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tchunkptr XP = X->parent;\
30559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tchunkptr R;\
30569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (X->bk != X) {\
30579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    tchunkptr F = X->fd;\
30589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    R = X->bk;\
30599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (RTCHECK(ok_address(M, F))) {\
30609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      F->bk = R;\
30619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      R->fd = F;\
30629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }\
30639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {\
30649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      CORRUPTION_ERROR_ACTION(M);\
30659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }\
30669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
30679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {\
30689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    tchunkptr* RP;\
30699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (((R = *(RP = &(X->child[1]))) != 0) ||\
30709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ((R = *(RP = &(X->child[0]))) != 0)) {\
30719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      tchunkptr* CP;\
30729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      while ((*(CP = &(R->child[1])) != 0) ||\
30739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall             (*(CP = &(R->child[0])) != 0)) {\
30749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        R = *(RP = CP);\
30759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }\
30769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (RTCHECK(ok_address(M, RP)))\
30779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        *RP = 0;\
30789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else {\
30799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CORRUPTION_ERROR_ACTION(M);\
30809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }\
30819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }\
30829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
30839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (XP != 0) {\
30849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    tbinptr* H = treebin_at(M, X->index);\
30859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (X == *H) {\
30869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if ((*H = R) == 0) \
30879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        clear_treemap(M, X->index);\
30889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }\
30899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else if (RTCHECK(ok_address(M, XP))) {\
30909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (XP->child[0] == X) \
30919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        XP->child[0] = R;\
30929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else \
30939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        XP->child[1] = R;\
30949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }\
30959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else\
30969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      CORRUPTION_ERROR_ACTION(M);\
30979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (R != 0) {\
30989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (RTCHECK(ok_address(M, R))) {\
30999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        tchunkptr C0, C1;\
31009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        R->parent = XP;\
31019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ((C0 = X->child[0]) != 0) {\
31029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (RTCHECK(ok_address(M, C0))) {\
31039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            R->child[0] = C0;\
31049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            C0->parent = R;\
31059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }\
31069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          else\
31079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CORRUPTION_ERROR_ACTION(M);\
31089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }\
31099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ((C1 = X->child[1]) != 0) {\
31109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (RTCHECK(ok_address(M, C1))) {\
31119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            R->child[1] = C1;\
31129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            C1->parent = R;\
31139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }\
31149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          else\
31159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CORRUPTION_ERROR_ACTION(M);\
31169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }\
31179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }\
31189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else\
31199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CORRUPTION_ERROR_ACTION(M);\
31209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }\
31219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }\
31229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
31239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
31249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Relays to large vs small bin operations */
31259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
31269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define insert_chunk(M, P, S)\
31279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (is_small(S)) insert_small_chunk(M, P, S)\
31289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
31299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
31309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define unlink_chunk(M, P, S)\
31319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (is_small(S)) unlink_small_chunk(M, P, S)\
31329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
31339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
31349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
31359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Relays to internal calls to malloc/free from realloc, memalign etc */
31369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
31379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if ONLY_MSPACES
31389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define internal_malloc(m, b) mspace_malloc(m, b)
31399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define internal_free(m, mem) mspace_free(m,mem);
31409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* ONLY_MSPACES */
31419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if MSPACES
31429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define internal_malloc(m, b)\
31439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
31449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define internal_free(m, mem)\
31459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   if (m == gm) dlfree(mem); else mspace_free(m,mem);
31469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* MSPACES */
31479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define internal_malloc(m, b) dlmalloc(b)
31489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define internal_free(m, mem) dlfree(mem)
31499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* MSPACES */
31509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* ONLY_MSPACES */
31519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
31529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -----------------------  Direct-mmapping chunks ----------------------- */
31539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
31549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
31559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Directly mmapped chunks are set up with an offset to the start of
31569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the mmapped region stored in the prev_foot field of the chunk. This
31579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  allows reconstruction of the required argument to MUNMAP when freed,
31589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  and also allows adjustment of the returned chunk to meet alignment
31599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  requirements (especially in memalign).  There is also enough space
31609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain
31619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  the PINUSE bit so frees can be checked.
31629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
31639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
31649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Malloc using mmap */
31659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void* mmap_alloc(mstate m, size_t nb) {
31669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
31679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (mmsize > nb) {     /* Check for wrap around 0 */
31689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    char* mm = (char*)(DIRECT_MMAP(mmsize));
31699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (mm != CMFAIL) {
31709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t offset = align_offset(chunk2mem(mm));
31719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t psize = mmsize - offset - MMAP_FOOT_PAD;
31729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr p = (mchunkptr)(mm + offset);
31739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      p->prev_foot = offset | IS_MMAPPED_BIT;
31749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      (p)->head = (psize|CINUSE_BIT);
31759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mark_inuse_foot(m, p, psize);
31769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
31779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
31789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
31799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (mm < m->least_addr)
31809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        m->least_addr = mm;
31819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if ((m->footprint += mmsize) > m->max_footprint)
31829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        m->max_footprint = m->footprint;
31839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(is_aligned(chunk2mem(p)));
31849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_mmapped_chunk(m, p);
31859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return chunk2mem(p);
31869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
31879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
31889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
31899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
31909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
31919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Realloc using mmap */
31929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
31939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t oldsize = chunksize(oldp);
31949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (is_small(nb)) /* Can't shrink mmap regions below small size */
31959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
31969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* Keep old chunk if big enough but not too big */
31979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (oldsize >= nb + SIZE_T_SIZE &&
31989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      (oldsize - nb) <= (mparams.granularity << 1))
31999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return oldp;
32009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {
32019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
32029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
32039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
32049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                         CHUNK_ALIGN_MASK);
32059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
32069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                  oldmmsize, newmmsize, 1);
32079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (cp != CMFAIL) {
32089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr newp = (mchunkptr)(cp + offset);
32099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
32109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      newp->head = (psize|CINUSE_BIT);
32119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mark_inuse_foot(m, newp, psize);
32129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
32139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
32149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
32159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (cp < m->least_addr)
32169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        m->least_addr = cp;
32179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
32189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        m->max_footprint = m->footprint;
32199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_mmapped_chunk(m, newp);
32209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return newp;
32219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
32229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
32239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
32249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
32259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
32269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -------------------------- mspace management -------------------------- */
32279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
32289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Initialize top chunk and its size */
32299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void init_top(mstate m, mchunkptr p, size_t psize) {
32309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* Ensure alignment */
32319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t offset = align_offset(chunk2mem(p));
32329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  p = (mchunkptr)((char*)p + offset);
32339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  psize -= offset;
32349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
32359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->top = p;
32369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->topsize = psize;
32379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  p->head = psize | PINUSE_BIT;
32389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* set size of fake trailing chunk holding overhead space only once */
32399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
32409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->trim_check = mparams.trim_threshold; /* reset on each update */
32419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
32429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
32439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Initialize bins for a new mstate that is otherwise zeroed out */
32449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void init_bins(mstate m) {
32459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* Establish circular links for smallbins */
32469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bindex_t i;
32479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  for (i = 0; i < NSMALLBINS; ++i) {
32489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    sbinptr bin = smallbin_at(m,i);
32499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    bin->fd = bin->bk = bin;
32509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
32519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
32529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
32539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if PROCEED_ON_ERROR
32549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
32559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* default corruption action */
32569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void reset_on_error(mstate m) {
32579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  int i;
32589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  ++malloc_corruption_error_count;
32599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* Reinitialize fields to forget about all memory */
32609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->smallbins = m->treebins = 0;
32619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->dvsize = m->topsize = 0;
32629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->seg.base = 0;
32639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->seg.size = 0;
32649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->seg.next = 0;
32659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->top = m->dv = 0;
32669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  for (i = 0; i < NTREEBINS; ++i)
32679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    *treebin_at(m, i) = 0;
32689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  init_bins(m);
32699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
32709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* PROCEED_ON_ERROR */
32719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
32729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Allocate chunk and prepend remainder with chunk in successor base. */
32739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void* prepend_alloc(mstate m, char* newbase, char* oldbase,
32749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                           size_t nb) {
32759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr p = align_as_chunk(newbase);
32769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr oldfirst = align_as_chunk(oldbase);
32779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t psize = (char*)oldfirst - (char*)p;
32789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr q = chunk_plus_offset(p, nb);
32799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t qsize = psize - nb;
32809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  set_size_and_pinuse_of_inuse_chunk(m, p, nb);
32819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
32829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert((char*)oldfirst > (char*)q);
32839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(pinuse(oldfirst));
32849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(qsize >= MIN_CHUNK_SIZE);
32859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
32869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* consolidate remainder with first chunk of old base */
32879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (oldfirst == m->top) {
32889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t tsize = m->topsize += qsize;
32899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    m->top = q;
32909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    q->head = tsize | PINUSE_BIT;
32919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    check_top_chunk(m, q);
32929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
32939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else if (oldfirst == m->dv) {
32949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t dsize = m->dvsize += qsize;
32959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    m->dv = q;
32969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    set_size_and_pinuse_of_free_chunk(q, dsize);
32979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
32989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {
32999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!cinuse(oldfirst)) {
33009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t nsize = chunksize(oldfirst);
33019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      unlink_chunk(m, oldfirst, nsize);
33029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      oldfirst = chunk_plus_offset(oldfirst, nsize);
33039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      qsize += nsize;
33049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
33059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    set_free_with_pinuse(q, qsize, oldfirst);
33069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    insert_chunk(m, q, qsize);
33079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    check_free_chunk(m, q);
33089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
33099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  check_malloced_chunk(m, chunk2mem(p), nb);
33119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return chunk2mem(p);
33129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
33139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Add a segment to hold a new noncontiguous region */
33169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
33179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* Determine locations and sizes of segment, fenceposts, old top */
33189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  char* old_top = (char*)m->top;
33199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  msegmentptr oldsp = segment_holding(m, old_top);
33209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  char* old_end = oldsp->base + oldsp->size;
33219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t ssize = pad_request(sizeof(struct malloc_segment));
33229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
33239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t offset = align_offset(chunk2mem(rawsp));
33249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  char* asp = rawsp + offset;
33259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
33269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr sp = (mchunkptr)csp;
33279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  msegmentptr ss = (msegmentptr)(chunk2mem(sp));
33289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr tnext = chunk_plus_offset(sp, ssize);
33299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr p = tnext;
33309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  int nfences = 0;
33319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* reset top to new space */
33339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
33349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* Set up segment record */
33369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(is_aligned(ss));
33379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
33389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  *ss = m->seg; /* Push current record */
33399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->seg.base = tbase;
33409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->seg.size = tsize;
33419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->seg.sflags = mmapped;
33429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->seg.next = ss;
33439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* Insert trailing fenceposts */
33459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  for (;;) {
33469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
33479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    p->head = FENCEPOST_HEAD;
33489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    ++nfences;
33499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ((char*)(&(nextp->head)) < old_end)
33509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      p = nextp;
33519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else
33529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      break;
33539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
33549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(nfences >= 2);
33559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* Insert the rest of old top into a bin as an ordinary free chunk */
33579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (csp != old_top) {
33589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr q = (mchunkptr)old_top;
33599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t psize = csp - old_top;
33609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr tn = chunk_plus_offset(q, psize);
33619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    set_free_with_pinuse(q, psize, tn);
33629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    insert_chunk(m, q, psize);
33639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
33649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  check_top_chunk(m, m->top);
33669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
33679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -------------------------- System allocation -------------------------- */
33699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Get memory from system using MORECORE or MMAP */
33719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void* sys_alloc(mstate m, size_t nb) {
33729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  char* tbase = CMFAIL;
33739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t tsize = 0;
33749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  flag_t mmap_flag = 0;
33759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  init_mparams();
33779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* Directly map large chunks */
33799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (use_mmap(m) && nb >= mparams.mmap_threshold) {
33809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    void* mem = mmap_alloc(m, nb);
33819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (mem != 0)
33829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return mem;
33839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
33849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
33859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /*
33869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Try getting memory in any of three ways (in most-preferred to
33879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    least-preferred order):
33889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    1. A call to MORECORE that can normally contiguously extend memory.
33899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
33909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       or main space is mmapped or a previous contiguous call failed)
33919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    2. A call to MMAP new space (disabled if not HAVE_MMAP).
33929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       Note that under the default settings, if MORECORE is unable to
33939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       fulfill a request, and HAVE_MMAP is true, then mmap is
33949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       used as a noncontiguous system allocator. This is a useful backup
33959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       strategy for systems with holes in address spaces -- in this case
33969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       sbrk cannot contiguously expand the heap, but mmap may be able to
33979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       find space.
33989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    3. A call to MORECORE that cannot usually contiguously extend memory.
33999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       (disabled if not HAVE_MORECORE)
34009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  */
34019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
34029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
34039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    char* br = CMFAIL;
34049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
34059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t asize = 0;
34069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    ACQUIRE_MORECORE_LOCK();
34079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
34089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (ss == 0) {  /* First time through or recovery */
34099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      char* base = (char*)CALL_MORECORE(0);
34109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (base != CMFAIL) {
34119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        asize = granularity_align(nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE);
34129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Adjust to end on a page boundary */
34139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (!is_page_aligned(base))
34149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          asize += (page_align((size_t)base) - (size_t)base);
34159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Can't call MORECORE if size is negative when treated as signed */
34169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (asize < HALF_MAX_SIZE_T &&
34179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            (br = (char*)(CALL_MORECORE(asize))) == base) {
34189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          tbase = base;
34199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          tsize = asize;
34209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
34219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
34229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
34239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
34249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      /* Subtract out existing available top space from MORECORE request. */
34259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE);
34269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      /* Use mem here only if it did continuously extend old space */
34279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (asize < HALF_MAX_SIZE_T &&
34289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
34299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        tbase = br;
34309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        tsize = asize;
34319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
34329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
34339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
34349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (tbase == CMFAIL) {    /* Cope with partial failure */
34359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (br != CMFAIL) {    /* Try to use/extend the space we did get */
34369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (asize < HALF_MAX_SIZE_T &&
34379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
34389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          size_t esize = granularity_align(nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE - asize);
34399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (esize < HALF_MAX_SIZE_T) {
34409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            char* end = (char*)CALL_MORECORE(esize);
34419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (end != CMFAIL)
34429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              asize += esize;
34439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            else {            /* Can't use; try to release */
34449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              end = (char*)CALL_MORECORE(-asize);
34459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              br = CMFAIL;
34469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
34479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
34489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
34499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
34509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (br != CMFAIL) {    /* Use the space we did get */
34519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        tbase = br;
34529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        tsize = asize;
34539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
34549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else
34559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        disable_contiguous(m); /* Don't try contiguous path in the future */
34569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
34579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
34589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    RELEASE_MORECORE_LOCK();
34599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
34609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
34619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (HAVE_MMAP && tbase == CMFAIL) {  /* Try MMAP */
34629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t req = nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE;
34639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t rsize = granularity_align(req);
34649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (rsize > nb) { /* Fail if wraps around zero */
34659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      char* mp = (char*)(CALL_MMAP(rsize));
34669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (mp != CMFAIL) {
34679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        tbase = mp;
34689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        tsize = rsize;
34699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mmap_flag = IS_MMAPPED_BIT;
34709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
34719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
34729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
34739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
34749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
34759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t asize = granularity_align(nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE);
34769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (asize < HALF_MAX_SIZE_T) {
34779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      char* br = CMFAIL;
34789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      char* end = CMFAIL;
34799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      ACQUIRE_MORECORE_LOCK();
34809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      br = (char*)(CALL_MORECORE(asize));
34819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      end = (char*)(CALL_MORECORE(0));
34829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      RELEASE_MORECORE_LOCK();
34839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (br != CMFAIL && end != CMFAIL && br < end) {
34849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t ssize = end - br;
34859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (ssize > nb + TOP_FOOT_SIZE) {
34869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          tbase = br;
34879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          tsize = ssize;
34889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
34899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
34909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
34919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
34929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
34939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (tbase != CMFAIL) {
34949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
34959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ((m->footprint += tsize) > m->max_footprint)
34969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      m->max_footprint = m->footprint;
34979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
34989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!is_initialized(m)) { /* first-time initialization */
34999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      m->seg.base = m->least_addr = tbase;
35009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      m->seg.size = tsize;
35019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      m->seg.sflags = mmap_flag;
35029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      m->magic = mparams.magic;
35039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      init_bins(m);
35049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (is_global(m))
35059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
35069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else {
35079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Offset top by embedded malloc_state */
35089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mchunkptr mn = next_chunk(mem2chunk(m));
35099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
35109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
35119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
35129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
35139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
35149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      /* Try to merge with an existing segment */
35159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      msegmentptr sp = &m->seg;
35169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      while (sp != 0 && tbase != sp->base + sp->size)
35179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        sp = sp->next;
35189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (sp != 0 &&
35199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          !is_extern_segment(sp) &&
35209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          (sp->sflags & IS_MMAPPED_BIT) == mmap_flag &&
35219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          segment_holds(sp, m->top)) { /* append */
35229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        sp->size += tsize;
35239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        init_top(m, m->top, m->topsize + tsize);
35249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
35259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else {
35269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (tbase < m->least_addr)
35279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          m->least_addr = tbase;
35289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        sp = &m->seg;
35299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        while (sp != 0 && sp->base != tbase + tsize)
35309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          sp = sp->next;
35319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (sp != 0 &&
35329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            !is_extern_segment(sp) &&
35339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) {
35349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          char* oldbase = sp->base;
35359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          sp->base = tbase;
35369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          sp->size += tsize;
35379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          return prepend_alloc(m, tbase, oldbase, nb);
35389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
35399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else
35409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          add_segment(m, tbase, tsize, mmap_flag);
35419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
35429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
35439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
35449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (nb < m->topsize) { /* Allocate from new or extended top space */
35459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t rsize = m->topsize -= nb;
35469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr p = m->top;
35479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr r = m->top = chunk_plus_offset(p, nb);
35489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      r->head = rsize | PINUSE_BIT;
35499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      set_size_and_pinuse_of_inuse_chunk(m, p, nb);
35509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_top_chunk(m, m->top);
35519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_malloced_chunk(m, chunk2mem(p), nb);
35529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return chunk2mem(p);
35539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
35549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
35559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
35569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  MALLOC_FAILURE_ACTION;
35579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
35589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
35599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
35609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -----------------------  system deallocation -------------------------- */
35619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
35629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Unmap and unlink any mmapped segments that don't contain used chunks */
35639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic size_t release_unused_segments(mstate m) {
35649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t released = 0;
35659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  msegmentptr pred = &m->seg;
35669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  msegmentptr sp = pred->next;
35679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  while (sp != 0) {
35689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    char* base = sp->base;
35699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t size = sp->size;
35709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    msegmentptr next = sp->next;
35719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
35729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr p = align_as_chunk(base);
35739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t psize = chunksize(p);
35749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      /* Can unmap if first chunk holds entire segment and not pinned */
35759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
35769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        tchunkptr tp = (tchunkptr)p;
35779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        assert(segment_holds(sp, (char*)sp));
35789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (p == m->dv) {
35799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          m->dv = 0;
35809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          m->dvsize = 0;
35819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
35829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else {
35839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          unlink_large_chunk(m, tp);
35849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
35859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (CALL_MUNMAP(base, size) == 0) {
35869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          released += size;
35879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          m->footprint -= size;
35889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          /* unlink obsoleted record */
35899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          sp = pred;
35909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          sp->next = next;
35919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
35929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else { /* back out if cannot unmap */
35939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          insert_large_chunk(m, tp, psize);
35949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
35959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
35969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
35979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    pred = sp;
35989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    sp = next;
35999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
36009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return released;
36019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
36029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
36039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int sys_trim(mstate m, size_t pad) {
36049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t released = 0;
36059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (pad < MAX_REQUEST && is_initialized(m)) {
36069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
36079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
36089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (m->topsize > pad) {
36099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      /* Shrink top space in granularity-size units, keeping at least one */
36109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t unit = mparams.granularity;
36119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
36129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                      SIZE_T_ONE) * unit;
36139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      msegmentptr sp = segment_holding(m, (char*)m->top);
36149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
36159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (!is_extern_segment(sp)) {
36169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (is_mmapped_segment(sp)) {
36179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (HAVE_MMAP &&
36189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              sp->size >= extra &&
36199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              !has_segment_link(m, sp)) { /* can't shrink if pinned */
36209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            size_t newsize = sp->size - extra;
36219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /* Prefer mremap, fall back to munmap */
36229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
36239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
36249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              released = extra;
36259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
36269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
36279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
36289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else if (HAVE_MORECORE) {
36299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
36309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
36319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          ACQUIRE_MORECORE_LOCK();
36329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          {
36339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /* Make sure end of memory is where we last set it. */
36349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            char* old_br = (char*)(CALL_MORECORE(0));
36359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (old_br == sp->base + sp->size) {
36369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              char* rel_br = (char*)(CALL_MORECORE(-extra));
36379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              char* new_br = (char*)(CALL_MORECORE(0));
36389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              if (rel_br != CMFAIL && new_br < old_br)
36399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                released = old_br - new_br;
36409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
36419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
36429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          RELEASE_MORECORE_LOCK();
36439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
36449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
36459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
36469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (released != 0) {
36479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        sp->size -= released;
36489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        m->footprint -= released;
36499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        init_top(m, m->top, m->topsize - released);
36509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        check_top_chunk(m, m->top);
36519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
36529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
36539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
36549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Unmap any unused mmapped segments */
36559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (HAVE_MMAP)
36569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      released += release_unused_segments(m);
36579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
36589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* On failure, disable autotrim to avoid repeated failed future calls */
36599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (released == 0)
36609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      m->trim_check = MAX_SIZE_T;
36619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
36629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
36639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return (released != 0)? 1 : 0;
36649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
36659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
36669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ---------------------------- malloc support --------------------------- */
36679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
36689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* allocate a large request from the best fitting chunk in a treebin */
36699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void* tmalloc_large(mstate m, size_t nb) {
36709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tchunkptr v = 0;
36719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t rsize = -nb; /* Unsigned negation */
36729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tchunkptr t;
36739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bindex_t idx;
36749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  compute_tree_index(nb, idx);
36759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
36769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if ((t = *treebin_at(m, idx)) != 0) {
36779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Traverse tree for this bin looking for node with size == nb */
36789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t sizebits = nb << leftshift_for_tree_index(idx);
36799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    tchunkptr rst = 0;  /* The deepest untaken right subtree */
36809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (;;) {
36819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      tchunkptr rt;
36829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t trem = chunksize(t) - nb;
36839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (trem < rsize) {
36849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        v = t;
36859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ((rsize = trem) == 0)
36869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          break;
36879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
36889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      rt = t->child[1];
36899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
36909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (rt != 0 && rt != t)
36919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        rst = rt;
36929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (t == 0) {
36939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        t = rst; /* set t to least subtree holding sizes > nb */
36949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        break;
36959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
36969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      sizebits <<= 1;
36979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
36989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
36999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
37019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
37029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (leftbits != 0) {
37039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      bindex_t i;
37049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      binmap_t leastbit = least_bit(leftbits);
37059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      compute_bit2idx(leastbit, i);
37069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      t = *treebin_at(m, i);
37079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
37089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
37099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  while (t != 0) { /* find smallest of tree or subtree */
37119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t trem = chunksize(t) - nb;
37129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (trem < rsize) {
37139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      rsize = trem;
37149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      v = t;
37159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
37169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    t = leftmost_child(t);
37179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
37189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /*  If dv is a better fit, return 0 so malloc will use it */
37209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
37219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (RTCHECK(ok_address(m, v))) { /* split */
37229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr r = chunk_plus_offset(v, nb);
37239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(chunksize(v) == rsize + nb);
37249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (RTCHECK(ok_next(v, r))) {
37259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        unlink_large_chunk(m, v);
37269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (rsize < MIN_CHUNK_SIZE)
37279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          set_inuse_and_pinuse(m, v, (rsize + nb));
37289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else {
37299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          set_size_and_pinuse_of_inuse_chunk(m, v, nb);
37309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          set_size_and_pinuse_of_free_chunk(r, rsize);
37319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          insert_chunk(m, r, rsize);
37329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
37339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return chunk2mem(v);
37349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
37359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
37369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CORRUPTION_ERROR_ACTION(m);
37379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
37389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
37399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
37409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* allocate a small request from the best fitting chunk in a treebin */
37429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void* tmalloc_small(mstate m, size_t nb) {
37439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  tchunkptr t, v;
37449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t rsize;
37459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  bindex_t i;
37469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  binmap_t leastbit = least_bit(m->treemap);
37479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  compute_bit2idx(leastbit, i);
37489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  v = t = *treebin_at(m, i);
37509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  rsize = chunksize(t) - nb;
37519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  while ((t = leftmost_child(t)) != 0) {
37539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t trem = chunksize(t) - nb;
37549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (trem < rsize) {
37559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      rsize = trem;
37569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      v = t;
37579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
37589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
37599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (RTCHECK(ok_address(m, v))) {
37619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr r = chunk_plus_offset(v, nb);
37629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    assert(chunksize(v) == rsize + nb);
37639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (RTCHECK(ok_next(v, r))) {
37649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      unlink_large_chunk(m, v);
37659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (rsize < MIN_CHUNK_SIZE)
37669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_inuse_and_pinuse(m, v, (rsize + nb));
37679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else {
37689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_size_and_pinuse_of_inuse_chunk(m, v, nb);
37699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_size_and_pinuse_of_free_chunk(r, rsize);
37709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        replace_dv(m, r, rsize);
37719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
37729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return chunk2mem(v);
37739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
37749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
37759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  CORRUPTION_ERROR_ACTION(m);
37779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
37789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
37799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* --------------------------- realloc support --------------------------- */
37819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
37839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (bytes >= MAX_REQUEST) {
37849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    MALLOC_FAILURE_ACTION;
37859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
37869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
37879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!PREACTION(m)) {
37889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr oldp = mem2chunk(oldmem);
37899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t oldsize = chunksize(oldp);
37909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr next = chunk_plus_offset(oldp, oldsize);
37919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr newp = 0;
37929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    void* extra = 0;
37939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Try to either shrink or extend into top. Else malloc-copy-free */
37959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
37969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
37979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                ok_next(oldp, next) && ok_pinuse(next))) {
37989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t nb = request2size(bytes);
37999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (is_mmapped(oldp))
38009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        newp = mmap_resize(m, oldp, nb);
38019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else if (oldsize >= nb) { /* already big enough */
38029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t rsize = oldsize - nb;
38039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        newp = oldp;
38049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (rsize >= MIN_CHUNK_SIZE) {
38059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          mchunkptr remainder = chunk_plus_offset(newp, nb);
38069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          set_inuse(m, newp, nb);
38079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          set_inuse(m, remainder, rsize);
38089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          extra = chunk2mem(remainder);
38099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
38109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
38119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else if (next == m->top && oldsize + m->topsize > nb) {
38129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Expand into top */
38139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t newsize = oldsize + m->topsize;
38149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t newtopsize = newsize - nb;
38159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mchunkptr newtop = chunk_plus_offset(oldp, nb);
38169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_inuse(m, oldp, nb);
38179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        newtop->head = newtopsize |PINUSE_BIT;
38189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        m->top = newtop;
38199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        m->topsize = newtopsize;
38209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        newp = oldp;
38219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
38229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
38239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
38249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      USAGE_ERROR_ACTION(m, oldmem);
38259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      POSTACTION(m);
38269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return 0;
38279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
38289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
38299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    POSTACTION(m);
38309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
38319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (newp != 0) {
38329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (extra != 0) {
38339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        internal_free(m, extra);
38349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
38359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_inuse_chunk(m, newp);
38369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return chunk2mem(newp);
38379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
38389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
38399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      void* newmem = internal_malloc(m, bytes);
38409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (newmem != 0) {
38419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t oc = oldsize - overhead_for(oldp);
38429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
38439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        internal_free(m, oldmem);
38449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
38459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return newmem;
38469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
38479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
38489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
38499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
38509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
38519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* --------------------------- memalign support -------------------------- */
38529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
38539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
38549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (alignment <= MALLOC_ALIGNMENT)    /* Can just use malloc */
38559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return internal_malloc(m, bytes);
38569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
38579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    alignment = MIN_CHUNK_SIZE;
38589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
38599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t a = MALLOC_ALIGNMENT << 1;
38609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    while (a < alignment) a <<= 1;
38619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    alignment = a;
38629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
38639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
38649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (bytes >= MAX_REQUEST - alignment) {
38659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (m != 0)  { /* Test isn't needed but avoids compiler warning */
38669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      MALLOC_FAILURE_ACTION;
38679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
38689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
38699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {
38709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t nb = request2size(bytes);
38719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
38729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    char* mem = (char*)internal_malloc(m, req);
38739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (mem != 0) {
38749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      void* leader = 0;
38759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      void* trailer = 0;
38769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr p = mem2chunk(mem);
38779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
38789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (PREACTION(m)) return 0;
38799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
38809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /*
38819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          Find an aligned spot inside chunk.  Since we need to give
38829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          back leading space in a chunk of at least MIN_CHUNK_SIZE, if
38839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          the first calculation places us at a spot with less than
38849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
38859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          We've allocated enough total room so that this is always
38869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          possible.
38879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        */
38889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
38899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                                       alignment -
38909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                                       SIZE_T_ONE)) &
38919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                             -alignment));
38929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
38939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          br : br+alignment;
38949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mchunkptr newp = (mchunkptr)pos;
38959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t leadsize = pos - (char*)(p);
38969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t newsize = chunksize(p) - leadsize;
38979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
38989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
38999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          newp->prev_foot = p->prev_foot + leadsize;
39009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          newp->head = (newsize|CINUSE_BIT);
39019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
39029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else { /* Otherwise, give back leader, use the rest */
39039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          set_inuse(m, newp, newsize);
39049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          set_inuse(m, p, leadsize);
39059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          leader = chunk2mem(p);
39069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
39079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        p = newp;
39089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
39099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
39109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      /* Give back spare room at the end */
39119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (!is_mmapped(p)) {
39129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t size = chunksize(p);
39139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (size > nb + MIN_CHUNK_SIZE) {
39149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          size_t remainder_size = size - nb;
39159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          mchunkptr remainder = chunk_plus_offset(p, nb);
39169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          set_inuse(m, p, nb);
39179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          set_inuse(m, remainder, remainder_size);
39189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          trailer = chunk2mem(remainder);
39199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
39209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
39219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
39229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert (chunksize(p) >= nb);
39239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert((((size_t)(chunk2mem(p))) % alignment) == 0);
39249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_inuse_chunk(m, p);
39259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      POSTACTION(m);
39269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (leader != 0) {
39279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        internal_free(m, leader);
39289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
39299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (trailer != 0) {
39309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        internal_free(m, trailer);
39319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
39329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return chunk2mem(p);
39339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
39349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
39359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
39369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
39379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
39389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ------------------------ comalloc/coalloc support --------------------- */
39399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
39409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void** ialloc(mstate m,
39419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                     size_t n_elements,
39429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                     size_t* sizes,
39439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                     int opts,
39449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                     void* chunks[]) {
39459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /*
39469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This provides common support for independent_X routines, handling
39479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    all of the combinations that can result.
39489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
39499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    The opts arg has:
39509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    bit 0 set if all elements are same size (using sizes[0])
39519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    bit 1 set if elements should be zeroed
39529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  */
39539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
39549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t    element_size;   /* chunksize of each element, if all same */
39559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t    contents_size;  /* total size of elements */
39569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t    array_size;     /* request size of pointer array */
39579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  void*     mem;            /* malloced aggregate space */
39589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr p;              /* corresponding chunk */
39599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t    remainder_size; /* remaining bytes while splitting */
39609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  void**    marray;         /* either "chunks" or malloced ptr array */
39619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr array_chunk;    /* chunk for malloced ptr array */
39629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  flag_t    was_enabled;    /* to disable mmap */
39639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t    size;
39649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t    i;
39659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
39669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* compute array length, if needed */
39679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (chunks != 0) {
39689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (n_elements == 0)
39699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return chunks; /* nothing to do */
39709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    marray = chunks;
39719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    array_size = 0;
39729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
39739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {
39749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* if empty req, must still return chunk representing empty array */
39759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (n_elements == 0)
39769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return (void**)internal_malloc(m, 0);
39779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    marray = 0;
39789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    array_size = request2size(n_elements * (sizeof(void*)));
39799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
39809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
39819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* compute total element size */
39829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (opts & 0x1) { /* all-same-size */
39839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    element_size = request2size(*sizes);
39849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    contents_size = n_elements * element_size;
39859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
39869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else { /* add up all the sizes */
39879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    element_size = 0;
39889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    contents_size = 0;
39899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (i = 0; i != n_elements; ++i)
39909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      contents_size += request2size(sizes[i]);
39919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
39929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
39939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size = contents_size + array_size;
39949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
39959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /*
39969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     Allocate the aggregate chunk.  First disable direct-mmapping so
39979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     malloc won't use it, since we would not be able to later
39989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     free/realloc space internal to a segregated mmap region.
39999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  */
40009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  was_enabled = use_mmap(m);
40019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  disable_mmap(m);
40029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mem = internal_malloc(m, size - CHUNK_OVERHEAD);
40039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (was_enabled)
40049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    enable_mmap(m);
40059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (mem == 0)
40069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
40079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (PREACTION(m)) return 0;
40099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  p = mem2chunk(mem);
40109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  remainder_size = chunksize(p);
40119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  assert(!is_mmapped(p));
40139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (opts & 0x2) {       /* optionally clear the elements */
40159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
40169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
40179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* If not provided, allocate the pointer array as final part of chunk */
40199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (marray == 0) {
40209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t  array_chunk_size;
40219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    array_chunk = chunk_plus_offset(p, contents_size);
40229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    array_chunk_size = remainder_size - contents_size;
40239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    marray = (void**) (chunk2mem(array_chunk));
40249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
40259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    remainder_size = contents_size;
40269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
40279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /* split out elements */
40299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  for (i = 0; ; ++i) {
40309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    marray[i] = chunk2mem(p);
40319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (i != n_elements-1) {
40329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (element_size != 0)
40339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size = element_size;
40349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else
40359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size = request2size(sizes[i]);
40369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      remainder_size -= size;
40379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      set_size_and_pinuse_of_inuse_chunk(m, p, size);
40389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      p = chunk_plus_offset(p, size);
40399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
40409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else { /* the final element absorbs any overallocation slop */
40419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
40429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      break;
40439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
40449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
40459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if DEBUG
40479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (marray != chunks) {
40489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* final element must have exactly exhausted chunk */
40499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (element_size != 0) {
40509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(remainder_size == element_size);
40519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
40529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
40539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      assert(remainder_size == request2size(sizes[i]));
40549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
40559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    check_inuse_chunk(m, mem2chunk(marray));
40569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
40579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  for (i = 0; i != n_elements; ++i)
40589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    check_inuse_chunk(m, mem2chunk(marray[i]));
40599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* DEBUG */
40619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  POSTACTION(m);
40639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return marray;
40649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
40659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -------------------------- public routines ---------------------------- */
40689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !ONLY_MSPACES
40709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* dlmalloc(size_t bytes) {
40729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /*
40739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     Basic algorithm:
40749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     If a small request (< 256 bytes minus per-chunk overhead):
40759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       1. If one exists, use a remainderless chunk in associated smallbin.
40769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          (Remainderless means that there are too few excess bytes to
40779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          represent as a chunk.)
40789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       2. If it is big enough, use the dv chunk, which is normally the
40799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          chunk adjacent to the one used for the most recent small request.
40809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       3. If one exists, split the smallest available chunk in a bin,
40819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          saving remainder in dv.
40829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       4. If it is big enough, use the top chunk.
40839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       5. If available, get memory from system and use it
40849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     Otherwise, for a large request:
40859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       1. Find the smallest available binned chunk that fits, and use it
40869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if it is better fitting than dv chunk, splitting if necessary.
40879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       2. If better fitting than any binned chunk, use the dv chunk.
40889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       3. If it is big enough, use the top chunk.
40899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       4. If request size >= mmap threshold, try to directly mmap this chunk.
40909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       5. If available, get memory from system and use it
40919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     The ugly goto's here ensure that postaction occurs along all paths.
40939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  */
40949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
40959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!PREACTION(gm)) {
40969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    void* mem;
40979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t nb;
40989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (bytes <= MAX_SMALL_REQUEST) {
40999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      bindex_t idx;
41009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      binmap_t smallbits;
41019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
41029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      idx = small_index(nb);
41039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      smallbits = gm->smallmap >> idx;
41049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
41059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
41069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mchunkptr b, p;
41079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
41089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        b = smallbin_at(gm, idx);
41099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        p = b->fd;
41109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        assert(chunksize(p) == small_index2size(idx));
41119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        unlink_first_small_chunk(gm, b, p, idx);
41129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_inuse_and_pinuse(gm, p, small_index2size(idx));
41139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mem = chunk2mem(p);
41149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        check_malloced_chunk(gm, mem, nb);
41159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        goto postaction;
41169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
41179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
41189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else if (nb > gm->dvsize) {
41199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
41209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          mchunkptr b, p, r;
41219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          size_t rsize;
41229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          bindex_t i;
41239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
41249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          binmap_t leastbit = least_bit(leftbits);
41259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          compute_bit2idx(leastbit, i);
41269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          b = smallbin_at(gm, i);
41279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          p = b->fd;
41289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          assert(chunksize(p) == small_index2size(i));
41299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          unlink_first_small_chunk(gm, b, p, i);
41309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          rsize = small_index2size(i) - nb;
41319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          /* Fit here cannot be remainderless if 4byte sizes */
41329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
41339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            set_inuse_and_pinuse(gm, p, small_index2size(i));
41349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          else {
41359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
41369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            r = chunk_plus_offset(p, nb);
41379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            set_size_and_pinuse_of_free_chunk(r, rsize);
41389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            replace_dv(gm, r, rsize);
41399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
41409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          mem = chunk2mem(p);
41419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          check_malloced_chunk(gm, mem, nb);
41429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          goto postaction;
41439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
41449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
41459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
41469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          check_malloced_chunk(gm, mem, nb);
41479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          goto postaction;
41489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
41499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
41509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
41519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else if (bytes >= MAX_REQUEST)
41529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
41539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
41549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nb = pad_request(bytes);
41559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
41569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        check_malloced_chunk(gm, mem, nb);
41579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        goto postaction;
41589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
41599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
41609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
41619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (nb <= gm->dvsize) {
41629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t rsize = gm->dvsize - nb;
41639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr p = gm->dv;
41649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
41659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
41669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        gm->dvsize = rsize;
41679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_size_and_pinuse_of_free_chunk(r, rsize);
41689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
41699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
41709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else { /* exhaust dv */
41719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t dvs = gm->dvsize;
41729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        gm->dvsize = 0;
41739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        gm->dv = 0;
41749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_inuse_and_pinuse(gm, p, dvs);
41759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
41769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mem = chunk2mem(p);
41779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_malloced_chunk(gm, mem, nb);
41789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      goto postaction;
41799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
41809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
41819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else if (nb < gm->topsize) { /* Split top */
41829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t rsize = gm->topsize -= nb;
41839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr p = gm->top;
41849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr r = gm->top = chunk_plus_offset(p, nb);
41859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      r->head = rsize | PINUSE_BIT;
41869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
41879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mem = chunk2mem(p);
41889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_top_chunk(gm, gm->top);
41899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_malloced_chunk(gm, mem, nb);
41909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      goto postaction;
41919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
41929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
41939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mem = sys_alloc(gm, nb);
41949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
41959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  postaction:
41969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    POSTACTION(gm);
41979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return mem;
41989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
41999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
42009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
42019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
42029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
42039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid dlfree(void* mem) {
42049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  /*
42059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     Consolidate freed chunks with preceeding or succeeding bordering
42069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     free chunks, if they exist, and then place in a bin.  Intermixed
42079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     with special cases for top, dv, mmapped chunks, and usage errors.
42089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  */
42099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
42109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (mem != 0) {
42119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr p  = mem2chunk(mem);
42129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if FOOTERS
42139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mstate fm = get_mstate_for(p);
42149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!ok_magic(fm)) {
42159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      USAGE_ERROR_ACTION(fm, p);
42169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return;
42179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
42189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* FOOTERS */
42199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define fm gm
42209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* FOOTERS */
42219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!PREACTION(fm)) {
42229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_inuse_chunk(fm, p);
42239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
42249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t psize = chunksize(p);
42259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mchunkptr next = chunk_plus_offset(p, psize);
42269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (!pinuse(p)) {
42279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          size_t prevsize = p->prev_foot;
42289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if ((prevsize & IS_MMAPPED_BIT) != 0) {
42299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            prevsize &= ~IS_MMAPPED_BIT;
42309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            psize += prevsize + MMAP_FOOT_PAD;
42319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
42329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              fm->footprint -= psize;
42339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            goto postaction;
42349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
42359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          else {
42369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            mchunkptr prev = chunk_minus_offset(p, prevsize);
42379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            psize += prevsize;
42389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            p = prev;
42399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
42409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              if (p != fm->dv) {
42419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                unlink_chunk(fm, p, prevsize);
42429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              }
42439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
42449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                fm->dvsize = psize;
42459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                set_free_with_pinuse(p, psize, next);
42469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                goto postaction;
42479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              }
42489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
42499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            else
42509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              goto erroraction;
42519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
42529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
42539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
42549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
42559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (!cinuse(next)) {  /* consolidate forward */
42569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (next == fm->top) {
42579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              size_t tsize = fm->topsize += psize;
42589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              fm->top = p;
42599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              p->head = tsize | PINUSE_BIT;
42609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              if (p == fm->dv) {
42619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                fm->dv = 0;
42629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                fm->dvsize = 0;
42639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              }
42649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              if (should_trim(fm, tsize))
42659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                sys_trim(fm, 0);
42669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              goto postaction;
42679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
42689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            else if (next == fm->dv) {
42699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              size_t dsize = fm->dvsize += psize;
42709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              fm->dv = p;
42719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              set_size_and_pinuse_of_free_chunk(p, dsize);
42729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              goto postaction;
42739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
42749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            else {
42759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              size_t nsize = chunksize(next);
42769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              psize += nsize;
42779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              unlink_chunk(fm, next, nsize);
42789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              set_size_and_pinuse_of_free_chunk(p, psize);
42799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              if (p == fm->dv) {
42809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                fm->dvsize = psize;
42819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                goto postaction;
42829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              }
42839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
42849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
42859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          else
42869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            set_free_with_pinuse(p, psize, next);
42879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          insert_chunk(fm, p, psize);
42889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          check_free_chunk(fm, p);
42899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          goto postaction;
42909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
42919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
42929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    erroraction:
42939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      USAGE_ERROR_ACTION(fm, p);
42949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    postaction:
42959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      POSTACTION(fm);
42969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
42979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
42989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !FOOTERS
42999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#undef fm
43009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* FOOTERS */
43019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* dlcalloc(size_t n_elements, size_t elem_size) {
43049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  void* mem;
43059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t req = 0;
43069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (n_elements != 0) {
43079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    req = n_elements * elem_size;
43089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
43099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        (req / n_elements != elem_size))
43109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      req = MAX_SIZE_T; /* force downstream failure on overflow */
43119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
43129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mem = dlmalloc(req);
43139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
43149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    memset(mem, 0, req);
43159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return mem;
43169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* dlrealloc(void* oldmem, size_t bytes) {
43199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (oldmem == 0)
43209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return dlmalloc(bytes);
43219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef REALLOC_ZERO_BYTES_FREES
43229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (bytes == 0) {
43239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    dlfree(oldmem);
43249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
43259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
43269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* REALLOC_ZERO_BYTES_FREES */
43279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {
43289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if ! FOOTERS
43299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mstate m = gm;
43309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* FOOTERS */
43319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mstate m = get_mstate_for(mem2chunk(oldmem));
43329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!ok_magic(m)) {
43339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      USAGE_ERROR_ACTION(m, oldmem);
43349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return 0;
43359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
43369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* FOOTERS */
43379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return internal_realloc(m, oldmem, bytes);
43389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
43399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* dlmemalign(size_t alignment, size_t bytes) {
43429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return internal_memalign(gm, alignment, bytes);
43439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid** dlindependent_calloc(size_t n_elements, size_t elem_size,
43469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                 void* chunks[]) {
43479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t sz = elem_size; /* serves as 1-element array */
43489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return ialloc(gm, n_elements, &sz, 3, chunks);
43499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid** dlindependent_comalloc(size_t n_elements, size_t sizes[],
43529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                   void* chunks[]) {
43539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return ialloc(gm, n_elements, sizes, 0, chunks);
43549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* dlvalloc(size_t bytes) {
43579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t pagesz;
43589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  init_mparams();
43599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  pagesz = mparams.page_size;
43609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return dlmemalign(pagesz, bytes);
43619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* dlpvalloc(size_t bytes) {
43649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t pagesz;
43659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  init_mparams();
43669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  pagesz = mparams.page_size;
43679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
43689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint dlmalloc_trim(size_t pad) {
43719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  int result = 0;
43729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!PREACTION(gm)) {
43739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    result = sys_trim(gm, pad);
43749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    POSTACTION(gm);
43759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
43769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return result;
43779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t dlmalloc_footprint(void) {
43809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return gm->footprint;
43819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t dlmalloc_max_footprint(void) {
43849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return gm->max_footprint;
43859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !NO_MALLINFO
43889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct mallinfo dlmallinfo(void) {
43899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return internal_mallinfo(gm);
43909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* NO_MALLINFO */
43929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid dlmalloc_stats() {
43949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  internal_malloc_stats(gm);
43959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
43969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
43979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t dlmalloc_usable_size(void* mem) {
43989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (mem != 0) {
43999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr p = mem2chunk(mem);
44009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (cinuse(p))
44019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return chunksize(p) - overhead_for(p);
44029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
44039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
44049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
44059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint dlmallopt(int param_number, int value) {
44079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return change_mparam(param_number, value);
44089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
44099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* !ONLY_MSPACES */
44119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* ----------------------------- user mspaces ---------------------------- */
44139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if MSPACES
44159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic mstate init_user_mstate(char* tbase, size_t tsize) {
44179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t msize = pad_request(sizeof(struct malloc_state));
44189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr mn;
44199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mchunkptr msp = align_as_chunk(tbase);
44209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate m = (mstate)(chunk2mem(msp));
44219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  memset(m, 0, msize);
44229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  INITIAL_LOCK(&m->mutex);
44239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
44249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->seg.base = m->least_addr = tbase;
44259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->seg.size = m->footprint = m->max_footprint = tsize;
44269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->magic = mparams.magic;
44279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  m->mflags = mparams.default_mflags;
44289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  disable_contiguous(m);
44299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  init_bins(m);
44309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mn = next_chunk(mem2chunk(m));
44319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
44329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  check_top_chunk(m, m->top);
44339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return m;
44349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
44359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallmspace create_mspace(size_t capacity, int locked) {
44379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate m = 0;
44389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t msize = pad_request(sizeof(struct malloc_state));
44399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  init_mparams(); /* Ensure pagesize etc initialized */
44409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
44429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t rs = ((capacity == 0)? mparams.granularity :
44439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                 (capacity + TOP_FOOT_SIZE + msize));
44449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t tsize = granularity_align(rs);
44459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    char* tbase = (char*)(CALL_MMAP(tsize));
44469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (tbase != CMFAIL) {
44479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      m = init_user_mstate(tbase, tsize);
44489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      m->seg.sflags = IS_MMAPPED_BIT;
44499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      set_lock(m, locked);
44509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
44519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
44529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return (mspace)m;
44539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
44549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallmspace create_mspace_with_base(void* base, size_t capacity, int locked) {
44569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate m = 0;
44579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t msize = pad_request(sizeof(struct malloc_state));
44589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  init_mparams(); /* Ensure pagesize etc initialized */
44599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (capacity > msize + TOP_FOOT_SIZE &&
44619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
44629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    m = init_user_mstate((char*)base, capacity);
44639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    m->seg.sflags = EXTERN_BIT;
44649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    set_lock(m, locked);
44659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
44669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return (mspace)m;
44679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
44689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t destroy_mspace(mspace msp) {
44709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t freed = 0;
44719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate ms = (mstate)msp;
44729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (ok_magic(ms)) {
44739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    msegmentptr sp = &ms->seg;
44749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    while (sp != 0) {
44759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      char* base = sp->base;
44769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t size = sp->size;
44779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      flag_t flag = sp->sflags;
44789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      sp = sp->next;
44799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
44809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          CALL_MUNMAP(base, size) == 0)
44819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        freed += size;
44829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
44839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
44849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {
44859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    USAGE_ERROR_ACTION(ms,ms);
44869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
44879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return freed;
44889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
44899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
44919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mspace versions of routines are near-clones of the global
44929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  versions. This is not so nice but better than the alternatives.
44939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
44949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
44969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* mspace_malloc(mspace msp, size_t bytes) {
44979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate ms = (mstate)msp;
44989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!ok_magic(ms)) {
44999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    USAGE_ERROR_ACTION(ms,ms);
45009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
45019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
45029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!PREACTION(ms)) {
45039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    void* mem;
45049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    size_t nb;
45059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (bytes <= MAX_SMALL_REQUEST) {
45069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      bindex_t idx;
45079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      binmap_t smallbits;
45089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
45099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      idx = small_index(nb);
45109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      smallbits = ms->smallmap >> idx;
45119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
45129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
45139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mchunkptr b, p;
45149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
45159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        b = smallbin_at(ms, idx);
45169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        p = b->fd;
45179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        assert(chunksize(p) == small_index2size(idx));
45189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        unlink_first_small_chunk(ms, b, p, idx);
45199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_inuse_and_pinuse(ms, p, small_index2size(idx));
45209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mem = chunk2mem(p);
45219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        check_malloced_chunk(ms, mem, nb);
45229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        goto postaction;
45239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
45249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
45259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else if (nb > ms->dvsize) {
45269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
45279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          mchunkptr b, p, r;
45289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          size_t rsize;
45299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          bindex_t i;
45309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
45319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          binmap_t leastbit = least_bit(leftbits);
45329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          compute_bit2idx(leastbit, i);
45339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          b = smallbin_at(ms, i);
45349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          p = b->fd;
45359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          assert(chunksize(p) == small_index2size(i));
45369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          unlink_first_small_chunk(ms, b, p, i);
45379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          rsize = small_index2size(i) - nb;
45389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          /* Fit here cannot be remainderless if 4byte sizes */
45399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
45409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            set_inuse_and_pinuse(ms, p, small_index2size(i));
45419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          else {
45429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
45439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            r = chunk_plus_offset(p, nb);
45449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            set_size_and_pinuse_of_free_chunk(r, rsize);
45459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            replace_dv(ms, r, rsize);
45469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
45479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          mem = chunk2mem(p);
45489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          check_malloced_chunk(ms, mem, nb);
45499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          goto postaction;
45509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
45519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
45529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
45539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          check_malloced_chunk(ms, mem, nb);
45549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          goto postaction;
45559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
45569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
45579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
45589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else if (bytes >= MAX_REQUEST)
45599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
45609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
45619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nb = pad_request(bytes);
45629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
45639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        check_malloced_chunk(ms, mem, nb);
45649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        goto postaction;
45659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
45669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
45679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
45689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (nb <= ms->dvsize) {
45699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t rsize = ms->dvsize - nb;
45709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr p = ms->dv;
45719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
45729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
45739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ms->dvsize = rsize;
45749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_size_and_pinuse_of_free_chunk(r, rsize);
45759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
45769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
45779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      else { /* exhaust dv */
45789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t dvs = ms->dvsize;
45799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ms->dvsize = 0;
45809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ms->dv = 0;
45819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        set_inuse_and_pinuse(ms, p, dvs);
45829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
45839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mem = chunk2mem(p);
45849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_malloced_chunk(ms, mem, nb);
45859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      goto postaction;
45869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
45879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
45889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else if (nb < ms->topsize) { /* Split top */
45899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      size_t rsize = ms->topsize -= nb;
45909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr p = ms->top;
45919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mchunkptr r = ms->top = chunk_plus_offset(p, nb);
45929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      r->head = rsize | PINUSE_BIT;
45939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
45949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      mem = chunk2mem(p);
45959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_top_chunk(ms, ms->top);
45969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_malloced_chunk(ms, mem, nb);
45979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      goto postaction;
45989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
45999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
46009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mem = sys_alloc(ms, nb);
46019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
46029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  postaction:
46039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    POSTACTION(ms);
46049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return mem;
46059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
46069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
46079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return 0;
46089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
46099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
46109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid mspace_free(mspace msp, void* mem) {
46119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (mem != 0) {
46129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr p  = mem2chunk(mem);
46139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if FOOTERS
46149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mstate fm = get_mstate_for(p);
46159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* FOOTERS */
46169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mstate fm = (mstate)msp;
46179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* FOOTERS */
46189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!ok_magic(fm)) {
46199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      USAGE_ERROR_ACTION(fm, p);
46209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return;
46219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
46229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!PREACTION(fm)) {
46239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      check_inuse_chunk(fm, p);
46249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
46259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        size_t psize = chunksize(p);
46269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mchunkptr next = chunk_plus_offset(p, psize);
46279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (!pinuse(p)) {
46289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          size_t prevsize = p->prev_foot;
46299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if ((prevsize & IS_MMAPPED_BIT) != 0) {
46309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            prevsize &= ~IS_MMAPPED_BIT;
46319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            psize += prevsize + MMAP_FOOT_PAD;
46329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
46339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              fm->footprint -= psize;
46349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            goto postaction;
46359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
46369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          else {
46379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            mchunkptr prev = chunk_minus_offset(p, prevsize);
46389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            psize += prevsize;
46399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            p = prev;
46409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
46419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              if (p != fm->dv) {
46429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                unlink_chunk(fm, p, prevsize);
46439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              }
46449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
46459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                fm->dvsize = psize;
46469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                set_free_with_pinuse(p, psize, next);
46479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                goto postaction;
46489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              }
46499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
46509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            else
46519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              goto erroraction;
46529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
46539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
46549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
46559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
46569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          if (!cinuse(next)) {  /* consolidate forward */
46579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (next == fm->top) {
46589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              size_t tsize = fm->topsize += psize;
46599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              fm->top = p;
46609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              p->head = tsize | PINUSE_BIT;
46619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              if (p == fm->dv) {
46629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                fm->dv = 0;
46639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                fm->dvsize = 0;
46649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              }
46659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              if (should_trim(fm, tsize))
46669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                sys_trim(fm, 0);
46679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              goto postaction;
46689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
46699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            else if (next == fm->dv) {
46709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              size_t dsize = fm->dvsize += psize;
46719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              fm->dv = p;
46729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              set_size_and_pinuse_of_free_chunk(p, dsize);
46739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              goto postaction;
46749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
46759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            else {
46769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              size_t nsize = chunksize(next);
46779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              psize += nsize;
46789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              unlink_chunk(fm, next, nsize);
46799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              set_size_and_pinuse_of_free_chunk(p, psize);
46809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              if (p == fm->dv) {
46819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                fm->dvsize = psize;
46829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                goto postaction;
46839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall              }
46849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
46859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          }
46869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          else
46879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            set_free_with_pinuse(p, psize, next);
46889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          insert_chunk(fm, p, psize);
46899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          check_free_chunk(fm, p);
46909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          goto postaction;
46919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
46929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
46939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    erroraction:
46949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      USAGE_ERROR_ACTION(fm, p);
46959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    postaction:
46969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      POSTACTION(fm);
46979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
46989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
46999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
47009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
47019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
47029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  void* mem;
47039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t req = 0;
47049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate ms = (mstate)msp;
47059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!ok_magic(ms)) {
47069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    USAGE_ERROR_ACTION(ms,ms);
47079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
47089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
47099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (n_elements != 0) {
47109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    req = n_elements * elem_size;
47119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
47129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        (req / n_elements != elem_size))
47139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      req = MAX_SIZE_T; /* force downstream failure on overflow */
47149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
47159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mem = internal_malloc(ms, req);
47169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
47179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    memset(mem, 0, req);
47189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return mem;
47199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
47209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
47219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
47229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (oldmem == 0)
47239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return mspace_malloc(msp, bytes);
47249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef REALLOC_ZERO_BYTES_FREES
47259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (bytes == 0) {
47269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mspace_free(msp, oldmem);
47279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
47289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
47299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* REALLOC_ZERO_BYTES_FREES */
47309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {
47319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if FOOTERS
47329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mchunkptr p  = mem2chunk(oldmem);
47339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mstate ms = get_mstate_for(p);
47349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else /* FOOTERS */
47359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mstate ms = (mstate)msp;
47369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* FOOTERS */
47379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!ok_magic(ms)) {
47389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      USAGE_ERROR_ACTION(ms,ms);
47399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return 0;
47409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
47419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return internal_realloc(ms, oldmem, bytes);
47429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
47439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
47449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
47459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
47469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate ms = (mstate)msp;
47479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!ok_magic(ms)) {
47489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    USAGE_ERROR_ACTION(ms,ms);
47499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
47509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
47519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return internal_memalign(ms, alignment, bytes);
47529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
47539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
47549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid** mspace_independent_calloc(mspace msp, size_t n_elements,
47559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                 size_t elem_size, void* chunks[]) {
47569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t sz = elem_size; /* serves as 1-element array */
47579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate ms = (mstate)msp;
47589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!ok_magic(ms)) {
47599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    USAGE_ERROR_ACTION(ms,ms);
47609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
47619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
47629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return ialloc(ms, n_elements, &sz, 3, chunks);
47639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
47649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
47659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid** mspace_independent_comalloc(mspace msp, size_t n_elements,
47669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                   size_t sizes[], void* chunks[]) {
47679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate ms = (mstate)msp;
47689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!ok_magic(ms)) {
47699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    USAGE_ERROR_ACTION(ms,ms);
47709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
47719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
47729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return ialloc(ms, n_elements, sizes, 0, chunks);
47739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
47749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
47759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint mspace_trim(mspace msp, size_t pad) {
47769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  int result = 0;
47779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate ms = (mstate)msp;
47789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (ok_magic(ms)) {
47799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!PREACTION(ms)) {
47809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      result = sys_trim(ms, pad);
47819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      POSTACTION(ms);
47829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
47839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
47849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {
47859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    USAGE_ERROR_ACTION(ms,ms);
47869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
47879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return result;
47889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
47899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
47909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid mspace_malloc_stats(mspace msp) {
47919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate ms = (mstate)msp;
47929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (ok_magic(ms)) {
47939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    internal_malloc_stats(ms);
47949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
47959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  else {
47969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    USAGE_ERROR_ACTION(ms,ms);
47979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
47989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
47999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t mspace_footprint(mspace msp) {
48019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t result;
48029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate ms = (mstate)msp;
48039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (ok_magic(ms)) {
48049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    result = ms->footprint;
48059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
48069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  USAGE_ERROR_ACTION(ms,ms);
48079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return result;
48089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
48099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallsize_t mspace_max_footprint(mspace msp) {
48129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  size_t result;
48139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate ms = (mstate)msp;
48149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (ok_magic(ms)) {
48159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    result = ms->max_footprint;
48169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
48179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  USAGE_ERROR_ACTION(ms,ms);
48189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return result;
48199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
48209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !NO_MALLINFO
48239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct mallinfo mspace_mallinfo(mspace msp) {
48249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  mstate ms = (mstate)msp;
48259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  if (!ok_magic(ms)) {
48269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    USAGE_ERROR_ACTION(ms,ms);
48279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
48289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return internal_mallinfo(ms);
48299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
48309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* NO_MALLINFO */
48319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint mspace_mallopt(int param_number, int value) {
48339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  return change_mparam(param_number, value);
48349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
48359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* MSPACES */
48379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -------------------- Alternative MORECORE functions ------------------- */
48399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
48419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  Guidelines for creating a custom version of MORECORE:
48429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * For best performance, MORECORE should allocate in multiples of pagesize.
48449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * MORECORE may allocate more memory than requested. (Or even less,
48459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      but this will usually result in a malloc failure.)
48469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * MORECORE must not allocate memory when given argument zero, but
48479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      instead return one past the end address of memory from previous
48489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      nonzero call.
48499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * For best performance, consecutive calls to MORECORE with positive
48509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      arguments should return increasing addresses, indicating that
48519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      space has been contiguously extended.
48529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * Even though consecutive calls to MORECORE need not return contiguous
48539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      addresses, it must be OK for malloc'ed chunks to span multiple
48549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      regions in those cases where they do happen to be contiguous.
48559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  * MORECORE need not handle negative arguments -- it may instead
48569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      just return MFAIL when given negative arguments.
48579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      Negative arguments are always multiples of pagesize. MORECORE
48589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      must not misinterpret negative args as large positive unsigned
48599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      args. You can suppress all such calls from even occurring by defining
48609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      MORECORE_CANNOT_TRIM,
48619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  As an example alternative MORECORE, here is a custom allocator
48639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  kindly contributed for pre-OSX macOS.  It uses virtually but not
48649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  necessarily physically contiguous non-paged memory (locked in,
48659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  present and won't get swapped out).  You can use it by uncommenting
48669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  this section, adding some #includes, and setting up the appropriate
48679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  defines above:
48689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      #define MORECORE osMoreCore
48709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  There is also a shutdown routine that should somehow be called for
48729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  cleanup upon program exit.
48739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  #define MAX_POOL_ENTRIES 100
48759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  #define MINIMUM_MORECORE_SIZE  (64 * 1024U)
48769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  static int next_os_pool;
48779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  void *our_os_pools[MAX_POOL_ENTRIES];
48789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  void *osMoreCore(int size)
48809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  {
48819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    void *ptr = 0;
48829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    static void *sbrk_top = 0;
48839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
48849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (size > 0)
48859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
48869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (size < MINIMUM_MORECORE_SIZE)
48879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         size = MINIMUM_MORECORE_SIZE;
48889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (CurrentExecutionLevel() == kTaskLevel)
48899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
48909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (ptr == 0)
48919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      {
48929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return (void *) MFAIL;
48939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
48949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      // save ptrs so they can be freed during cleanup
48959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      our_os_pools[next_os_pool] = ptr;
48969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      next_os_pool++;
48979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
48989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      sbrk_top = (char *) ptr + size;
48999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return ptr;
49009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
49019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else if (size < 0)
49029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
49039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      // we don't currently support shrink behavior
49049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return (void *) MFAIL;
49059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
49069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else
49079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
49089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      return sbrk_top;
49099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
49109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
49119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  // cleanup any allocated memory pools
49139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  // called as last thing before shutting down driver
49149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  void osCleanupMem(void)
49169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  {
49179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    void **ptr;
49189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
49209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      if (*ptr)
49219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      {
49229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         PoolDeallocate(*ptr);
49239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         *ptr = 0;
49249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      }
49259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  }
49269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
49289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* -----------------------------------------------------------------------
49319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallHistory:
49329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.8.3 Thu Sep 22 11:16:32 2005  Doug Lea  (dl at gee)
49339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Add max_footprint functions
49349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Ensure all appropriate literals are size_t
49359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Fix conditional compilation problem for some #define settings
49369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Avoid concatenating segments with the one provided
49379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        in create_mspace_with_base
49389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Rename some variables to avoid compiler shadowing warnings
49399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Use explicit lock initialization.
49409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Better handling of sbrk interference.
49419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Simplify and fix segment insertion, trimming and mspace_destroy
49429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
49439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Thanks especially to Dennis Flanagan for help on these.
49449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.8.2 Sun Jun 12 16:01:10 2005  Doug Lea  (dl at gee)
49469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Fix memalign brace error.
49479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.8.1 Wed Jun  8 16:11:46 2005  Doug Lea  (dl at gee)
49499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Fix improper #endif nesting in C++
49509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Add explicit casts needed for C++
49519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.8.0 Mon May 30 14:09:02 2005  Doug Lea  (dl at gee)
49539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Use trees for large bins
49549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Support mspaces
49559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Use segments to unify sbrk-based and mmap-based system allocation,
49569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        removing need for emulation on most platforms without sbrk.
49579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Default safety checks
49589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Optional footer checks. Thanks to William Robertson for the idea.
49599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Internal code refactoring
49609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Incorporate suggestions and platform-specific changes.
49619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
49629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Aaron Bachmann,  Emery Berger, and others.
49639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Speed up non-fastbin processing enough to remove fastbins.
49649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Remove useless cfree() to avoid conflicts with other apps.
49659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Remove internal memcpy, memset. Compilers handle builtins better.
49669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Remove some options that no one ever used and rename others.
49679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
49699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Fix malloc_state bitmap array misdeclaration
49709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.7.1 Thu Jul 25 10:58:03 2002  Doug Lea  (dl at gee)
49729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Allow tuning of FIRST_SORTED_BIN_SIZE
49739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
49749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Better detection and support for non-contiguousness of MORECORE.
49759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
49769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Bypass most of malloc if no frees. Thanks To Emery Berger.
49779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Fix freeing of old top non-contiguous chunk im sysmalloc.
49789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Raised default trim and map thresholds to 256K.
49799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Fix mmap-related #defines. Thanks to Lubos Lunak.
49809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
49819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Branch-free bin calculation
49829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Default trim and mmap thresholds now 256K.
49839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
49859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Introduce independent_comalloc and independent_calloc.
49869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Thanks to Michael Pachos for motivation and help.
49879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Make optional .h file available
49889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Allow > 2GB requests on 32bit systems.
49899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
49909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
49919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        and Anonymous.
49929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
49939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        helping test this.)
49949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * memalign: check alignment arg
49959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * realloc: don't try to shift chunks backwards, since this
49969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        leads to  more fragmentation in some programs and doesn't
49979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        seem to help in any others.
49989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Collect all cases in malloc requiring system memory into sysmalloc
49999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Use mmap as backup to sbrk
50009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Place all internal state in malloc_state
50019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Introduce fastbins (although similar to 2.5.1)
50029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Many minor tunings and cosmetic improvements
50039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
50049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
50059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
50069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Include errno.h to support default failure action.
50079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
50089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
50099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * return null for negative arguments
50109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
50119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
50129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          (e.g. WIN32 platforms)
50139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * Cleanup header file inclusion for WIN32 platforms
50149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * Cleanup code to avoid Microsoft Visual C++ compiler complaints
50159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
50169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           memory allocation routines
50179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
50189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
50199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           usage of 'assert' in non-WIN32 code
50209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
50219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           avoid infinite loop
50229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Always call 'fREe()' rather than 'free()'
50239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
50249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
50259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Fixed ordering problem with boundary-stamping
50269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
50279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
50289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Added pvalloc, as recommended by H.J. Liu
50299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Added 64bit pointer support mainly from Wolfram Gloger
50309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Added anonymously donated WIN32 sbrk emulation
50319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
50329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * malloc_extend_top: fix mask error that caused wastage after
50339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        foreign sbrks
50349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Add linux mremap support code from HJ Liu
50359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
50369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
50379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Integrated most documentation with the code.
50389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Add support for mmap, with help from
50399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
50409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Use last_remainder in more cases.
50419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Pack bins using idea from  colin@nyx10.cs.du.edu
50429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Use ordered bins instead of best-fit threshhold
50439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Eliminate block-local decls to simplify tracing and debugging.
50449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Support another case of realloc via move into top
50459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Fix error occuring when initial sbrk_base not word-aligned.
50469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Rely on page size for units instead of SBRK_UNIT to
50479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        avoid surprises about sbrk alignment conventions.
50489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
50499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        (raymond@es.ele.tue.nl) for the suggestion.
50509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
50519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * More precautions for cases where other routines call sbrk,
50529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
50539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Added macros etc., allowing use in linux libc from
50549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        H.J. Lu (hjl@gnu.ai.mit.edu)
50559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Inverted this history list
50569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
50579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
50589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
50599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Removed all preallocation code since under current scheme
50609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        the work required to undo bad preallocations exceeds
50619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        the work saved in good cases for most test programs.
50629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * No longer use return list or unconsolidated bins since
50639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        no scheme using them consistently outperforms those that don't
50649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        given above changes.
50659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Use best fit for very large chunks to prevent some worst-cases.
50669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Added some support for debugging
50679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
50689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
50699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Removed footers when chunks are in use. Thanks to
50709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Paul Wilson (wilson@cs.texas.edu) for the suggestion.
50719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
50729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
50739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Added malloc_trim, with help from Wolfram Gloger
50749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        (wmglo@Dent.MED.Uni-Muenchen.DE).
50759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
50769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
50779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
50789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
50799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * realloc: try to expand in both directions
50809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * malloc: swap order of clean-bin strategy;
50819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * realloc: only conditionally expand backwards
50829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Try not to scavenge used bins
50839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Use bin counts as a guide to preallocation
50849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Occasionally bin return list chunks in first scan
50859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Add a few optimizations from colin@nyx10.cs.du.edu
50869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
50879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
50889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * faster bin computation & slightly different binning
50899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * merged all consolidations to one part of malloc proper
50909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         (eliminating old malloc_find_space & malloc_clean_bin)
50919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Scan 2 returns chunks (not just 1)
50929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Propagate failure in realloc if malloc returns 0
50939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Add stuff to allow compilation on non-ANSI compilers
50949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          from kpv@research.att.com
50959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
50969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
50979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * removed potential for odd address access in prev_chunk
50989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * removed dependency on getpagesize.h
50999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * misc cosmetics and a bit more internal documentation
51009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * anticosmetics: mangled names in macros to evade debugger strangeness
51019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * tested on sparc, hp-700, dec-mips, rs6000
51029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          with gcc & native cc (hp, dec only) allowing
51039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          Detlefs & Zorn comparison study (in SIGPLAN Notices.)
51049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
51059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
51069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall      * Based loosely on libg++-1.2X malloc. (It retains some of the overall
51079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         structure of old version,  but most details differ.)
51089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
51099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
51109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
51119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* !HAVE_MALLOC */
5112