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