146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL - Simple DirectMedia Layer
346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Copyright (C) 1997-2006 Sam Lantinga
446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is free software; you can redistribute it and/or
646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    modify it under the terms of the GNU Lesser General Public
746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License as published by the Free Software Foundation; either
846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    version 2.1 of the License, or (at your option) any later version.
946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is distributed in the hope that it will be useful,
1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    but WITHOUT ANY WARRANTY; without even the implied warranty of
1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Lesser General Public License for more details.
1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    You should have received a copy of the GNU Lesser General Public
1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License along with this library; if not, write to the Free Software
1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Sam Lantinga
2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    slouken@libsdl.org
2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h"
2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* This file contains portable memory management functions for SDL */
2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_stdinc.h"
2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef HAVE_MALLOC
2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_SYS_TYPES_H
3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_STDIO_H
3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_STRINGS_H
3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_STRING_H
3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_STDLIB_H
3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ABORT
3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  This is a version (aka dlmalloc) of malloc/free/realloc written by
3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Doug Lea and released to the public domain, as explained at
4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  http://creativecommons.org/licenses/publicdomain.  Send questions,
4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  comments, complaints, performance data, etc to dl@cs.oswego.edu
4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner* Version 2.8.3 Thu Sep 22 11:16:15 2005  Doug Lea  (dl at gee)
4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   Note: There may be an updated version of this malloc obtainable at
4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner           ftp://gee.cs.oswego.edu/pub/misc/malloc.c
4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         Check before installing!
4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner* Quickstart
5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  This library is all in one file to simplify the most common usage:
5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ftp it, compile it (-O3), and link it into another program. All of
5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the compile-time options default to reasonable values for use on
5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  most platforms.  You might later want to step through various
5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  compile-time and dynamic tuning options.
5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  For convenience, an include file for code using this malloc is at:
5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h
5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  You don't really need this .h file unless you call functions not
6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  defined in your system include files.  The .h file contains only the
6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  excerpts from this file needed for using this malloc on ANSI C/C++
6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  systems, so long as you haven't changed compile-time options about
6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  naming and tuning parameters.  If you do, then you can create your
6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  own malloc.h that does include all settings by cutting at the point
6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  indicated below. Note that you may already by default be using a C
6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  library containing a malloc that is based on some version of this
6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc (for example in linux). You might still want to use the one
6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  in this file to customize settings or to avoid overheads associated
6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  with library versions.
7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner* Vital statistics:
7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Supported pointer/size_t representation:       4 or 8 bytes
7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       size_t MUST be an unsigned type of the same width as
7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       pointers. (If you are using an ancient system that declares
7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       size_t as a signed type, or need it to be a different width
7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       than pointers, you can use a previous release of this malloc
7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       (e.g. 2.7.2) supporting these.)
7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Alignment:                                     8 bytes (default)
8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       This suffices for nearly all current machines and C compilers.
8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       However, you can define MALLOC_ALIGNMENT to be wider than this
8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       if necessary (up to 128bytes), at the expense of using more space.
8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Minimum overhead per allocated chunk:   4 or  8 bytes (if 4byte sizes)
8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                          8 or 16 bytes (if 8byte sizes)
8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       Each malloced chunk has a hidden word of overhead holding size
8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       and status information, and additional cross-check word
8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       if FOOTERS is defined.
9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Minimum allocated size: 4-byte ptrs:  16 bytes    (including overhead)
9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                          8-byte ptrs:  32 bytes    (including overhead)
9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       Even a request for zero bytes (i.e., malloc(0)) returns a
9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       pointer to something of the minimum allocatable size.
9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       The maximum overhead wastage (i.e., number of extra bytes
9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       allocated than were requested in malloc) is less than or equal
9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       to the minimum size, except for requests >= mmap_threshold that
9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       are serviced via mmap(), where the worst case wastage is about
10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       32 bytes plus the remainder from a system page (the minimal
10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       mmap unit); typically 4096 or 8192 bytes.
10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Security: static-safe; optionally more or less
10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       The "security" of malloc refers to the ability of malicious
10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       code to accentuate the effects of errors (for example, freeing
10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       space that is not currently malloc'ed or overwriting past the
10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       ends of chunks) in code that calls malloc.  This malloc
10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       guarantees not to modify any memory locations below the base of
10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       heap, i.e., static variables, even in the presence of usage
11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       errors.  The routines additionally detect most improper frees
11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       and reallocs.  All this holds as long as the static bookkeeping
11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       for malloc itself is not corrupted by some other means.  This
11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       is only one aspect of security -- these checks do not, and
11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       cannot, detect all possible programming errors.
11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       If FOOTERS is defined nonzero, then each allocated chunk
11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       carries an additional check word to verify that it was malloced
11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       from its space.  These check words are the same within each
11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       execution of a program using malloc, but differ across
12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       executions, so externally crafted fake chunks cannot be
12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       freed. This improves security by rejecting frees/reallocs that
12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       could corrupt heap memory, in addition to the checks preventing
12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       writes to statics that are always on.  This may further improve
12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       security at the expense of time and space overhead.  (Note that
12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       FOOTERS may also be worth using with MSPACES.)
12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       By default detected errors cause the program to abort (calling
12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       "abort()"). You can override this to instead proceed past
12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       errors by defining PROCEED_ON_ERROR.  In this case, a bad free
13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       has no effect, and a malloc that encounters a bad address
13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       caused by user overwrites will ignore the bad address by
13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       dropping pointers and indices to all known memory. This may
13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       be appropriate for programs that should continue if at all
13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       possible in the face of programming errors, although they may
13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       run out of memory because dropped memory is never reclaimed.
13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       If you don't like either of these options, you can define
13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       else. And if if you are sure that your program using malloc has
14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       no errors or vulnerabilities, you can define INSECURE to 1,
14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       which might (or might not) provide a small performance improvement.
14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Thread-safety: NOT thread-safe unless USE_LOCKS defined
14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       When USE_LOCKS is defined, each public call to malloc, free,
14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       etc is surrounded with either a pthread mutex or a win32
14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       spinlock (depending on WIN32). This is not especially fast, and
14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       can be a major bottleneck.  It is designed only to provide
14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       minimal protection in concurrent environments, and to provide a
14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       basis for extensions.  If you are using malloc in a concurrent
15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       program, consider instead using ptmalloc, which is derived from
15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       a version of this malloc. (See http://www.malloc.de).
15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       This malloc can use unix sbrk or any emulation (invoked using
15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       the CALL_MORECORE macro) and/or mmap/munmap or any emulation
15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       memory.  On most unix systems, it tends to work best if both
15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       MORECORE and MMAP are enabled.  On Win32, it uses emulations
15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       based on VirtualAlloc. It also uses common C library functions
16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       like memset.
16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Compliance: I believe it is compliant with the Single Unix Specification
16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       others as well.
16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner* Overview of algorithms
16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  This is not the fastest, most space-conserving, most portable, or
16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  most tunable malloc ever written. However it is among the fastest
17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  while also being among the most space-conserving, portable and
17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tunable.  Consistent balance across these factors results in a good
17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  general-purpose allocator for malloc-intensive programs.
17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  In most ways, this malloc is a best-fit allocator. Generally, it
17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  chooses the best-fitting existing chunk for a request, with ties
17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  broken in approximately least-recently-used order. (This strategy
17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  normally maintains low fragmentation.) However, for requests less
17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  than 256bytes, it deviates from best-fit when there is not an
17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  exactly fitting available chunk by preferring to use space adjacent
18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  to that used for the previous small request, as well as by breaking
18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ties in approximately most-recently-used order. (These enhance
18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  locality of series of small allocations.)  And for very large requests
18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (>= 256Kb by default), it relies on system memory mapping
18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  facilities, if supported.  (This helps avoid carrying around and
18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  possibly fragmenting memory used only for large chunks.)
18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  All operations (except malloc_stats and mallinfo) have execution
18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  times that are bounded by a constant factor of the number of bits in
18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  a size_t, not counting any clearing in calloc or copying in realloc,
19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  or actions surrounding MORECORE and MMAP that have times
19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  proportional to the number of non-contiguous regions returned by
19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  system allocation routines, which is often just 1.
19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The implementation is not very modular and seriously overuses
19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  macros. Perhaps someday all C compilers will do as good a job
19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  inlining modular code as can now be done by brute-force expansion,
19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  but now, enough of them seem not to.
19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Some compilers issue a lot of warnings about code that is
20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  dead/unreachable only on some platforms, and also about intentional
20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  uses of negation on unsigned types. All known cases of each can be
20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ignored.
20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  For a longer but out of date high-level description, see
20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     http://gee.cs.oswego.edu/dl/html/malloc.html
20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner* MSPACES
20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If MSPACES is defined, then in addition to malloc, free, etc.,
20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  this file also defines mspace_malloc, mspace_free, etc. These
21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  are versions of malloc routines that take an "mspace" argument
21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  obtained using create_mspace, to control all internal bookkeeping.
21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If ONLY_MSPACES is defined, only these versions are compiled.
21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  So if you would like to use this allocator for only some allocations,
21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  and your system malloc for others, you can compile with
21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ONLY_MSPACES and then do something like...
21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    static mspace mymspace = create_mspace(0,0); // for example
21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    #define mymalloc(bytes)  mspace_malloc(mymspace, bytes)
21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (Note: If you only need one instance of an mspace, you can instead
22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  use "USE_DL_PREFIX" to relabel the global malloc.)
22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  You can similarly create thread-local allocators by storing
22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspaces as thread-locals. For example:
22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    static __thread mspace tlms = 0;
22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    void*  tlmalloc(size_t bytes) {
22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (tlms == 0) tlms = create_mspace(0, 0);
22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return mspace_malloc(tlms, bytes);
22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    void  tlfree(void* mem) { mspace_free(tlms, mem); }
23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Unless FOOTERS is defined, each mspace is completely independent.
23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  You cannot allocate from one and free to another (although
23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  conformance is only weakly checked, so usage errors are not always
23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  caught). If FOOTERS is defined, then each chunk carries around a tag
23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  indicating its originating mspace, and frees are directed to their
23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  originating spaces.
23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner -------------------------  Compile-time options ---------------------------
23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
24046be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerBe careful in setting #define values for numerical constants of type
24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t. On some systems, literal values are not automatically extended
24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerto size_t precision unless they are explicitly casted.
24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
24446be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerWIN32                    default: defined if _WIN32 defined
24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Defining WIN32 sets up defaults for MS environment and compilers.
24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Otherwise defaults are for unix.
24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
24846be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerMALLOC_ALIGNMENT         default: (size_t)8
24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Controls the minimum alignment for malloc'ed chunks.  It must be a
25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  power of two and at least 8, even on machines for which smaller
25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  alignments would suffice. It may be defined as larger than this
25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  though. Note however that code and data structures are optimized for
25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the case of 8-byte alignment.
25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
25546be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerMSPACES                  default: 0 (false)
25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If true, compile in support for independent allocation spaces.
25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  This is only supported if HAVE_MMAP is true.
25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
25946be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerONLY_MSPACES             default: 0 (false)
26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If true, only compile in mspace versions, not regular versions.
26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
26246be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUSE_LOCKS                default: 0 (false)
26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Causes each call to each public routine to be surrounded with
26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  pthread or WIN32 mutex lock/unlock. (If set true, this can be
26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  overridden on a per-mspace basis for mspace versions.)
26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
26746be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerFOOTERS                  default: 0
26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If true, provide extra checking and dispatching by placing
26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  information in the footers of allocated chunks. This adds
27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  space and time overhead.
27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
27246be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerINSECURE                 default: 0
27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If true, omit checks for usage errors and heap space overwrites.
27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
27546be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUSE_DL_PREFIX            default: NOT defined
27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Causes compiler to prefix all public routines with the string 'dl'.
27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  This can be useful when you only want to use this malloc in one part
27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  of a program, using your regular system malloc elsewhere.
27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
28046be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerABORT                    default: defined as abort()
28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Defines how to abort on failed checks.  On most systems, a failed
28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  check cannot die with an "assert" or even print an informative
28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  message, because the underlying print routines in turn call malloc,
28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  which will fail again.  Generally, the best policy is to simply call
28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  abort(). It's not very useful to do more than this because many
28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  errors due to overwriting will show up as address faults (null, odd
28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  addresses etc) rather than malloc-triggered checks, so will also
28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  abort.  Also, most compilers know that abort() does not return, so
28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  can better optimize code conditionally calling it.
29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
29146be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerPROCEED_ON_ERROR           default: defined as 0 (false)
29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Controls whether detected bad addresses cause them to bypassed
29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  rather than aborting. If set, detected bad arguments to free and
29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  realloc are ignored. And all bookkeeping information is zeroed out
29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  upon a detected overwrite of freed heap space, thus losing the
29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ability to ever return it from malloc again, but enabling the
29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  application to proceed. If PROCEED_ON_ERROR is defined, the
29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  static variable malloc_corruption_error_count is compiled in
29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  and can be examined to see if errors have occurred. This option
30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  generates slower code than the default abort policy.
30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
30246be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerDEBUG                    default: NOT defined
30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The DEBUG setting is mainly intended for people trying to modify
30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  this code or diagnose problems when porting to new platforms.
30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  However, it may also be able to better isolate user errors than just
30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  using runtime checks.  The assertions in the check routines spell
30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  out in more detail the assumptions and invariants underlying the
30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  algorithms.  The checking is fairly extensive, and will slow down
30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  execution noticeably. Calling malloc_stats or mallinfo with DEBUG
31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  set will attempt to check every non-mmapped allocated and free chunk
31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  in the course of computing the summaries.
31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
31346be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerABORT_ON_ASSERT_FAILURE   default: defined as 1 (true)
31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Debugging assertion failures can be nearly impossible if your
31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  version of the assert macro causes malloc to be called, which will
31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  lead to a cascade of further failures, blowing the runtime stack.
31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),
31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  which will usually make debugging easier.
31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
32046be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerMALLOC_FAILURE_ACTION     default: sets errno to ENOMEM, or no-op on win32
32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The action to take before "return 0" when malloc fails to be able to
32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return memory because there is none available.
32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
32446be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerHAVE_MORECORE             default: 1 (true) unless win32 or ONLY_MSPACES
32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  True if this system supports sbrk or an emulation of it.
32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
32746be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerMORECORE                  default: sbrk
32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The name of the sbrk-style system routine to call to obtain more
32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  memory.  See below for guidance on writing custom MORECORE
33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  functions. The type of the argument to sbrk/MORECORE varies across
33146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  systems.  It cannot be size_t, because it supports negative
33246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  arguments, so it is normally the signed type of the same width as
33346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t (sometimes declared as "intptr_t").  It doesn't much matter
33446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  though. Internally, we only call it with arguments less than half
33546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the max value of a size_t, which should work across all reasonable
33646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  possibilities, although sometimes generating compiler warnings.  See
33746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  near the end of this file for guidelines for creating a custom
33846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  version of MORECORE.
33946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
34046be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerMORECORE_CONTIGUOUS       default: 1 (true)
34146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If true, take advantage of fact that consecutive calls to MORECORE
34246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  with positive arguments always return contiguous increasing
34346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  addresses.  This is true of unix sbrk. It does not hurt too much to
34446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  set it true anyway, since malloc copes with non-contiguities.
34546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Setting it false when definitely non-contiguous saves time
34646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  and possibly wasted space it would take to discover this though.
34746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
34846be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerMORECORE_CANNOT_TRIM      default: NOT defined
34946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  True if MORECORE cannot release space back to the system when given
35046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  negative arguments. This is generally necessary only if you are
35146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  using a hand-crafted MORECORE function that cannot handle negative
35246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  arguments.
35346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
35446be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerHAVE_MMAP                 default: 1 (true)
35546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  True if this system supports mmap or an emulation of it.  If so, and
35646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  HAVE_MORECORE is not true, MMAP is used for all system
35746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  allocation. If set and HAVE_MORECORE is true as well, MMAP is
35846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  primarily used to directly allocate very large blocks. It is also
35946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  used as a backup strategy in cases where MORECORE fails to provide
36046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  space from system. Note: A single call to MUNMAP is assumed to be
36146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  able to unmap memory that may have be allocated using multiple calls
36246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  to MMAP, so long as they are adjacent.
36346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
36446be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerHAVE_MREMAP               default: 1 on linux, else 0
36546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If true realloc() uses mremap() to re-allocate large blocks and
36646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  extend or shrink allocation spaces.
36746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
36846be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerMMAP_CLEARS               default: 1 on unix
36946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  True if mmap clears memory so calloc doesn't need to. This is true
37046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  for standard unix mmap using /dev/zero.
37146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
37246be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUSE_BUILTIN_FFS            default: 0 (i.e., not used)
37346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Causes malloc to use the builtin ffs() function to compute indices.
37446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Some compilers may recognize and intrinsify ffs to be faster than the
37546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  supplied C version. Also, the case of x86 using gcc is special-cased
37646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  to an asm instruction, so is already as fast as it can be, and so
37746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  this setting has no effect. (On most x86s, the asm version is only
37846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  slightly faster than the C version.)
37946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
38046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnermalloc_getpagesize         default: derive from system includes, or 4096.
38146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The system page size. To the extent possible, this malloc manages
38246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  memory from the system in page-size units.  This may be (and
38346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  usually is) a function rather than a constant. This is ignored
38446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if WIN32, where page size is determined using getSystemInfo during
38546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  initialization.
38646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
38746be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUSE_DEV_RANDOM             default: 0 (i.e., not used)
38846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Causes malloc to use /dev/random to initialize secure magic seed for
38946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  stamping footers. Otherwise, the current time is used.
39046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
39146be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerNO_MALLINFO                default: 0
39246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If defined, don't compile "mallinfo". This can be a simple way
39346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  of dealing with mismatches between system declarations and
39446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  those in this file.
39546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
39646be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerMALLINFO_FIELD_TYPE        default: size_t
39746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The type of the fields in the mallinfo struct. This was originally
39846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  defined as "int" in SVID etc, but is more usefully defined as
39946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t. The value is used only if  HAVE_USR_INCLUDE_MALLOC_H is not set
40046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
40146be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerREALLOC_ZERO_BYTES_FREES    default: not defined
40246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  This should be set if a call to realloc with zero bytes should
40346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  be the same as a call to free. Some people think it should. Otherwise,
40446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  since this malloc returns a unique pointer for malloc(0), so does
40546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  realloc(p, 0).
40646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
40746be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerLACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H
40846be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerLACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H,  LACKS_ERRNO_H
40946be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerLACKS_STDLIB_H                default: NOT defined unless on WIN32
41046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Define these if your system does not have these header files.
41146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  You might need to manually insert some of the declarations they provide.
41246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
41346be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerDEFAULT_GRANULARITY        default: page size if MORECORE_CONTIGUOUS,
41446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                system_info.dwAllocationGranularity in WIN32,
41546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                otherwise 64K.
41646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      Also settable using mallopt(M_GRANULARITY, x)
41746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The unit for allocating and deallocating memory from the system.  On
41846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  most systems with contiguous MORECORE, there is no reason to
41946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  make this more than a page. However, systems with MMAP tend to
42046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  either require or encourage larger granularities.  You can increase
42146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  this value to prevent system allocation functions to be called so
42246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  often, especially if they are slow.  The value must be at least one
42346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  page and must be a power of two.  Setting to 0 causes initialization
42446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  to either page size or win32 region size.  (Note: In previous
42546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  versions of malloc, the equivalent of this option was called
42646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  "TOP_PAD")
42746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
42846be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerDEFAULT_TRIM_THRESHOLD    default: 2MB
42946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      Also settable using mallopt(M_TRIM_THRESHOLD, x)
43046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The maximum amount of unused top-most memory to keep before
43146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  releasing via malloc_trim in free().  Automatic trimming is mainly
43246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  useful in long-lived programs using contiguous MORECORE.  Because
43346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  trimming via sbrk can be slow on some systems, and can sometimes be
43446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  wasteful (in cases where programs immediately afterward allocate
43546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  more large chunks) the value should be high enough so that your
43646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  overall system performance would improve by releasing this much
43746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  memory.  As a rough guide, you might set to a value close to the
43846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  average size of a process (program) running on your system.
43946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Releasing this much memory would allow such a process to run in
44046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  memory.  Generally, it is worth tuning trim thresholds when a
44146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  program undergoes phases where several large chunks are allocated
44246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  and released in ways that can reuse each other's storage, perhaps
44346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mixed with phases where there are no such chunks at all. The trim
44446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  value must be greater than page size to have any useful effect.  To
44546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  disable trimming completely, you can set to MAX_SIZE_T. Note that the trick
44646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  some people use of mallocing a huge space and then freeing it at
44746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  program startup, in an attempt to reserve system memory, doesn't
44846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  have the intended effect under automatic trimming, since that memory
44946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  will immediately be returned to the system.
45046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
45146be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerDEFAULT_MMAP_THRESHOLD       default: 256K
45246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      Also settable using mallopt(M_MMAP_THRESHOLD, x)
45346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The request size threshold for using MMAP to directly service a
45446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  request. Requests of at least this size that cannot be allocated
45546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  using already-existing space will be serviced via mmap.  (If enough
45646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  normal freed space already exists it is used instead.)  Using mmap
45746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  segregates relatively large chunks of memory so that they can be
45846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  individually obtained and released from the host system. A request
45946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  serviced through mmap is never reused by any other request (at least
46046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  not directly; the system may just so happen to remap successive
46146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  requests to the same locations).  Segregating space in this way has
46246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the benefits that: Mmapped space can always be individually released
46346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  back to the system, which helps keep the system level memory demands
46446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  of a long-lived program low.  Also, mapped memory doesn't become
46546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  `locked' between other chunks, as can happen with normally allocated
46646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  chunks, which means that even trimming via malloc_trim would not
46746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  release them.  However, it has the disadvantage that the space
46846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  cannot be reclaimed, consolidated, and then used to service later
46946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  requests, as happens with normal chunks.  The advantages of mmap
47046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  nearly always outweigh disadvantages for "large" chunks, but the
47146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  value of "large" may vary across systems.  The default is an
47246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  empirically derived value that works well in most systems. You can
47346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  disable mmap by setting to MAX_SIZE_T.
47446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
47546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
47646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
47746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef WIN32
47846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef _WIN32
47946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define WIN32 1
48046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* _WIN32 */
48146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* WIN32 */
48246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef WIN32
48346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define WIN32_LEAN_AND_MEAN
48446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <windows.h>
48546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define HAVE_MMAP 1
48646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define HAVE_MORECORE 0
48746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_UNISTD_H
48846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_SYS_PARAM_H
48946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_SYS_MMAN_H
49046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_STRING_H
49146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_STRINGS_H
49246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_SYS_TYPES_H
49346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_ERRNO_H
49446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define LACKS_FCNTL_H
49546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MALLOC_FAILURE_ACTION
49646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */
49746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* WIN32 */
49846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
49946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(DARWIN) || defined(_DARWIN)
50046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
50146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef HAVE_MORECORE
50246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define HAVE_MORECORE 0
50346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define HAVE_MMAP 1
50446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* HAVE_MORECORE */
50546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* DARWIN */
50646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
50746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef LACKS_SYS_TYPES_H
50846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/types.h>  /* For size_t */
50946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* LACKS_SYS_TYPES_H */
51046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
51146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The maximum possible size_t value has all bits set */
51246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MAX_SIZE_T           (~(size_t)0)
51346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
51446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef ONLY_MSPACES
51546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ONLY_MSPACES 0
51646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* ONLY_MSPACES */
51746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef MSPACES
51846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if ONLY_MSPACES
51946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MSPACES 1
52046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else   /* ONLY_MSPACES */
52146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MSPACES 0
52246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* ONLY_MSPACES */
52346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* MSPACES */
52446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef MALLOC_ALIGNMENT
52546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MALLOC_ALIGNMENT ((size_t)8U)
52646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* MALLOC_ALIGNMENT */
52746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef FOOTERS
52846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define FOOTERS 0
52946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* FOOTERS */
53046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef ABORT
53146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ABORT  abort()
53246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* ABORT */
53346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef ABORT_ON_ASSERT_FAILURE
53446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ABORT_ON_ASSERT_FAILURE 1
53546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* ABORT_ON_ASSERT_FAILURE */
53646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef PROCEED_ON_ERROR
53746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define PROCEED_ON_ERROR 0
53846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* PROCEED_ON_ERROR */
53946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef USE_LOCKS
54046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define USE_LOCKS 0
54146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* USE_LOCKS */
54246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef INSECURE
54346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define INSECURE 0
54446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* INSECURE */
54546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef HAVE_MMAP
54646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define HAVE_MMAP 1
54746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* HAVE_MMAP */
54846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef MMAP_CLEARS
54946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MMAP_CLEARS 1
55046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* MMAP_CLEARS */
55146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef HAVE_MREMAP
55246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef linux
55346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define HAVE_MREMAP 1
55446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else   /* linux */
55546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define HAVE_MREMAP 0
55646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* linux */
55746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* HAVE_MREMAP */
55846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef MALLOC_FAILURE_ACTION
55946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MALLOC_FAILURE_ACTION  errno = ENOMEM;
56046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* MALLOC_FAILURE_ACTION */
56146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef HAVE_MORECORE
56246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if ONLY_MSPACES
56346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define HAVE_MORECORE 0
56446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else   /* ONLY_MSPACES */
56546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define HAVE_MORECORE 1
56646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* ONLY_MSPACES */
56746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* HAVE_MORECORE */
56846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !HAVE_MORECORE
56946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MORECORE_CONTIGUOUS 0
57046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else   /* !HAVE_MORECORE */
57146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef MORECORE
57246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MORECORE sbrk
57346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* MORECORE */
57446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef MORECORE_CONTIGUOUS
57546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MORECORE_CONTIGUOUS 1
57646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* MORECORE_CONTIGUOUS */
57746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* HAVE_MORECORE */
57846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef DEFAULT_GRANULARITY
57946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if MORECORE_CONTIGUOUS
58046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DEFAULT_GRANULARITY (0)  /* 0 means to compute in init_mparams */
58146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else   /* MORECORE_CONTIGUOUS */
58246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
58346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* MORECORE_CONTIGUOUS */
58446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* DEFAULT_GRANULARITY */
58546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef DEFAULT_TRIM_THRESHOLD
58646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef MORECORE_CANNOT_TRIM
58746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
58846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else   /* MORECORE_CANNOT_TRIM */
58946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
59046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* MORECORE_CANNOT_TRIM */
59146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* DEFAULT_TRIM_THRESHOLD */
59246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef DEFAULT_MMAP_THRESHOLD
59346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if HAVE_MMAP
59446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
59546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else   /* HAVE_MMAP */
59646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
59746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* HAVE_MMAP */
59846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* DEFAULT_MMAP_THRESHOLD */
59946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef USE_BUILTIN_FFS
60046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define USE_BUILTIN_FFS 0
60146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* USE_BUILTIN_FFS */
60246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef USE_DEV_RANDOM
60346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define USE_DEV_RANDOM 0
60446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* USE_DEV_RANDOM */
60546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef NO_MALLINFO
60646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define NO_MALLINFO 0
60746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* NO_MALLINFO */
60846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef MALLINFO_FIELD_TYPE
60946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MALLINFO_FIELD_TYPE size_t
61046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* MALLINFO_FIELD_TYPE */
61146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
61246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define memset	SDL_memset
61346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define memcpy	SDL_memcpy
61446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define malloc	SDL_malloc
61546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define calloc	SDL_calloc
61646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define realloc	SDL_realloc
61746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define free	SDL_free
61846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
61946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
62046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mallopt tuning options.  SVID/XPG defines four standard parameter
62146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  numbers for mallopt, normally defined in malloc.h.  None of these
62246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  are used in this malloc, so setting them has no effect. But this
62346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc does support the following options.
62446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
62546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
62646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define M_TRIM_THRESHOLD     (-1)
62746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define M_GRANULARITY        (-2)
62846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define M_MMAP_THRESHOLD     (-3)
62946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
63046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ------------------------ Mallinfo declarations ------------------------ */
63146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
63246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !NO_MALLINFO
63346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
63446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  This version of malloc supports the standard SVID/XPG mallinfo
63546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  routine that returns a struct containing usage properties and
63646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  statistics. It should work on any system that has a
63746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /usr/include/malloc.h defining struct mallinfo.  The main
63846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  declaration needed is the mallinfo struct that is returned (by-copy)
63946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  by mallinfo().  The malloinfo struct contains a bunch of fields that
64046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  are not even meaningful in this version of malloc.  These fields are
64146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  are instead filled by mallinfo() with other numbers that might be of
64246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  interest.
64346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
64446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
64546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /usr/include/malloc.h file that includes a declaration of struct
64646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mallinfo.  If so, it is included; else a compliant version is
64746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  declared below.  These must be precisely the same for mallinfo() to
64846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  work.  The original SVID version of this struct, defined on most
64946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  systems with mallinfo, declares all fields as ints. But some others
65046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  define as unsigned long. If your system defines the fields using a
65146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  type of different width than listed here, you MUST #include your
65246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  system version and #define HAVE_USR_INCLUDE_MALLOC_H.
65346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
65446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
65546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* #define HAVE_USR_INCLUDE_MALLOC_H */
65646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
65746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef HAVE_USR_INCLUDE_MALLOC_H
65846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "/usr/include/malloc.h"
65946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* HAVE_USR_INCLUDE_MALLOC_H */
66046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
66146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct mallinfo {
66246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MALLINFO_FIELD_TYPE arena;    /* non-mmapped space allocated from system */
66346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MALLINFO_FIELD_TYPE ordblks;  /* number of free chunks */
66446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MALLINFO_FIELD_TYPE smblks;   /* always 0 */
66546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MALLINFO_FIELD_TYPE hblks;    /* always 0 */
66646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MALLINFO_FIELD_TYPE hblkhd;   /* space in mmapped regions */
66746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MALLINFO_FIELD_TYPE usmblks;  /* maximum total allocated space */
66846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MALLINFO_FIELD_TYPE fsmblks;  /* always 0 */
66946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
67046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MALLINFO_FIELD_TYPE fordblks; /* total free space */
67146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
67246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner};
67346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
67446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* HAVE_USR_INCLUDE_MALLOC_H */
67546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* NO_MALLINFO */
67646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
67746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef __cplusplus
67846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerextern "C" {
67946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* __cplusplus */
68046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
68146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !ONLY_MSPACES
68246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
68346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ------------------- Declarations of public routines ------------------- */
68446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
68546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef USE_DL_PREFIX
68646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlcalloc               calloc
68746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlfree                 free
68846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlmalloc               malloc
68946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlmemalign             memalign
69046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlrealloc              realloc
69146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlvalloc               valloc
69246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlpvalloc              pvalloc
69346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlmallinfo             mallinfo
69446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlmallopt              mallopt
69546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlmalloc_trim          malloc_trim
69646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlmalloc_stats         malloc_stats
69746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlmalloc_usable_size   malloc_usable_size
69846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlmalloc_footprint     malloc_footprint
69946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlmalloc_max_footprint malloc_max_footprint
70046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlindependent_calloc   independent_calloc
70146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define dlindependent_comalloc independent_comalloc
70246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* USE_DL_PREFIX */
70346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
70446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
70546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
70646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc(size_t n)
70746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Returns a pointer to a newly allocated chunk of at least n bytes, or
70846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  null if no space is available, in which case errno is set to ENOMEM
70946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  on ANSI C systems.
71046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
71146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If n is zero, malloc returns a minimum-sized chunk. (The minimum
71246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
71346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  systems.)  Note that size_t is an unsigned type, so calls with
71446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  arguments that would be negative if signed are interpreted as
71546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  requests for huge amounts of space, which will often fail. The
71646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  maximum supported value of n differs across systems, but is in all
71746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  cases less than the maximum representable value of a size_t.
71846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
71946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* dlmalloc(size_t);
72046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
72146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
72246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  free(void* p)
72346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Releases the chunk of memory pointed to by p, that had been previously
72446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  allocated using malloc or a related routine such as realloc.
72546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  It has no effect if p is null. If p was not malloced or already
72646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  freed, free(p) will by default cause the current program to abort.
72746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
72846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid  dlfree(void*);
72946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
73046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
73146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  calloc(size_t n_elements, size_t element_size);
73246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Returns a pointer to n_elements * element_size bytes, with all locations
73346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  set to zero.
73446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
73546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* dlcalloc(size_t, size_t);
73646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
73746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
73846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  realloc(void* p, size_t n)
73946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Returns a pointer to a chunk of size n that contains the same data
74046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  as does chunk p up to the minimum of (n, p's size) bytes, or null
74146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if no space is available.
74246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
74346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The returned pointer may or may not be the same as p. The algorithm
74446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  prefers extending p in most cases when possible, otherwise it
74546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  employs the equivalent of a malloc-copy-free sequence.
74646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
74746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If p is null, realloc is equivalent to malloc.
74846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
74946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If space is not available, realloc returns null, errno is set (if on
75046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ANSI) and p is NOT freed.
75146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
75246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if n is for fewer bytes than already held by p, the newly unused
75346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  space is lopped off and freed if possible.  realloc with a size
75446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  argument of zero (re)allocates a minimum-sized chunk.
75546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
75646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The old unix realloc convention of allowing the last-free'd chunk
75746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  to be used as an argument to realloc is not supported.
75846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
75946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
76046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* dlrealloc(void*, size_t);
76146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
76246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
76346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  memalign(size_t alignment, size_t n);
76446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Returns a pointer to a newly allocated chunk of n bytes, aligned
76546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  in accord with the alignment argument.
76646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
76746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The alignment argument should be a power of two. If the argument is
76846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  not a power of two, the nearest greater power is used.
76946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  8-byte alignment is guaranteed by normal malloc calls, so don't
77046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bother calling memalign with an argument of 8 or less.
77146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
77246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Overreliance on memalign is a sure way to fragment space.
77346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
77446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* dlmemalign(size_t, size_t);
77546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
77646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
77746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  valloc(size_t n);
77846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Equivalent to memalign(pagesize, n), where pagesize is the page
77946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size of the system. If the pagesize is unknown, 4096 is used.
78046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
78146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* dlvalloc(size_t);
78246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
78346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
78446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mallopt(int parameter_number, int parameter_value)
78546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Sets tunable parameters The format is to provide a
78646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (parameter-number, parameter-value) pair.  mallopt then sets the
78746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  corresponding parameter to the argument value if it can (i.e., so
78846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  long as the value is meaningful), and returns 1 if successful else
78946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  0.  SVID/XPG/ANSI defines four standard param numbers for mallopt,
79046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  normally defined in malloc.h.  None of these are use in this malloc,
79146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  so setting them has no effect. But this malloc also supports other
79246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  options in mallopt. See below for details.  Briefly, supported
79346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  parameters are as follows (listed defaults are for "typical"
79446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  configurations).
79546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
79646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Symbol            param #  default    allowed param values
79746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  M_TRIM_THRESHOLD     -1   2*1024*1024   any   (MAX_SIZE_T disables)
79846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  M_GRANULARITY        -2     page size   any power of 2 >= page size
79946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  M_MMAP_THRESHOLD     -3      256*1024   any   (or 0 if no MMAP support)
80046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
80146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint dlmallopt(int, int);
80246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
80346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
80446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc_footprint();
80546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Returns the number of bytes obtained from the system.  The total
80646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  number of bytes allocated by malloc, realloc etc., is less than this
80746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  value. Unlike mallinfo, this function returns only a precomputed
80846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  result, so can be called frequently to monitor memory consumption.
80946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Even if locks are otherwise defined, this function does not use them,
81046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  so results might not be up to date.
81146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
81246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t dlmalloc_footprint(void);
81346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
81446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
81546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc_max_footprint();
81646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Returns the maximum number of bytes obtained from the system. This
81746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  value will be greater than current footprint if deallocated space
81846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  has been reclaimed by the system. The peak number of bytes allocated
81946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  by malloc, realloc etc., is less than this value. Unlike mallinfo,
82046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  this function returns only a precomputed result, so can be called
82146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  frequently to monitor memory consumption.  Even if locks are
82246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  otherwise defined, this function does not use them, so results might
82346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  not be up to date.
82446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
82546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t dlmalloc_max_footprint(void);
82646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
82746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !NO_MALLINFO
82846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
82946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mallinfo()
83046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Returns (by copy) a struct containing various summary statistics:
83146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
83246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  arena:     current total non-mmapped bytes allocated from system
83346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ordblks:   the number of free chunks
83446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  smblks:    always zero.
83546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  hblks:     current number of mmapped regions
83646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  hblkhd:    total bytes held in mmapped regions
83746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  usmblks:   the maximum total allocated space. This will be greater
83846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                than current total if trimming has occurred.
83946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  fsmblks:   always zero
84046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  uordblks:  current total allocated space (normal or mmapped)
84146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  fordblks:  total free space
84246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  keepcost:  the maximum number of bytes that could ideally be released
84346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner               back to system via malloc_trim. ("ideally" means that
84446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner               it ignores page restrictions etc.)
84546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
84646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Because these fields are ints, but internal bookkeeping may
84746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  be kept as longs, the reported values may wrap around zero and
84846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  thus be inaccurate.
84946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
85046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct mallinfo dlmallinfo(void);
85146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* NO_MALLINFO */
85246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
85346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
85446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
85546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
85646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  independent_calloc is similar to calloc, but instead of returning a
85746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  single cleared space, it returns an array of pointers to n_elements
85846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  independent elements that can hold contents of size elem_size, each
85946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  of which starts out cleared, and can be independently freed,
86046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  realloc'ed etc. The elements are guaranteed to be adjacently
86146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  allocated (this is not guaranteed to occur with multiple callocs or
86246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mallocs), which may also improve cache locality in some
86346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  applications.
86446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
86546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The "chunks" argument is optional (i.e., may be null, which is
86646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  probably the most typical usage). If it is null, the returned array
86746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  is itself dynamically allocated and should also be freed when it is
86846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  no longer needed. Otherwise, the chunks array must be of at least
86946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  n_elements in length. It is filled in with the pointers to the
87046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  chunks.
87146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
87246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  In either case, independent_calloc returns this pointer array, or
87346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  null if the allocation failed.  If n_elements is zero and "chunks"
87446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  is null, it returns a chunk representing an array with zero elements
87546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (which should be freed if not wanted).
87646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
87746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Each element must be individually freed when it is no longer
87846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  needed. If you'd like to instead be able to free all at once, you
87946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  should instead use regular calloc and assign pointers into this
88046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  space to represent elements.  (In this case though, you cannot
88146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  independently free elements.)
88246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
88346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  independent_calloc simplifies and speeds up implementations of many
88446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  kinds of pools.  It may also be useful when constructing large data
88546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  structures that initially have a fixed number of fixed-sized nodes,
88646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  but the number is not known at compile time, and some of the nodes
88746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  may later need to be freed. For example:
88846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
88946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct Node { int item; struct Node* next; };
89046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
89146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct Node* build_list() {
89246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    struct Node** pool;
89346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int n = read_number_of_nodes_needed();
89446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (n <= 0) return 0;
89546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
89646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (pool == 0) die();
89746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    // organize into a linked list...
89846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    struct Node* first = pool[0];
89946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for (i = 0; i < n-1; ++i)
90046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      pool[i]->next = pool[i+1];
90146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    free(pool);     // Can now free the array (or not, if it is needed later)
90246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return first;
90346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
90446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
90546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid** dlindependent_calloc(size_t, size_t, void**);
90646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
90746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
90846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
90946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
91046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  independent_comalloc allocates, all at once, a set of n_elements
91146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  chunks with sizes indicated in the "sizes" array.    It returns
91246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  an array of pointers to these elements, each of which can be
91346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  independently freed, realloc'ed etc. The elements are guaranteed to
91446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  be adjacently allocated (this is not guaranteed to occur with
91546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  multiple callocs or mallocs), which may also improve cache locality
91646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  in some applications.
91746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
91846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The "chunks" argument is optional (i.e., may be null). If it is null
91946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the returned array is itself dynamically allocated and should also
92046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  be freed when it is no longer needed. Otherwise, the chunks array
92146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  must be of at least n_elements in length. It is filled in with the
92246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  pointers to the chunks.
92346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
92446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  In either case, independent_comalloc returns this pointer array, or
92546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  null if the allocation failed.  If n_elements is zero and chunks is
92646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  null, it returns a chunk representing an array with zero elements
92746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (which should be freed if not wanted).
92846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
92946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Each element must be individually freed when it is no longer
93046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  needed. If you'd like to instead be able to free all at once, you
93146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  should instead use a single regular malloc, and assign pointers at
93246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  particular offsets in the aggregate space. (In this case though, you
93346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  cannot independently free elements.)
93446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
93546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  independent_comallac differs from independent_calloc in that each
93646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  element may have a different size, and also that it does not
93746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  automatically clear elements.
93846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
93946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  independent_comalloc can be used to speed up allocation in cases
94046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  where several structs or objects must always be allocated at the
94146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  same time.  For example:
94246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
94346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct Head { ... }
94446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct Foot { ... }
94546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
94646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  void send_message(char* msg) {
94746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    int msglen = strlen(msg);
94846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
94946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    void* chunks[3];
95046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (independent_comalloc(3, sizes, chunks) == 0)
95146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      die();
95246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    struct Head* head = (struct Head*)(chunks[0]);
95346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    char*        body = (char*)(chunks[1]);
95446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    struct Foot* foot = (struct Foot*)(chunks[2]);
95546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    // ...
95646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
95746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
95846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  In general though, independent_comalloc is worth using only for
95946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  larger values of n_elements. For small values, you probably won't
96046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  detect enough difference from series of malloc calls to bother.
96146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
96246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Overuse of independent_comalloc can increase overall memory usage,
96346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  since it cannot reuse existing noncontiguous small chunks that
96446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  might be available for some of the elements.
96546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
96646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid** dlindependent_comalloc(size_t, size_t*, void**);
96746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
96846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
96946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
97046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  pvalloc(size_t n);
97146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Equivalent to valloc(minimum-page-that-holds(n)), that is,
97246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  round up n to nearest pagesize.
97346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
97446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid*  dlpvalloc(size_t);
97546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
97646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
97746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc_trim(size_t pad);
97846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
97946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If possible, gives memory back to the system (via negative arguments
98046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  to sbrk) if there is unused memory at the `high' end of the malloc
98146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  pool or in unused MMAP segments. You can call this after freeing
98246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  large blocks of memory to potentially reduce the system-level memory
98346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  requirements of a program. However, it cannot guarantee to reduce
98446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  memory. Under some allocation patterns, some large free blocks of
98546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  memory will be locked between two used chunks, so they cannot be
98646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  given back to the system.
98746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
98846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The `pad' argument to malloc_trim represents the amount of free
98946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  trailing space to leave untrimmed. If this argument is zero, only
99046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the minimum amount of memory to maintain internal data structures
99146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  will be left. Non-zero arguments can be supplied to maintain enough
99246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  trailing space to service future expected allocations without having
99346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  to re-obtain memory from the system.
99446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
99546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Malloc_trim returns 1 if it actually released any memory, else 0.
99646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
99746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint  dlmalloc_trim(size_t);
99846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
99946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
100046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc_usable_size(void* p);
100146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
100246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Returns the number of bytes you can actually use in
100346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  an allocated chunk, which may be more than you requested (although
100446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  often not) due to alignment and minimum size constraints.
100546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  You can use this many bytes without worrying about
100646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  overwriting other allocated objects. This is not a particularly great
100746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  programming practice. malloc_usable_size can be more useful in
100846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  debugging and assertions, for example:
100946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
101046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  p = malloc(n);
101146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(malloc_usable_size(p) >= 256);
101246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
101346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t dlmalloc_usable_size(void*);
101446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
101546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
101646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc_stats();
101746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Prints on stderr the amount of space obtained from the system (both
101846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  via sbrk and mmap), the maximum amount (which may be more than
101946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  current if malloc_trim and/or munmap got called), and the current
102046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  number of bytes allocated via malloc (or realloc, etc) but not yet
102146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  freed. Note that this is the number of bytes allocated, not the
102246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  number requested. It will be larger than the number requested
102346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  because of alignment and bookkeeping overhead. Because it includes
102446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  alignment wastage as being in use, this figure may be greater than
102546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  zero even when no user-level chunks are allocated.
102646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
102746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The reported current and maximum system memory can be inaccurate if
102846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  a program makes other calls to system memory allocation functions
102946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (normally sbrk) outside of malloc.
103046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
103146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc_stats prints only the most commonly interesting statistics.
103246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  More information can be obtained by calling mallinfo.
103346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
103446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid  dlmalloc_stats(void);
103546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
103646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* ONLY_MSPACES */
103746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
103846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if MSPACES
103946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
104046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
104146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace is an opaque type representing an independent
104246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  region of space that supports mspace_malloc, etc.
104346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
104446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef void* mspace;
104546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
104646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
104746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  create_mspace creates and returns a new independent space with the
104846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  given initial capacity, or, if 0, the default granularity size.  It
104946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  returns null if there is no system memory available to create the
105046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  space.  If argument locked is non-zero, the space uses a separate
105146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  lock to control access. The capacity of the space will grow
105246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  dynamically as needed to service mspace_malloc requests.  You can
105346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  control the sizes of incremental increases of this space by
105446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  compiling with a different DEFAULT_GRANULARITY or dynamically
105546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  setting with mallopt(M_GRANULARITY, value).
105646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
105746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnermspace create_mspace(size_t capacity, int locked);
105846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
105946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
106046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  destroy_mspace destroys the given space, and attempts to return all
106146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  of its memory back to the system, returning the total number of
106246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bytes freed. After destruction, the results of access to all memory
106346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  used by the space become undefined.
106446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
106546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t destroy_mspace(mspace msp);
106646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
106746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
106846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  create_mspace_with_base uses the memory supplied as the initial base
106946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
107046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  space is used for bookkeeping, so the capacity must be at least this
107146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  large. (Otherwise 0 is returned.) When this initial space is
107246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  exhausted, additional memory will be obtained from the system.
107346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Destroying this space will deallocate all additionally allocated
107446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  space (if possible) but not the initial base.
107546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
107646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnermspace create_mspace_with_base(void* base, size_t capacity, int locked);
107746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
107846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
107946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_malloc behaves as malloc, but operates within
108046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the given space.
108146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
108246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* mspace_malloc(mspace msp, size_t bytes);
108346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
108446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
108546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_free behaves as free, but operates within
108646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the given space.
108746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
108846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If compiled with FOOTERS==1, mspace_free is not actually needed.
108946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  free may be called instead of mspace_free because freed chunks from
109046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  any space are handled by their originating spaces.
109146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
109246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid mspace_free(mspace msp, void* mem);
109346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
109446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
109546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_realloc behaves as realloc, but operates within
109646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the given space.
109746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
109846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If compiled with FOOTERS==1, mspace_realloc is not actually
109946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  needed.  realloc may be called instead of mspace_realloc because
110046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  realloced chunks from any space are handled by their originating
110146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  spaces.
110246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
110346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* mspace_realloc(mspace msp, void* mem, size_t newsize);
110446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
110546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
110646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_calloc behaves as calloc, but operates within
110746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the given space.
110846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
110946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
111046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
111146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
111246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_memalign behaves as memalign, but operates within
111346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the given space.
111446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
111546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
111646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
111746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
111846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_independent_calloc behaves as independent_calloc, but
111946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  operates within the given space.
112046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
112146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid** mspace_independent_calloc(mspace msp, size_t n_elements,
112246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                 size_t elem_size, void* chunks[]);
112346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
112446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
112546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_independent_comalloc behaves as independent_comalloc, but
112646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  operates within the given space.
112746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
112846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid** mspace_independent_comalloc(mspace msp, size_t n_elements,
112946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                   size_t sizes[], void* chunks[]);
113046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
113146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
113246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_footprint() returns the number of bytes obtained from the
113346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  system for this space.
113446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
113546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t mspace_footprint(mspace msp);
113646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
113746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
113846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_max_footprint() returns the peak number of bytes obtained from the
113946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  system for this space.
114046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
114146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t mspace_max_footprint(mspace msp);
114246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
114346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
114446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !NO_MALLINFO
114546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
114646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_mallinfo behaves as mallinfo, but reports properties of
114746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the given space.
114846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
114946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct mallinfo mspace_mallinfo(mspace msp);
115046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* NO_MALLINFO */
115146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
115246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
115346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_malloc_stats behaves as malloc_stats, but reports
115446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  properties of the given space.
115546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
115646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid mspace_malloc_stats(mspace msp);
115746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
115846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
115946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace_trim behaves as malloc_trim, but
116046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  operates within the given space.
116146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
116246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint mspace_trim(mspace msp, size_t pad);
116346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
116446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
116546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  An alias for mallopt.
116646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
116746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint mspace_mallopt(int, int);
116846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
116946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* MSPACES */
117046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
117146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef __cplusplus
117246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner};  /* end of extern "C" */
117346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* __cplusplus */
117446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
117546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
117646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ========================================================================
117746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  To make a fully customizable malloc.h header file, cut everything
117846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  above this line, put into file malloc.h, edit to suit, and #include it
117946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  on the next line, as well as in programs that use this malloc.
118046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ========================================================================
118146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
118246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
118346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* #include "malloc.h" */
118446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
118546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*------------------------------ internal #includes ---------------------- */
118646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
118746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef _MSC_VER
118846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#pragma warning( disable : 4146 ) /* no "unsigned" warnings */
118946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* _MSC_VER */
119046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
119146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef LACKS_STDIO_H
119246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <stdio.h>       /* for printing in malloc_stats */
119346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
119446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
119546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef LACKS_ERRNO_H
119646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <errno.h>       /* for MALLOC_FAILURE_ACTION */
119746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* LACKS_ERRNO_H */
119846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if FOOTERS
119946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <time.h>        /* for magic initialization */
120046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* FOOTERS */
120146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef LACKS_STDLIB_H
120246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <stdlib.h>      /* for abort() */
120346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* LACKS_STDLIB_H */
120446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG
120546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if ABORT_ON_ASSERT_FAILURE
120646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define assert(x) if(!(x)) ABORT
120746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* ABORT_ON_ASSERT_FAILURE */
120846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <assert.h>
120946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* ABORT_ON_ASSERT_FAILURE */
121046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else  /* DEBUG */
121146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define assert(x)
121246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* DEBUG */
121346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef LACKS_STRING_H
121446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <string.h>      /* for memset etc */
121546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* LACKS_STRING_H */
121646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if USE_BUILTIN_FFS
121746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef LACKS_STRINGS_H
121846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <strings.h>     /* for ffs */
121946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* LACKS_STRINGS_H */
122046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* USE_BUILTIN_FFS */
122146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if HAVE_MMAP
122246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef LACKS_SYS_MMAN_H
122346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/mman.h>    /* for mmap */
122446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* LACKS_SYS_MMAN_H */
122546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef LACKS_FCNTL_H
122646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <fcntl.h>
122746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* LACKS_FCNTL_H */
122846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* HAVE_MMAP */
122946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if HAVE_MORECORE
123046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef LACKS_UNISTD_H
123146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <unistd.h>     /* for sbrk */
123246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* LACKS_UNISTD_H */
123346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
123446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerextern void*     sbrk(ptrdiff_t);
123546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* FreeBSD etc */
123646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* LACKS_UNISTD_H */
123746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* HAVE_MMAP */
123846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
123946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef WIN32
124046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef malloc_getpagesize
124146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
124246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#    ifndef _SC_PAGE_SIZE
124346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#      define _SC_PAGE_SIZE _SC_PAGESIZE
124446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#    endif
124546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#  endif
124646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#  ifdef _SC_PAGE_SIZE
124746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
124846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#  else
124946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
125046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       extern size_t getpagesize();
125146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#      define malloc_getpagesize getpagesize()
125246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#    else
125346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#      ifdef WIN32 /* use supplied emulation of getpagesize */
125446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#        define malloc_getpagesize getpagesize()
125546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#      else
125646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#        ifndef LACKS_SYS_PARAM_H
125746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#          include <sys/param.h>
125846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#        endif
125946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#        ifdef EXEC_PAGESIZE
126046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#          define malloc_getpagesize EXEC_PAGESIZE
126146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#        else
126246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#          ifdef NBPG
126346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#            ifndef CLSIZE
126446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#              define malloc_getpagesize NBPG
126546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#            else
126646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#              define malloc_getpagesize (NBPG * CLSIZE)
126746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#            endif
126846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#          else
126946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#            ifdef NBPC
127046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#              define malloc_getpagesize NBPC
127146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#            else
127246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#              ifdef PAGESIZE
127346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#                define malloc_getpagesize PAGESIZE
127446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#              else /* just guess */
127546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#                define malloc_getpagesize ((size_t)4096U)
127646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#              endif
127746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#            endif
127846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#          endif
127946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#        endif
128046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#      endif
128146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#    endif
128246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#  endif
128346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
128446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
128546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
128646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ------------------- size_t and alignment properties -------------------- */
128746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
128846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The byte and bit size of a size_t */
128946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define SIZE_T_SIZE         (sizeof(size_t))
129046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define SIZE_T_BITSIZE      (sizeof(size_t) << 3)
129146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
129246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Some constants coerced to size_t */
129346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Annoying but necessary to avoid errors on some plaftorms */
129446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define SIZE_T_ZERO         ((size_t)0)
129546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define SIZE_T_ONE          ((size_t)1)
129646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define SIZE_T_TWO          ((size_t)2)
129746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define TWO_SIZE_T_SIZES    (SIZE_T_SIZE<<1)
129846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define FOUR_SIZE_T_SIZES   (SIZE_T_SIZE<<2)
129946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define SIX_SIZE_T_SIZES    (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
130046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define HALF_MAX_SIZE_T     (MAX_SIZE_T / 2U)
130146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
130246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The bit mask value corresponding to MALLOC_ALIGNMENT */
130346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CHUNK_ALIGN_MASK    (MALLOC_ALIGNMENT - SIZE_T_ONE)
130446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
130546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* True if address a has acceptable alignment */
130646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define is_aligned(A)       (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
130746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
130846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* the number of bytes to offset an address to align it */
130946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define align_offset(A)\
131046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
131146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
131246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
131346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -------------------------- MMAP preliminaries ------------------------- */
131446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
131546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
131646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
131746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   checks to fail so compiler optimizer can delete code rather than
131846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   using so many "#if"s.
131946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
132046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
132146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
132246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* MORECORE and MMAP must return MFAIL on failure */
132346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MFAIL                ((void*)(MAX_SIZE_T))
132446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CMFAIL               ((char*)(MFAIL)) /* defined for convenience */
132546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
132646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !HAVE_MMAP
132746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define IS_MMAPPED_BIT       (SIZE_T_ZERO)
132846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define USE_MMAP_BIT         (SIZE_T_ZERO)
132946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CALL_MMAP(s)         MFAIL
133046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CALL_MUNMAP(a, s)    (-1)
133146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DIRECT_MMAP(s)       MFAIL
133246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
133346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* HAVE_MMAP */
133446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define IS_MMAPPED_BIT       (SIZE_T_ONE)
133546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define USE_MMAP_BIT         (SIZE_T_ONE)
133646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
133746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef WIN32
133846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CALL_MUNMAP(a, s)    munmap((a), (s))
133946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MMAP_PROT            (PROT_READ|PROT_WRITE)
134046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
134146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MAP_ANONYMOUS        MAP_ANON
134246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* MAP_ANON */
134346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef MAP_ANONYMOUS
134446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MMAP_FLAGS           (MAP_PRIVATE|MAP_ANONYMOUS)
134546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CALL_MMAP(s)         mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
134646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* MAP_ANONYMOUS */
134746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
134846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   Nearly all versions of mmap support MAP_ANONYMOUS, so the following
134946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   is unlikely to be needed, but is supplied just in case.
135046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
135146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MMAP_FLAGS           (MAP_PRIVATE)
135246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
135346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
135446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner           (dev_zero_fd = open("/dev/zero", O_RDWR), \
135546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
135646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
135746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* MAP_ANONYMOUS */
135846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
135946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DIRECT_MMAP(s)       CALL_MMAP(s)
136046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* WIN32 */
136146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
136246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Win32 MMAP via VirtualAlloc */
136346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void* win32mmap(size_t size) {
136446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
136546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return (ptr != 0)? ptr: MFAIL;
136646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
136746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
136846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
136946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void* win32direct_mmap(size_t size) {
137046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
137146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                           PAGE_READWRITE);
137246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return (ptr != 0)? ptr: MFAIL;
137346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
137446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
137546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* This function supports releasing coalesed segments */
137646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int win32munmap(void* ptr, size_t size) {
137746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MEMORY_BASIC_INFORMATION minfo;
137846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  char* cptr = ptr;
137946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  while (size) {
138046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
138146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return -1;
138246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
138346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        minfo.State != MEM_COMMIT || minfo.RegionSize > size)
138446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return -1;
138546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
138646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return -1;
138746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    cptr += minfo.RegionSize;
138846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size -= minfo.RegionSize;
138946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
139046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
139146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
139246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
139346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CALL_MMAP(s)         win32mmap(s)
139446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CALL_MUNMAP(a, s)    win32munmap((a), (s))
139546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DIRECT_MMAP(s)       win32direct_mmap(s)
139646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* WIN32 */
139746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* HAVE_MMAP */
139846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
139946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if HAVE_MMAP && HAVE_MREMAP
140046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
140146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else  /* HAVE_MMAP && HAVE_MREMAP */
140246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
140346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* HAVE_MMAP && HAVE_MREMAP */
140446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
140546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if HAVE_MORECORE
140646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CALL_MORECORE(S)     MORECORE(S)
140746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else  /* HAVE_MORECORE */
140846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CALL_MORECORE(S)     MFAIL
140946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* HAVE_MORECORE */
141046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
141146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* mstate bit set if continguous morecore disabled or failed */
141246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define USE_NONCONTIGUOUS_BIT (4U)
141346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
141446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* segment bit set in create_mspace_with_base */
141546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define EXTERN_BIT            (8U)
141646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
141746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
141846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* --------------------------- Lock preliminaries ------------------------ */
141946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
142046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if USE_LOCKS
142146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
142246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
142346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  When locks are defined, there are up to two global locks:
142446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
142546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * If HAVE_MORECORE, morecore_mutex protects sequences of calls to
142646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MORECORE.  In many cases sys_alloc requires two calls, that should
142746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    not be interleaved with calls by other threads.  This does not
142846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    protect against direct calls to MORECORE by other threads not
142946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    using this lock, so there is still code to cope the best we can on
143046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    interference.
143146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
143246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * magic_init_mutex ensures that mparams.magic and other
143346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    unique mparams values are initialized only once.
143446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
143546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
143646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef WIN32
143746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* By default use posix locks */
143846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <pthread.h>
143946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MLOCK_T pthread_mutex_t
144046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define INITIAL_LOCK(l)      pthread_mutex_init(l, NULL)
144146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ACQUIRE_LOCK(l)      pthread_mutex_lock(l)
144246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RELEASE_LOCK(l)      pthread_mutex_unlock(l)
144346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
144446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if HAVE_MORECORE
144546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER;
144646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* HAVE_MORECORE */
144746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
144846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER;
144946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
145046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* WIN32 */
145146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
145246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   Because lock-protected regions have bounded times, and there
145346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   are no recursive lock calls, we can use simple spinlocks.
145446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
145546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
145646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MLOCK_T long
145746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int win32_acquire_lock (MLOCK_T *sl) {
145846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  for (;;) {
145946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef InterlockedCompareExchangePointer
146046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (!InterlockedCompareExchange(sl, 1, 0))
146146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return 0;
146246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else  /* Use older void* version */
146346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0))
146446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return 0;
146546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* InterlockedCompareExchangePointer */
146646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Sleep (0);
146746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
146846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
146946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
147046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void win32_release_lock (MLOCK_T *sl) {
147146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  InterlockedExchange (sl, 0);
147246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
147346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
147446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define INITIAL_LOCK(l)      *(l)=0
147546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ACQUIRE_LOCK(l)      win32_acquire_lock(l)
147646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RELEASE_LOCK(l)      win32_release_lock(l)
147746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if HAVE_MORECORE
147846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic MLOCK_T morecore_mutex;
147946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* HAVE_MORECORE */
148046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic MLOCK_T magic_init_mutex;
148146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* WIN32 */
148246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
148346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define USE_LOCK_BIT               (2U)
148446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else  /* USE_LOCKS */
148546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define USE_LOCK_BIT               (0U)
148646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define INITIAL_LOCK(l)
148746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* USE_LOCKS */
148846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
148946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if USE_LOCKS && HAVE_MORECORE
149046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ACQUIRE_MORECORE_LOCK()    ACQUIRE_LOCK(&morecore_mutex);
149146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RELEASE_MORECORE_LOCK()    RELEASE_LOCK(&morecore_mutex);
149246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* USE_LOCKS && HAVE_MORECORE */
149346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ACQUIRE_MORECORE_LOCK()
149446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RELEASE_MORECORE_LOCK()
149546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* USE_LOCKS && HAVE_MORECORE */
149646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
149746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if USE_LOCKS
149846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ACQUIRE_MAGIC_INIT_LOCK()  ACQUIRE_LOCK(&magic_init_mutex);
149946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RELEASE_MAGIC_INIT_LOCK()  RELEASE_LOCK(&magic_init_mutex);
150046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else  /* USE_LOCKS */
150146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ACQUIRE_MAGIC_INIT_LOCK()
150246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RELEASE_MAGIC_INIT_LOCK()
150346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* USE_LOCKS */
150446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
150546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
150646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -----------------------  Chunk representations ------------------------ */
150746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
150846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
150946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (The following includes lightly edited explanations by Colin Plumb.)
151046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
151146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The malloc_chunk declaration below is misleading (but accurate and
151246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  necessary).  It declares a "view" into memory allowing access to
151346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  necessary fields at known offsets from a given base.
151446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
151546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Chunks of memory are maintained using a `boundary tag' method as
151646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  originally described by Knuth.  (See the paper by Paul Wilson
151746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
151846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  techniques.)  Sizes of free chunks are stored both in the front of
151946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  each chunk and at the end.  This makes consolidating fragmented
152046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  chunks into bigger chunks fast.  The head fields also hold bits
152146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  representing whether chunks are free or in use.
152246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
152346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Here are some pictures to make it clearer.  They are "exploded" to
152446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  show that the state of a chunk can be thought of as extending from
152546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the high 31 bits of the head field of its header through the
152646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  prev_foot and PINUSE_BIT bit of the following chunk header.
152746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
152846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  A chunk that's in use looks like:
152946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
153046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
153146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner           | Size of previous chunk (if P = 1)                             |
153246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
153346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
153446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         | Size of this chunk                                         1| +-+
153546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
153646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         |                                                               |
153746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         +-                                                             -+
153846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         |                                                               |
153946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         +-                                                             -+
154046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         |                                                               :
154146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         +-      size - sizeof(size_t) available payload bytes          -+
154246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         :                                                               |
154346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner chunk-> +-                                                             -+
154446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         |                                                               |
154546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
154746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       | Size of next chunk (may or may not be in use)               | +-+
154846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
155046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    And if it's free, it looks like this:
155146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
155246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   chunk-> +-                                                             -+
155346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner           | User payload (must be in use, or we would have merged!)       |
155446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
155646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         | Size of this chunk                                         0| +-+
155746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         | Next pointer                                                  |
155946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         | Prev pointer                                                  |
156146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         |                                                               :
156346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         +-      size - sizeof(struct chunk) unused bytes               -+
156446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         :                                                               |
156546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         | Size of this chunk                                            |
156746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
156946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       | Size of next chunk (must be in use, or we would have merged)| +-+
157046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       |                                                               :
157246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       +- User payload                                                -+
157346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       :                                                               |
157446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                                                     |0|
157646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                                                     +-+
157746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Note that since we always merge adjacent free chunks, the chunks
157846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  adjacent to a free chunk must be in use.
157946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
158046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Given a pointer to a chunk (which can be derived trivially from the
158146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  payload pointer) we can, in O(1) time, find out whether the adjacent
158246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  chunks are free, and if so, unlink them from the lists that they
158346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  are on and merge them with the current chunk.
158446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
158546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Chunks always begin on even word boundaries, so the mem portion
158646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (which is returned to the user) is also on an even word boundary, and
158746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  thus at least double-word aligned.
158846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
158946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
159046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  chunk size (which is always a multiple of two words), is an in-use
159146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bit for the *previous* chunk.  If that bit is *clear*, then the
159246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  word before the current chunk size contains the previous chunk
159346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size, and can be used to find the front of the previous chunk.
159446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The very first chunk allocated always has this bit set, preventing
159546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  access to non-existent (or non-owned) memory. If pinuse is set for
159646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  any given chunk, then you CANNOT determine the size of the
159746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  previous chunk, and might even get a memory addressing fault when
159846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  trying to do so.
159946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
160046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
160146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the chunk size redundantly records whether the current chunk is
160246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  inuse. This redundancy enables usage checks within free and realloc,
160346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  and reduces indirection when freeing and consolidating chunks.
160446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
160546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Each freshly allocated chunk must have both cinuse and pinuse set.
160646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  That is, each allocated chunk borders either a previously allocated
160746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  and still in-use chunk, or the base of its memory arena. This is
160846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ensured by making all allocations from the the `lowest' part of any
160946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  found chunk.  Further, no free chunk physically borders another one,
161046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  so each free chunk is known to be preceded and followed by either
161146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  inuse chunks or the ends of memory.
161246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
161346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Note that the `foot' of the current chunk is actually represented
161446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  as the prev_foot of the NEXT chunk. This makes it easier to
161546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  deal with alignments etc but can be very confusing when trying
161646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  to extend or adapt this code.
161746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
161846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The exceptions to all this are
161946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
162046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     1. The special chunk `top' is the top-most available chunk (i.e.,
162146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        the one bordering the end of available memory). It is treated
162246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        specially.  Top is never included in any bin, is used only if
162346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        no other chunk is available, and is released back to the
162446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        system if it is very large (see M_TRIM_THRESHOLD).  In effect,
162546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        the top chunk is treated as larger (and thus less well
162646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        fitting) than any other available chunk.  The top chunk
162746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        doesn't update its trailing size field since there is no next
162846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        contiguous chunk that would have to index off it. However,
162946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        space is still allocated for it (TOP_FOOT_SIZE) to enable
163046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        separation or merging when space is extended.
163146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
163246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     3. Chunks allocated via mmap, which have the lowest-order bit
163346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set
163446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        PINUSE_BIT in their head fields.  Because they are allocated
163546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        one-by-one, each must carry its own prev_foot field, which is
163646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        also used to hold the offset this chunk has within its mmapped
163746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        region, which is needed to preserve alignment. Each mmapped
163846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        chunk is trailed by the first two fields of a fake next-chunk
163946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        for sake of usage checks.
164046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
164146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
164246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
164346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct malloc_chunk {
164446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t               prev_foot;  /* Size of previous chunk (if free).  */
164546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t               head;       /* Size and inuse bits. */
164646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct malloc_chunk* fd;         /* double links -- used only if free. */
164746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct malloc_chunk* bk;
164846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner};
164946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
165046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef struct malloc_chunk  mchunk;
165146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef struct malloc_chunk* mchunkptr;
165246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */
165346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef size_t bindex_t;               /* Described below */
165446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef unsigned int binmap_t;         /* Described below */
165546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef unsigned int flag_t;           /* The type of various bit flag sets */
165646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
165746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ------------------- Chunks sizes and alignments ----------------------- */
165846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
165946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MCHUNK_SIZE         (sizeof(mchunk))
166046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
166146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if FOOTERS
166246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CHUNK_OVERHEAD      (TWO_SIZE_T_SIZES)
166346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* FOOTERS */
166446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CHUNK_OVERHEAD      (SIZE_T_SIZE)
166546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* FOOTERS */
166646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
166746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* MMapped chunks need a second word of overhead ... */
166846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
166946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ... and additional padding for fake next-chunk at foot */
167046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MMAP_FOOT_PAD       (FOUR_SIZE_T_SIZES)
167146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
167246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The smallest size we can malloc is an aligned minimal chunk */
167346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MIN_CHUNK_SIZE\
167446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
167546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
167646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* conversion from malloc headers to user pointers, and back */
167746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define chunk2mem(p)        ((void*)((char*)(p)       + TWO_SIZE_T_SIZES))
167846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define mem2chunk(mem)      ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
167946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* chunk associated with aligned address A */
168046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define align_as_chunk(A)   (mchunkptr)((A) + align_offset(chunk2mem(A)))
168146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
168246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Bounds on request (not chunk) sizes. */
168346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MAX_REQUEST         ((-MIN_CHUNK_SIZE) << 2)
168446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MIN_REQUEST         (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
168546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
168646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* pad request bytes into a usable size */
168746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define pad_request(req) \
168846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
168946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
169046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* pad request, checking for minimum (but not maximum) */
169146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define request2size(req) \
169246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
169346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
169446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
169546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ------------------ Operations on head and foot fields ----------------- */
169646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
169746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
169846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The head field of a chunk is or'ed with PINUSE_BIT when previous
169946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
170046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  use. If the chunk was obtained with mmap, the prev_foot field has
170146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  IS_MMAPPED_BIT set, otherwise holding the offset of the base of the
170246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mmapped region to the base of the chunk.
170346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
170446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
170546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define PINUSE_BIT          (SIZE_T_ONE)
170646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CINUSE_BIT          (SIZE_T_TWO)
170746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define INUSE_BITS          (PINUSE_BIT|CINUSE_BIT)
170846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
170946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Head value for fenceposts */
171046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define FENCEPOST_HEAD      (INUSE_BITS|SIZE_T_SIZE)
171146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
171246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* extraction of fields from head words */
171346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define cinuse(p)           ((p)->head & CINUSE_BIT)
171446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define pinuse(p)           ((p)->head & PINUSE_BIT)
171546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define chunksize(p)        ((p)->head & ~(INUSE_BITS))
171646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
171746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define clear_pinuse(p)     ((p)->head &= ~PINUSE_BIT)
171846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define clear_cinuse(p)     ((p)->head &= ~CINUSE_BIT)
171946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
172046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Treat space at ptr +/- offset as a chunk */
172146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define chunk_plus_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
172246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
172346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
172446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Ptr to next or previous physical malloc_chunk. */
172546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS)))
172646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
172746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
172846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* extract next chunk's pinuse bit */
172946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define next_pinuse(p)  ((next_chunk(p)->head) & PINUSE_BIT)
173046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
173146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Get/set size at footer */
173246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define get_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot)
173346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define set_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
173446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
173546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Set size, pinuse bit, and foot */
173646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define set_size_and_pinuse_of_free_chunk(p, s)\
173746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
173846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
173946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Set size, pinuse bit, foot, and clear next pinuse */
174046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define set_free_with_pinuse(p, s, n)\
174146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
174246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
174346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define is_mmapped(p)\
174446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT))
174546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
174646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Get the internal overhead associated with chunk p */
174746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define overhead_for(p)\
174846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
174946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
175046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Return true if malloced space is not necessarily cleared */
175146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if MMAP_CLEARS
175246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define calloc_must_clear(p) (!is_mmapped(p))
175346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* MMAP_CLEARS */
175446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define calloc_must_clear(p) (1)
175546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* MMAP_CLEARS */
175646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
175746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ---------------------- Overlaid data structures ----------------------- */
175846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
175946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
176046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  When chunks are not in use, they are treated as nodes of either
176146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  lists or trees.
176246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
176346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  "Small"  chunks are stored in circular doubly-linked lists, and look
176446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  like this:
176546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
176646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
176746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             Size of previous chunk                            |
176846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
176946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    `head:' |             Size of chunk, in bytes                         |P|
177046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             Forward pointer to next chunk in list             |
177246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             Back pointer to previous chunk in list            |
177446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             Unused space (may be 0 bytes long)                .
177646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            .                                                               .
177746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            .                                                               |
177846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnernextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    `foot:' |             Size of chunk, in bytes                           |
178046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
178146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
178246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Larger chunks are kept in a form of bitwise digital trees (aka
178346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tries) keyed on chunksizes.  Because malloc_tree_chunks are only for
178446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  free chunks greater than 256 bytes, their size doesn't impose any
178546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  constraints on user chunk sizes.  Each node looks like:
178646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
178746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
178846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             Size of previous chunk                            |
178946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    `head:' |             Size of chunk, in bytes                         |P|
179146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             Forward pointer to next chunk of same size        |
179346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             Back pointer to previous chunk of same size       |
179546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             Pointer to left child (child[0])                  |
179746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             Pointer to right child (child[1])                 |
179946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
180046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             Pointer to parent                                 |
180146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
180246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             bin index of this chunk                           |
180346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
180446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            |             Unused space                                      .
180546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            .                                                               |
180646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnernextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
180746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    `foot:' |             Size of chunk, in bytes                           |
180846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
180946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
181046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Each tree holding treenodes is a tree of unique chunk sizes.  Chunks
181146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  of the same size are arranged in a circularly-linked list, with only
181246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the oldest chunk (the next to be used, in our FIFO ordering)
181346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  actually in the tree.  (Tree members are distinguished by a non-null
181446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  parent pointer.)  If a chunk with the same size an an existing node
181546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  is inserted, it is linked off the existing node using pointers that
181646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  work in the same way as fd/bk pointers of small chunks.
181746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
181846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Each tree contains a power of 2 sized range of chunk sizes (the
181946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  smallest is 0x100 <= x < 0x180), which is is divided in half at each
182046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tree level, with the chunks in the smaller half of the range (0x100
182146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  <= x < 0x140 for the top nose) in the left subtree and the larger
182246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  half (0x140 <= x < 0x180) in the right subtree.  This is, of course,
182346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  done by inspecting individual bits.
182446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
182546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Using these rules, each node's left subtree contains all smaller
182646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  sizes than its right subtree.  However, the node at the root of each
182746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  subtree has no particular ordering relationship to either.  (The
182846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  dividing line between the subtree sizes is based on trie relation.)
182946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  If we remove the last chunk of a given size from the interior of the
183046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tree, we need to replace it with a leaf node.  The tree ordering
183146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  rules permit a node to be replaced by any leaf below it.
183246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
183346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The smallest chunk in a tree (a common operation in a best-fit
183446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  allocator) can be found by walking a path to the leftmost leaf in
183546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the tree.  Unlike a usual binary tree, where we follow left child
183646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  pointers until we reach a null, here we follow the right child
183746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  pointer any time the left one is null, until we reach a leaf with
183846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  both child pointers null. The smallest chunk in the tree will be
183946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  somewhere along that path.
184046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
184146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  The worst case number of steps to add, find, or remove a node is
184246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bounded by the number of bits differentiating chunks within
184346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bins. Under current bin calculations, this ranges from 6 up to 21
184446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
184546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  is of course much better.
184646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
184746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
184846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct malloc_tree_chunk {
184946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* The first four fields must be compatible with malloc_chunk */
185046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t                    prev_foot;
185146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t                    head;
185246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct malloc_tree_chunk* fd;
185346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct malloc_tree_chunk* bk;
185446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
185546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct malloc_tree_chunk* child[2];
185646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct malloc_tree_chunk* parent;
185746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bindex_t                  index;
185846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner};
185946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
186046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef struct malloc_tree_chunk  tchunk;
186146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef struct malloc_tree_chunk* tchunkptr;
186246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
186346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
186446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* A little helper macro for trees */
186546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
186646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
186746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ----------------------------- Segments -------------------------------- */
186846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
186946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
187046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Each malloc space may include non-contiguous segments, held in a
187146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  list headed by an embedded malloc_segment record representing the
187246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  top-most space. Segments also include flags holding properties of
187346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the space. Large chunks that are directly allocated by mmap are not
187446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  included in this list. They are instead independently created and
187546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  destroyed without otherwise keeping track of them.
187646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
187746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Segment management mainly comes into play for spaces allocated by
187846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MMAP.  Any call to MMAP might or might not return memory that is
187946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  adjacent to an existing segment.  MORECORE normally contiguously
188046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  extends the current space, so this space is almost always adjacent,
188146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  which is simpler and faster to deal with. (This is why MORECORE is
188246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  used preferentially to MMAP when both are available -- see
188346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  sys_alloc.)  When allocating using MMAP, we don't use any of the
188446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  hinting mechanisms (inconsistently) supported in various
188546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  implementations of unix mmap, or distinguish reserving from
188646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  committing memory. Instead, we just ask for space, and exploit
188746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  contiguity when we get it.  It is probably possible to do
188846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  better than this on some systems, but no general scheme seems
188946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  to be significantly better.
189046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
189146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Management entails a simpler variant of the consolidation scheme
189246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  used for chunks to reduce fragmentation -- new adjacent memory is
189346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  normally prepended or appended to an existing segment. However,
189446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  there are limitations compared to chunk consolidation that mostly
189546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  reflect the fact that segment processing is relatively infrequent
189646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (occurring only when getting memory from system) and that we
189746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  don't expect to have huge numbers of segments:
189846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
189946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * Segments are not indexed, so traversal requires linear scans.  (It
190046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    would be possible to index these, but is not worth the extra
190146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overhead and complexity for most programs on most platforms.)
190246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * New segments are only appended to old ones when holding top-most
190346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    memory; if they cannot be prepended to others, they are held in
190446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    different segments.
190546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
190646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Except for the top-most segment of an mstate, each segment record
190746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  is kept at the tail of its segment. Segments are added by pushing
190846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  segment records onto the list headed by &mstate.seg for the
190946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  containing mstate.
191046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
191146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Segment flags control allocation/merge/deallocation policies:
191246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * If EXTERN_BIT set, then we did not allocate this segment,
191346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    and so should not try to deallocate or merge with others.
191446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (This currently holds only for the initial segment passed
191546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    into create_mspace_with_base.)
191646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * If IS_MMAPPED_BIT set, the segment may be merged with
191746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    other surrounding mmapped segments and trimmed/de-allocated
191846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    using munmap.
191946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * If neither bit is set, then the segment was obtained using
192046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MORECORE so can be merged with surrounding MORECORE'd segments
192146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    and deallocated/trimmed using MORECORE with negative arguments.
192246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
192346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
192446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct malloc_segment {
192546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  char*        base;             /* base address */
192646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t       size;             /* allocated size */
192746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct malloc_segment* next;   /* ptr to next segment */
192846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  flag_t       sflags;           /* mmap and extern flag */
192946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner};
193046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
193146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define is_mmapped_segment(S)  ((S)->sflags & IS_MMAPPED_BIT)
193246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define is_extern_segment(S)   ((S)->sflags & EXTERN_BIT)
193346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
193446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef struct malloc_segment  msegment;
193546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef struct malloc_segment* msegmentptr;
193646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
193746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ---------------------------- malloc_state ----------------------------- */
193846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
193946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
194046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   A malloc_state holds all of the bookkeeping for a space.
194146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   The main fields are:
194246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
194346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Top
194446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    The topmost chunk of the currently active segment. Its size is
194546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    cached in topsize.  The actual size of topmost space is
194646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    topsize+TOP_FOOT_SIZE, which includes space reserved for adding
194746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    fenceposts and segment records if necessary when getting more
194846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    space from the system.  The size at which to autotrim top is
194946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    cached from mparams in trim_check, except that it is disabled if
195046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    an autotrim fails.
195146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
195246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Designated victim (dv)
195346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This is the preferred chunk for servicing small requests that
195446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    don't have exact fits.  It is normally the chunk split off most
195546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    recently to service another small request.  Its size is cached in
195646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    dvsize. The link fields of this chunk are not maintained since it
195746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    is not kept in a bin.
195846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
195946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  SmallBins
196046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    An array of bin headers for free chunks.  These bins hold chunks
196146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
196246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    chunks of all the same size, spaced 8 bytes apart.  To simplify
196346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    use in double-linked lists, each bin header acts as a malloc_chunk
196446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    pointing to the real first node, if it exists (else pointing to
196546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    itself).  This avoids special-casing for headers.  But to avoid
196646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    waste, we allocate only the fd/bk pointers of bins, and then use
196746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    repositioning tricks to treat these as the fields of a chunk.
196846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
196946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  TreeBins
197046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Treebins are pointers to the roots of trees holding a range of
197146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    sizes. There are 2 equally spaced treebins for each power of two
197246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
197346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    larger.
197446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
197546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Bin maps
197646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    There is one bit map for small bins ("smallmap") and one for
197746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    treebins ("treemap).  Each bin sets its bit when non-empty, and
197846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    clears the bit when empty.  Bit operations are then used to avoid
197946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    bin-by-bin searching -- nearly all "search" is done without ever
198046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    looking at bins that won't be selected.  The bit maps
198146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    conservatively use 32 bits per map word, even if on 64bit system.
198246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    For a good description of some of the bit-based techniques used
198346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    here, see Henry S. Warren Jr's book "Hacker's Delight" (and
198446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    supplement at http://hackersdelight.org/). Many of these are
198546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    intended to reduce the branchiness of paths through malloc etc, as
198646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    well as to reduce the number of memory locations read or written.
198746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
198846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Segments
198946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    A list of segments headed by an embedded malloc_segment record
199046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    representing the initial space.
199146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
199246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Address check support
199346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    The least_addr field is the least address ever obtained from
199446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MORECORE or MMAP. Attempted frees and reallocs of any address less
199546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    than this are trapped (unless INSECURE is defined).
199646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
199746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Magic tag
199846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    A cross-check field that should always hold same value as mparams.magic.
199946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
200046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Flags
200146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Bits recording whether to use MMAP, locks, or contiguous MORECORE
200246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
200346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Statistics
200446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Each space keeps track of current and maximum system memory
200546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    obtained via MORECORE or MMAP.
200646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
200746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Locking
200846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    If USE_LOCKS is defined, the "mutex" lock is acquired and released
200946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    around every public call using this mspace.
201046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
201146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
201246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Bin types, widths and sizes */
201346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define NSMALLBINS        (32U)
201446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define NTREEBINS         (32U)
201546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define SMALLBIN_SHIFT    (3U)
201646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define SMALLBIN_WIDTH    (SIZE_T_ONE << SMALLBIN_SHIFT)
201746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define TREEBIN_SHIFT     (8U)
201846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MIN_LARGE_SIZE    (SIZE_T_ONE << TREEBIN_SHIFT)
201946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MAX_SMALL_SIZE    (MIN_LARGE_SIZE - SIZE_T_ONE)
202046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
202146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
202246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct malloc_state {
202346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  binmap_t   smallmap;
202446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  binmap_t   treemap;
202546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t     dvsize;
202646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t     topsize;
202746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  char*      least_addr;
202846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr  dv;
202946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr  top;
203046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t     trim_check;
203146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t     magic;
203246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr  smallbins[(NSMALLBINS+1)*2];
203346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tbinptr    treebins[NTREEBINS];
203446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t     footprint;
203546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t     max_footprint;
203646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  flag_t     mflags;
203746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if USE_LOCKS
203846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MLOCK_T    mutex;     /* locate lock among fields that rarely change */
203946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* USE_LOCKS */
204046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  msegment   seg;
204146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner};
204246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
204346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef struct malloc_state*    mstate;
204446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
204546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ------------- Global malloc_state and malloc_params ------------------- */
204646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
204746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
204846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc_params holds global properties, including those that can be
204946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  dynamically set using mallopt. There is a single instance, mparams,
205046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  initialized in init_mparams.
205146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
205246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
205346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct malloc_params {
205446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t magic;
205546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t page_size;
205646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t granularity;
205746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t mmap_threshold;
205846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t trim_threshold;
205946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  flag_t default_mflags;
206046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner};
206146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
206246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic struct malloc_params mparams;
206346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
206446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The global malloc_state used for all non-"mspace" calls */
206546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic struct malloc_state _gm_;
206646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define gm                 (&_gm_)
206746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define is_global(M)       ((M) == &_gm_)
206846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define is_initialized(M)  ((M)->top != 0)
206946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
207046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -------------------------- system alloc setup ------------------------- */
207146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
207246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Operations on mflags */
207346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
207446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define use_lock(M)           ((M)->mflags &   USE_LOCK_BIT)
207546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define enable_lock(M)        ((M)->mflags |=  USE_LOCK_BIT)
207646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define disable_lock(M)       ((M)->mflags &= ~USE_LOCK_BIT)
207746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
207846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define use_mmap(M)           ((M)->mflags &   USE_MMAP_BIT)
207946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define enable_mmap(M)        ((M)->mflags |=  USE_MMAP_BIT)
208046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define disable_mmap(M)       ((M)->mflags &= ~USE_MMAP_BIT)
208146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
208246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define use_noncontiguous(M)  ((M)->mflags &   USE_NONCONTIGUOUS_BIT)
208346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define disable_contiguous(M) ((M)->mflags |=  USE_NONCONTIGUOUS_BIT)
208446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
208546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define set_lock(M,L)\
208646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ((M)->mflags = (L)?\
208746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((M)->mflags | USE_LOCK_BIT) :\
208846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((M)->mflags & ~USE_LOCK_BIT))
208946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
209046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* page-align a size */
209146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define page_align(S)\
209246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))
209346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
209446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* granularity-align a size */
209546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define granularity_align(S)\
209646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))
209746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
209846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define is_page_aligned(S)\
209946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
210046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define is_granularity_aligned(S)\
210146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
210246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
210346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*  True if segment S holds address A */
210446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define segment_holds(S, A)\
210546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
210646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
210746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Return segment holding given address */
210846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic msegmentptr segment_holding(mstate m, char* addr) {
210946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  msegmentptr sp = &m->seg;
211046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  for (;;) {
211146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (addr >= sp->base && addr < sp->base + sp->size)
211246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return sp;
211346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ((sp = sp->next) == 0)
211446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return 0;
211546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
211646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
211746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
211846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Return true if segment contains a segment link */
211946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int has_segment_link(mstate m, msegmentptr ss) {
212046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  msegmentptr sp = &m->seg;
212146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  for (;;) {
212246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
212346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return 1;
212446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ((sp = sp->next) == 0)
212546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return 0;
212646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
212746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
212846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
212946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef MORECORE_CANNOT_TRIM
213046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define should_trim(M,s)  ((s) > (M)->trim_check)
213146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else  /* MORECORE_CANNOT_TRIM */
213246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define should_trim(M,s)  (0)
213346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* MORECORE_CANNOT_TRIM */
213446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
213546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
213646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  TOP_FOOT_SIZE is padding at the end of a segment, including space
213746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  that may be needed to place segment records and fenceposts when new
213846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  noncontiguous segments are added.
213946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
214046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define TOP_FOOT_SIZE\
214146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
214246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
214346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
214446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -------------------------------  Hooks -------------------------------- */
214546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
214646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
214746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  PREACTION should be defined to return 0 on success, and nonzero on
214846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  failure. If you are not using locking, you can redefine these to do
214946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  anything you like.
215046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
215146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
215246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if USE_LOCKS
215346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
215446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Ensure locks are initialized */
215546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())
215646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
215746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define PREACTION(M)  ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
215846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
215946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* USE_LOCKS */
216046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
216146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef PREACTION
216246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define PREACTION(M) (0)
216346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* PREACTION */
216446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
216546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef POSTACTION
216646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define POSTACTION(M)
216746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif  /* POSTACTION */
216846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
216946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* USE_LOCKS */
217046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
217146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
217246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
217346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  USAGE_ERROR_ACTION is triggered on detected bad frees and
217446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  reallocs. The argument p is an address that might have triggered the
217546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  fault. It is ignored by the two predefined actions, but might be
217646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  useful in custom actions that try to help diagnose errors.
217746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
217846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
217946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if PROCEED_ON_ERROR
218046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
218146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* A count of the number of corruption errors causing resets */
218246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint malloc_corruption_error_count;
218346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
218446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* default corruption action */
218546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void reset_on_error(mstate m);
218646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
218746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CORRUPTION_ERROR_ACTION(m)  reset_on_error(m)
218846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define USAGE_ERROR_ACTION(m, p)
218946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
219046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* PROCEED_ON_ERROR */
219146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
219246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef CORRUPTION_ERROR_ACTION
219346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CORRUPTION_ERROR_ACTION(m) ABORT
219446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* CORRUPTION_ERROR_ACTION */
219546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
219646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef USAGE_ERROR_ACTION
219746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define USAGE_ERROR_ACTION(m,p) ABORT
219846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* USAGE_ERROR_ACTION */
219946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
220046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* PROCEED_ON_ERROR */
220146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
220246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -------------------------- Debugging setup ---------------------------- */
220346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
220446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if ! DEBUG
220546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
220646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_free_chunk(M,P)
220746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_inuse_chunk(M,P)
220846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_malloced_chunk(M,P,N)
220946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_mmapped_chunk(M,P)
221046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_malloc_state(M)
221146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_top_chunk(M,P)
221246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
221346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* DEBUG */
221446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_free_chunk(M,P)       do_check_free_chunk(M,P)
221546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_inuse_chunk(M,P)      do_check_inuse_chunk(M,P)
221646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_top_chunk(M,P)        do_check_top_chunk(M,P)
221746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
221846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_mmapped_chunk(M,P)    do_check_mmapped_chunk(M,P)
221946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define check_malloc_state(M)       do_check_malloc_state(M)
222046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
222146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void   do_check_any_chunk(mstate m, mchunkptr p);
222246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void   do_check_top_chunk(mstate m, mchunkptr p);
222346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void   do_check_mmapped_chunk(mstate m, mchunkptr p);
222446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void   do_check_inuse_chunk(mstate m, mchunkptr p);
222546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void   do_check_free_chunk(mstate m, mchunkptr p);
222646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void   do_check_malloced_chunk(mstate m, void* mem, size_t s);
222746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void   do_check_tree(mstate m, tchunkptr t);
222846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void   do_check_treebin(mstate m, bindex_t i);
222946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void   do_check_smallbin(mstate m, bindex_t i);
223046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void   do_check_malloc_state(mstate m);
223146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int    bin_find(mstate m, mchunkptr x);
223246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic size_t traverse_and_check(mstate m);
223346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* DEBUG */
223446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
223546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ---------------------------- Indexing Bins ---------------------------- */
223646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
223746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define is_small(s)         (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
223846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define small_index(s)      ((s)  >> SMALLBIN_SHIFT)
223946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define small_index2size(i) ((i)  << SMALLBIN_SHIFT)
224046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))
224146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
224246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* addressing by index. See above about smallbin repositioning */
224346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
224446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define treebin_at(M,i)     (&((M)->treebins[i]))
224546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
224646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* assign tree index for size S to variable I */
224746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(__GNUC__) && defined(i386)
224846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define compute_tree_index(S, I)\
224946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{\
225046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t X = S >> TREEBIN_SHIFT;\
225146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (X == 0)\
225246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    I = 0;\
225346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else if (X > 0xFFFF)\
225446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    I = NTREEBINS-1;\
225546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {\
225646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    unsigned int K;\
225746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm"  (X));\
225846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
225946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
226046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
226146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* GNUC */
226246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define compute_tree_index(S, I)\
226346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{\
226446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t X = S >> TREEBIN_SHIFT;\
226546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (X == 0)\
226646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    I = 0;\
226746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else if (X > 0xFFFF)\
226846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    I = NTREEBINS-1;\
226946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {\
227046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    unsigned int Y = (unsigned int)X;\
227146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    unsigned int N = ((Y - 0x100) >> 16) & 8;\
227246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
227346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    N += K;\
227446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
227546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    K = 14 - N + ((Y <<= K) >> 15);\
227646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
227746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
227846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
227946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* GNUC */
228046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
228146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Bit representing maximum resolved size in a treebin at i */
228246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define bit_for_tree_index(i) \
228346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
228446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
228546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Shift placing maximum resolved bit in a treebin at i as sign bit */
228646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define leftshift_for_tree_index(i) \
228746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   ((i == NTREEBINS-1)? 0 : \
228846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
228946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
229046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The size of the smallest chunk held in bin with index i */
229146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define minsize_for_tree_index(i) \
229246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) |  \
229346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
229446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
229546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
229646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ------------------------ Operations on bin maps ----------------------- */
229746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
229846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* bit corresponding to given index */
229946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define idx2bit(i)              ((binmap_t)(1) << (i))
230046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
230146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Mark/Clear bits with given index */
230246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define mark_smallmap(M,i)      ((M)->smallmap |=  idx2bit(i))
230346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define clear_smallmap(M,i)     ((M)->smallmap &= ~idx2bit(i))
230446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define smallmap_is_marked(M,i) ((M)->smallmap &   idx2bit(i))
230546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
230646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define mark_treemap(M,i)       ((M)->treemap  |=  idx2bit(i))
230746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define clear_treemap(M,i)      ((M)->treemap  &= ~idx2bit(i))
230846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define treemap_is_marked(M,i)  ((M)->treemap  &   idx2bit(i))
230946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
231046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* index corresponding to given bit */
231146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
231246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(__GNUC__) && defined(i386)
231346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define compute_bit2idx(X, I)\
231446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{\
231546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  unsigned int J;\
231646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\
231746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  I = (bindex_t)J;\
231846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
231946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
232046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* GNUC */
232146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if  USE_BUILTIN_FFS
232246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define compute_bit2idx(X, I) I = ffs(X)-1
232346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
232446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* USE_BUILTIN_FFS */
232546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define compute_bit2idx(X, I)\
232646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{\
232746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  unsigned int Y = X - 1;\
232846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  unsigned int K = Y >> (16-4) & 16;\
232946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  unsigned int N = K;        Y >>= K;\
233046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  N += K = Y >> (8-3) &  8;  Y >>= K;\
233146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  N += K = Y >> (4-2) &  4;  Y >>= K;\
233246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  N += K = Y >> (2-1) &  2;  Y >>= K;\
233346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  N += K = Y >> (1-0) &  1;  Y >>= K;\
233446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  I = (bindex_t)(N + Y);\
233546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
233646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* USE_BUILTIN_FFS */
233746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* GNUC */
233846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
233946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* isolate the least set bit of a bitmap */
234046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define least_bit(x)         ((x) & -(x))
234146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
234246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* mask with all bits to left of least bit of x on */
234346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define left_bits(x)         ((x<<1) | -(x<<1))
234446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
234546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* mask with all bits to left of or equal to least bit of x on */
234646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define same_or_left_bits(x) ((x) | -(x))
234746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
234846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
234946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ----------------------- Runtime Check Support ------------------------- */
235046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
235146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
235246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  For security, the main invariant is that malloc/free/etc never
235346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  writes to a static address other than malloc_state, unless static
235446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc_state itself has been corrupted, which cannot occur via
235546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  malloc (because of these checks). In essence this means that we
235646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  believe all pointers, sizes, maps etc held in malloc_state, but
235746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  check all of those linked or offsetted from other embedded data
235846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  structures.  These checks are interspersed with main code in a way
235946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  that tends to minimize their run-time cost.
236046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
236146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  When FOOTERS is defined, in addition to range checking, we also
236246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  verify footer fields of inuse chunks, which can be used guarantee
236346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  that the mstate controlling malloc/free is intact.  This is a
236446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  streamlined version of the approach described by William Robertson
236546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  et al in "Run-time Detection of Heap-based Overflows" LISA'03
236646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  http://www.usenix.org/events/lisa03/tech/robertson.html The footer
236746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  of an inuse chunk holds the xor of its mstate and a random seed,
236846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  that is checked upon calls to free() and realloc().  This is
236946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (probablistically) unguessable from outside the program, but can be
237046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  computed by any code successfully malloc'ing any chunk, so does not
237146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  itself provide protection against code that has already broken
237246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  security through some other means.  Unlike Robertson et al, we
237346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  always dynamically check addresses of all offset chunks (previous,
237446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  next, etc). This turns out to be cheaper than relying on hashes.
237546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
237646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
237746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !INSECURE
237846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check if address a is at least as high as any from MORECORE or MMAP */
237946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
238046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check if address of next chunk n is higher than base chunk p */
238146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ok_next(p, n)    ((char*)(p) < (char*)(n))
238246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check if p has its cinuse bit on */
238346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ok_cinuse(p)     cinuse(p)
238446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check if p has its pinuse bit on */
238546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ok_pinuse(p)     pinuse(p)
238646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
238746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* !INSECURE */
238846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ok_address(M, a) (1)
238946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ok_next(b, n)    (1)
239046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ok_cinuse(p)     (1)
239146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ok_pinuse(p)     (1)
239246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* !INSECURE */
239346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
239446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if (FOOTERS && !INSECURE)
239546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check if (alleged) mstate m has expected magic field */
239646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ok_magic(M)      ((M)->magic == mparams.magic)
239746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else  /* (FOOTERS && !INSECURE) */
239846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ok_magic(M)      (1)
239946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* (FOOTERS && !INSECURE) */
240046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
240146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
240246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* In gcc, use __builtin_expect to minimize impact of checks */
240346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !INSECURE
240446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(__GNUC__) && __GNUC__ >= 3
240546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RTCHECK(e)  __builtin_expect(e, 1)
240646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* GNUC */
240746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RTCHECK(e)  (e)
240846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* GNUC */
240946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* !INSECURE */
241046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define RTCHECK(e)  (1)
241146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* !INSECURE */
241246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
241346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* macros to set up inuse chunks with or without footers */
241446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
241546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !FOOTERS
241646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
241746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define mark_inuse_foot(M,p,s)
241846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
241946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Set cinuse bit and pinuse bit of next chunk */
242046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define set_inuse(M,p,s)\
242146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
242246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
242346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
242446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
242546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define set_inuse_and_pinuse(M,p,s)\
242646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
242746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
242846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
242946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Set size, cinuse and pinuse bit of this chunk */
243046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
243146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
243246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
243346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* FOOTERS */
243446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
243546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Set foot of inuse chunk to be xor of mstate and seed */
243646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define mark_inuse_foot(M,p,s)\
243746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
243846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
243946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define get_mstate_for(p)\
244046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((mstate)(((mchunkptr)((char*)(p) +\
244146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (chunksize(p))))->prev_foot ^ mparams.magic))
244246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
244346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define set_inuse(M,p,s)\
244446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
244546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
244646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mark_inuse_foot(M,p,s))
244746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
244846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define set_inuse_and_pinuse(M,p,s)\
244946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
245046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
245146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner mark_inuse_foot(M,p,s))
245246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
245346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
245446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
245546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mark_inuse_foot(M, p, s))
245646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
245746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* !FOOTERS */
245846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
245946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ---------------------------- setting mparams -------------------------- */
246046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
246146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Initialize mparams */
246246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int init_mparams(void) {
246346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (mparams.page_size == 0) {
246446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t s;
246546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
246646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
246746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
246846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if MORECORE_CONTIGUOUS
246946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
247046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else  /* MORECORE_CONTIGUOUS */
247146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
247246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* MORECORE_CONTIGUOUS */
247346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
247446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if (FOOTERS && !INSECURE)
247546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    {
247646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if USE_DEV_RANDOM
247746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      int fd;
247846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      unsigned char buf[sizeof(size_t)];
247946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      /* Try to use /dev/urandom, else fall back on using time */
248046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
248146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          read(fd, buf, sizeof(buf)) == sizeof(buf)) {
248246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        s = *((size_t *) buf);
248346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        close(fd);
248446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
248546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else
248646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* USE_DEV_RANDOM */
248746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        s = (size_t)(time(0) ^ (size_t)0x55555555U);
248846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
248946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      s |= (size_t)8U;    /* ensure nonzero */
249046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      s &= ~(size_t)7U;   /* improve chances of fault for bad values */
249146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
249246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
249346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* (FOOTERS && !INSECURE) */
249446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    s = (size_t)0x58585858U;
249546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* (FOOTERS && !INSECURE) */
249646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    ACQUIRE_MAGIC_INIT_LOCK();
249746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (mparams.magic == 0) {
249846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mparams.magic = s;
249946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      /* Set up lock for main malloc area */
250046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      INITIAL_LOCK(&gm->mutex);
250146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      gm->mflags = mparams.default_mflags;
250246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
250346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    RELEASE_MAGIC_INIT_LOCK();
250446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
250546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef WIN32
250646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mparams.page_size = malloc_getpagesize;
250746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
250846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                           DEFAULT_GRANULARITY : mparams.page_size);
250946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* WIN32 */
251046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    {
251146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      SYSTEM_INFO system_info;
251246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      GetSystemInfo(&system_info);
251346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mparams.page_size = system_info.dwPageSize;
251446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mparams.granularity = system_info.dwAllocationGranularity;
251546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
251646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* WIN32 */
251746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
251846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* Sanity-check configuration:
251946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       size_t must be unsigned and as wide as pointer type.
252046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       ints must be at least 4 bytes.
252146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       alignment must be at least 8.
252246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       Alignment, min chunk size, and page size must all be powers of 2.
252346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    */
252446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ((sizeof(size_t) != sizeof(char*)) ||
252546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        (MAX_SIZE_T < MIN_CHUNK_SIZE)  ||
252646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        (sizeof(int) < 4)  ||
252746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        (MALLOC_ALIGNMENT < (size_t)8U) ||
252846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        ((MALLOC_ALIGNMENT    & (MALLOC_ALIGNMENT-SIZE_T_ONE))    != 0) ||
252946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        ((MCHUNK_SIZE         & (MCHUNK_SIZE-SIZE_T_ONE))         != 0) ||
253046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||
253146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        ((mparams.page_size   & (mparams.page_size-SIZE_T_ONE))   != 0))
253246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      ABORT;
253346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
253446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
253546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
253646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
253746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* support for mallopt */
253846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int change_mparam(int param_number, int value) {
253946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t val = (size_t)value;
254046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  init_mparams();
254146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  switch(param_number) {
254246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  case M_TRIM_THRESHOLD:
254346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mparams.trim_threshold = val;
254446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 1;
254546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  case M_GRANULARITY:
254646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
254746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mparams.granularity = val;
254846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return 1;
254946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
255046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else
255146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return 0;
255246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  case M_MMAP_THRESHOLD:
255346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mparams.mmap_threshold = val;
255446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 1;
255546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  default:
255646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
255746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
255846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
255946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
256046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if DEBUG
256146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ------------------------- Debugging Support --------------------------- */
256246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
256346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check properties of any chunk, whether free, inuse, mmapped etc  */
256446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void do_check_any_chunk(mstate m, mchunkptr p) {
256546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
256646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(ok_address(m, p));
256746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
256846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
256946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check properties of top chunk */
257046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void do_check_top_chunk(mstate m, mchunkptr p) {
257146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  msegmentptr sp = segment_holding(m, (char*)p);
257246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t  sz = chunksize(p);
257346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(sp != 0);
257446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
257546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(ok_address(m, p));
257646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(sz == m->topsize);
257746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(sz > 0);
257846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
257946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(pinuse(p));
258046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(!next_pinuse(p));
258146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
258246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
258346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check properties of (inuse) mmapped chunks */
258446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void do_check_mmapped_chunk(mstate m, mchunkptr p) {
258546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t  sz = chunksize(p);
258646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD);
258746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(is_mmapped(p));
258846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(use_mmap(m));
258946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
259046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(ok_address(m, p));
259146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(!is_small(sz));
259246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
259346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
259446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
259546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
259646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
259746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check properties of inuse chunks */
259846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void do_check_inuse_chunk(mstate m, mchunkptr p) {
259946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  do_check_any_chunk(m, p);
260046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(cinuse(p));
260146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(next_pinuse(p));
260246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* If not pinuse and not mmapped, previous chunk has OK offset */
260346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
260446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (is_mmapped(p))
260546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do_check_mmapped_chunk(m, p);
260646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
260746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
260846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check properties of free chunks */
260946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void do_check_free_chunk(mstate m, mchunkptr p) {
261046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
261146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr next = chunk_plus_offset(p, sz);
261246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  do_check_any_chunk(m, p);
261346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(!cinuse(p));
261446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(!next_pinuse(p));
261546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert (!is_mmapped(p));
261646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (p != m->dv && p != m->top) {
261746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (sz >= MIN_CHUNK_SIZE) {
261846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert((sz & CHUNK_ALIGN_MASK) == 0);
261946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(is_aligned(chunk2mem(p)));
262046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(next->prev_foot == sz);
262146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(pinuse(p));
262246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert (next == m->top || cinuse(next));
262346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(p->fd->bk == p);
262446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(p->bk->fd == p);
262546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
262646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else  /* markers are always of size SIZE_T_SIZE */
262746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(sz == SIZE_T_SIZE);
262846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
262946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
263046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
263146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check properties of malloced chunks at the point they are malloced */
263246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
263346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (mem != 0) {
263446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr p = mem2chunk(mem);
263546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
263646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do_check_inuse_chunk(m, p);
263746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert((sz & CHUNK_ALIGN_MASK) == 0);
263846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(sz >= MIN_CHUNK_SIZE);
263946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(sz >= s);
264046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
264146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
264246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
264346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
264446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
264546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check a tree and its subtrees.  */
264646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void do_check_tree(mstate m, tchunkptr t) {
264746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tchunkptr head = 0;
264846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tchunkptr u = t;
264946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bindex_t tindex = t->index;
265046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t tsize = chunksize(t);
265146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bindex_t idx;
265246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  compute_tree_index(tsize, idx);
265346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(tindex == idx);
265446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(tsize >= MIN_LARGE_SIZE);
265546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(tsize >= minsize_for_tree_index(idx));
265646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
265746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
265846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  do { /* traverse through chain of same-sized nodes */
265946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do_check_any_chunk(m, ((mchunkptr)u));
266046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(u->index == tindex);
266146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(chunksize(u) == tsize);
266246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(!cinuse(u));
266346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(!next_pinuse(u));
266446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(u->fd->bk == u);
266546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(u->bk->fd == u);
266646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (u->parent == 0) {
266746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(u->child[0] == 0);
266846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(u->child[1] == 0);
266946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
267046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else {
267146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(head == 0); /* only one node on chain has parent */
267246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      head = u;
267346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(u->parent != u);
267446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert (u->parent->child[0] == u ||
267546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              u->parent->child[1] == u ||
267646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              *((tbinptr*)(u->parent)) == u);
267746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (u->child[0] != 0) {
267846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        assert(u->child[0]->parent == u);
267946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        assert(u->child[0] != u);
268046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        do_check_tree(m, u->child[0]);
268146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
268246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (u->child[1] != 0) {
268346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        assert(u->child[1]->parent == u);
268446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        assert(u->child[1] != u);
268546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        do_check_tree(m, u->child[1]);
268646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
268746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (u->child[0] != 0 && u->child[1] != 0) {
268846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        assert(chunksize(u->child[0]) < chunksize(u->child[1]));
268946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
269046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
269146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    u = u->fd;
269246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  } while (u != t);
269346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(head != 0);
269446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
269546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
269646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*  Check all the chunks in a treebin.  */
269746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void do_check_treebin(mstate m, bindex_t i) {
269846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tbinptr* tb = treebin_at(m, i);
269946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tchunkptr t = *tb;
270046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  int empty = (m->treemap & (1U << i)) == 0;
270146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (t == 0)
270246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(empty);
270346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!empty)
270446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do_check_tree(m, t);
270546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
270646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
270746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*  Check all the chunks in a smallbin.  */
270846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void do_check_smallbin(mstate m, bindex_t i) {
270946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  sbinptr b = smallbin_at(m, i);
271046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr p = b->bk;
271146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  unsigned int empty = (m->smallmap & (1U << i)) == 0;
271246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (p == b)
271346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(empty);
271446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!empty) {
271546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for (; p != b; p = p->bk) {
271646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t size = chunksize(p);
271746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr q;
271846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      /* each chunk claims to be free */
271946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      do_check_free_chunk(m, p);
272046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      /* chunk belongs in bin */
272146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(small_index(size) == i);
272246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(p->bk == b || chunksize(p->bk) == chunksize(p));
272346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      /* chunk is followed by an inuse chunk */
272446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      q = next_chunk(p);
272546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (q->head != FENCEPOST_HEAD)
272646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        do_check_inuse_chunk(m, q);
272746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
272846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
272946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
273046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
273146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Find x in a bin. Used in other check functions. */
273246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int bin_find(mstate m, mchunkptr x) {
273346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t size = chunksize(x);
273446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (is_small(size)) {
273546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    bindex_t sidx = small_index(size);
273646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    sbinptr b = smallbin_at(m, sidx);
273746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (smallmap_is_marked(m, sidx)) {
273846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr p = b;
273946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      do {
274046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (p == x)
274146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          return 1;
274246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      } while ((p = p->fd) != b);
274346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
274446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
274546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {
274646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    bindex_t tidx;
274746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    compute_tree_index(size, tidx);
274846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (treemap_is_marked(m, tidx)) {
274946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      tchunkptr t = *treebin_at(m, tidx);
275046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t sizebits = size << leftshift_for_tree_index(tidx);
275146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      while (t != 0 && chunksize(t) != size) {
275246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
275346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        sizebits <<= 1;
275446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
275546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (t != 0) {
275646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        tchunkptr u = t;
275746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        do {
275846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (u == (tchunkptr)x)
275946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            return 1;
276046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        } while ((u = u->fd) != t);
276146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
276246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
276346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
276446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
276546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
276646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
276746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Traverse each chunk and check it; return total */
276846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic size_t traverse_and_check(mstate m) {
276946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t sum = 0;
277046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (is_initialized(m)) {
277146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    msegmentptr s = &m->seg;
277246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    sum += m->topsize + TOP_FOOT_SIZE;
277346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    while (s != 0) {
277446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr q = align_as_chunk(s->base);
277546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr lastq = 0;
277646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(pinuse(q));
277746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      while (segment_holds(s, q) &&
277846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner             q != m->top && q->head != FENCEPOST_HEAD) {
277946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        sum += chunksize(q);
278046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (cinuse(q)) {
278146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          assert(!bin_find(m, q));
278246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          do_check_inuse_chunk(m, q);
278346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
278446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else {
278546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          assert(q == m->dv || bin_find(m, q));
278646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */
278746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          do_check_free_chunk(m, q);
278846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
278946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        lastq = q;
279046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        q = next_chunk(q);
279146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
279246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      s = s->next;
279346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
279446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
279546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return sum;
279646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
279746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
279846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check all properties of malloc_state. */
279946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void do_check_malloc_state(mstate m) {
280046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bindex_t i;
280146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t total;
280246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* check bins */
280346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  for (i = 0; i < NSMALLBINS; ++i)
280446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do_check_smallbin(m, i);
280546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  for (i = 0; i < NTREEBINS; ++i)
280646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do_check_treebin(m, i);
280746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
280846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (m->dvsize != 0) { /* check dv chunk */
280946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do_check_any_chunk(m, m->dv);
281046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(m->dvsize == chunksize(m->dv));
281146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(m->dvsize >= MIN_CHUNK_SIZE);
281246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(bin_find(m, m->dv) == 0);
281346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
281446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
281546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (m->top != 0) {   /* check top chunk */
281646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    do_check_top_chunk(m, m->top);
281746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(m->topsize == chunksize(m->top));
281846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(m->topsize > 0);
281946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(bin_find(m, m->top) == 0);
282046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
282146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
282246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  total = traverse_and_check(m);
282346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(total <= m->footprint);
282446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(m->footprint <= m->max_footprint);
282546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
282646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* DEBUG */
282746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
282846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ----------------------------- statistics ------------------------------ */
282946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
283046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !NO_MALLINFO
283146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic struct mallinfo internal_mallinfo(mstate m) {
283246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
283346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!PREACTION(m)) {
283446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    check_malloc_state(m);
283546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (is_initialized(m)) {
283646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t nfree = SIZE_T_ONE; /* top always free */
283746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t mfree = m->topsize + TOP_FOOT_SIZE;
283846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t sum = mfree;
283946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      msegmentptr s = &m->seg;
284046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      while (s != 0) {
284146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mchunkptr q = align_as_chunk(s->base);
284246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        while (segment_holds(s, q) &&
284346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner               q != m->top && q->head != FENCEPOST_HEAD) {
284446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          size_t sz = chunksize(q);
284546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          sum += sz;
284646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (!cinuse(q)) {
284746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            mfree += sz;
284846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            ++nfree;
284946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
285046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          q = next_chunk(q);
285146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
285246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        s = s->next;
285346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
285446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
285546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nm.arena    = sum;
285646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nm.ordblks  = nfree;
285746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nm.hblkhd   = m->footprint - sum;
285846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nm.usmblks  = m->max_footprint;
285946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nm.uordblks = m->footprint - mfree;
286046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nm.fordblks = mfree;
286146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nm.keepcost = m->topsize;
286246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
286346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
286446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    POSTACTION(m);
286546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
286646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return nm;
286746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
286846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* !NO_MALLINFO */
286946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
287046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void internal_malloc_stats(mstate m) {
287146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!PREACTION(m)) {
287246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t maxfp = 0;
287346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t fp = 0;
287446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t used = 0;
287546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    check_malloc_state(m);
287646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (is_initialized(m)) {
287746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      msegmentptr s = &m->seg;
287846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      maxfp = m->max_footprint;
287946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      fp = m->footprint;
288046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      used = fp - (m->topsize + TOP_FOOT_SIZE);
288146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
288246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      while (s != 0) {
288346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mchunkptr q = align_as_chunk(s->base);
288446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        while (segment_holds(s, q) &&
288546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner               q != m->top && q->head != FENCEPOST_HEAD) {
288646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (!cinuse(q))
288746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            used -= chunksize(q);
288846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          q = next_chunk(q);
288946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
289046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        s = s->next;
289146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
289246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
289346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
289446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef LACKS_STDIO_H
289546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
289646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    fprintf(stderr, "system bytes     = %10lu\n", (unsigned long)(fp));
289746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    fprintf(stderr, "in use bytes     = %10lu\n", (unsigned long)(used));
289846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
289946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
290046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    POSTACTION(m);
290146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
290246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
290346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
290446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ----------------------- Operations on smallbins ----------------------- */
290546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
290646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
290746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Various forms of linking and unlinking are defined as macros.  Even
290846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the ones for trees, which are very long but have very short typical
290946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  paths.  This is ugly but reduces reliance on inlining support of
291046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  compilers.
291146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
291246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
291346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Link a free chunk into a smallbin  */
291446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define insert_small_chunk(M, P, S) {\
291546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bindex_t I  = small_index(S);\
291646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr B = smallbin_at(M, I);\
291746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr F = B;\
291846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(S >= MIN_CHUNK_SIZE);\
291946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!smallmap_is_marked(M, I))\
292046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mark_smallmap(M, I);\
292146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else if (RTCHECK(ok_address(M, B->fd)))\
292246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    F = B->fd;\
292346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {\
292446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    CORRUPTION_ERROR_ACTION(M);\
292546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
292646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  B->fd = P;\
292746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  F->bk = P;\
292846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  P->fd = F;\
292946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  P->bk = B;\
293046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
293146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
293246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Unlink a chunk from a smallbin  */
293346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define unlink_small_chunk(M, P, S) {\
293446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr F = P->fd;\
293546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr B = P->bk;\
293646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bindex_t I = small_index(S);\
293746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(P != B);\
293846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(P != F);\
293946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(chunksize(P) == small_index2size(I));\
294046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (F == B)\
294146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    clear_smallmap(M, I);\
294246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
294346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                   (B == smallbin_at(M,I) || ok_address(M, B)))) {\
294446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    F->bk = B;\
294546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    B->fd = F;\
294646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
294746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {\
294846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    CORRUPTION_ERROR_ACTION(M);\
294946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
295046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
295146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
295246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Unlink the first chunk from a smallbin */
295346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define unlink_first_small_chunk(M, B, P, I) {\
295446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr F = P->fd;\
295546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(P != B);\
295646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(P != F);\
295746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(chunksize(P) == small_index2size(I));\
295846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (B == F)\
295946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    clear_smallmap(M, I);\
296046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else if (RTCHECK(ok_address(M, F))) {\
296146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    B->fd = F;\
296246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    F->bk = B;\
296346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
296446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {\
296546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    CORRUPTION_ERROR_ACTION(M);\
296646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
296746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
296846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
296946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Replace dv node, binning the old one */
297046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Used only when dvsize known to be small */
297146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define replace_dv(M, P, S) {\
297246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t DVS = M->dvsize;\
297346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (DVS != 0) {\
297446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr DV = M->dv;\
297546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(is_small(DVS));\
297646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    insert_small_chunk(M, DV, DVS);\
297746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
297846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  M->dvsize = S;\
297946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  M->dv = P;\
298046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
298146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
298246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ------------------------- Operations on trees ------------------------- */
298346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
298446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Insert chunk into tree */
298546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define insert_large_chunk(M, X, S) {\
298646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tbinptr* H;\
298746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bindex_t I;\
298846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  compute_tree_index(S, I);\
298946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  H = treebin_at(M, I);\
299046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  X->index = I;\
299146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  X->child[0] = X->child[1] = 0;\
299246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!treemap_is_marked(M, I)) {\
299346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mark_treemap(M, I);\
299446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    *H = X;\
299546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    X->parent = (tchunkptr)H;\
299646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    X->fd = X->bk = X;\
299746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
299846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {\
299946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    tchunkptr T = *H;\
300046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t K = S << leftshift_for_tree_index(I);\
300146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for (;;) {\
300246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (chunksize(T) != S) {\
300346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
300446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        K <<= 1;\
300546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (*C != 0)\
300646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          T = *C;\
300746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else if (RTCHECK(ok_address(M, C))) {\
300846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          *C = X;\
300946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          X->parent = T;\
301046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          X->fd = X->bk = X;\
301146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          break;\
301246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }\
301346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else {\
301446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          CORRUPTION_ERROR_ACTION(M);\
301546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          break;\
301646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }\
301746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }\
301846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else {\
301946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        tchunkptr F = T->fd;\
302046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
302146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          T->fd = F->bk = X;\
302246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          X->fd = F;\
302346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          X->bk = T;\
302446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          X->parent = 0;\
302546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          break;\
302646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }\
302746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else {\
302846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          CORRUPTION_ERROR_ACTION(M);\
302946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          break;\
303046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }\
303146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }\
303246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }\
303346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
303446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
303546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
303646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
303746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Unlink steps:
303846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
303946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  1. If x is a chained node, unlink it from its same-sized fd/bk links
304046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     and choose its bk node as its replacement.
304146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  2. If x was the last node of its size, but not a leaf node, it must
304246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     be replaced with a leaf node (not merely one with an open left or
304346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     right), to make sure that lefts and rights of descendents
304446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     correspond properly to bit masks.  We use the rightmost descendent
304546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     of x.  We could use any other leaf, but this is easy to locate and
304646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     tends to counteract removal of leftmosts elsewhere, and so keeps
304746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     paths shorter than minimally guaranteed.  This doesn't loop much
304846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     because on average a node in a tree is near the bottom.
304946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  3. If x is the base of a chain (i.e., has parent links) relink
305046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     x's parent and children to x's replacement (or null if none).
305146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
305246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
305346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define unlink_large_chunk(M, X) {\
305446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tchunkptr XP = X->parent;\
305546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tchunkptr R;\
305646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (X->bk != X) {\
305746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    tchunkptr F = X->fd;\
305846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    R = X->bk;\
305946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (RTCHECK(ok_address(M, F))) {\
306046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      F->bk = R;\
306146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      R->fd = F;\
306246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }\
306346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else {\
306446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      CORRUPTION_ERROR_ACTION(M);\
306546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }\
306646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
306746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {\
306846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    tchunkptr* RP;\
306946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (((R = *(RP = &(X->child[1]))) != 0) ||\
307046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        ((R = *(RP = &(X->child[0]))) != 0)) {\
307146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      tchunkptr* CP;\
307246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      while ((*(CP = &(R->child[1])) != 0) ||\
307346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner             (*(CP = &(R->child[0])) != 0)) {\
307446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        R = *(RP = CP);\
307546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }\
307646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (RTCHECK(ok_address(M, RP)))\
307746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        *RP = 0;\
307846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else {\
307946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        CORRUPTION_ERROR_ACTION(M);\
308046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }\
308146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }\
308246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
308346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (XP != 0) {\
308446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    tbinptr* H = treebin_at(M, X->index);\
308546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (X == *H) {\
308646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if ((*H = R) == 0) \
308746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        clear_treemap(M, X->index);\
308846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }\
308946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else if (RTCHECK(ok_address(M, XP))) {\
309046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (XP->child[0] == X) \
309146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        XP->child[0] = R;\
309246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else \
309346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        XP->child[1] = R;\
309446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }\
309546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else\
309646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      CORRUPTION_ERROR_ACTION(M);\
309746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (R != 0) {\
309846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (RTCHECK(ok_address(M, R))) {\
309946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        tchunkptr C0, C1;\
310046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        R->parent = XP;\
310146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if ((C0 = X->child[0]) != 0) {\
310246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (RTCHECK(ok_address(M, C0))) {\
310346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            R->child[0] = C0;\
310446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            C0->parent = R;\
310546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }\
310646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          else\
310746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            CORRUPTION_ERROR_ACTION(M);\
310846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }\
310946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if ((C1 = X->child[1]) != 0) {\
311046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (RTCHECK(ok_address(M, C1))) {\
311146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            R->child[1] = C1;\
311246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            C1->parent = R;\
311346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }\
311446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          else\
311546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            CORRUPTION_ERROR_ACTION(M);\
311646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }\
311746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }\
311846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else\
311946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        CORRUPTION_ERROR_ACTION(M);\
312046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }\
312146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }\
312246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
312346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
312446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Relays to large vs small bin operations */
312546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
312646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define insert_chunk(M, P, S)\
312746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (is_small(S)) insert_small_chunk(M, P, S)\
312846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
312946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
313046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define unlink_chunk(M, P, S)\
313146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (is_small(S)) unlink_small_chunk(M, P, S)\
313246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
313346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
313446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
313546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Relays to internal calls to malloc/free from realloc, memalign etc */
313646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
313746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if ONLY_MSPACES
313846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define internal_malloc(m, b) mspace_malloc(m, b)
313946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define internal_free(m, mem) mspace_free(m,mem);
314046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* ONLY_MSPACES */
314146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if MSPACES
314246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define internal_malloc(m, b)\
314346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
314446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define internal_free(m, mem)\
314546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   if (m == gm) dlfree(mem); else mspace_free(m,mem);
314646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* MSPACES */
314746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define internal_malloc(m, b) dlmalloc(b)
314846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define internal_free(m, mem) dlfree(mem)
314946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* MSPACES */
315046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* ONLY_MSPACES */
315146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
315246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -----------------------  Direct-mmapping chunks ----------------------- */
315346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
315446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
315546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Directly mmapped chunks are set up with an offset to the start of
315646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the mmapped region stored in the prev_foot field of the chunk. This
315746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  allows reconstruction of the required argument to MUNMAP when freed,
315846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  and also allows adjustment of the returned chunk to meet alignment
315946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  requirements (especially in memalign).  There is also enough space
316046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain
316146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  the PINUSE bit so frees can be checked.
316246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
316346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
316446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Malloc using mmap */
316546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void* mmap_alloc(mstate m, size_t nb) {
316646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
316746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (mmsize > nb) {     /* Check for wrap around 0 */
316846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    char* mm = (char*)(DIRECT_MMAP(mmsize));
316946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (mm != CMFAIL) {
317046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t offset = align_offset(chunk2mem(mm));
317146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t psize = mmsize - offset - MMAP_FOOT_PAD;
317246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr p = (mchunkptr)(mm + offset);
317346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      p->prev_foot = offset | IS_MMAPPED_BIT;
317446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      (p)->head = (psize|CINUSE_BIT);
317546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mark_inuse_foot(m, p, psize);
317646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
317746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
317846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
317946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (mm < m->least_addr)
318046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        m->least_addr = mm;
318146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if ((m->footprint += mmsize) > m->max_footprint)
318246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        m->max_footprint = m->footprint;
318346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(is_aligned(chunk2mem(p)));
318446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_mmapped_chunk(m, p);
318546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return chunk2mem(p);
318646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
318746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
318846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
318946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
319046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
319146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Realloc using mmap */
319246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
319346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t oldsize = chunksize(oldp);
319446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (is_small(nb)) /* Can't shrink mmap regions below small size */
319546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
319646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* Keep old chunk if big enough but not too big */
319746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (oldsize >= nb + SIZE_T_SIZE &&
319846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      (oldsize - nb) <= (mparams.granularity << 1))
319946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return oldp;
320046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {
320146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
320246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
320346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
320446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                         CHUNK_ALIGN_MASK);
320546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
320646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                  oldmmsize, newmmsize, 1);
320746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (cp != CMFAIL) {
320846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr newp = (mchunkptr)(cp + offset);
320946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
321046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      newp->head = (psize|CINUSE_BIT);
321146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mark_inuse_foot(m, newp, psize);
321246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
321346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
321446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
321546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (cp < m->least_addr)
321646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        m->least_addr = cp;
321746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
321846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        m->max_footprint = m->footprint;
321946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_mmapped_chunk(m, newp);
322046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return newp;
322146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
322246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
322346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
322446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
322546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
322646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -------------------------- mspace management -------------------------- */
322746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
322846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Initialize top chunk and its size */
322946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void init_top(mstate m, mchunkptr p, size_t psize) {
323046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* Ensure alignment */
323146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t offset = align_offset(chunk2mem(p));
323246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  p = (mchunkptr)((char*)p + offset);
323346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  psize -= offset;
323446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
323546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->top = p;
323646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->topsize = psize;
323746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  p->head = psize | PINUSE_BIT;
323846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* set size of fake trailing chunk holding overhead space only once */
323946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
324046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->trim_check = mparams.trim_threshold; /* reset on each update */
324146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
324246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
324346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Initialize bins for a new mstate that is otherwise zeroed out */
324446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void init_bins(mstate m) {
324546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* Establish circular links for smallbins */
324646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bindex_t i;
324746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  for (i = 0; i < NSMALLBINS; ++i) {
324846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    sbinptr bin = smallbin_at(m,i);
324946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    bin->fd = bin->bk = bin;
325046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
325146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
325246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
325346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if PROCEED_ON_ERROR
325446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
325546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* default corruption action */
325646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void reset_on_error(mstate m) {
325746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  int i;
325846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  ++malloc_corruption_error_count;
325946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* Reinitialize fields to forget about all memory */
326046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->smallbins = m->treebins = 0;
326146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->dvsize = m->topsize = 0;
326246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->seg.base = 0;
326346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->seg.size = 0;
326446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->seg.next = 0;
326546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->top = m->dv = 0;
326646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  for (i = 0; i < NTREEBINS; ++i)
326746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    *treebin_at(m, i) = 0;
326846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  init_bins(m);
326946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
327046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* PROCEED_ON_ERROR */
327146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
327246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Allocate chunk and prepend remainder with chunk in successor base. */
327346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void* prepend_alloc(mstate m, char* newbase, char* oldbase,
327446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                           size_t nb) {
327546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr p = align_as_chunk(newbase);
327646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr oldfirst = align_as_chunk(oldbase);
327746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t psize = (char*)oldfirst - (char*)p;
327846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr q = chunk_plus_offset(p, nb);
327946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t qsize = psize - nb;
328046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  set_size_and_pinuse_of_inuse_chunk(m, p, nb);
328146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
328246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert((char*)oldfirst > (char*)q);
328346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(pinuse(oldfirst));
328446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(qsize >= MIN_CHUNK_SIZE);
328546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
328646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* consolidate remainder with first chunk of old base */
328746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (oldfirst == m->top) {
328846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t tsize = m->topsize += qsize;
328946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    m->top = q;
329046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    q->head = tsize | PINUSE_BIT;
329146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    check_top_chunk(m, q);
329246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
329346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else if (oldfirst == m->dv) {
329446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t dsize = m->dvsize += qsize;
329546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    m->dv = q;
329646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    set_size_and_pinuse_of_free_chunk(q, dsize);
329746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
329846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {
329946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (!cinuse(oldfirst)) {
330046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t nsize = chunksize(oldfirst);
330146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      unlink_chunk(m, oldfirst, nsize);
330246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      oldfirst = chunk_plus_offset(oldfirst, nsize);
330346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      qsize += nsize;
330446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
330546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    set_free_with_pinuse(q, qsize, oldfirst);
330646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    insert_chunk(m, q, qsize);
330746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    check_free_chunk(m, q);
330846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
330946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
331046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  check_malloced_chunk(m, chunk2mem(p), nb);
331146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return chunk2mem(p);
331246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
331346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
331446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
331546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Add a segment to hold a new noncontiguous region */
331646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
331746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* Determine locations and sizes of segment, fenceposts, old top */
331846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  char* old_top = (char*)m->top;
331946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  msegmentptr oldsp = segment_holding(m, old_top);
332046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  char* old_end = oldsp->base + oldsp->size;
332146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t ssize = pad_request(sizeof(struct malloc_segment));
332246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
332346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t offset = align_offset(chunk2mem(rawsp));
332446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  char* asp = rawsp + offset;
332546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
332646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr sp = (mchunkptr)csp;
332746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  msegmentptr ss = (msegmentptr)(chunk2mem(sp));
332846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr tnext = chunk_plus_offset(sp, ssize);
332946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr p = tnext;
333046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  int nfences = 0;
333146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
333246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* reset top to new space */
333346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
333446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
333546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* Set up segment record */
333646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(is_aligned(ss));
333746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
333846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  *ss = m->seg; /* Push current record */
333946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->seg.base = tbase;
334046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->seg.size = tsize;
334146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->seg.sflags = mmapped;
334246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->seg.next = ss;
334346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
334446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* Insert trailing fenceposts */
334546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  for (;;) {
334646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
334746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    p->head = FENCEPOST_HEAD;
334846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    ++nfences;
334946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ((char*)(&(nextp->head)) < old_end)
335046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      p = nextp;
335146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else
335246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      break;
335346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
335446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(nfences >= 2);
335546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
335646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* Insert the rest of old top into a bin as an ordinary free chunk */
335746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (csp != old_top) {
335846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr q = (mchunkptr)old_top;
335946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t psize = csp - old_top;
336046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr tn = chunk_plus_offset(q, psize);
336146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    set_free_with_pinuse(q, psize, tn);
336246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    insert_chunk(m, q, psize);
336346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
336446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
336546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  check_top_chunk(m, m->top);
336646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
336746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
336846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -------------------------- System allocation -------------------------- */
336946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
337046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Get memory from system using MORECORE or MMAP */
337146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void* sys_alloc(mstate m, size_t nb) {
337246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  char* tbase = CMFAIL;
337346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t tsize = 0;
337446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  flag_t mmap_flag = 0;
337546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
337646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  init_mparams();
337746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
337846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* Directly map large chunks */
337946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (use_mmap(m) && nb >= mparams.mmap_threshold) {
338046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    void* mem = mmap_alloc(m, nb);
338146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (mem != 0)
338246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return mem;
338346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
338446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
338546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /*
338646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Try getting memory in any of three ways (in most-preferred to
338746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    least-preferred order):
338846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    1. A call to MORECORE that can normally contiguously extend memory.
338946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
339046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       or main space is mmapped or a previous contiguous call failed)
339146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    2. A call to MMAP new space (disabled if not HAVE_MMAP).
339246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       Note that under the default settings, if MORECORE is unable to
339346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       fulfill a request, and HAVE_MMAP is true, then mmap is
339446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       used as a noncontiguous system allocator. This is a useful backup
339546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       strategy for systems with holes in address spaces -- in this case
339646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       sbrk cannot contiguously expand the heap, but mmap may be able to
339746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       find space.
339846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    3. A call to MORECORE that cannot usually contiguously extend memory.
339946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       (disabled if not HAVE_MORECORE)
340046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  */
340146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
340246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
340346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    char* br = CMFAIL;
340446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
340546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t asize = 0;
340646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    ACQUIRE_MORECORE_LOCK();
340746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
340846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (ss == 0) {  /* First time through or recovery */
340946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      char* base = (char*)CALL_MORECORE(0);
341046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (base != CMFAIL) {
341146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        asize = granularity_align(nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE);
341246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /* Adjust to end on a page boundary */
341346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (!is_page_aligned(base))
341446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          asize += (page_align((size_t)base) - (size_t)base);
341546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /* Can't call MORECORE if size is negative when treated as signed */
341646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (asize < HALF_MAX_SIZE_T &&
341746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            (br = (char*)(CALL_MORECORE(asize))) == base) {
341846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          tbase = base;
341946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          tsize = asize;
342046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
342146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
342246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
342346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else {
342446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      /* Subtract out existing available top space from MORECORE request. */
342546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE);
342646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      /* Use mem here only if it did continuously extend old space */
342746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (asize < HALF_MAX_SIZE_T &&
342846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
342946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        tbase = br;
343046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        tsize = asize;
343146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
343246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
343346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
343446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (tbase == CMFAIL) {    /* Cope with partial failure */
343546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (br != CMFAIL) {    /* Try to use/extend the space we did get */
343646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (asize < HALF_MAX_SIZE_T &&
343746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
343846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          size_t esize = granularity_align(nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE - asize);
343946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (esize < HALF_MAX_SIZE_T) {
344046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            char* end = (char*)CALL_MORECORE(esize);
344146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            if (end != CMFAIL)
344246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              asize += esize;
344346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            else {            /* Can't use; try to release */
344446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              end = (char*)CALL_MORECORE(-asize);
344546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              br = CMFAIL;
344646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
344746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
344846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
344946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
345046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (br != CMFAIL) {    /* Use the space we did get */
345146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        tbase = br;
345246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        tsize = asize;
345346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
345446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else
345546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        disable_contiguous(m); /* Don't try contiguous path in the future */
345646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
345746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
345846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    RELEASE_MORECORE_LOCK();
345946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
346046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
346146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (HAVE_MMAP && tbase == CMFAIL) {  /* Try MMAP */
346246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t req = nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE;
346346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t rsize = granularity_align(req);
346446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (rsize > nb) { /* Fail if wraps around zero */
346546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      char* mp = (char*)(CALL_MMAP(rsize));
346646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (mp != CMFAIL) {
346746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        tbase = mp;
346846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        tsize = rsize;
346946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mmap_flag = IS_MMAPPED_BIT;
347046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
347146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
347246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
347346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
347446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
347546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t asize = granularity_align(nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE);
347646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (asize < HALF_MAX_SIZE_T) {
347746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      char* br = CMFAIL;
347846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      char* end = CMFAIL;
347946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      ACQUIRE_MORECORE_LOCK();
348046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      br = (char*)(CALL_MORECORE(asize));
348146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      end = (char*)(CALL_MORECORE(0));
348246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      RELEASE_MORECORE_LOCK();
348346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (br != CMFAIL && end != CMFAIL && br < end) {
348446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t ssize = end - br;
348546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (ssize > nb + TOP_FOOT_SIZE) {
348646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          tbase = br;
348746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          tsize = ssize;
348846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
348946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
349046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
349146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
349246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
349346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (tbase != CMFAIL) {
349446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
349546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ((m->footprint += tsize) > m->max_footprint)
349646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      m->max_footprint = m->footprint;
349746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
349846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (!is_initialized(m)) { /* first-time initialization */
349946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      m->seg.base = m->least_addr = tbase;
350046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      m->seg.size = tsize;
350146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      m->seg.sflags = mmap_flag;
350246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      m->magic = mparams.magic;
350346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      init_bins(m);
350446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (is_global(m))
350546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
350646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else {
350746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /* Offset top by embedded malloc_state */
350846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mchunkptr mn = next_chunk(mem2chunk(m));
350946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
351046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
351146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
351246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
351346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else {
351446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      /* Try to merge with an existing segment */
351546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      msegmentptr sp = &m->seg;
351646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      while (sp != 0 && tbase != sp->base + sp->size)
351746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        sp = sp->next;
351846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (sp != 0 &&
351946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          !is_extern_segment(sp) &&
352046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          (sp->sflags & IS_MMAPPED_BIT) == mmap_flag &&
352146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          segment_holds(sp, m->top)) { /* append */
352246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        sp->size += tsize;
352346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        init_top(m, m->top, m->topsize + tsize);
352446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
352546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else {
352646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (tbase < m->least_addr)
352746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          m->least_addr = tbase;
352846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        sp = &m->seg;
352946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        while (sp != 0 && sp->base != tbase + tsize)
353046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          sp = sp->next;
353146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (sp != 0 &&
353246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            !is_extern_segment(sp) &&
353346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) {
353446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          char* oldbase = sp->base;
353546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          sp->base = tbase;
353646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          sp->size += tsize;
353746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          return prepend_alloc(m, tbase, oldbase, nb);
353846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
353946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else
354046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          add_segment(m, tbase, tsize, mmap_flag);
354146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
354246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
354346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
354446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (nb < m->topsize) { /* Allocate from new or extended top space */
354546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t rsize = m->topsize -= nb;
354646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr p = m->top;
354746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr r = m->top = chunk_plus_offset(p, nb);
354846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      r->head = rsize | PINUSE_BIT;
354946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      set_size_and_pinuse_of_inuse_chunk(m, p, nb);
355046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_top_chunk(m, m->top);
355146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_malloced_chunk(m, chunk2mem(p), nb);
355246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return chunk2mem(p);
355346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
355446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
355546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
355646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  MALLOC_FAILURE_ACTION;
355746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
355846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
355946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
356046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -----------------------  system deallocation -------------------------- */
356146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
356246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Unmap and unlink any mmapped segments that don't contain used chunks */
356346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic size_t release_unused_segments(mstate m) {
356446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t released = 0;
356546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  msegmentptr pred = &m->seg;
356646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  msegmentptr sp = pred->next;
356746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  while (sp != 0) {
356846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    char* base = sp->base;
356946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t size = sp->size;
357046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    msegmentptr next = sp->next;
357146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
357246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr p = align_as_chunk(base);
357346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t psize = chunksize(p);
357446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      /* Can unmap if first chunk holds entire segment and not pinned */
357546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
357646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        tchunkptr tp = (tchunkptr)p;
357746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        assert(segment_holds(sp, (char*)sp));
357846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (p == m->dv) {
357946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          m->dv = 0;
358046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          m->dvsize = 0;
358146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
358246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else {
358346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          unlink_large_chunk(m, tp);
358446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
358546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (CALL_MUNMAP(base, size) == 0) {
358646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          released += size;
358746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          m->footprint -= size;
358846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          /* unlink obsoleted record */
358946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          sp = pred;
359046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          sp->next = next;
359146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
359246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else { /* back out if cannot unmap */
359346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          insert_large_chunk(m, tp, psize);
359446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
359546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
359646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
359746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    pred = sp;
359846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    sp = next;
359946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
360046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return released;
360146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
360246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
360346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int sys_trim(mstate m, size_t pad) {
360446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t released = 0;
360546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (pad < MAX_REQUEST && is_initialized(m)) {
360646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
360746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
360846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (m->topsize > pad) {
360946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      /* Shrink top space in granularity-size units, keeping at least one */
361046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t unit = mparams.granularity;
361146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
361246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                      SIZE_T_ONE) * unit;
361346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      msegmentptr sp = segment_holding(m, (char*)m->top);
361446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
361546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (!is_extern_segment(sp)) {
361646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (is_mmapped_segment(sp)) {
361746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (HAVE_MMAP &&
361846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              sp->size >= extra &&
361946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              !has_segment_link(m, sp)) { /* can't shrink if pinned */
362046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            size_t newsize = sp->size - extra;
362146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            /* Prefer mremap, fall back to munmap */
362246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
362346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
362446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              released = extra;
362546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
362646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
362746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
362846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else if (HAVE_MORECORE) {
362946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
363046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
363146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          ACQUIRE_MORECORE_LOCK();
363246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          {
363346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            /* Make sure end of memory is where we last set it. */
363446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            char* old_br = (char*)(CALL_MORECORE(0));
363546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            if (old_br == sp->base + sp->size) {
363646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              char* rel_br = (char*)(CALL_MORECORE(-extra));
363746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              char* new_br = (char*)(CALL_MORECORE(0));
363846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              if (rel_br != CMFAIL && new_br < old_br)
363946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                released = old_br - new_br;
364046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
364146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
364246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          RELEASE_MORECORE_LOCK();
364346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
364446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
364546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
364646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (released != 0) {
364746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        sp->size -= released;
364846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        m->footprint -= released;
364946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        init_top(m, m->top, m->topsize - released);
365046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        check_top_chunk(m, m->top);
365146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
365246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
365346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
365446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* Unmap any unused mmapped segments */
365546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (HAVE_MMAP)
365646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      released += release_unused_segments(m);
365746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
365846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* On failure, disable autotrim to avoid repeated failed future calls */
365946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (released == 0)
366046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      m->trim_check = MAX_SIZE_T;
366146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
366246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
366346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return (released != 0)? 1 : 0;
366446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
366546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
366646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ---------------------------- malloc support --------------------------- */
366746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
366846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* allocate a large request from the best fitting chunk in a treebin */
366946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void* tmalloc_large(mstate m, size_t nb) {
367046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tchunkptr v = 0;
367146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t rsize = -nb; /* Unsigned negation */
367246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tchunkptr t;
367346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bindex_t idx;
367446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  compute_tree_index(nb, idx);
367546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
367646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if ((t = *treebin_at(m, idx)) != 0) {
367746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* Traverse tree for this bin looking for node with size == nb */
367846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t sizebits = nb << leftshift_for_tree_index(idx);
367946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    tchunkptr rst = 0;  /* The deepest untaken right subtree */
368046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for (;;) {
368146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      tchunkptr rt;
368246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t trem = chunksize(t) - nb;
368346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (trem < rsize) {
368446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        v = t;
368546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if ((rsize = trem) == 0)
368646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          break;
368746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
368846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      rt = t->child[1];
368946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
369046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (rt != 0 && rt != t)
369146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        rst = rt;
369246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (t == 0) {
369346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        t = rst; /* set t to least subtree holding sizes > nb */
369446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        break;
369546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
369646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      sizebits <<= 1;
369746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
369846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
369946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
370046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
370146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
370246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (leftbits != 0) {
370346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      bindex_t i;
370446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      binmap_t leastbit = least_bit(leftbits);
370546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      compute_bit2idx(leastbit, i);
370646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      t = *treebin_at(m, i);
370746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
370846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
370946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
371046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  while (t != 0) { /* find smallest of tree or subtree */
371146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t trem = chunksize(t) - nb;
371246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (trem < rsize) {
371346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      rsize = trem;
371446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      v = t;
371546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
371646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    t = leftmost_child(t);
371746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
371846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
371946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /*  If dv is a better fit, return 0 so malloc will use it */
372046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
372146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (RTCHECK(ok_address(m, v))) { /* split */
372246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr r = chunk_plus_offset(v, nb);
372346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(chunksize(v) == rsize + nb);
372446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (RTCHECK(ok_next(v, r))) {
372546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        unlink_large_chunk(m, v);
372646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (rsize < MIN_CHUNK_SIZE)
372746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          set_inuse_and_pinuse(m, v, (rsize + nb));
372846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else {
372946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          set_size_and_pinuse_of_inuse_chunk(m, v, nb);
373046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          set_size_and_pinuse_of_free_chunk(r, rsize);
373146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          insert_chunk(m, r, rsize);
373246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
373346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return chunk2mem(v);
373446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
373546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
373646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    CORRUPTION_ERROR_ACTION(m);
373746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
373846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
373946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
374046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
374146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* allocate a small request from the best fitting chunk in a treebin */
374246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void* tmalloc_small(mstate m, size_t nb) {
374346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  tchunkptr t, v;
374446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t rsize;
374546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  bindex_t i;
374646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  binmap_t leastbit = least_bit(m->treemap);
374746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  compute_bit2idx(leastbit, i);
374846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
374946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  v = t = *treebin_at(m, i);
375046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  rsize = chunksize(t) - nb;
375146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
375246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  while ((t = leftmost_child(t)) != 0) {
375346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t trem = chunksize(t) - nb;
375446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (trem < rsize) {
375546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      rsize = trem;
375646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      v = t;
375746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
375846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
375946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
376046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (RTCHECK(ok_address(m, v))) {
376146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr r = chunk_plus_offset(v, nb);
376246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    assert(chunksize(v) == rsize + nb);
376346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (RTCHECK(ok_next(v, r))) {
376446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      unlink_large_chunk(m, v);
376546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (rsize < MIN_CHUNK_SIZE)
376646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_inuse_and_pinuse(m, v, (rsize + nb));
376746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else {
376846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_size_and_pinuse_of_inuse_chunk(m, v, nb);
376946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_size_and_pinuse_of_free_chunk(r, rsize);
377046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        replace_dv(m, r, rsize);
377146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
377246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return chunk2mem(v);
377346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
377446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
377546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
377646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  CORRUPTION_ERROR_ACTION(m);
377746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
377846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
377946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
378046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* --------------------------- realloc support --------------------------- */
378146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
378246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
378346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (bytes >= MAX_REQUEST) {
378446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MALLOC_FAILURE_ACTION;
378546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
378646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
378746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!PREACTION(m)) {
378846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr oldp = mem2chunk(oldmem);
378946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t oldsize = chunksize(oldp);
379046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr next = chunk_plus_offset(oldp, oldsize);
379146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr newp = 0;
379246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    void* extra = 0;
379346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
379446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* Try to either shrink or extend into top. Else malloc-copy-free */
379546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
379646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
379746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                ok_next(oldp, next) && ok_pinuse(next))) {
379846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t nb = request2size(bytes);
379946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (is_mmapped(oldp))
380046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        newp = mmap_resize(m, oldp, nb);
380146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else if (oldsize >= nb) { /* already big enough */
380246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t rsize = oldsize - nb;
380346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        newp = oldp;
380446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (rsize >= MIN_CHUNK_SIZE) {
380546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          mchunkptr remainder = chunk_plus_offset(newp, nb);
380646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          set_inuse(m, newp, nb);
380746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          set_inuse(m, remainder, rsize);
380846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          extra = chunk2mem(remainder);
380946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
381046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
381146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else if (next == m->top && oldsize + m->topsize > nb) {
381246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /* Expand into top */
381346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t newsize = oldsize + m->topsize;
381446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t newtopsize = newsize - nb;
381546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mchunkptr newtop = chunk_plus_offset(oldp, nb);
381646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_inuse(m, oldp, nb);
381746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        newtop->head = newtopsize |PINUSE_BIT;
381846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        m->top = newtop;
381946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        m->topsize = newtopsize;
382046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        newp = oldp;
382146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
382246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
382346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else {
382446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      USAGE_ERROR_ACTION(m, oldmem);
382546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      POSTACTION(m);
382646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return 0;
382746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
382846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
382946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    POSTACTION(m);
383046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
383146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (newp != 0) {
383246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (extra != 0) {
383346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        internal_free(m, extra);
383446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
383546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_inuse_chunk(m, newp);
383646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return chunk2mem(newp);
383746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
383846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else {
383946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      void* newmem = internal_malloc(m, bytes);
384046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (newmem != 0) {
384146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t oc = oldsize - overhead_for(oldp);
384246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
384346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        internal_free(m, oldmem);
384446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
384546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return newmem;
384646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
384746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
384846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
384946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
385046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
385146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* --------------------------- memalign support -------------------------- */
385246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
385346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
385446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (alignment <= MALLOC_ALIGNMENT)    /* Can just use malloc */
385546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return internal_malloc(m, bytes);
385646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
385746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    alignment = MIN_CHUNK_SIZE;
385846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
385946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t a = MALLOC_ALIGNMENT << 1;
386046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    while (a < alignment) a <<= 1;
386146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    alignment = a;
386246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
386346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
386446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (bytes >= MAX_REQUEST - alignment) {
386546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (m != 0)  { /* Test isn't needed but avoids compiler warning */
386646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      MALLOC_FAILURE_ACTION;
386746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
386846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
386946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {
387046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t nb = request2size(bytes);
387146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
387246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    char* mem = (char*)internal_malloc(m, req);
387346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (mem != 0) {
387446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      void* leader = 0;
387546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      void* trailer = 0;
387646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr p = mem2chunk(mem);
387746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
387846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (PREACTION(m)) return 0;
387946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
388046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /*
388146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          Find an aligned spot inside chunk.  Since we need to give
388246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          back leading space in a chunk of at least MIN_CHUNK_SIZE, if
388346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          the first calculation places us at a spot with less than
388446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
388546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          We've allocated enough total room so that this is always
388646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          possible.
388746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        */
388846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
388946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                                       alignment -
389046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                                       SIZE_T_ONE)) &
389146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                             -alignment));
389246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
389346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          br : br+alignment;
389446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mchunkptr newp = (mchunkptr)pos;
389546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t leadsize = pos - (char*)(p);
389646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t newsize = chunksize(p) - leadsize;
389746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
389846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
389946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          newp->prev_foot = p->prev_foot + leadsize;
390046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          newp->head = (newsize|CINUSE_BIT);
390146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
390246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else { /* Otherwise, give back leader, use the rest */
390346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          set_inuse(m, newp, newsize);
390446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          set_inuse(m, p, leadsize);
390546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          leader = chunk2mem(p);
390646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
390746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        p = newp;
390846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
390946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
391046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      /* Give back spare room at the end */
391146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (!is_mmapped(p)) {
391246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t size = chunksize(p);
391346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (size > nb + MIN_CHUNK_SIZE) {
391446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          size_t remainder_size = size - nb;
391546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          mchunkptr remainder = chunk_plus_offset(p, nb);
391646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          set_inuse(m, p, nb);
391746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          set_inuse(m, remainder, remainder_size);
391846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          trailer = chunk2mem(remainder);
391946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
392046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
392146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
392246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert (chunksize(p) >= nb);
392346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert((((size_t)(chunk2mem(p))) % alignment) == 0);
392446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_inuse_chunk(m, p);
392546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      POSTACTION(m);
392646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (leader != 0) {
392746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        internal_free(m, leader);
392846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
392946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (trailer != 0) {
393046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        internal_free(m, trailer);
393146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
393246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return chunk2mem(p);
393346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
393446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
393546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
393646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
393746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
393846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ------------------------ comalloc/coalloc support --------------------- */
393946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
394046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void** ialloc(mstate m,
394146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                     size_t n_elements,
394246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                     size_t* sizes,
394346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                     int opts,
394446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                     void* chunks[]) {
394546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /*
394646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This provides common support for independent_X routines, handling
394746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    all of the combinations that can result.
394846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
394946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    The opts arg has:
395046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    bit 0 set if all elements are same size (using sizes[0])
395146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    bit 1 set if elements should be zeroed
395246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  */
395346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
395446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t    element_size;   /* chunksize of each element, if all same */
395546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t    contents_size;  /* total size of elements */
395646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t    array_size;     /* request size of pointer array */
395746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  void*     mem;            /* malloced aggregate space */
395846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr p;              /* corresponding chunk */
395946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t    remainder_size; /* remaining bytes while splitting */
396046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  void**    marray;         /* either "chunks" or malloced ptr array */
396146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr array_chunk;    /* chunk for malloced ptr array */
396246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  flag_t    was_enabled;    /* to disable mmap */
396346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t    size;
396446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t    i;
396546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
396646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* compute array length, if needed */
396746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (chunks != 0) {
396846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (n_elements == 0)
396946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return chunks; /* nothing to do */
397046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    marray = chunks;
397146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    array_size = 0;
397246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
397346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {
397446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* if empty req, must still return chunk representing empty array */
397546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (n_elements == 0)
397646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return (void**)internal_malloc(m, 0);
397746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    marray = 0;
397846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    array_size = request2size(n_elements * (sizeof(void*)));
397946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
398046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
398146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* compute total element size */
398246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (opts & 0x1) { /* all-same-size */
398346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    element_size = request2size(*sizes);
398446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    contents_size = n_elements * element_size;
398546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
398646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else { /* add up all the sizes */
398746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    element_size = 0;
398846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    contents_size = 0;
398946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for (i = 0; i != n_elements; ++i)
399046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      contents_size += request2size(sizes[i]);
399146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
399246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
399346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size = contents_size + array_size;
399446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
399546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /*
399646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     Allocate the aggregate chunk.  First disable direct-mmapping so
399746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     malloc won't use it, since we would not be able to later
399846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     free/realloc space internal to a segregated mmap region.
399946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  */
400046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  was_enabled = use_mmap(m);
400146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  disable_mmap(m);
400246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mem = internal_malloc(m, size - CHUNK_OVERHEAD);
400346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (was_enabled)
400446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    enable_mmap(m);
400546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (mem == 0)
400646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
400746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
400846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (PREACTION(m)) return 0;
400946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  p = mem2chunk(mem);
401046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  remainder_size = chunksize(p);
401146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
401246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  assert(!is_mmapped(p));
401346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
401446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (opts & 0x2) {       /* optionally clear the elements */
401546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
401646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
401746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
401846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* If not provided, allocate the pointer array as final part of chunk */
401946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (marray == 0) {
402046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t  array_chunk_size;
402146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    array_chunk = chunk_plus_offset(p, contents_size);
402246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    array_chunk_size = remainder_size - contents_size;
402346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    marray = (void**) (chunk2mem(array_chunk));
402446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
402546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    remainder_size = contents_size;
402646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
402746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
402846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /* split out elements */
402946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  for (i = 0; ; ++i) {
403046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    marray[i] = chunk2mem(p);
403146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (i != n_elements-1) {
403246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (element_size != 0)
403346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size = element_size;
403446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else
403546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size = request2size(sizes[i]);
403646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      remainder_size -= size;
403746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      set_size_and_pinuse_of_inuse_chunk(m, p, size);
403846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      p = chunk_plus_offset(p, size);
403946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
404046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else { /* the final element absorbs any overallocation slop */
404146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
404246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      break;
404346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
404446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
404546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
404646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if DEBUG
404746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (marray != chunks) {
404846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* final element must have exactly exhausted chunk */
404946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (element_size != 0) {
405046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(remainder_size == element_size);
405146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
405246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else {
405346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      assert(remainder_size == request2size(sizes[i]));
405446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
405546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    check_inuse_chunk(m, mem2chunk(marray));
405646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
405746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  for (i = 0; i != n_elements; ++i)
405846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    check_inuse_chunk(m, mem2chunk(marray[i]));
405946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
406046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* DEBUG */
406146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
406246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  POSTACTION(m);
406346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return marray;
406446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
406546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
406646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
406746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -------------------------- public routines ---------------------------- */
406846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
406946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !ONLY_MSPACES
407046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
407146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* dlmalloc(size_t bytes) {
407246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /*
407346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     Basic algorithm:
407446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     If a small request (< 256 bytes minus per-chunk overhead):
407546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       1. If one exists, use a remainderless chunk in associated smallbin.
407646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          (Remainderless means that there are too few excess bytes to
407746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          represent as a chunk.)
407846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       2. If it is big enough, use the dv chunk, which is normally the
407946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          chunk adjacent to the one used for the most recent small request.
408046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       3. If one exists, split the smallest available chunk in a bin,
408146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          saving remainder in dv.
408246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       4. If it is big enough, use the top chunk.
408346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       5. If available, get memory from system and use it
408446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     Otherwise, for a large request:
408546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       1. Find the smallest available binned chunk that fits, and use it
408646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if it is better fitting than dv chunk, splitting if necessary.
408746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       2. If better fitting than any binned chunk, use the dv chunk.
408846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       3. If it is big enough, use the top chunk.
408946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       4. If request size >= mmap threshold, try to directly mmap this chunk.
409046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner       5. If available, get memory from system and use it
409146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
409246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     The ugly goto's here ensure that postaction occurs along all paths.
409346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  */
409446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
409546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!PREACTION(gm)) {
409646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    void* mem;
409746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t nb;
409846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (bytes <= MAX_SMALL_REQUEST) {
409946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      bindex_t idx;
410046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      binmap_t smallbits;
410146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
410246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      idx = small_index(nb);
410346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      smallbits = gm->smallmap >> idx;
410446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
410546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
410646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mchunkptr b, p;
410746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
410846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        b = smallbin_at(gm, idx);
410946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        p = b->fd;
411046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        assert(chunksize(p) == small_index2size(idx));
411146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        unlink_first_small_chunk(gm, b, p, idx);
411246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_inuse_and_pinuse(gm, p, small_index2size(idx));
411346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mem = chunk2mem(p);
411446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        check_malloced_chunk(gm, mem, nb);
411546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        goto postaction;
411646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
411746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
411846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else if (nb > gm->dvsize) {
411946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
412046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          mchunkptr b, p, r;
412146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          size_t rsize;
412246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          bindex_t i;
412346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
412446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          binmap_t leastbit = least_bit(leftbits);
412546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          compute_bit2idx(leastbit, i);
412646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          b = smallbin_at(gm, i);
412746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          p = b->fd;
412846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          assert(chunksize(p) == small_index2size(i));
412946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          unlink_first_small_chunk(gm, b, p, i);
413046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          rsize = small_index2size(i) - nb;
413146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          /* Fit here cannot be remainderless if 4byte sizes */
413246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
413346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            set_inuse_and_pinuse(gm, p, small_index2size(i));
413446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          else {
413546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
413646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            r = chunk_plus_offset(p, nb);
413746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            set_size_and_pinuse_of_free_chunk(r, rsize);
413846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            replace_dv(gm, r, rsize);
413946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
414046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          mem = chunk2mem(p);
414146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          check_malloced_chunk(gm, mem, nb);
414246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          goto postaction;
414346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
414446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
414546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
414646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          check_malloced_chunk(gm, mem, nb);
414746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          goto postaction;
414846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
414946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
415046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
415146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else if (bytes >= MAX_REQUEST)
415246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
415346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else {
415446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nb = pad_request(bytes);
415546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
415646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        check_malloced_chunk(gm, mem, nb);
415746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        goto postaction;
415846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
415946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
416046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
416146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (nb <= gm->dvsize) {
416246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t rsize = gm->dvsize - nb;
416346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr p = gm->dv;
416446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
416546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
416646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        gm->dvsize = rsize;
416746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_size_and_pinuse_of_free_chunk(r, rsize);
416846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
416946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
417046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else { /* exhaust dv */
417146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t dvs = gm->dvsize;
417246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        gm->dvsize = 0;
417346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        gm->dv = 0;
417446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_inuse_and_pinuse(gm, p, dvs);
417546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
417646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mem = chunk2mem(p);
417746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_malloced_chunk(gm, mem, nb);
417846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      goto postaction;
417946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
418046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
418146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else if (nb < gm->topsize) { /* Split top */
418246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t rsize = gm->topsize -= nb;
418346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr p = gm->top;
418446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr r = gm->top = chunk_plus_offset(p, nb);
418546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      r->head = rsize | PINUSE_BIT;
418646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
418746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mem = chunk2mem(p);
418846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_top_chunk(gm, gm->top);
418946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_malloced_chunk(gm, mem, nb);
419046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      goto postaction;
419146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
419246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
419346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mem = sys_alloc(gm, nb);
419446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
419546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  postaction:
419646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    POSTACTION(gm);
419746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return mem;
419846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
419946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
420046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
420146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
420246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
420346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid dlfree(void* mem) {
420446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  /*
420546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     Consolidate freed chunks with preceeding or succeeding bordering
420646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     free chunks, if they exist, and then place in a bin.  Intermixed
420746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner     with special cases for top, dv, mmapped chunks, and usage errors.
420846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  */
420946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
421046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (mem != 0) {
421146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr p  = mem2chunk(mem);
421246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if FOOTERS
421346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mstate fm = get_mstate_for(p);
421446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (!ok_magic(fm)) {
421546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      USAGE_ERROR_ACTION(fm, p);
421646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return;
421746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
421846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* FOOTERS */
421946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define fm gm
422046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* FOOTERS */
422146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (!PREACTION(fm)) {
422246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_inuse_chunk(fm, p);
422346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
422446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t psize = chunksize(p);
422546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mchunkptr next = chunk_plus_offset(p, psize);
422646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (!pinuse(p)) {
422746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          size_t prevsize = p->prev_foot;
422846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if ((prevsize & IS_MMAPPED_BIT) != 0) {
422946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            prevsize &= ~IS_MMAPPED_BIT;
423046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            psize += prevsize + MMAP_FOOT_PAD;
423146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
423246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              fm->footprint -= psize;
423346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            goto postaction;
423446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
423546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          else {
423646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            mchunkptr prev = chunk_minus_offset(p, prevsize);
423746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            psize += prevsize;
423846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            p = prev;
423946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
424046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              if (p != fm->dv) {
424146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                unlink_chunk(fm, p, prevsize);
424246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              }
424346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
424446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                fm->dvsize = psize;
424546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                set_free_with_pinuse(p, psize, next);
424646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                goto postaction;
424746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              }
424846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
424946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            else
425046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              goto erroraction;
425146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
425246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
425346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
425446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
425546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (!cinuse(next)) {  /* consolidate forward */
425646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            if (next == fm->top) {
425746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              size_t tsize = fm->topsize += psize;
425846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              fm->top = p;
425946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              p->head = tsize | PINUSE_BIT;
426046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              if (p == fm->dv) {
426146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                fm->dv = 0;
426246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                fm->dvsize = 0;
426346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              }
426446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              if (should_trim(fm, tsize))
426546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                sys_trim(fm, 0);
426646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              goto postaction;
426746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
426846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            else if (next == fm->dv) {
426946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              size_t dsize = fm->dvsize += psize;
427046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              fm->dv = p;
427146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              set_size_and_pinuse_of_free_chunk(p, dsize);
427246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              goto postaction;
427346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
427446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            else {
427546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              size_t nsize = chunksize(next);
427646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              psize += nsize;
427746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              unlink_chunk(fm, next, nsize);
427846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              set_size_and_pinuse_of_free_chunk(p, psize);
427946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              if (p == fm->dv) {
428046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                fm->dvsize = psize;
428146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                goto postaction;
428246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              }
428346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
428446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
428546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          else
428646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            set_free_with_pinuse(p, psize, next);
428746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          insert_chunk(fm, p, psize);
428846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          check_free_chunk(fm, p);
428946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          goto postaction;
429046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
429146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
429246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    erroraction:
429346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      USAGE_ERROR_ACTION(fm, p);
429446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    postaction:
429546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      POSTACTION(fm);
429646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
429746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
429846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !FOOTERS
429946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#undef fm
430046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* FOOTERS */
430146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
430246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
430346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* dlcalloc(size_t n_elements, size_t elem_size) {
430446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  void* mem;
430546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t req = 0;
430646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (n_elements != 0) {
430746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    req = n_elements * elem_size;
430846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
430946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        (req / n_elements != elem_size))
431046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      req = MAX_SIZE_T; /* force downstream failure on overflow */
431146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
431246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mem = dlmalloc(req);
431346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
431446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    memset(mem, 0, req);
431546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return mem;
431646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
431746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
431846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* dlrealloc(void* oldmem, size_t bytes) {
431946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (oldmem == 0)
432046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return dlmalloc(bytes);
432146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef REALLOC_ZERO_BYTES_FREES
432246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (bytes == 0) {
432346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    dlfree(oldmem);
432446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
432546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
432646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* REALLOC_ZERO_BYTES_FREES */
432746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {
432846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if ! FOOTERS
432946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mstate m = gm;
433046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* FOOTERS */
433146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mstate m = get_mstate_for(mem2chunk(oldmem));
433246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (!ok_magic(m)) {
433346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      USAGE_ERROR_ACTION(m, oldmem);
433446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return 0;
433546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
433646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* FOOTERS */
433746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return internal_realloc(m, oldmem, bytes);
433846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
433946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
434046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
434146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* dlmemalign(size_t alignment, size_t bytes) {
434246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return internal_memalign(gm, alignment, bytes);
434346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
434446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
434546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid** dlindependent_calloc(size_t n_elements, size_t elem_size,
434646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                 void* chunks[]) {
434746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t sz = elem_size; /* serves as 1-element array */
434846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return ialloc(gm, n_elements, &sz, 3, chunks);
434946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
435046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
435146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid** dlindependent_comalloc(size_t n_elements, size_t sizes[],
435246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                   void* chunks[]) {
435346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return ialloc(gm, n_elements, sizes, 0, chunks);
435446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
435546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
435646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* dlvalloc(size_t bytes) {
435746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t pagesz;
435846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  init_mparams();
435946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  pagesz = mparams.page_size;
436046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return dlmemalign(pagesz, bytes);
436146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
436246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
436346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* dlpvalloc(size_t bytes) {
436446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t pagesz;
436546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  init_mparams();
436646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  pagesz = mparams.page_size;
436746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
436846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
436946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
437046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint dlmalloc_trim(size_t pad) {
437146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  int result = 0;
437246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!PREACTION(gm)) {
437346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    result = sys_trim(gm, pad);
437446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    POSTACTION(gm);
437546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
437646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return result;
437746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
437846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
437946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t dlmalloc_footprint(void) {
438046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return gm->footprint;
438146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
438246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
438346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t dlmalloc_max_footprint(void) {
438446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return gm->max_footprint;
438546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
438646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
438746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !NO_MALLINFO
438846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct mallinfo dlmallinfo(void) {
438946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return internal_mallinfo(gm);
439046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
439146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* NO_MALLINFO */
439246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
439346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid dlmalloc_stats() {
439446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  internal_malloc_stats(gm);
439546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
439646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
439746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t dlmalloc_usable_size(void* mem) {
439846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (mem != 0) {
439946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr p = mem2chunk(mem);
440046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (cinuse(p))
440146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return chunksize(p) - overhead_for(p);
440246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
440346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
440446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
440546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
440646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint dlmallopt(int param_number, int value) {
440746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return change_mparam(param_number, value);
440846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
440946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
441046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* !ONLY_MSPACES */
441146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
441246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* ----------------------------- user mspaces ---------------------------- */
441346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
441446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if MSPACES
441546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
441646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic mstate init_user_mstate(char* tbase, size_t tsize) {
441746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t msize = pad_request(sizeof(struct malloc_state));
441846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr mn;
441946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mchunkptr msp = align_as_chunk(tbase);
442046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate m = (mstate)(chunk2mem(msp));
442146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  memset(m, 0, msize);
442246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  INITIAL_LOCK(&m->mutex);
442346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
442446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->seg.base = m->least_addr = tbase;
442546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->seg.size = m->footprint = m->max_footprint = tsize;
442646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->magic = mparams.magic;
442746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  m->mflags = mparams.default_mflags;
442846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  disable_contiguous(m);
442946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  init_bins(m);
443046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mn = next_chunk(mem2chunk(m));
443146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
443246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  check_top_chunk(m, m->top);
443346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return m;
443446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
443546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
443646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnermspace create_mspace(size_t capacity, int locked) {
443746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate m = 0;
443846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t msize = pad_request(sizeof(struct malloc_state));
443946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  init_mparams(); /* Ensure pagesize etc initialized */
444046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
444146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
444246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t rs = ((capacity == 0)? mparams.granularity :
444346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                 (capacity + TOP_FOOT_SIZE + msize));
444446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t tsize = granularity_align(rs);
444546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    char* tbase = (char*)(CALL_MMAP(tsize));
444646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (tbase != CMFAIL) {
444746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      m = init_user_mstate(tbase, tsize);
444846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      m->seg.sflags = IS_MMAPPED_BIT;
444946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      set_lock(m, locked);
445046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
445146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
445246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return (mspace)m;
445346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
445446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
445546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnermspace create_mspace_with_base(void* base, size_t capacity, int locked) {
445646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate m = 0;
445746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t msize = pad_request(sizeof(struct malloc_state));
445846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  init_mparams(); /* Ensure pagesize etc initialized */
445946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
446046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (capacity > msize + TOP_FOOT_SIZE &&
446146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
446246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    m = init_user_mstate((char*)base, capacity);
446346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    m->seg.sflags = EXTERN_BIT;
446446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    set_lock(m, locked);
446546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
446646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return (mspace)m;
446746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
446846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
446946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t destroy_mspace(mspace msp) {
447046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t freed = 0;
447146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate ms = (mstate)msp;
447246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (ok_magic(ms)) {
447346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    msegmentptr sp = &ms->seg;
447446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    while (sp != 0) {
447546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      char* base = sp->base;
447646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t size = sp->size;
447746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      flag_t flag = sp->sflags;
447846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      sp = sp->next;
447946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
448046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          CALL_MUNMAP(base, size) == 0)
448146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        freed += size;
448246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
448346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
448446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {
448546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    USAGE_ERROR_ACTION(ms,ms);
448646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
448746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return freed;
448846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
448946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
449046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
449146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mspace versions of routines are near-clones of the global
449246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  versions. This is not so nice but better than the alternatives.
449346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
449446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
449546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
449646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* mspace_malloc(mspace msp, size_t bytes) {
449746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate ms = (mstate)msp;
449846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!ok_magic(ms)) {
449946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    USAGE_ERROR_ACTION(ms,ms);
450046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
450146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
450246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!PREACTION(ms)) {
450346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    void* mem;
450446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    size_t nb;
450546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (bytes <= MAX_SMALL_REQUEST) {
450646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      bindex_t idx;
450746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      binmap_t smallbits;
450846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
450946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      idx = small_index(nb);
451046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      smallbits = ms->smallmap >> idx;
451146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
451246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
451346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mchunkptr b, p;
451446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
451546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        b = smallbin_at(ms, idx);
451646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        p = b->fd;
451746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        assert(chunksize(p) == small_index2size(idx));
451846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        unlink_first_small_chunk(ms, b, p, idx);
451946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_inuse_and_pinuse(ms, p, small_index2size(idx));
452046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mem = chunk2mem(p);
452146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        check_malloced_chunk(ms, mem, nb);
452246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        goto postaction;
452346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
452446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
452546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else if (nb > ms->dvsize) {
452646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
452746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          mchunkptr b, p, r;
452846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          size_t rsize;
452946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          bindex_t i;
453046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
453146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          binmap_t leastbit = least_bit(leftbits);
453246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          compute_bit2idx(leastbit, i);
453346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          b = smallbin_at(ms, i);
453446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          p = b->fd;
453546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          assert(chunksize(p) == small_index2size(i));
453646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          unlink_first_small_chunk(ms, b, p, i);
453746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          rsize = small_index2size(i) - nb;
453846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          /* Fit here cannot be remainderless if 4byte sizes */
453946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
454046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            set_inuse_and_pinuse(ms, p, small_index2size(i));
454146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          else {
454246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
454346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            r = chunk_plus_offset(p, nb);
454446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            set_size_and_pinuse_of_free_chunk(r, rsize);
454546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            replace_dv(ms, r, rsize);
454646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
454746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          mem = chunk2mem(p);
454846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          check_malloced_chunk(ms, mem, nb);
454946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          goto postaction;
455046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
455146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
455246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
455346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          check_malloced_chunk(ms, mem, nb);
455446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          goto postaction;
455546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
455646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
455746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
455846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else if (bytes >= MAX_REQUEST)
455946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
456046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else {
456146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nb = pad_request(bytes);
456246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
456346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        check_malloced_chunk(ms, mem, nb);
456446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        goto postaction;
456546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
456646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
456746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
456846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (nb <= ms->dvsize) {
456946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t rsize = ms->dvsize - nb;
457046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr p = ms->dv;
457146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
457246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
457346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        ms->dvsize = rsize;
457446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_size_and_pinuse_of_free_chunk(r, rsize);
457546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
457646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
457746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      else { /* exhaust dv */
457846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t dvs = ms->dvsize;
457946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        ms->dvsize = 0;
458046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        ms->dv = 0;
458146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        set_inuse_and_pinuse(ms, p, dvs);
458246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
458346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mem = chunk2mem(p);
458446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_malloced_chunk(ms, mem, nb);
458546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      goto postaction;
458646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
458746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
458846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else if (nb < ms->topsize) { /* Split top */
458946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      size_t rsize = ms->topsize -= nb;
459046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr p = ms->top;
459146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mchunkptr r = ms->top = chunk_plus_offset(p, nb);
459246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      r->head = rsize | PINUSE_BIT;
459346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
459446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      mem = chunk2mem(p);
459546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_top_chunk(ms, ms->top);
459646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_malloced_chunk(ms, mem, nb);
459746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      goto postaction;
459846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
459946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
460046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mem = sys_alloc(ms, nb);
460146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
460246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  postaction:
460346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    POSTACTION(ms);
460446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return mem;
460546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
460646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
460746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return 0;
460846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
460946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
461046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid mspace_free(mspace msp, void* mem) {
461146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (mem != 0) {
461246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr p  = mem2chunk(mem);
461346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if FOOTERS
461446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mstate fm = get_mstate_for(p);
461546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* FOOTERS */
461646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mstate fm = (mstate)msp;
461746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* FOOTERS */
461846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (!ok_magic(fm)) {
461946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      USAGE_ERROR_ACTION(fm, p);
462046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return;
462146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
462246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (!PREACTION(fm)) {
462346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      check_inuse_chunk(fm, p);
462446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
462546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        size_t psize = chunksize(p);
462646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        mchunkptr next = chunk_plus_offset(p, psize);
462746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (!pinuse(p)) {
462846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          size_t prevsize = p->prev_foot;
462946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if ((prevsize & IS_MMAPPED_BIT) != 0) {
463046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            prevsize &= ~IS_MMAPPED_BIT;
463146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            psize += prevsize + MMAP_FOOT_PAD;
463246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
463346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              fm->footprint -= psize;
463446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            goto postaction;
463546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
463646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          else {
463746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            mchunkptr prev = chunk_minus_offset(p, prevsize);
463846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            psize += prevsize;
463946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            p = prev;
464046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
464146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              if (p != fm->dv) {
464246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                unlink_chunk(fm, p, prevsize);
464346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              }
464446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
464546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                fm->dvsize = psize;
464646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                set_free_with_pinuse(p, psize, next);
464746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                goto postaction;
464846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              }
464946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
465046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            else
465146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              goto erroraction;
465246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
465346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
465446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
465546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
465646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          if (!cinuse(next)) {  /* consolidate forward */
465746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            if (next == fm->top) {
465846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              size_t tsize = fm->topsize += psize;
465946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              fm->top = p;
466046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              p->head = tsize | PINUSE_BIT;
466146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              if (p == fm->dv) {
466246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                fm->dv = 0;
466346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                fm->dvsize = 0;
466446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              }
466546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              if (should_trim(fm, tsize))
466646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                sys_trim(fm, 0);
466746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              goto postaction;
466846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
466946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            else if (next == fm->dv) {
467046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              size_t dsize = fm->dvsize += psize;
467146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              fm->dv = p;
467246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              set_size_and_pinuse_of_free_chunk(p, dsize);
467346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              goto postaction;
467446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
467546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            else {
467646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              size_t nsize = chunksize(next);
467746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              psize += nsize;
467846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              unlink_chunk(fm, next, nsize);
467946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              set_size_and_pinuse_of_free_chunk(p, psize);
468046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              if (p == fm->dv) {
468146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                fm->dvsize = psize;
468246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                goto postaction;
468346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner              }
468446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
468546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
468646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          else
468746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            set_free_with_pinuse(p, psize, next);
468846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          insert_chunk(fm, p, psize);
468946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          check_free_chunk(fm, p);
469046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          goto postaction;
469146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
469246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
469346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    erroraction:
469446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      USAGE_ERROR_ACTION(fm, p);
469546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    postaction:
469646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      POSTACTION(fm);
469746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
469846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
469946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
470046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
470146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
470246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  void* mem;
470346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t req = 0;
470446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate ms = (mstate)msp;
470546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!ok_magic(ms)) {
470646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    USAGE_ERROR_ACTION(ms,ms);
470746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
470846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
470946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (n_elements != 0) {
471046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    req = n_elements * elem_size;
471146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
471246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        (req / n_elements != elem_size))
471346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      req = MAX_SIZE_T; /* force downstream failure on overflow */
471446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
471546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mem = internal_malloc(ms, req);
471646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
471746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    memset(mem, 0, req);
471846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return mem;
471946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
472046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
472146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
472246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (oldmem == 0)
472346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return mspace_malloc(msp, bytes);
472446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef REALLOC_ZERO_BYTES_FREES
472546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (bytes == 0) {
472646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mspace_free(msp, oldmem);
472746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
472846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
472946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* REALLOC_ZERO_BYTES_FREES */
473046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {
473146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if FOOTERS
473246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mchunkptr p  = mem2chunk(oldmem);
473346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mstate ms = get_mstate_for(p);
473446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else /* FOOTERS */
473546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    mstate ms = (mstate)msp;
473646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* FOOTERS */
473746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (!ok_magic(ms)) {
473846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      USAGE_ERROR_ACTION(ms,ms);
473946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return 0;
474046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
474146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return internal_realloc(ms, oldmem, bytes);
474246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
474346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
474446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
474546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
474646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate ms = (mstate)msp;
474746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!ok_magic(ms)) {
474846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    USAGE_ERROR_ACTION(ms,ms);
474946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
475046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
475146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return internal_memalign(ms, alignment, bytes);
475246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
475346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
475446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid** mspace_independent_calloc(mspace msp, size_t n_elements,
475546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                 size_t elem_size, void* chunks[]) {
475646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t sz = elem_size; /* serves as 1-element array */
475746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate ms = (mstate)msp;
475846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!ok_magic(ms)) {
475946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    USAGE_ERROR_ACTION(ms,ms);
476046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
476146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
476246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return ialloc(ms, n_elements, &sz, 3, chunks);
476346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
476446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
476546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid** mspace_independent_comalloc(mspace msp, size_t n_elements,
476646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                   size_t sizes[], void* chunks[]) {
476746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate ms = (mstate)msp;
476846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!ok_magic(ms)) {
476946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    USAGE_ERROR_ACTION(ms,ms);
477046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
477146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
477246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return ialloc(ms, n_elements, sizes, 0, chunks);
477346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
477446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
477546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint mspace_trim(mspace msp, size_t pad) {
477646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  int result = 0;
477746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate ms = (mstate)msp;
477846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (ok_magic(ms)) {
477946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (!PREACTION(ms)) {
478046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      result = sys_trim(ms, pad);
478146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      POSTACTION(ms);
478246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
478346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
478446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {
478546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    USAGE_ERROR_ACTION(ms,ms);
478646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
478746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return result;
478846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
478946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
479046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid mspace_malloc_stats(mspace msp) {
479146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate ms = (mstate)msp;
479246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (ok_magic(ms)) {
479346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    internal_malloc_stats(ms);
479446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
479546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  else {
479646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    USAGE_ERROR_ACTION(ms,ms);
479746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
479846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
479946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
480046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t mspace_footprint(mspace msp) {
480146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t result;
480246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate ms = (mstate)msp;
480346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (ok_magic(ms)) {
480446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    result = ms->footprint;
480546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
480646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  USAGE_ERROR_ACTION(ms,ms);
480746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return result;
480846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
480946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
481046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
481146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnersize_t mspace_max_footprint(mspace msp) {
481246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  size_t result;
481346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate ms = (mstate)msp;
481446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (ok_magic(ms)) {
481546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    result = ms->max_footprint;
481646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
481746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  USAGE_ERROR_ACTION(ms,ms);
481846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return result;
481946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
482046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
482146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
482246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if !NO_MALLINFO
482346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct mallinfo mspace_mallinfo(mspace msp) {
482446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  mstate ms = (mstate)msp;
482546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  if (!ok_magic(ms)) {
482646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    USAGE_ERROR_ACTION(ms,ms);
482746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
482846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return internal_mallinfo(ms);
482946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
483046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* NO_MALLINFO */
483146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
483246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint mspace_mallopt(int param_number, int value) {
483346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  return change_mparam(param_number, value);
483446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
483546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
483646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* MSPACES */
483746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
483846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -------------------- Alternative MORECORE functions ------------------- */
483946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
484046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
484146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  Guidelines for creating a custom version of MORECORE:
484246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
484346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * For best performance, MORECORE should allocate in multiples of pagesize.
484446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * MORECORE may allocate more memory than requested. (Or even less,
484546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      but this will usually result in a malloc failure.)
484646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * MORECORE must not allocate memory when given argument zero, but
484746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      instead return one past the end address of memory from previous
484846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      nonzero call.
484946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * For best performance, consecutive calls to MORECORE with positive
485046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      arguments should return increasing addresses, indicating that
485146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      space has been contiguously extended.
485246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * Even though consecutive calls to MORECORE need not return contiguous
485346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      addresses, it must be OK for malloc'ed chunks to span multiple
485446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      regions in those cases where they do happen to be contiguous.
485546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  * MORECORE need not handle negative arguments -- it may instead
485646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      just return MFAIL when given negative arguments.
485746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      Negative arguments are always multiples of pagesize. MORECORE
485846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      must not misinterpret negative args as large positive unsigned
485946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      args. You can suppress all such calls from even occurring by defining
486046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      MORECORE_CANNOT_TRIM,
486146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
486246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  As an example alternative MORECORE, here is a custom allocator
486346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  kindly contributed for pre-OSX macOS.  It uses virtually but not
486446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  necessarily physically contiguous non-paged memory (locked in,
486546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  present and won't get swapped out).  You can use it by uncommenting
486646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  this section, adding some #includes, and setting up the appropriate
486746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  defines above:
486846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
486946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      #define MORECORE osMoreCore
487046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
487146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  There is also a shutdown routine that should somehow be called for
487246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  cleanup upon program exit.
487346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
487446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  #define MAX_POOL_ENTRIES 100
487546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  #define MINIMUM_MORECORE_SIZE  (64 * 1024U)
487646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  static int next_os_pool;
487746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  void *our_os_pools[MAX_POOL_ENTRIES];
487846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
487946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  void *osMoreCore(int size)
488046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  {
488146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    void *ptr = 0;
488246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    static void *sbrk_top = 0;
488346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
488446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (size > 0)
488546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    {
488646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (size < MINIMUM_MORECORE_SIZE)
488746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         size = MINIMUM_MORECORE_SIZE;
488846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (CurrentExecutionLevel() == kTaskLevel)
488946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
489046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (ptr == 0)
489146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      {
489246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return (void *) MFAIL;
489346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
489446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      // save ptrs so they can be freed during cleanup
489546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      our_os_pools[next_os_pool] = ptr;
489646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      next_os_pool++;
489746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
489846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      sbrk_top = (char *) ptr + size;
489946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return ptr;
490046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
490146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else if (size < 0)
490246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    {
490346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      // we don't currently support shrink behavior
490446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return (void *) MFAIL;
490546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
490646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else
490746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    {
490846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      return sbrk_top;
490946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
491046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
491146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
491246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  // cleanup any allocated memory pools
491346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  // called as last thing before shutting down driver
491446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
491546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  void osCleanupMem(void)
491646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  {
491746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    void **ptr;
491846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
491946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
492046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      if (*ptr)
492146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      {
492246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         PoolDeallocate(*ptr);
492346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         *ptr = 0;
492446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      }
492546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  }
492646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
492746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
492846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
492946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
493046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* -----------------------------------------------------------------------
493146be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerHistory:
493246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.8.3 Thu Sep 22 11:16:32 2005  Doug Lea  (dl at gee)
493346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Add max_footprint functions
493446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Ensure all appropriate literals are size_t
493546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Fix conditional compilation problem for some #define settings
493646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Avoid concatenating segments with the one provided
493746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        in create_mspace_with_base
493846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Rename some variables to avoid compiler shadowing warnings
493946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Use explicit lock initialization.
494046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Better handling of sbrk interference.
494146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Simplify and fix segment insertion, trimming and mspace_destroy
494246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
494346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Thanks especially to Dennis Flanagan for help on these.
494446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
494546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.8.2 Sun Jun 12 16:01:10 2005  Doug Lea  (dl at gee)
494646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Fix memalign brace error.
494746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
494846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.8.1 Wed Jun  8 16:11:46 2005  Doug Lea  (dl at gee)
494946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Fix improper #endif nesting in C++
495046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Add explicit casts needed for C++
495146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
495246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.8.0 Mon May 30 14:09:02 2005  Doug Lea  (dl at gee)
495346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Use trees for large bins
495446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Support mspaces
495546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Use segments to unify sbrk-based and mmap-based system allocation,
495646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        removing need for emulation on most platforms without sbrk.
495746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Default safety checks
495846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Optional footer checks. Thanks to William Robertson for the idea.
495946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Internal code refactoring
496046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Incorporate suggestions and platform-specific changes.
496146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
496246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Aaron Bachmann,  Emery Berger, and others.
496346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Speed up non-fastbin processing enough to remove fastbins.
496446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Remove useless cfree() to avoid conflicts with other apps.
496546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Remove internal memcpy, memset. Compilers handle builtins better.
496646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Remove some options that no one ever used and rename others.
496746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
496846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
496946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Fix malloc_state bitmap array misdeclaration
497046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
497146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.7.1 Thu Jul 25 10:58:03 2002  Doug Lea  (dl at gee)
497246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Allow tuning of FIRST_SORTED_BIN_SIZE
497346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
497446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Better detection and support for non-contiguousness of MORECORE.
497546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
497646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Bypass most of malloc if no frees. Thanks To Emery Berger.
497746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Fix freeing of old top non-contiguous chunk im sysmalloc.
497846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Raised default trim and map thresholds to 256K.
497946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Fix mmap-related #defines. Thanks to Lubos Lunak.
498046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
498146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Branch-free bin calculation
498246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Default trim and mmap thresholds now 256K.
498346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
498446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
498546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Introduce independent_comalloc and independent_calloc.
498646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Thanks to Michael Pachos for motivation and help.
498746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Make optional .h file available
498846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Allow > 2GB requests on 32bit systems.
498946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
499046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
499146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        and Anonymous.
499246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
499346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        helping test this.)
499446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * memalign: check alignment arg
499546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * realloc: don't try to shift chunks backwards, since this
499646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        leads to  more fragmentation in some programs and doesn't
499746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        seem to help in any others.
499846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Collect all cases in malloc requiring system memory into sysmalloc
499946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Use mmap as backup to sbrk
500046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Place all internal state in malloc_state
500146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Introduce fastbins (although similar to 2.5.1)
500246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Many minor tunings and cosmetic improvements
500346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
500446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
500546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
500646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Include errno.h to support default failure action.
500746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
500846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
500946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * return null for negative arguments
501046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
501146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
501246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          (e.g. WIN32 platforms)
501346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         * Cleanup header file inclusion for WIN32 platforms
501446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         * Cleanup code to avoid Microsoft Visual C++ compiler complaints
501546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
501646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner           memory allocation routines
501746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
501846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
501946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner           usage of 'assert' in non-WIN32 code
502046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
502146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner           avoid infinite loop
502246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Always call 'fREe()' rather than 'free()'
502346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
502446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
502546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Fixed ordering problem with boundary-stamping
502646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
502746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
502846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Added pvalloc, as recommended by H.J. Liu
502946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Added 64bit pointer support mainly from Wolfram Gloger
503046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Added anonymously donated WIN32 sbrk emulation
503146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
503246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * malloc_extend_top: fix mask error that caused wastage after
503346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        foreign sbrks
503446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Add linux mremap support code from HJ Liu
503546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
503646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
503746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Integrated most documentation with the code.
503846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Add support for mmap, with help from
503946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
504046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Use last_remainder in more cases.
504146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Pack bins using idea from  colin@nyx10.cs.du.edu
504246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Use ordered bins instead of best-fit threshhold
504346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Eliminate block-local decls to simplify tracing and debugging.
504446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Support another case of realloc via move into top
504546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Fix error occuring when initial sbrk_base not word-aligned.
504646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Rely on page size for units instead of SBRK_UNIT to
504746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        avoid surprises about sbrk alignment conventions.
504846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
504946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        (raymond@es.ele.tue.nl) for the suggestion.
505046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
505146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * More precautions for cases where other routines call sbrk,
505246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
505346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Added macros etc., allowing use in linux libc from
505446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        H.J. Lu (hjl@gnu.ai.mit.edu)
505546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Inverted this history list
505646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
505746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
505846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
505946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Removed all preallocation code since under current scheme
506046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        the work required to undo bad preallocations exceeds
506146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        the work saved in good cases for most test programs.
506246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * No longer use return list or unconsolidated bins since
506346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        no scheme using them consistently outperforms those that don't
506446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        given above changes.
506546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Use best fit for very large chunks to prevent some worst-cases.
506646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Added some support for debugging
506746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
506846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
506946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Removed footers when chunks are in use. Thanks to
507046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Paul Wilson (wilson@cs.texas.edu) for the suggestion.
507146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
507246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
507346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Added malloc_trim, with help from Wolfram Gloger
507446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        (wmglo@Dent.MED.Uni-Muenchen.DE).
507546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
507646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
507746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
507846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
507946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * realloc: try to expand in both directions
508046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * malloc: swap order of clean-bin strategy;
508146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * realloc: only conditionally expand backwards
508246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Try not to scavenge used bins
508346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Use bin counts as a guide to preallocation
508446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Occasionally bin return list chunks in first scan
508546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Add a few optimizations from colin@nyx10.cs.du.edu
508646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
508746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
508846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * faster bin computation & slightly different binning
508946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * merged all consolidations to one part of malloc proper
509046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         (eliminating old malloc_find_space & malloc_clean_bin)
509146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Scan 2 returns chunks (not just 1)
509246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Propagate failure in realloc if malloc returns 0
509346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Add stuff to allow compilation on non-ANSI compilers
509446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          from kpv@research.att.com
509546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
509646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
509746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * removed potential for odd address access in prev_chunk
509846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * removed dependency on getpagesize.h
509946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * misc cosmetics and a bit more internal documentation
510046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * anticosmetics: mangled names in macros to evade debugger strangeness
510146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * tested on sparc, hp-700, dec-mips, rs6000
510246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          with gcc & native cc (hp, dec only) allowing
510346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          Detlefs & Zorn comparison study (in SIGPLAN Notices.)
510446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
510546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
510646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner      * Based loosely on libg++-1.2X malloc. (It retains some of the overall
510746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner         structure of old version,  but most details differ.)
510846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
510946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
511046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
511146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* !HAVE_MALLOC */
5112