xref: /openbmc/u-boot/common/dlmalloc.src (revision 345be0b2)
140c85557Swdenk/* ---------- To make a malloc.h, start cutting here ------------ */
240c85557Swdenk
340c85557Swdenk/*
440c85557Swdenk  A version of malloc/free/realloc written by Doug Lea and released to the
540c85557Swdenk  public domain.  Send questions/comments/complaints/performance data
640c85557Swdenk  to dl@cs.oswego.edu
740c85557Swdenk
840c85557Swdenk* VERSION 2.6.6  Sun Mar  5 19:10:03 2000  Doug Lea  (dl at gee)
940c85557Swdenk
1040c85557Swdenk   Note: There may be an updated version of this malloc obtainable at
1140c85557Swdenk	   ftp://g.oswego.edu/pub/misc/malloc.c
1240c85557Swdenk	 Check before installing!
1340c85557Swdenk
1440c85557Swdenk* Why use this malloc?
1540c85557Swdenk
1640c85557Swdenk  This is not the fastest, most space-conserving, most portable, or
1740c85557Swdenk  most tunable malloc ever written. However it is among the fastest
1840c85557Swdenk  while also being among the most space-conserving, portable and tunable.
1940c85557Swdenk  Consistent balance across these factors results in a good general-purpose
2040c85557Swdenk  allocator. For a high-level description, see
2140c85557Swdenk     http://g.oswego.edu/dl/html/malloc.html
2240c85557Swdenk
2340c85557Swdenk* Synopsis of public routines
2440c85557Swdenk
2540c85557Swdenk  (Much fuller descriptions are contained in the program documentation below.)
2640c85557Swdenk
2740c85557Swdenk  malloc(size_t n);
2840c85557Swdenk     Return a pointer to a newly allocated chunk of at least n bytes, or null
2940c85557Swdenk     if no space is available.
3040c85557Swdenk  free(Void_t* p);
3140c85557Swdenk     Release the chunk of memory pointed to by p, or no effect if p is null.
3240c85557Swdenk  realloc(Void_t* p, size_t n);
3340c85557Swdenk     Return a pointer to a chunk of size n that contains the same data
3440c85557Swdenk     as does chunk p up to the minimum of (n, p's size) bytes, or null
3540c85557Swdenk     if no space is available. The returned pointer may or may not be
3640c85557Swdenk     the same as p. If p is null, equivalent to malloc.  Unless the
3740c85557Swdenk     #define REALLOC_ZERO_BYTES_FREES below is set, realloc with a
3840c85557Swdenk     size argument of zero (re)allocates a minimum-sized chunk.
3940c85557Swdenk  memalign(size_t alignment, size_t n);
4040c85557Swdenk     Return a pointer to a newly allocated chunk of n bytes, aligned
4140c85557Swdenk     in accord with the alignment argument, which must be a power of
4240c85557Swdenk     two.
4340c85557Swdenk  valloc(size_t n);
4440c85557Swdenk     Equivalent to memalign(pagesize, n), where pagesize is the page
4540c85557Swdenk     size of the system (or as near to this as can be figured out from
4640c85557Swdenk     all the includes/defines below.)
4740c85557Swdenk  pvalloc(size_t n);
4840c85557Swdenk     Equivalent to valloc(minimum-page-that-holds(n)), that is,
4940c85557Swdenk     round up n to nearest pagesize.
5040c85557Swdenk  calloc(size_t unit, size_t quantity);
5140c85557Swdenk     Returns a pointer to quantity * unit bytes, with all locations
5240c85557Swdenk     set to zero.
5340c85557Swdenk  cfree(Void_t* p);
5440c85557Swdenk     Equivalent to free(p).
5540c85557Swdenk  malloc_trim(size_t pad);
5640c85557Swdenk     Release all but pad bytes of freed top-most memory back
5740c85557Swdenk     to the system. Return 1 if successful, else 0.
5840c85557Swdenk  malloc_usable_size(Void_t* p);
5940c85557Swdenk     Report the number usable allocated bytes associated with allocated
6040c85557Swdenk     chunk p. This may or may not report more bytes than were requested,
6140c85557Swdenk     due to alignment and minimum size constraints.
6240c85557Swdenk  malloc_stats();
6340c85557Swdenk     Prints brief summary statistics on stderr.
6440c85557Swdenk  mallinfo()
6540c85557Swdenk     Returns (by copy) a struct containing various summary statistics.
6640c85557Swdenk  mallopt(int parameter_number, int parameter_value)
6740c85557Swdenk     Changes one of the tunable parameters described below. Returns
6840c85557Swdenk     1 if successful in changing the parameter, else 0.
6940c85557Swdenk
7040c85557Swdenk* Vital statistics:
7140c85557Swdenk
7240c85557Swdenk  Alignment:                            8-byte
7340c85557Swdenk       8 byte alignment is currently hardwired into the design.  This
7440c85557Swdenk       seems to suffice for all current machines and C compilers.
7540c85557Swdenk
7640c85557Swdenk  Assumed pointer representation:       4 or 8 bytes
7740c85557Swdenk       Code for 8-byte pointers is untested by me but has worked
7840c85557Swdenk       reliably by Wolfram Gloger, who contributed most of the
7940c85557Swdenk       changes supporting this.
8040c85557Swdenk
8140c85557Swdenk  Assumed size_t  representation:       4 or 8 bytes
8240c85557Swdenk       Note that size_t is allowed to be 4 bytes even if pointers are 8.
8340c85557Swdenk
8440c85557Swdenk  Minimum overhead per allocated chunk: 4 or 8 bytes
8540c85557Swdenk       Each malloced chunk has a hidden overhead of 4 bytes holding size
8640c85557Swdenk       and status information.
8740c85557Swdenk
8840c85557Swdenk  Minimum allocated size: 4-byte ptrs:  16 bytes    (including 4 overhead)
8940c85557Swdenk			  8-byte ptrs:  24/32 bytes (including, 4/8 overhead)
9040c85557Swdenk
9140c85557Swdenk       When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
9240c85557Swdenk       ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
9340c85557Swdenk       needed; 4 (8) for a trailing size field
9440c85557Swdenk       and 8 (16) bytes for free list pointers. Thus, the minimum
9540c85557Swdenk       allocatable size is 16/24/32 bytes.
9640c85557Swdenk
9740c85557Swdenk       Even a request for zero bytes (i.e., malloc(0)) returns a
9840c85557Swdenk       pointer to something of the minimum allocatable size.
9940c85557Swdenk
10040c85557Swdenk  Maximum allocated size: 4-byte size_t: 2^31 -  8 bytes
10140c85557Swdenk			  8-byte size_t: 2^63 - 16 bytes
10240c85557Swdenk
10340c85557Swdenk       It is assumed that (possibly signed) size_t bit values suffice to
10440c85557Swdenk       represent chunk sizes. `Possibly signed' is due to the fact
10540c85557Swdenk       that `size_t' may be defined on a system as either a signed or
10640c85557Swdenk       an unsigned type. To be conservative, values that would appear
10740c85557Swdenk       as negative numbers are avoided.
10840c85557Swdenk       Requests for sizes with a negative sign bit when the request
10940c85557Swdenk       size is treaded as a long will return null.
11040c85557Swdenk
11140c85557Swdenk  Maximum overhead wastage per allocated chunk: normally 15 bytes
11240c85557Swdenk
11340c85557Swdenk       Alignnment demands, plus the minimum allocatable size restriction
11440c85557Swdenk       make the normal worst-case wastage 15 bytes (i.e., up to 15
11540c85557Swdenk       more bytes will be allocated than were requested in malloc), with
11640c85557Swdenk       two exceptions:
11740c85557Swdenk	 1. Because requests for zero bytes allocate non-zero space,
11840c85557Swdenk	    the worst case wastage for a request of zero bytes is 24 bytes.
11940c85557Swdenk	 2. For requests >= mmap_threshold that are serviced via
12040c85557Swdenk	    mmap(), the worst case wastage is 8 bytes plus the remainder
12140c85557Swdenk	    from a system page (the minimal mmap unit); typically 4096 bytes.
12240c85557Swdenk
12340c85557Swdenk* Limitations
12440c85557Swdenk
12540c85557Swdenk    Here are some features that are NOT currently supported
12640c85557Swdenk
12740c85557Swdenk    * No user-definable hooks for callbacks and the like.
12840c85557Swdenk    * No automated mechanism for fully checking that all accesses
12940c85557Swdenk      to malloced memory stay within their bounds.
13040c85557Swdenk    * No support for compaction.
13140c85557Swdenk
13240c85557Swdenk* Synopsis of compile-time options:
13340c85557Swdenk
13440c85557Swdenk    People have reported using previous versions of this malloc on all
13540c85557Swdenk    versions of Unix, sometimes by tweaking some of the defines
13640c85557Swdenk    below. It has been tested most extensively on Solaris and
13740c85557Swdenk    Linux. It is also reported to work on WIN32 platforms.
13840c85557Swdenk    People have also reported adapting this malloc for use in
13940c85557Swdenk    stand-alone embedded systems.
14040c85557Swdenk
14140c85557Swdenk    The implementation is in straight, hand-tuned ANSI C.  Among other
14240c85557Swdenk    consequences, it uses a lot of macros.  Because of this, to be at
14340c85557Swdenk    all usable, this code should be compiled using an optimizing compiler
14440c85557Swdenk    (for example gcc -O2) that can simplify expressions and control
14540c85557Swdenk    paths.
14640c85557Swdenk
14740c85557Swdenk  __STD_C                  (default: derived from C compiler defines)
14840c85557Swdenk     Nonzero if using ANSI-standard C compiler, a C++ compiler, or
14940c85557Swdenk     a C compiler sufficiently close to ANSI to get away with it.
15040c85557Swdenk  DEBUG                    (default: NOT defined)
15140c85557Swdenk     Define to enable debugging. Adds fairly extensive assertion-based
15240c85557Swdenk     checking to help track down memory errors, but noticeably slows down
15340c85557Swdenk     execution.
15440c85557Swdenk  REALLOC_ZERO_BYTES_FREES (default: NOT defined)
15540c85557Swdenk     Define this if you think that realloc(p, 0) should be equivalent
15640c85557Swdenk     to free(p). Otherwise, since malloc returns a unique pointer for
15740c85557Swdenk     malloc(0), so does realloc(p, 0).
15840c85557Swdenk  HAVE_MEMCPY               (default: defined)
15940c85557Swdenk     Define if you are not otherwise using ANSI STD C, but still
16040c85557Swdenk     have memcpy and memset in your C library and want to use them.
16140c85557Swdenk     Otherwise, simple internal versions are supplied.
16240c85557Swdenk  USE_MEMCPY               (default: 1 if HAVE_MEMCPY is defined, 0 otherwise)
16340c85557Swdenk     Define as 1 if you want the C library versions of memset and
16440c85557Swdenk     memcpy called in realloc and calloc (otherwise macro versions are used).
16540c85557Swdenk     At least on some platforms, the simple macro versions usually
16640c85557Swdenk     outperform libc versions.
16740c85557Swdenk  HAVE_MMAP                 (default: defined as 1)
16840c85557Swdenk     Define to non-zero to optionally make malloc() use mmap() to
16940c85557Swdenk     allocate very large blocks.
17040c85557Swdenk  HAVE_MREMAP                 (default: defined as 0 unless Linux libc set)
17140c85557Swdenk     Define to non-zero to optionally make realloc() use mremap() to
17240c85557Swdenk     reallocate very large blocks.
17340c85557Swdenk  malloc_getpagesize        (default: derived from system #includes)
17440c85557Swdenk     Either a constant or routine call returning the system page size.
17540c85557Swdenk  HAVE_USR_INCLUDE_MALLOC_H (default: NOT defined)
17640c85557Swdenk     Optionally define if you are on a system with a /usr/include/malloc.h
17740c85557Swdenk     that declares struct mallinfo. It is not at all necessary to
17840c85557Swdenk     define this even if you do, but will ensure consistency.
17940c85557Swdenk  INTERNAL_SIZE_T           (default: size_t)
18040c85557Swdenk     Define to a 32-bit type (probably `unsigned int') if you are on a
18140c85557Swdenk     64-bit machine, yet do not want or need to allow malloc requests of
18240c85557Swdenk     greater than 2^31 to be handled. This saves space, especially for
18340c85557Swdenk     very small chunks.
18440c85557Swdenk  INTERNAL_LINUX_C_LIB      (default: NOT defined)
18540c85557Swdenk     Defined only when compiled as part of Linux libc.
18640c85557Swdenk     Also note that there is some odd internal name-mangling via defines
18740c85557Swdenk     (for example, internally, `malloc' is named `mALLOc') needed
18840c85557Swdenk     when compiling in this case. These look funny but don't otherwise
18940c85557Swdenk     affect anything.
19040c85557Swdenk  WIN32                     (default: undefined)
19140c85557Swdenk     Define this on MS win (95, nt) platforms to compile in sbrk emulation.
19240c85557Swdenk  LACKS_UNISTD_H            (default: undefined if not WIN32)
19340c85557Swdenk     Define this if your system does not have a <unistd.h>.
19440c85557Swdenk  LACKS_SYS_PARAM_H         (default: undefined if not WIN32)
19540c85557Swdenk     Define this if your system does not have a <sys/param.h>.
19640c85557Swdenk  MORECORE                  (default: sbrk)
19740c85557Swdenk     The name of the routine to call to obtain more memory from the system.
19840c85557Swdenk  MORECORE_FAILURE          (default: -1)
19940c85557Swdenk     The value returned upon failure of MORECORE.
20040c85557Swdenk  MORECORE_CLEARS           (default 1)
201*472d5460SYork Sun     true (1) if the routine mapped to MORECORE zeroes out memory (which
20240c85557Swdenk     holds for sbrk).
20340c85557Swdenk  DEFAULT_TRIM_THRESHOLD
20440c85557Swdenk  DEFAULT_TOP_PAD
20540c85557Swdenk  DEFAULT_MMAP_THRESHOLD
20640c85557Swdenk  DEFAULT_MMAP_MAX
20740c85557Swdenk     Default values of tunable parameters (described in detail below)
20840c85557Swdenk     controlling interaction with host system routines (sbrk, mmap, etc).
20940c85557Swdenk     These values may also be changed dynamically via mallopt(). The
21040c85557Swdenk     preset defaults are those that give best performance for typical
21140c85557Swdenk     programs/systems.
21240c85557Swdenk  USE_DL_PREFIX             (default: undefined)
21340c85557Swdenk     Prefix all public routines with the string 'dl'.  Useful to
21440c85557Swdenk     quickly avoid procedure declaration conflicts and linker symbol
21540c85557Swdenk     conflicts with existing memory allocation routines.
21640c85557Swdenk
21740c85557Swdenk
21840c85557Swdenk*/
21940c85557Swdenk
22040c85557Swdenk
22140c85557Swdenk
22240c85557Swdenk
22340c85557Swdenk/* Preliminaries */
22440c85557Swdenk
22540c85557Swdenk#ifndef __STD_C
22640c85557Swdenk#ifdef __STDC__
22740c85557Swdenk#define __STD_C     1
22840c85557Swdenk#else
22940c85557Swdenk#if __cplusplus
23040c85557Swdenk#define __STD_C     1
23140c85557Swdenk#else
23240c85557Swdenk#define __STD_C     0
23340c85557Swdenk#endif /*__cplusplus*/
23440c85557Swdenk#endif /*__STDC__*/
23540c85557Swdenk#endif /*__STD_C*/
23640c85557Swdenk
23740c85557Swdenk#ifndef Void_t
23840c85557Swdenk#if (__STD_C || defined(WIN32))
23940c85557Swdenk#define Void_t      void
24040c85557Swdenk#else
24140c85557Swdenk#define Void_t      char
24240c85557Swdenk#endif
24340c85557Swdenk#endif /*Void_t*/
24440c85557Swdenk
24540c85557Swdenk#if __STD_C
24640c85557Swdenk#include <stddef.h>   /* for size_t */
24740c85557Swdenk#else
24840c85557Swdenk#include <sys/types.h>
24940c85557Swdenk#endif
25040c85557Swdenk
25140c85557Swdenk#ifdef __cplusplus
25240c85557Swdenkextern "C" {
25340c85557Swdenk#endif
25440c85557Swdenk
25540c85557Swdenk#include <stdio.h>    /* needed for malloc_stats */
25640c85557Swdenk
25740c85557Swdenk
25840c85557Swdenk/*
25940c85557Swdenk  Compile-time options
26040c85557Swdenk*/
26140c85557Swdenk
26240c85557Swdenk
26340c85557Swdenk/*
26440c85557Swdenk    Debugging:
26540c85557Swdenk
26640c85557Swdenk    Because freed chunks may be overwritten with link fields, this
26740c85557Swdenk    malloc will often die when freed memory is overwritten by user
26840c85557Swdenk    programs.  This can be very effective (albeit in an annoying way)
26940c85557Swdenk    in helping track down dangling pointers.
27040c85557Swdenk
27140c85557Swdenk    If you compile with -DDEBUG, a number of assertion checks are
27240c85557Swdenk    enabled that will catch more memory errors. You probably won't be
27340c85557Swdenk    able to make much sense of the actual assertion errors, but they
27440c85557Swdenk    should help you locate incorrectly overwritten memory.  The
27540c85557Swdenk    checking is fairly extensive, and will slow down execution
27640c85557Swdenk    noticeably. Calling malloc_stats or mallinfo with DEBUG set will
27740c85557Swdenk    attempt to check every non-mmapped allocated and free chunk in the
27840c85557Swdenk    course of computing the summmaries. (By nature, mmapped regions
27940c85557Swdenk    cannot be checked very much automatically.)
28040c85557Swdenk
28140c85557Swdenk    Setting DEBUG may also be helpful if you are trying to modify
28240c85557Swdenk    this code. The assertions in the check routines spell out in more
28340c85557Swdenk    detail the assumptions and invariants underlying the algorithms.
28440c85557Swdenk
28540c85557Swdenk*/
28640c85557Swdenk
28740c85557Swdenk#if DEBUG
28840c85557Swdenk#include <assert.h>
28940c85557Swdenk#else
29040c85557Swdenk#define assert(x) ((void)0)
29140c85557Swdenk#endif
29240c85557Swdenk
29340c85557Swdenk
29440c85557Swdenk/*
29540c85557Swdenk  INTERNAL_SIZE_T is the word-size used for internal bookkeeping
29640c85557Swdenk  of chunk sizes. On a 64-bit machine, you can reduce malloc
29740c85557Swdenk  overhead by defining INTERNAL_SIZE_T to be a 32 bit `unsigned int'
29840c85557Swdenk  at the expense of not being able to handle requests greater than
29940c85557Swdenk  2^31. This limitation is hardly ever a concern; you are encouraged
30040c85557Swdenk  to set this. However, the default version is the same as size_t.
30140c85557Swdenk*/
30240c85557Swdenk
30340c85557Swdenk#ifndef INTERNAL_SIZE_T
30440c85557Swdenk#define INTERNAL_SIZE_T size_t
30540c85557Swdenk#endif
30640c85557Swdenk
30740c85557Swdenk/*
30840c85557Swdenk  REALLOC_ZERO_BYTES_FREES should be set if a call to
30940c85557Swdenk  realloc with zero bytes should be the same as a call to free.
31040c85557Swdenk  Some people think it should. Otherwise, since this malloc
31140c85557Swdenk  returns a unique pointer for malloc(0), so does realloc(p, 0).
31240c85557Swdenk*/
31340c85557Swdenk
31440c85557Swdenk
31540c85557Swdenk/*   #define REALLOC_ZERO_BYTES_FREES */
31640c85557Swdenk
31740c85557Swdenk
31840c85557Swdenk/*
31940c85557Swdenk  WIN32 causes an emulation of sbrk to be compiled in
32040c85557Swdenk  mmap-based options are not currently supported in WIN32.
32140c85557Swdenk*/
32240c85557Swdenk
32340c85557Swdenk/* #define WIN32 */
32440c85557Swdenk#ifdef WIN32
32540c85557Swdenk#define MORECORE wsbrk
32640c85557Swdenk#define HAVE_MMAP 0
32740c85557Swdenk
32840c85557Swdenk#define LACKS_UNISTD_H
32940c85557Swdenk#define LACKS_SYS_PARAM_H
33040c85557Swdenk
33140c85557Swdenk/*
33240c85557Swdenk  Include 'windows.h' to get the necessary declarations for the
33340c85557Swdenk  Microsoft Visual C++ data structures and routines used in the 'sbrk'
33440c85557Swdenk  emulation.
33540c85557Swdenk
33640c85557Swdenk  Define WIN32_LEAN_AND_MEAN so that only the essential Microsoft
33740c85557Swdenk  Visual C++ header files are included.
33840c85557Swdenk*/
33940c85557Swdenk#define WIN32_LEAN_AND_MEAN
34040c85557Swdenk#include <windows.h>
34140c85557Swdenk#endif
34240c85557Swdenk
34340c85557Swdenk
34440c85557Swdenk/*
34540c85557Swdenk  HAVE_MEMCPY should be defined if you are not otherwise using
34640c85557Swdenk  ANSI STD C, but still have memcpy and memset in your C library
34740c85557Swdenk  and want to use them in calloc and realloc. Otherwise simple
34840c85557Swdenk  macro versions are defined here.
34940c85557Swdenk
35040c85557Swdenk  USE_MEMCPY should be defined as 1 if you actually want to
35140c85557Swdenk  have memset and memcpy called. People report that the macro
35240c85557Swdenk  versions are often enough faster than libc versions on many
35340c85557Swdenk  systems that it is better to use them.
35440c85557Swdenk
35540c85557Swdenk*/
35640c85557Swdenk
35740c85557Swdenk#define HAVE_MEMCPY
35840c85557Swdenk
35940c85557Swdenk#ifndef USE_MEMCPY
36040c85557Swdenk#ifdef HAVE_MEMCPY
36140c85557Swdenk#define USE_MEMCPY 1
36240c85557Swdenk#else
36340c85557Swdenk#define USE_MEMCPY 0
36440c85557Swdenk#endif
36540c85557Swdenk#endif
36640c85557Swdenk
36740c85557Swdenk#if (__STD_C || defined(HAVE_MEMCPY))
36840c85557Swdenk
36940c85557Swdenk#if __STD_C
37040c85557Swdenkvoid* memset(void*, int, size_t);
37140c85557Swdenkvoid* memcpy(void*, const void*, size_t);
37240c85557Swdenk#else
37340c85557Swdenk#ifdef WIN32
3748bde7f77Swdenk/* On Win32 platforms, 'memset()' and 'memcpy()' are already declared in */
3758bde7f77Swdenk/* 'windows.h' */
37640c85557Swdenk#else
37740c85557SwdenkVoid_t* memset();
37840c85557SwdenkVoid_t* memcpy();
37940c85557Swdenk#endif
38040c85557Swdenk#endif
38140c85557Swdenk#endif
38240c85557Swdenk
38340c85557Swdenk#if USE_MEMCPY
38440c85557Swdenk
38540c85557Swdenk/* The following macros are only invoked with (2n+1)-multiples of
38640c85557Swdenk   INTERNAL_SIZE_T units, with a positive integer n. This is exploited
38740c85557Swdenk   for fast inline execution when n is small. */
38840c85557Swdenk
38940c85557Swdenk#define MALLOC_ZERO(charp, nbytes)                                            \
39040c85557Swdenkdo {                                                                          \
39140c85557Swdenk  INTERNAL_SIZE_T mzsz = (nbytes);                                            \
39240c85557Swdenk  if(mzsz <= 9*sizeof(mzsz)) {                                                \
39340c85557Swdenk    INTERNAL_SIZE_T* mz = (INTERNAL_SIZE_T*) (charp);                         \
39440c85557Swdenk    if(mzsz >= 5*sizeof(mzsz)) {     *mz++ = 0;                               \
39540c85557Swdenk				     *mz++ = 0;                               \
39640c85557Swdenk      if(mzsz >= 7*sizeof(mzsz)) {   *mz++ = 0;                               \
39740c85557Swdenk				     *mz++ = 0;                               \
39840c85557Swdenk	if(mzsz >= 9*sizeof(mzsz)) { *mz++ = 0;                               \
39940c85557Swdenk				     *mz++ = 0; }}}                           \
40040c85557Swdenk				     *mz++ = 0;                               \
40140c85557Swdenk				     *mz++ = 0;                               \
40240c85557Swdenk				     *mz   = 0;                               \
40340c85557Swdenk  } else memset((charp), 0, mzsz);                                            \
40440c85557Swdenk} while(0)
40540c85557Swdenk
40640c85557Swdenk#define MALLOC_COPY(dest,src,nbytes)                                          \
40740c85557Swdenkdo {                                                                          \
40840c85557Swdenk  INTERNAL_SIZE_T mcsz = (nbytes);                                            \
40940c85557Swdenk  if(mcsz <= 9*sizeof(mcsz)) {                                                \
41040c85557Swdenk    INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) (src);                        \
41140c85557Swdenk    INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) (dest);                       \
41240c85557Swdenk    if(mcsz >= 5*sizeof(mcsz)) {     *mcdst++ = *mcsrc++;                     \
41340c85557Swdenk				     *mcdst++ = *mcsrc++;                     \
41440c85557Swdenk      if(mcsz >= 7*sizeof(mcsz)) {   *mcdst++ = *mcsrc++;                     \
41540c85557Swdenk				     *mcdst++ = *mcsrc++;                     \
41640c85557Swdenk	if(mcsz >= 9*sizeof(mcsz)) { *mcdst++ = *mcsrc++;                     \
41740c85557Swdenk				     *mcdst++ = *mcsrc++; }}}                 \
41840c85557Swdenk				     *mcdst++ = *mcsrc++;                     \
41940c85557Swdenk				     *mcdst++ = *mcsrc++;                     \
42040c85557Swdenk				     *mcdst   = *mcsrc  ;                     \
42140c85557Swdenk  } else memcpy(dest, src, mcsz);                                             \
42240c85557Swdenk} while(0)
42340c85557Swdenk
42440c85557Swdenk#else /* !USE_MEMCPY */
42540c85557Swdenk
42640c85557Swdenk/* Use Duff's device for good zeroing/copying performance. */
42740c85557Swdenk
42840c85557Swdenk#define MALLOC_ZERO(charp, nbytes)                                            \
42940c85557Swdenkdo {                                                                          \
43040c85557Swdenk  INTERNAL_SIZE_T* mzp = (INTERNAL_SIZE_T*)(charp);                           \
43140c85557Swdenk  long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn;                         \
43240c85557Swdenk  if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \
43340c85557Swdenk  switch (mctmp) {                                                            \
43440c85557Swdenk    case 0: for(;;) { *mzp++ = 0;                                             \
43540c85557Swdenk    case 7:           *mzp++ = 0;                                             \
43640c85557Swdenk    case 6:           *mzp++ = 0;                                             \
43740c85557Swdenk    case 5:           *mzp++ = 0;                                             \
43840c85557Swdenk    case 4:           *mzp++ = 0;                                             \
43940c85557Swdenk    case 3:           *mzp++ = 0;                                             \
44040c85557Swdenk    case 2:           *mzp++ = 0;                                             \
44140c85557Swdenk    case 1:           *mzp++ = 0; if(mcn <= 0) break; mcn--; }                \
44240c85557Swdenk  }                                                                           \
44340c85557Swdenk} while(0)
44440c85557Swdenk
44540c85557Swdenk#define MALLOC_COPY(dest,src,nbytes)                                          \
44640c85557Swdenkdo {                                                                          \
44740c85557Swdenk  INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src;                            \
44840c85557Swdenk  INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest;                           \
44940c85557Swdenk  long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn;                         \
45040c85557Swdenk  if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \
45140c85557Swdenk  switch (mctmp) {                                                            \
45240c85557Swdenk    case 0: for(;;) { *mcdst++ = *mcsrc++;                                    \
45340c85557Swdenk    case 7:           *mcdst++ = *mcsrc++;                                    \
45440c85557Swdenk    case 6:           *mcdst++ = *mcsrc++;                                    \
45540c85557Swdenk    case 5:           *mcdst++ = *mcsrc++;                                    \
45640c85557Swdenk    case 4:           *mcdst++ = *mcsrc++;                                    \
45740c85557Swdenk    case 3:           *mcdst++ = *mcsrc++;                                    \
45840c85557Swdenk    case 2:           *mcdst++ = *mcsrc++;                                    \
45940c85557Swdenk    case 1:           *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; }       \
46040c85557Swdenk  }                                                                           \
46140c85557Swdenk} while(0)
46240c85557Swdenk
46340c85557Swdenk#endif
46440c85557Swdenk
46540c85557Swdenk
46640c85557Swdenk/*
46740c85557Swdenk  Define HAVE_MMAP to optionally make malloc() use mmap() to
46840c85557Swdenk  allocate very large blocks.  These will be returned to the
46940c85557Swdenk  operating system immediately after a free().
47040c85557Swdenk*/
47140c85557Swdenk
47240c85557Swdenk#ifndef HAVE_MMAP
47340c85557Swdenk#define HAVE_MMAP 1
47440c85557Swdenk#endif
47540c85557Swdenk
47640c85557Swdenk/*
47740c85557Swdenk  Define HAVE_MREMAP to make realloc() use mremap() to re-allocate
47840c85557Swdenk  large blocks.  This is currently only possible on Linux with
47940c85557Swdenk  kernel versions newer than 1.3.77.
48040c85557Swdenk*/
48140c85557Swdenk
48240c85557Swdenk#ifndef HAVE_MREMAP
48340c85557Swdenk#ifdef INTERNAL_LINUX_C_LIB
48440c85557Swdenk#define HAVE_MREMAP 1
48540c85557Swdenk#else
48640c85557Swdenk#define HAVE_MREMAP 0
48740c85557Swdenk#endif
48840c85557Swdenk#endif
48940c85557Swdenk
49040c85557Swdenk#if HAVE_MMAP
49140c85557Swdenk
49240c85557Swdenk#include <unistd.h>
49340c85557Swdenk#include <fcntl.h>
49440c85557Swdenk#include <sys/mman.h>
49540c85557Swdenk
49640c85557Swdenk#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
49740c85557Swdenk#define MAP_ANONYMOUS MAP_ANON
49840c85557Swdenk#endif
49940c85557Swdenk
50040c85557Swdenk#endif /* HAVE_MMAP */
50140c85557Swdenk
50240c85557Swdenk/*
50340c85557Swdenk  Access to system page size. To the extent possible, this malloc
50440c85557Swdenk  manages memory from the system in page-size units.
50540c85557Swdenk
50640c85557Swdenk  The following mechanics for getpagesize were adapted from
50740c85557Swdenk  bsd/gnu getpagesize.h
50840c85557Swdenk*/
50940c85557Swdenk
51040c85557Swdenk#ifndef LACKS_UNISTD_H
51140c85557Swdenk#  include <unistd.h>
51240c85557Swdenk#endif
51340c85557Swdenk
51440c85557Swdenk#ifndef malloc_getpagesize
51540c85557Swdenk#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
51640c85557Swdenk#    ifndef _SC_PAGE_SIZE
51740c85557Swdenk#      define _SC_PAGE_SIZE _SC_PAGESIZE
51840c85557Swdenk#    endif
51940c85557Swdenk#  endif
52040c85557Swdenk#  ifdef _SC_PAGE_SIZE
52140c85557Swdenk#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
52240c85557Swdenk#  else
52340c85557Swdenk#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
52440c85557Swdenk       extern size_t getpagesize();
52540c85557Swdenk#      define malloc_getpagesize getpagesize()
52640c85557Swdenk#    else
52740c85557Swdenk#      ifdef WIN32
52840c85557Swdenk#        define malloc_getpagesize (4096) /* TBD: Use 'GetSystemInfo' instead */
52940c85557Swdenk#      else
53040c85557Swdenk#        ifndef LACKS_SYS_PARAM_H
53140c85557Swdenk#          include <sys/param.h>
53240c85557Swdenk#        endif
53340c85557Swdenk#        ifdef EXEC_PAGESIZE
53440c85557Swdenk#          define malloc_getpagesize EXEC_PAGESIZE
53540c85557Swdenk#        else
53640c85557Swdenk#          ifdef NBPG
53740c85557Swdenk#            ifndef CLSIZE
53840c85557Swdenk#              define malloc_getpagesize NBPG
53940c85557Swdenk#            else
54040c85557Swdenk#              define malloc_getpagesize (NBPG * CLSIZE)
54140c85557Swdenk#            endif
54240c85557Swdenk#          else
54340c85557Swdenk#            ifdef NBPC
54440c85557Swdenk#              define malloc_getpagesize NBPC
54540c85557Swdenk#            else
54640c85557Swdenk#              ifdef PAGESIZE
54740c85557Swdenk#                define malloc_getpagesize PAGESIZE
54840c85557Swdenk#              else
54940c85557Swdenk#                define malloc_getpagesize (4096) /* just guess */
55040c85557Swdenk#              endif
55140c85557Swdenk#            endif
55240c85557Swdenk#          endif
55340c85557Swdenk#        endif
55440c85557Swdenk#      endif
55540c85557Swdenk#    endif
55640c85557Swdenk#  endif
55740c85557Swdenk#endif
55840c85557Swdenk
55940c85557Swdenk
56040c85557Swdenk/*
56140c85557Swdenk
56240c85557Swdenk  This version of malloc supports the standard SVID/XPG mallinfo
56340c85557Swdenk  routine that returns a struct containing the same kind of
56440c85557Swdenk  information you can get from malloc_stats. It should work on
56540c85557Swdenk  any SVID/XPG compliant system that has a /usr/include/malloc.h
56640c85557Swdenk  defining struct mallinfo. (If you'd like to install such a thing
56740c85557Swdenk  yourself, cut out the preliminary declarations as described above
56840c85557Swdenk  and below and save them in a malloc.h file. But there's no
56940c85557Swdenk  compelling reason to bother to do this.)
57040c85557Swdenk
57140c85557Swdenk  The main declaration needed is the mallinfo struct that is returned
57240c85557Swdenk  (by-copy) by mallinfo().  The SVID/XPG malloinfo struct contains a
57340c85557Swdenk  bunch of fields, most of which are not even meaningful in this
57440c85557Swdenk  version of malloc. Some of these fields are are instead filled by
57540c85557Swdenk  mallinfo() with other numbers that might possibly be of interest.
57640c85557Swdenk
57740c85557Swdenk  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
57840c85557Swdenk  /usr/include/malloc.h file that includes a declaration of struct
57940c85557Swdenk  mallinfo.  If so, it is included; else an SVID2/XPG2 compliant
58040c85557Swdenk  version is declared below.  These must be precisely the same for
58140c85557Swdenk  mallinfo() to work.
58240c85557Swdenk
58340c85557Swdenk*/
58440c85557Swdenk
58540c85557Swdenk/* #define HAVE_USR_INCLUDE_MALLOC_H */
58640c85557Swdenk
58740c85557Swdenk#if HAVE_USR_INCLUDE_MALLOC_H
58840c85557Swdenk#include "/usr/include/malloc.h"
58940c85557Swdenk#else
59040c85557Swdenk
59140c85557Swdenk/* SVID2/XPG mallinfo structure */
59240c85557Swdenk
59340c85557Swdenkstruct mallinfo {
59440c85557Swdenk  int arena;    /* total space allocated from system */
59540c85557Swdenk  int ordblks;  /* number of non-inuse chunks */
59640c85557Swdenk  int smblks;   /* unused -- always zero */
59740c85557Swdenk  int hblks;    /* number of mmapped regions */
59840c85557Swdenk  int hblkhd;   /* total space in mmapped regions */
59940c85557Swdenk  int usmblks;  /* unused -- always zero */
60040c85557Swdenk  int fsmblks;  /* unused -- always zero */
60140c85557Swdenk  int uordblks; /* total allocated space */
60240c85557Swdenk  int fordblks; /* total non-inuse space */
60340c85557Swdenk  int keepcost; /* top-most, releasable (via malloc_trim) space */
60440c85557Swdenk};
60540c85557Swdenk
60640c85557Swdenk/* SVID2/XPG mallopt options */
60740c85557Swdenk
60840c85557Swdenk#define M_MXFAST  1    /* UNUSED in this malloc */
60940c85557Swdenk#define M_NLBLKS  2    /* UNUSED in this malloc */
61040c85557Swdenk#define M_GRAIN   3    /* UNUSED in this malloc */
61140c85557Swdenk#define M_KEEP    4    /* UNUSED in this malloc */
61240c85557Swdenk
61340c85557Swdenk#endif
61440c85557Swdenk
61540c85557Swdenk/* mallopt options that actually do something */
61640c85557Swdenk
61740c85557Swdenk#define M_TRIM_THRESHOLD    -1
61840c85557Swdenk#define M_TOP_PAD           -2
61940c85557Swdenk#define M_MMAP_THRESHOLD    -3
62040c85557Swdenk#define M_MMAP_MAX          -4
62140c85557Swdenk
62240c85557Swdenk
62340c85557Swdenk#ifndef DEFAULT_TRIM_THRESHOLD
62440c85557Swdenk#define DEFAULT_TRIM_THRESHOLD (128 * 1024)
62540c85557Swdenk#endif
62640c85557Swdenk
62740c85557Swdenk/*
62840c85557Swdenk    M_TRIM_THRESHOLD is the maximum amount of unused top-most memory
62940c85557Swdenk      to keep before releasing via malloc_trim in free().
63040c85557Swdenk
63140c85557Swdenk      Automatic trimming is mainly useful in long-lived programs.
63240c85557Swdenk      Because trimming via sbrk can be slow on some systems, and can
63340c85557Swdenk      sometimes be wasteful (in cases where programs immediately
63440c85557Swdenk      afterward allocate more large chunks) the value should be high
63540c85557Swdenk      enough so that your overall system performance would improve by
63640c85557Swdenk      releasing.
63740c85557Swdenk
63840c85557Swdenk      The trim threshold and the mmap control parameters (see below)
63940c85557Swdenk      can be traded off with one another. Trimming and mmapping are
64040c85557Swdenk      two different ways of releasing unused memory back to the
64140c85557Swdenk      system. Between these two, it is often possible to keep
64240c85557Swdenk      system-level demands of a long-lived program down to a bare
64340c85557Swdenk      minimum. For example, in one test suite of sessions measuring
64440c85557Swdenk      the XF86 X server on Linux, using a trim threshold of 128K and a
64540c85557Swdenk      mmap threshold of 192K led to near-minimal long term resource
64640c85557Swdenk      consumption.
64740c85557Swdenk
64840c85557Swdenk      If you are using this malloc in a long-lived program, it should
64940c85557Swdenk      pay to experiment with these values.  As a rough guide, you
65040c85557Swdenk      might set to a value close to the average size of a process
65140c85557Swdenk      (program) running on your system.  Releasing this much memory
65240c85557Swdenk      would allow such a process to run in memory.  Generally, it's
65340c85557Swdenk      worth it to tune for trimming rather tham memory mapping when a
65440c85557Swdenk      program undergoes phases where several large chunks are
65540c85557Swdenk      allocated and released in ways that can reuse each other's
65640c85557Swdenk      storage, perhaps mixed with phases where there are no such
65740c85557Swdenk      chunks at all.  And in well-behaved long-lived programs,
65840c85557Swdenk      controlling release of large blocks via trimming versus mapping
65940c85557Swdenk      is usually faster.
66040c85557Swdenk
66140c85557Swdenk      However, in most programs, these parameters serve mainly as
66240c85557Swdenk      protection against the system-level effects of carrying around
66340c85557Swdenk      massive amounts of unneeded memory. Since frequent calls to
66440c85557Swdenk      sbrk, mmap, and munmap otherwise degrade performance, the default
66540c85557Swdenk      parameters are set to relatively high values that serve only as
66640c85557Swdenk      safeguards.
66740c85557Swdenk
66840c85557Swdenk      The default trim value is high enough to cause trimming only in
66940c85557Swdenk      fairly extreme (by current memory consumption standards) cases.
67040c85557Swdenk      It must be greater than page size to have any useful effect.  To
67140c85557Swdenk      disable trimming completely, you can set to (unsigned long)(-1);
67240c85557Swdenk
67340c85557Swdenk
67440c85557Swdenk*/
67540c85557Swdenk
67640c85557Swdenk
67740c85557Swdenk#ifndef DEFAULT_TOP_PAD
67840c85557Swdenk#define DEFAULT_TOP_PAD        (0)
67940c85557Swdenk#endif
68040c85557Swdenk
68140c85557Swdenk/*
68240c85557Swdenk    M_TOP_PAD is the amount of extra `padding' space to allocate or
68340c85557Swdenk      retain whenever sbrk is called. It is used in two ways internally:
68440c85557Swdenk
68540c85557Swdenk      * When sbrk is called to extend the top of the arena to satisfy
68640c85557Swdenk	a new malloc request, this much padding is added to the sbrk
68740c85557Swdenk	request.
68840c85557Swdenk
68940c85557Swdenk      * When malloc_trim is called automatically from free(),
69040c85557Swdenk	it is used as the `pad' argument.
69140c85557Swdenk
69240c85557Swdenk      In both cases, the actual amount of padding is rounded
69340c85557Swdenk      so that the end of the arena is always a system page boundary.
69440c85557Swdenk
69540c85557Swdenk      The main reason for using padding is to avoid calling sbrk so
69640c85557Swdenk      often. Having even a small pad greatly reduces the likelihood
69740c85557Swdenk      that nearly every malloc request during program start-up (or
69840c85557Swdenk      after trimming) will invoke sbrk, which needlessly wastes
69940c85557Swdenk      time.
70040c85557Swdenk
70140c85557Swdenk      Automatic rounding-up to page-size units is normally sufficient
70240c85557Swdenk      to avoid measurable overhead, so the default is 0.  However, in
70340c85557Swdenk      systems where sbrk is relatively slow, it can pay to increase
70440c85557Swdenk      this value, at the expense of carrying around more memory than
70540c85557Swdenk      the program needs.
70640c85557Swdenk
70740c85557Swdenk*/
70840c85557Swdenk
70940c85557Swdenk
71040c85557Swdenk#ifndef DEFAULT_MMAP_THRESHOLD
71140c85557Swdenk#define DEFAULT_MMAP_THRESHOLD (128 * 1024)
71240c85557Swdenk#endif
71340c85557Swdenk
71440c85557Swdenk/*
71540c85557Swdenk
71640c85557Swdenk    M_MMAP_THRESHOLD is the request size threshold for using mmap()
71740c85557Swdenk      to service a request. Requests of at least this size that cannot
71840c85557Swdenk      be allocated using already-existing space will be serviced via mmap.
71940c85557Swdenk      (If enough normal freed space already exists it is used instead.)
72040c85557Swdenk
72140c85557Swdenk      Using mmap segregates relatively large chunks of memory so that
72240c85557Swdenk      they can be individually obtained and released from the host
72340c85557Swdenk      system. A request serviced through mmap is never reused by any
72440c85557Swdenk      other request (at least not directly; the system may just so
72540c85557Swdenk      happen to remap successive requests to the same locations).
72640c85557Swdenk
72740c85557Swdenk      Segregating space in this way has the benefit that mmapped space
72840c85557Swdenk      can ALWAYS be individually released back to the system, which
72940c85557Swdenk      helps keep the system level memory demands of a long-lived
73040c85557Swdenk      program low. Mapped memory can never become `locked' between
73140c85557Swdenk      other chunks, as can happen with normally allocated chunks, which
73240c85557Swdenk      menas that even trimming via malloc_trim would not release them.
73340c85557Swdenk
73440c85557Swdenk      However, it has the disadvantages that:
73540c85557Swdenk
73640c85557Swdenk	 1. The space cannot be reclaimed, consolidated, and then
73740c85557Swdenk	    used to service later requests, as happens with normal chunks.
73840c85557Swdenk	 2. It can lead to more wastage because of mmap page alignment
73940c85557Swdenk	    requirements
74040c85557Swdenk	 3. It causes malloc performance to be more dependent on host
74140c85557Swdenk	    system memory management support routines which may vary in
74240c85557Swdenk	    implementation quality and may impose arbitrary
74340c85557Swdenk	    limitations. Generally, servicing a request via normal
74440c85557Swdenk	    malloc steps is faster than going through a system's mmap.
74540c85557Swdenk
74640c85557Swdenk      All together, these considerations should lead you to use mmap
74740c85557Swdenk      only for relatively large requests.
74840c85557Swdenk
74940c85557Swdenk
75040c85557Swdenk*/
75140c85557Swdenk
75240c85557Swdenk
75340c85557Swdenk#ifndef DEFAULT_MMAP_MAX
75440c85557Swdenk#if HAVE_MMAP
75540c85557Swdenk#define DEFAULT_MMAP_MAX       (64)
75640c85557Swdenk#else
75740c85557Swdenk#define DEFAULT_MMAP_MAX       (0)
75840c85557Swdenk#endif
75940c85557Swdenk#endif
76040c85557Swdenk
76140c85557Swdenk/*
76240c85557Swdenk    M_MMAP_MAX is the maximum number of requests to simultaneously
76340c85557Swdenk      service using mmap. This parameter exists because:
76440c85557Swdenk
76540c85557Swdenk	 1. Some systems have a limited number of internal tables for
76640c85557Swdenk	    use by mmap.
76740c85557Swdenk	 2. In most systems, overreliance on mmap can degrade overall
76840c85557Swdenk	    performance.
76940c85557Swdenk	 3. If a program allocates many large regions, it is probably
77040c85557Swdenk	    better off using normal sbrk-based allocation routines that
77140c85557Swdenk	    can reclaim and reallocate normal heap memory. Using a
77240c85557Swdenk	    small value allows transition into this mode after the
77340c85557Swdenk	    first few allocations.
77440c85557Swdenk
77540c85557Swdenk      Setting to 0 disables all use of mmap.  If HAVE_MMAP is not set,
77640c85557Swdenk      the default value is 0, and attempts to set it to non-zero values
77740c85557Swdenk      in mallopt will fail.
77840c85557Swdenk*/
77940c85557Swdenk
78040c85557Swdenk
78140c85557Swdenk/*
78240c85557Swdenk    USE_DL_PREFIX will prefix all public routines with the string 'dl'.
78340c85557Swdenk      Useful to quickly avoid procedure declaration conflicts and linker
78440c85557Swdenk      symbol conflicts with existing memory allocation routines.
78540c85557Swdenk
78640c85557Swdenk*/
78740c85557Swdenk
78840c85557Swdenk/* #define USE_DL_PREFIX */
78940c85557Swdenk
79040c85557Swdenk
79140c85557Swdenk/*
79240c85557Swdenk
79340c85557Swdenk  Special defines for linux libc
79440c85557Swdenk
79540c85557Swdenk  Except when compiled using these special defines for Linux libc
79640c85557Swdenk  using weak aliases, this malloc is NOT designed to work in
79740c85557Swdenk  multithreaded applications.  No semaphores or other concurrency
79840c85557Swdenk  control are provided to ensure that multiple malloc or free calls
79940c85557Swdenk  don't run at the same time, which could be disasterous. A single
80040c85557Swdenk  semaphore could be used across malloc, realloc, and free (which is
80140c85557Swdenk  essentially the effect of the linux weak alias approach). It would
80240c85557Swdenk  be hard to obtain finer granularity.
80340c85557Swdenk
80440c85557Swdenk*/
80540c85557Swdenk
80640c85557Swdenk
80740c85557Swdenk#ifdef INTERNAL_LINUX_C_LIB
80840c85557Swdenk
80940c85557Swdenk#if __STD_C
81040c85557Swdenk
81140c85557SwdenkVoid_t * __default_morecore_init (ptrdiff_t);
81240c85557SwdenkVoid_t *(*__morecore)(ptrdiff_t) = __default_morecore_init;
81340c85557Swdenk
81440c85557Swdenk#else
81540c85557Swdenk
81640c85557SwdenkVoid_t * __default_morecore_init ();
81740c85557SwdenkVoid_t *(*__morecore)() = __default_morecore_init;
81840c85557Swdenk
81940c85557Swdenk#endif
82040c85557Swdenk
82140c85557Swdenk#define MORECORE (*__morecore)
82240c85557Swdenk#define MORECORE_FAILURE 0
82340c85557Swdenk#define MORECORE_CLEARS 1
82440c85557Swdenk
82540c85557Swdenk#else /* INTERNAL_LINUX_C_LIB */
82640c85557Swdenk
82740c85557Swdenk#if __STD_C
82840c85557Swdenkextern Void_t*     sbrk(ptrdiff_t);
82940c85557Swdenk#else
83040c85557Swdenkextern Void_t*     sbrk();
83140c85557Swdenk#endif
83240c85557Swdenk
83340c85557Swdenk#ifndef MORECORE
83440c85557Swdenk#define MORECORE sbrk
83540c85557Swdenk#endif
83640c85557Swdenk
83740c85557Swdenk#ifndef MORECORE_FAILURE
83840c85557Swdenk#define MORECORE_FAILURE -1
83940c85557Swdenk#endif
84040c85557Swdenk
84140c85557Swdenk#ifndef MORECORE_CLEARS
84240c85557Swdenk#define MORECORE_CLEARS 1
84340c85557Swdenk#endif
84440c85557Swdenk
84540c85557Swdenk#endif /* INTERNAL_LINUX_C_LIB */
84640c85557Swdenk
84740c85557Swdenk#if defined(INTERNAL_LINUX_C_LIB) && defined(__ELF__)
84840c85557Swdenk
84940c85557Swdenk#define cALLOc		__libc_calloc
85040c85557Swdenk#define fREe		__libc_free
85140c85557Swdenk#define mALLOc		__libc_malloc
85240c85557Swdenk#define mEMALIGn	__libc_memalign
85340c85557Swdenk#define rEALLOc		__libc_realloc
85440c85557Swdenk#define vALLOc		__libc_valloc
85540c85557Swdenk#define pvALLOc		__libc_pvalloc
85640c85557Swdenk#define mALLINFo	__libc_mallinfo
85740c85557Swdenk#define mALLOPt		__libc_mallopt
85840c85557Swdenk
85940c85557Swdenk#pragma weak calloc = __libc_calloc
86040c85557Swdenk#pragma weak free = __libc_free
86140c85557Swdenk#pragma weak cfree = __libc_free
86240c85557Swdenk#pragma weak malloc = __libc_malloc
86340c85557Swdenk#pragma weak memalign = __libc_memalign
86440c85557Swdenk#pragma weak realloc = __libc_realloc
86540c85557Swdenk#pragma weak valloc = __libc_valloc
86640c85557Swdenk#pragma weak pvalloc = __libc_pvalloc
86740c85557Swdenk#pragma weak mallinfo = __libc_mallinfo
86840c85557Swdenk#pragma weak mallopt = __libc_mallopt
86940c85557Swdenk
87040c85557Swdenk#else
87140c85557Swdenk
87240c85557Swdenk#ifdef USE_DL_PREFIX
87340c85557Swdenk#define cALLOc		dlcalloc
87440c85557Swdenk#define fREe		dlfree
87540c85557Swdenk#define mALLOc		dlmalloc
87640c85557Swdenk#define mEMALIGn	dlmemalign
87740c85557Swdenk#define rEALLOc		dlrealloc
87840c85557Swdenk#define vALLOc		dlvalloc
87940c85557Swdenk#define pvALLOc		dlpvalloc
88040c85557Swdenk#define mALLINFo	dlmallinfo
88140c85557Swdenk#define mALLOPt		dlmallopt
88240c85557Swdenk#else /* USE_DL_PREFIX */
88340c85557Swdenk#define cALLOc		calloc
88440c85557Swdenk#define fREe		free
88540c85557Swdenk#define mALLOc		malloc
88640c85557Swdenk#define mEMALIGn	memalign
88740c85557Swdenk#define rEALLOc		realloc
88840c85557Swdenk#define vALLOc		valloc
88940c85557Swdenk#define pvALLOc		pvalloc
89040c85557Swdenk#define mALLINFo	mallinfo
89140c85557Swdenk#define mALLOPt		mallopt
89240c85557Swdenk#endif /* USE_DL_PREFIX */
89340c85557Swdenk
89440c85557Swdenk#endif
89540c85557Swdenk
89640c85557Swdenk/* Public routines */
89740c85557Swdenk
89840c85557Swdenk#if __STD_C
89940c85557Swdenk
90040c85557SwdenkVoid_t* mALLOc(size_t);
90140c85557Swdenkvoid    fREe(Void_t*);
90240c85557SwdenkVoid_t* rEALLOc(Void_t*, size_t);
90340c85557SwdenkVoid_t* mEMALIGn(size_t, size_t);
90440c85557SwdenkVoid_t* vALLOc(size_t);
90540c85557SwdenkVoid_t* pvALLOc(size_t);
90640c85557SwdenkVoid_t* cALLOc(size_t, size_t);
90740c85557Swdenkvoid    cfree(Void_t*);
90840c85557Swdenkint     malloc_trim(size_t);
90940c85557Swdenksize_t  malloc_usable_size(Void_t*);
91040c85557Swdenkvoid    malloc_stats();
91140c85557Swdenkint     mALLOPt(int, int);
91240c85557Swdenkstruct mallinfo mALLINFo(void);
91340c85557Swdenk#else
91440c85557SwdenkVoid_t* mALLOc();
91540c85557Swdenkvoid    fREe();
91640c85557SwdenkVoid_t* rEALLOc();
91740c85557SwdenkVoid_t* mEMALIGn();
91840c85557SwdenkVoid_t* vALLOc();
91940c85557SwdenkVoid_t* pvALLOc();
92040c85557SwdenkVoid_t* cALLOc();
92140c85557Swdenkvoid    cfree();
92240c85557Swdenkint     malloc_trim();
92340c85557Swdenksize_t  malloc_usable_size();
92440c85557Swdenkvoid    malloc_stats();
92540c85557Swdenkint     mALLOPt();
92640c85557Swdenkstruct mallinfo mALLINFo();
92740c85557Swdenk#endif
92840c85557Swdenk
92940c85557Swdenk
93040c85557Swdenk#ifdef __cplusplus
93140c85557Swdenk};  /* end of extern "C" */
93240c85557Swdenk#endif
93340c85557Swdenk
93440c85557Swdenk/* ---------- To make a malloc.h, end cutting here ------------ */
93540c85557Swdenk
93640c85557Swdenk
93740c85557Swdenk/*
93840c85557Swdenk  Emulation of sbrk for WIN32
93940c85557Swdenk  All code within the ifdef WIN32 is untested by me.
94040c85557Swdenk
94140c85557Swdenk  Thanks to Martin Fong and others for supplying this.
94240c85557Swdenk*/
94340c85557Swdenk
94440c85557Swdenk
94540c85557Swdenk#ifdef WIN32
94640c85557Swdenk
94740c85557Swdenk#define AlignPage(add) (((add) + (malloc_getpagesize-1)) & \
94840c85557Swdenk~(malloc_getpagesize-1))
94940c85557Swdenk#define AlignPage64K(add) (((add) + (0x10000 - 1)) & ~(0x10000 - 1))
95040c85557Swdenk
95140c85557Swdenk/* resrve 64MB to insure large contiguous space */
95240c85557Swdenk#define RESERVED_SIZE (1024*1024*64)
95340c85557Swdenk#define NEXT_SIZE (2048*1024)
95440c85557Swdenk#define TOP_MEMORY ((unsigned long)2*1024*1024*1024)
95540c85557Swdenk
95640c85557Swdenkstruct GmListElement;
95740c85557Swdenktypedef struct GmListElement GmListElement;
95840c85557Swdenk
95940c85557Swdenkstruct GmListElement
96040c85557Swdenk{
96140c85557Swdenk	GmListElement* next;
96240c85557Swdenk	void* base;
96340c85557Swdenk};
96440c85557Swdenk
96540c85557Swdenkstatic GmListElement* head = 0;
96640c85557Swdenkstatic unsigned int gNextAddress = 0;
96740c85557Swdenkstatic unsigned int gAddressBase = 0;
96840c85557Swdenkstatic unsigned int gAllocatedSize = 0;
96940c85557Swdenk
97040c85557Swdenkstatic
97140c85557SwdenkGmListElement* makeGmListElement (void* bas)
97240c85557Swdenk{
97340c85557Swdenk	GmListElement* this;
97440c85557Swdenk	this = (GmListElement*)(void*)LocalAlloc (0, sizeof (GmListElement));
97540c85557Swdenk	assert (this);
97640c85557Swdenk	if (this)
97740c85557Swdenk	{
97840c85557Swdenk		this->base = bas;
97940c85557Swdenk		this->next = head;
98040c85557Swdenk		head = this;
98140c85557Swdenk	}
98240c85557Swdenk	return this;
98340c85557Swdenk}
98440c85557Swdenk
98540c85557Swdenkvoid gcleanup ()
98640c85557Swdenk{
98740c85557Swdenk	BOOL rval;
98840c85557Swdenk	assert ( (head == NULL) || (head->base == (void*)gAddressBase));
98940c85557Swdenk	if (gAddressBase && (gNextAddress - gAddressBase))
99040c85557Swdenk	{
99140c85557Swdenk		rval = VirtualFree ((void*)gAddressBase,
99240c85557Swdenk							gNextAddress - gAddressBase,
99340c85557Swdenk							MEM_DECOMMIT);
99440c85557Swdenk	assert (rval);
99540c85557Swdenk	}
99640c85557Swdenk	while (head)
99740c85557Swdenk	{
99840c85557Swdenk		GmListElement* next = head->next;
99940c85557Swdenk		rval = VirtualFree (head->base, 0, MEM_RELEASE);
100040c85557Swdenk		assert (rval);
100140c85557Swdenk		LocalFree (head);
100240c85557Swdenk		head = next;
100340c85557Swdenk	}
100440c85557Swdenk}
100540c85557Swdenk
100640c85557Swdenkstatic
100740c85557Swdenkvoid* findRegion (void* start_address, unsigned long size)
100840c85557Swdenk{
100940c85557Swdenk	MEMORY_BASIC_INFORMATION info;
101040c85557Swdenk	if (size >= TOP_MEMORY) return NULL;
101140c85557Swdenk
101240c85557Swdenk	while ((unsigned long)start_address + size < TOP_MEMORY)
101340c85557Swdenk	{
101440c85557Swdenk		VirtualQuery (start_address, &info, sizeof (info));
101540c85557Swdenk		if ((info.State == MEM_FREE) && (info.RegionSize >= size))
101640c85557Swdenk			return start_address;
101740c85557Swdenk		else
101840c85557Swdenk		{
10198bde7f77Swdenk			/* Requested region is not available so see if the */
10208bde7f77Swdenk			/* next region is available.  Set 'start_address' */
10218bde7f77Swdenk			/* to the next region and call 'VirtualQuery()' */
10228bde7f77Swdenk			/* again. */
102340c85557Swdenk
102440c85557Swdenk			start_address = (char*)info.BaseAddress + info.RegionSize;
102540c85557Swdenk
10268bde7f77Swdenk			/* Make sure we start looking for the next region */
10278bde7f77Swdenk			/* on the *next* 64K boundary.  Otherwise, even if */
10288bde7f77Swdenk			/* the new region is free according to */
10298bde7f77Swdenk			/* 'VirtualQuery()', the subsequent call to */
10308bde7f77Swdenk			/* 'VirtualAlloc()' (which follows the call to */
10318bde7f77Swdenk			/* this routine in 'wsbrk()') will round *down* */
10328bde7f77Swdenk			/* the requested address to a 64K boundary which */
10338bde7f77Swdenk			/* we already know is an address in the */
10348bde7f77Swdenk			/* unavailable region.  Thus, the subsequent call */
10358bde7f77Swdenk			/* to 'VirtualAlloc()' will fail and bring us back */
10368bde7f77Swdenk			/* here, causing us to go into an infinite loop. */
103740c85557Swdenk
103840c85557Swdenk			start_address =
103940c85557Swdenk				(void *) AlignPage64K((unsigned long) start_address);
104040c85557Swdenk		}
104140c85557Swdenk	}
104240c85557Swdenk	return NULL;
104340c85557Swdenk
104440c85557Swdenk}
104540c85557Swdenk
104640c85557Swdenk
104740c85557Swdenkvoid* wsbrk (long size)
104840c85557Swdenk{
104940c85557Swdenk	void* tmp;
105040c85557Swdenk	if (size > 0)
105140c85557Swdenk	{
105240c85557Swdenk		if (gAddressBase == 0)
105340c85557Swdenk		{
105440c85557Swdenk			gAllocatedSize = max (RESERVED_SIZE, AlignPage (size));
105540c85557Swdenk			gNextAddress = gAddressBase =
105640c85557Swdenk				(unsigned int)VirtualAlloc (NULL, gAllocatedSize,
105740c85557Swdenk											MEM_RESERVE, PAGE_NOACCESS);
105840c85557Swdenk		} else if (AlignPage (gNextAddress + size) > (gAddressBase +
105940c85557SwdenkgAllocatedSize))
106040c85557Swdenk		{
106140c85557Swdenk			long new_size = max (NEXT_SIZE, AlignPage (size));
106240c85557Swdenk			void* new_address = (void*)(gAddressBase+gAllocatedSize);
106340c85557Swdenk			do
106440c85557Swdenk			{
106540c85557Swdenk				new_address = findRegion (new_address, new_size);
106640c85557Swdenk
106740c85557Swdenk				if (new_address == 0)
106840c85557Swdenk					return (void*)-1;
106940c85557Swdenk
107040c85557Swdenk				gAddressBase = gNextAddress =
107140c85557Swdenk					(unsigned int)VirtualAlloc (new_address, new_size,
107240c85557Swdenk												MEM_RESERVE, PAGE_NOACCESS);
10738bde7f77Swdenk				/* repeat in case of race condition */
10748bde7f77Swdenk				/* The region that we found has been snagged */
10758bde7f77Swdenk				/* by another thread */
107640c85557Swdenk			}
107740c85557Swdenk			while (gAddressBase == 0);
107840c85557Swdenk
107940c85557Swdenk			assert (new_address == (void*)gAddressBase);
108040c85557Swdenk
108140c85557Swdenk			gAllocatedSize = new_size;
108240c85557Swdenk
108340c85557Swdenk			if (!makeGmListElement ((void*)gAddressBase))
108440c85557Swdenk				return (void*)-1;
108540c85557Swdenk		}
108640c85557Swdenk		if ((size + gNextAddress) > AlignPage (gNextAddress))
108740c85557Swdenk		{
108840c85557Swdenk			void* res;
108940c85557Swdenk			res = VirtualAlloc ((void*)AlignPage (gNextAddress),
109040c85557Swdenk								(size + gNextAddress -
109140c85557Swdenk								 AlignPage (gNextAddress)),
109240c85557Swdenk								MEM_COMMIT, PAGE_READWRITE);
109340c85557Swdenk			if (res == 0)
109440c85557Swdenk				return (void*)-1;
109540c85557Swdenk		}
109640c85557Swdenk		tmp = (void*)gNextAddress;
109740c85557Swdenk		gNextAddress = (unsigned int)tmp + size;
109840c85557Swdenk		return tmp;
109940c85557Swdenk	}
110040c85557Swdenk	else if (size < 0)
110140c85557Swdenk	{
110240c85557Swdenk		unsigned int alignedGoal = AlignPage (gNextAddress + size);
110340c85557Swdenk		/* Trim by releasing the virtual memory */
110440c85557Swdenk		if (alignedGoal >= gAddressBase)
110540c85557Swdenk		{
110640c85557Swdenk			VirtualFree ((void*)alignedGoal, gNextAddress - alignedGoal,
110740c85557Swdenk						 MEM_DECOMMIT);
110840c85557Swdenk			gNextAddress = gNextAddress + size;
110940c85557Swdenk			return (void*)gNextAddress;
111040c85557Swdenk		}
111140c85557Swdenk		else
111240c85557Swdenk		{
111340c85557Swdenk			VirtualFree ((void*)gAddressBase, gNextAddress - gAddressBase,
111440c85557Swdenk						 MEM_DECOMMIT);
111540c85557Swdenk			gNextAddress = gAddressBase;
111640c85557Swdenk			return (void*)-1;
111740c85557Swdenk		}
111840c85557Swdenk	}
111940c85557Swdenk	else
112040c85557Swdenk	{
112140c85557Swdenk		return (void*)gNextAddress;
112240c85557Swdenk	}
112340c85557Swdenk}
112440c85557Swdenk
112540c85557Swdenk#endif
112640c85557Swdenk
112740c85557Swdenk
112840c85557Swdenk
112940c85557Swdenk/*
113040c85557Swdenk  Type declarations
113140c85557Swdenk*/
113240c85557Swdenk
113340c85557Swdenk
113440c85557Swdenkstruct malloc_chunk
113540c85557Swdenk{
113640c85557Swdenk  INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
113740c85557Swdenk  INTERNAL_SIZE_T size;      /* Size in bytes, including overhead. */
113840c85557Swdenk  struct malloc_chunk* fd;   /* double links -- used only if free. */
113940c85557Swdenk  struct malloc_chunk* bk;
114040c85557Swdenk};
114140c85557Swdenk
114240c85557Swdenktypedef struct malloc_chunk* mchunkptr;
114340c85557Swdenk
114440c85557Swdenk/*
114540c85557Swdenk
114640c85557Swdenk   malloc_chunk details:
114740c85557Swdenk
114840c85557Swdenk    (The following includes lightly edited explanations by Colin Plumb.)
114940c85557Swdenk
115040c85557Swdenk    Chunks of memory are maintained using a `boundary tag' method as
115140c85557Swdenk    described in e.g., Knuth or Standish.  (See the paper by Paul
115240c85557Swdenk    Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a
115340c85557Swdenk    survey of such techniques.)  Sizes of free chunks are stored both
115440c85557Swdenk    in the front of each chunk and at the end.  This makes
115540c85557Swdenk    consolidating fragmented chunks into bigger chunks very fast.  The
115640c85557Swdenk    size fields also hold bits representing whether chunks are free or
115740c85557Swdenk    in use.
115840c85557Swdenk
115940c85557Swdenk    An allocated chunk looks like this:
116040c85557Swdenk
116140c85557Swdenk
116240c85557Swdenk    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116340c85557Swdenk	    |             Size of previous chunk, if allocated            | |
116440c85557Swdenk	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116540c85557Swdenk	    |             Size of chunk, in bytes                         |P|
116640c85557Swdenk      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116740c85557Swdenk	    |             User data starts here...                          .
116840c85557Swdenk	    .                                                               .
116940c85557Swdenk	    .             (malloc_usable_space() bytes)                     .
117040c85557Swdenk	    .                                                               |
117140c85557Swdenknextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117240c85557Swdenk	    |             Size of chunk                                     |
117340c85557Swdenk	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117440c85557Swdenk
117540c85557Swdenk
117640c85557Swdenk    Where "chunk" is the front of the chunk for the purpose of most of
117740c85557Swdenk    the malloc code, but "mem" is the pointer that is returned to the
117840c85557Swdenk    user.  "Nextchunk" is the beginning of the next contiguous chunk.
117940c85557Swdenk
118040c85557Swdenk    Chunks always begin on even word boundries, so the mem portion
118140c85557Swdenk    (which is returned to the user) is also on an even word boundary, and
118240c85557Swdenk    thus double-word aligned.
118340c85557Swdenk
118440c85557Swdenk    Free chunks are stored in circular doubly-linked lists, and look like this:
118540c85557Swdenk
118640c85557Swdenk    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118740c85557Swdenk	    |             Size of previous chunk                            |
118840c85557Swdenk	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118940c85557Swdenk    `head:' |             Size of chunk, in bytes                         |P|
119040c85557Swdenk      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119140c85557Swdenk	    |             Forward pointer to next chunk in list             |
119240c85557Swdenk	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119340c85557Swdenk	    |             Back pointer to previous chunk in list            |
119440c85557Swdenk	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119540c85557Swdenk	    |             Unused space (may be 0 bytes long)                .
119640c85557Swdenk	    .                                                               .
119740c85557Swdenk	    .                                                               |
119840c85557Swdenknextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119940c85557Swdenk    `foot:' |             Size of chunk, in bytes                           |
120040c85557Swdenk	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120140c85557Swdenk
120240c85557Swdenk    The P (PREV_INUSE) bit, stored in the unused low-order bit of the
120340c85557Swdenk    chunk size (which is always a multiple of two words), is an in-use
120440c85557Swdenk    bit for the *previous* chunk.  If that bit is *clear*, then the
120540c85557Swdenk    word before the current chunk size contains the previous chunk
120640c85557Swdenk    size, and can be used to find the front of the previous chunk.
120740c85557Swdenk    (The very first chunk allocated always has this bit set,
120840c85557Swdenk    preventing access to non-existent (or non-owned) memory.)
120940c85557Swdenk
121040c85557Swdenk    Note that the `foot' of the current chunk is actually represented
121140c85557Swdenk    as the prev_size of the NEXT chunk. (This makes it easier to
121240c85557Swdenk    deal with alignments etc).
121340c85557Swdenk
121440c85557Swdenk    The two exceptions to all this are
121540c85557Swdenk
121640c85557Swdenk     1. The special chunk `top', which doesn't bother using the
121740c85557Swdenk	trailing size field since there is no
121840c85557Swdenk	next contiguous chunk that would have to index off it. (After
121940c85557Swdenk	initialization, `top' is forced to always exist.  If it would
122040c85557Swdenk	become less than MINSIZE bytes long, it is replenished via
122140c85557Swdenk	malloc_extend_top.)
122240c85557Swdenk
122340c85557Swdenk     2. Chunks allocated via mmap, which have the second-lowest-order
122440c85557Swdenk	bit (IS_MMAPPED) set in their size fields.  Because they are
122540c85557Swdenk	never merged or traversed from any other chunk, they have no
122640c85557Swdenk	foot size or inuse information.
122740c85557Swdenk
122840c85557Swdenk    Available chunks are kept in any of several places (all declared below):
122940c85557Swdenk
123040c85557Swdenk    * `av': An array of chunks serving as bin headers for consolidated
123140c85557Swdenk       chunks. Each bin is doubly linked.  The bins are approximately
123240c85557Swdenk       proportionally (log) spaced.  There are a lot of these bins
123340c85557Swdenk       (128). This may look excessive, but works very well in
123440c85557Swdenk       practice.  All procedures maintain the invariant that no
123540c85557Swdenk       consolidated chunk physically borders another one. Chunks in
123640c85557Swdenk       bins are kept in size order, with ties going to the
123740c85557Swdenk       approximately least recently used chunk.
123840c85557Swdenk
123940c85557Swdenk       The chunks in each bin are maintained in decreasing sorted order by
124040c85557Swdenk       size.  This is irrelevant for the small bins, which all contain
124140c85557Swdenk       the same-sized chunks, but facilitates best-fit allocation for
124240c85557Swdenk       larger chunks. (These lists are just sequential. Keeping them in
124340c85557Swdenk       order almost never requires enough traversal to warrant using
124440c85557Swdenk       fancier ordered data structures.)  Chunks of the same size are
124540c85557Swdenk       linked with the most recently freed at the front, and allocations
124640c85557Swdenk       are taken from the back.  This results in LRU or FIFO allocation
124740c85557Swdenk       order, which tends to give each chunk an equal opportunity to be
124840c85557Swdenk       consolidated with adjacent freed chunks, resulting in larger free
124940c85557Swdenk       chunks and less fragmentation.
125040c85557Swdenk
125140c85557Swdenk    * `top': The top-most available chunk (i.e., the one bordering the
125240c85557Swdenk       end of available memory) is treated specially. It is never
125340c85557Swdenk       included in any bin, is used only if no other chunk is
125440c85557Swdenk       available, and is released back to the system if it is very
125540c85557Swdenk       large (see M_TRIM_THRESHOLD).
125640c85557Swdenk
125740c85557Swdenk    * `last_remainder': A bin holding only the remainder of the
125840c85557Swdenk       most recently split (non-top) chunk. This bin is checked
125940c85557Swdenk       before other non-fitting chunks, so as to provide better
126040c85557Swdenk       locality for runs of sequentially allocated chunks.
126140c85557Swdenk
126240c85557Swdenk    *  Implicitly, through the host system's memory mapping tables.
126340c85557Swdenk       If supported, requests greater than a threshold are usually
126440c85557Swdenk       serviced via calls to mmap, and then later released via munmap.
126540c85557Swdenk
126640c85557Swdenk*/
126740c85557Swdenk
126840c85557Swdenk
126940c85557Swdenk
127040c85557Swdenk
127140c85557Swdenk
127240c85557Swdenk/*  sizes, alignments */
127340c85557Swdenk
127440c85557Swdenk#define SIZE_SZ                (sizeof(INTERNAL_SIZE_T))
127540c85557Swdenk#define MALLOC_ALIGNMENT       (SIZE_SZ + SIZE_SZ)
127640c85557Swdenk#define MALLOC_ALIGN_MASK      (MALLOC_ALIGNMENT - 1)
127740c85557Swdenk#define MINSIZE                (sizeof(struct malloc_chunk))
127840c85557Swdenk
127940c85557Swdenk/* conversion from malloc headers to user pointers, and back */
128040c85557Swdenk
128140c85557Swdenk#define chunk2mem(p)   ((Void_t*)((char*)(p) + 2*SIZE_SZ))
128240c85557Swdenk#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
128340c85557Swdenk
128440c85557Swdenk/* pad request bytes into a usable size */
128540c85557Swdenk
128640c85557Swdenk#define request2size(req) \
128740c85557Swdenk (((long)((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) < \
128840c85557Swdenk  (long)(MINSIZE + MALLOC_ALIGN_MASK)) ? MINSIZE : \
128940c85557Swdenk   (((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) & ~(MALLOC_ALIGN_MASK)))
129040c85557Swdenk
129140c85557Swdenk/* Check if m has acceptable alignment */
129240c85557Swdenk
129340c85557Swdenk#define aligned_OK(m)    (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0)
129440c85557Swdenk
129540c85557Swdenk
129640c85557Swdenk
129740c85557Swdenk
129840c85557Swdenk/*
129940c85557Swdenk  Physical chunk operations
130040c85557Swdenk*/
130140c85557Swdenk
130240c85557Swdenk
130340c85557Swdenk/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
130440c85557Swdenk
130540c85557Swdenk#define PREV_INUSE 0x1
130640c85557Swdenk
130740c85557Swdenk/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
130840c85557Swdenk
130940c85557Swdenk#define IS_MMAPPED 0x2
131040c85557Swdenk
131140c85557Swdenk/* Bits to mask off when extracting size */
131240c85557Swdenk
131340c85557Swdenk#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)
131440c85557Swdenk
131540c85557Swdenk
131640c85557Swdenk/* Ptr to next physical malloc_chunk. */
131740c85557Swdenk
131840c85557Swdenk#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
131940c85557Swdenk
132040c85557Swdenk/* Ptr to previous physical malloc_chunk */
132140c85557Swdenk
132240c85557Swdenk#define prev_chunk(p)\
132340c85557Swdenk   ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
132440c85557Swdenk
132540c85557Swdenk
132640c85557Swdenk/* Treat space at ptr + offset as a chunk */
132740c85557Swdenk
132840c85557Swdenk#define chunk_at_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
132940c85557Swdenk
133040c85557Swdenk
133140c85557Swdenk
133240c85557Swdenk
133340c85557Swdenk/*
133440c85557Swdenk  Dealing with use bits
133540c85557Swdenk*/
133640c85557Swdenk
133740c85557Swdenk/* extract p's inuse bit */
133840c85557Swdenk
133940c85557Swdenk#define inuse(p)\
134040c85557Swdenk((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
134140c85557Swdenk
134240c85557Swdenk/* extract inuse bit of previous chunk */
134340c85557Swdenk
134440c85557Swdenk#define prev_inuse(p)  ((p)->size & PREV_INUSE)
134540c85557Swdenk
134640c85557Swdenk/* check for mmap()'ed chunk */
134740c85557Swdenk
134840c85557Swdenk#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
134940c85557Swdenk
135040c85557Swdenk/* set/clear chunk as in use without otherwise disturbing */
135140c85557Swdenk
135240c85557Swdenk#define set_inuse(p)\
135340c85557Swdenk((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
135440c85557Swdenk
135540c85557Swdenk#define clear_inuse(p)\
135640c85557Swdenk((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
135740c85557Swdenk
135840c85557Swdenk/* check/set/clear inuse bits in known places */
135940c85557Swdenk
136040c85557Swdenk#define inuse_bit_at_offset(p, s)\
136140c85557Swdenk (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
136240c85557Swdenk
136340c85557Swdenk#define set_inuse_bit_at_offset(p, s)\
136440c85557Swdenk (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
136540c85557Swdenk
136640c85557Swdenk#define clear_inuse_bit_at_offset(p, s)\
136740c85557Swdenk (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
136840c85557Swdenk
136940c85557Swdenk
137040c85557Swdenk
137140c85557Swdenk
137240c85557Swdenk/*
137340c85557Swdenk  Dealing with size fields
137440c85557Swdenk*/
137540c85557Swdenk
137640c85557Swdenk/* Get size, ignoring use bits */
137740c85557Swdenk
137840c85557Swdenk#define chunksize(p)          ((p)->size & ~(SIZE_BITS))
137940c85557Swdenk
138040c85557Swdenk/* Set size at head, without disturbing its use bit */
138140c85557Swdenk
138240c85557Swdenk#define set_head_size(p, s)   ((p)->size = (((p)->size & PREV_INUSE) | (s)))
138340c85557Swdenk
138440c85557Swdenk/* Set size/use ignoring previous bits in header */
138540c85557Swdenk
138640c85557Swdenk#define set_head(p, s)        ((p)->size = (s))
138740c85557Swdenk
138840c85557Swdenk/* Set size at footer (only when chunk is not in use) */
138940c85557Swdenk
139040c85557Swdenk#define set_foot(p, s)   (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
139140c85557Swdenk
139240c85557Swdenk
139340c85557Swdenk
139440c85557Swdenk
139540c85557Swdenk
139640c85557Swdenk/*
139740c85557Swdenk   Bins
139840c85557Swdenk
139940c85557Swdenk    The bins, `av_' are an array of pairs of pointers serving as the
140040c85557Swdenk    heads of (initially empty) doubly-linked lists of chunks, laid out
140140c85557Swdenk    in a way so that each pair can be treated as if it were in a
140240c85557Swdenk    malloc_chunk. (This way, the fd/bk offsets for linking bin heads
140340c85557Swdenk    and chunks are the same).
140440c85557Swdenk
140540c85557Swdenk    Bins for sizes < 512 bytes contain chunks of all the same size, spaced
140640c85557Swdenk    8 bytes apart. Larger bins are approximately logarithmically
140740c85557Swdenk    spaced. (See the table below.) The `av_' array is never mentioned
140840c85557Swdenk    directly in the code, but instead via bin access macros.
140940c85557Swdenk
141040c85557Swdenk    Bin layout:
141140c85557Swdenk
141240c85557Swdenk    64 bins of size       8
141340c85557Swdenk    32 bins of size      64
141440c85557Swdenk    16 bins of size     512
141540c85557Swdenk     8 bins of size    4096
141640c85557Swdenk     4 bins of size   32768
141740c85557Swdenk     2 bins of size  262144
141840c85557Swdenk     1 bin  of size what's left
141940c85557Swdenk
142040c85557Swdenk    There is actually a little bit of slop in the numbers in bin_index
142140c85557Swdenk    for the sake of speed. This makes no difference elsewhere.
142240c85557Swdenk
142340c85557Swdenk    The special chunks `top' and `last_remainder' get their own bins,
142440c85557Swdenk    (this is implemented via yet more trickery with the av_ array),
142540c85557Swdenk    although `top' is never properly linked to its bin since it is
142640c85557Swdenk    always handled specially.
142740c85557Swdenk
142840c85557Swdenk*/
142940c85557Swdenk
143040c85557Swdenk#define NAV             128   /* number of bins */
143140c85557Swdenk
143240c85557Swdenktypedef struct malloc_chunk* mbinptr;
143340c85557Swdenk
143440c85557Swdenk/* access macros */
143540c85557Swdenk
143640c85557Swdenk#define bin_at(i)      ((mbinptr)((char*)&(av_[2*(i) + 2]) - 2*SIZE_SZ))
143740c85557Swdenk#define next_bin(b)    ((mbinptr)((char*)(b) + 2 * sizeof(mbinptr)))
143840c85557Swdenk#define prev_bin(b)    ((mbinptr)((char*)(b) - 2 * sizeof(mbinptr)))
143940c85557Swdenk
144040c85557Swdenk/*
144140c85557Swdenk   The first 2 bins are never indexed. The corresponding av_ cells are instead
144240c85557Swdenk   used for bookkeeping. This is not to save space, but to simplify
144340c85557Swdenk   indexing, maintain locality, and avoid some initialization tests.
144440c85557Swdenk*/
144540c85557Swdenk
144640c85557Swdenk#define top            (bin_at(0)->fd)   /* The topmost chunk */
144740c85557Swdenk#define last_remainder (bin_at(1))       /* remainder from last split */
144840c85557Swdenk
144940c85557Swdenk
145040c85557Swdenk/*
145140c85557Swdenk   Because top initially points to its own bin with initial
145240c85557Swdenk   zero size, thus forcing extension on the first malloc request,
145340c85557Swdenk   we avoid having any special code in malloc to check whether
145440c85557Swdenk   it even exists yet. But we still need to in malloc_extend_top.
145540c85557Swdenk*/
145640c85557Swdenk
145740c85557Swdenk#define initial_top    ((mchunkptr)(bin_at(0)))
145840c85557Swdenk
145940c85557Swdenk/* Helper macro to initialize bins */
146040c85557Swdenk
146140c85557Swdenk#define IAV(i)  bin_at(i), bin_at(i)
146240c85557Swdenk
146340c85557Swdenkstatic mbinptr av_[NAV * 2 + 2] = {
146440c85557Swdenk 0, 0,
146540c85557Swdenk IAV(0),   IAV(1),   IAV(2),   IAV(3),   IAV(4),   IAV(5),   IAV(6),   IAV(7),
146640c85557Swdenk IAV(8),   IAV(9),   IAV(10),  IAV(11),  IAV(12),  IAV(13),  IAV(14),  IAV(15),
146740c85557Swdenk IAV(16),  IAV(17),  IAV(18),  IAV(19),  IAV(20),  IAV(21),  IAV(22),  IAV(23),
146840c85557Swdenk IAV(24),  IAV(25),  IAV(26),  IAV(27),  IAV(28),  IAV(29),  IAV(30),  IAV(31),
146940c85557Swdenk IAV(32),  IAV(33),  IAV(34),  IAV(35),  IAV(36),  IAV(37),  IAV(38),  IAV(39),
147040c85557Swdenk IAV(40),  IAV(41),  IAV(42),  IAV(43),  IAV(44),  IAV(45),  IAV(46),  IAV(47),
147140c85557Swdenk IAV(48),  IAV(49),  IAV(50),  IAV(51),  IAV(52),  IAV(53),  IAV(54),  IAV(55),
147240c85557Swdenk IAV(56),  IAV(57),  IAV(58),  IAV(59),  IAV(60),  IAV(61),  IAV(62),  IAV(63),
147340c85557Swdenk IAV(64),  IAV(65),  IAV(66),  IAV(67),  IAV(68),  IAV(69),  IAV(70),  IAV(71),
147440c85557Swdenk IAV(72),  IAV(73),  IAV(74),  IAV(75),  IAV(76),  IAV(77),  IAV(78),  IAV(79),
147540c85557Swdenk IAV(80),  IAV(81),  IAV(82),  IAV(83),  IAV(84),  IAV(85),  IAV(86),  IAV(87),
147640c85557Swdenk IAV(88),  IAV(89),  IAV(90),  IAV(91),  IAV(92),  IAV(93),  IAV(94),  IAV(95),
147740c85557Swdenk IAV(96),  IAV(97),  IAV(98),  IAV(99),  IAV(100), IAV(101), IAV(102), IAV(103),
147840c85557Swdenk IAV(104), IAV(105), IAV(106), IAV(107), IAV(108), IAV(109), IAV(110), IAV(111),
147940c85557Swdenk IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117), IAV(118), IAV(119),
148040c85557Swdenk IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), IAV(127)
148140c85557Swdenk};
148240c85557Swdenk
148340c85557Swdenk
148440c85557Swdenk
148540c85557Swdenk/* field-extraction macros */
148640c85557Swdenk
148740c85557Swdenk#define first(b) ((b)->fd)
148840c85557Swdenk#define last(b)  ((b)->bk)
148940c85557Swdenk
149040c85557Swdenk/*
149140c85557Swdenk  Indexing into bins
149240c85557Swdenk*/
149340c85557Swdenk
149440c85557Swdenk#define bin_index(sz)                                                          \
149540c85557Swdenk(((((unsigned long)(sz)) >> 9) ==    0) ?       (((unsigned long)(sz)) >>  3): \
149640c85557Swdenk ((((unsigned long)(sz)) >> 9) <=    4) ?  56 + (((unsigned long)(sz)) >>  6): \
149740c85557Swdenk ((((unsigned long)(sz)) >> 9) <=   20) ?  91 + (((unsigned long)(sz)) >>  9): \
149840c85557Swdenk ((((unsigned long)(sz)) >> 9) <=   84) ? 110 + (((unsigned long)(sz)) >> 12): \
149940c85557Swdenk ((((unsigned long)(sz)) >> 9) <=  340) ? 119 + (((unsigned long)(sz)) >> 15): \
150040c85557Swdenk ((((unsigned long)(sz)) >> 9) <= 1364) ? 124 + (((unsigned long)(sz)) >> 18): \
150140c85557Swdenk					  126)
150240c85557Swdenk/*
150340c85557Swdenk  bins for chunks < 512 are all spaced 8 bytes apart, and hold
150440c85557Swdenk  identically sized chunks. This is exploited in malloc.
150540c85557Swdenk*/
150640c85557Swdenk
150740c85557Swdenk#define MAX_SMALLBIN         63
150840c85557Swdenk#define MAX_SMALLBIN_SIZE   512
150940c85557Swdenk#define SMALLBIN_WIDTH        8
151040c85557Swdenk
151140c85557Swdenk#define smallbin_index(sz)  (((unsigned long)(sz)) >> 3)
151240c85557Swdenk
151340c85557Swdenk/*
151440c85557Swdenk   Requests are `small' if both the corresponding and the next bin are small
151540c85557Swdenk*/
151640c85557Swdenk
151740c85557Swdenk#define is_small_request(nb) (nb < MAX_SMALLBIN_SIZE - SMALLBIN_WIDTH)
151840c85557Swdenk
151940c85557Swdenk
152040c85557Swdenk
152140c85557Swdenk/*
152240c85557Swdenk    To help compensate for the large number of bins, a one-level index
152340c85557Swdenk    structure is used for bin-by-bin searching.  `binblocks' is a
152440c85557Swdenk    one-word bitvector recording whether groups of BINBLOCKWIDTH bins
152540c85557Swdenk    have any (possibly) non-empty bins, so they can be skipped over
152640c85557Swdenk    all at once during during traversals. The bits are NOT always
152740c85557Swdenk    cleared as soon as all bins in a block are empty, but instead only
152840c85557Swdenk    when all are noticed to be empty during traversal in malloc.
152940c85557Swdenk*/
153040c85557Swdenk
153140c85557Swdenk#define BINBLOCKWIDTH     4   /* bins per block */
153240c85557Swdenk
153340c85557Swdenk#define binblocks      (bin_at(0)->size) /* bitvector of nonempty blocks */
153440c85557Swdenk
153540c85557Swdenk/* bin<->block macros */
153640c85557Swdenk
153740c85557Swdenk#define idx2binblock(ix)    ((unsigned)1 << (ix / BINBLOCKWIDTH))
153840c85557Swdenk#define mark_binblock(ii)   (binblocks |= idx2binblock(ii))
153940c85557Swdenk#define clear_binblock(ii)  (binblocks &= ~(idx2binblock(ii)))
154040c85557Swdenk
154140c85557Swdenk
154240c85557Swdenk
154340c85557Swdenk
154440c85557Swdenk
154540c85557Swdenk/*  Other static bookkeeping data */
154640c85557Swdenk
154740c85557Swdenk/* variables holding tunable values */
154840c85557Swdenk
154940c85557Swdenkstatic unsigned long trim_threshold   = DEFAULT_TRIM_THRESHOLD;
155040c85557Swdenkstatic unsigned long top_pad          = DEFAULT_TOP_PAD;
155140c85557Swdenkstatic unsigned int  n_mmaps_max      = DEFAULT_MMAP_MAX;
155240c85557Swdenkstatic unsigned long mmap_threshold   = DEFAULT_MMAP_THRESHOLD;
155340c85557Swdenk
155440c85557Swdenk/* The first value returned from sbrk */
155540c85557Swdenkstatic char* sbrk_base = (char*)(-1);
155640c85557Swdenk
155740c85557Swdenk/* The maximum memory obtained from system via sbrk */
155840c85557Swdenkstatic unsigned long max_sbrked_mem = 0;
155940c85557Swdenk
156040c85557Swdenk/* The maximum via either sbrk or mmap */
156140c85557Swdenkstatic unsigned long max_total_mem = 0;
156240c85557Swdenk
156340c85557Swdenk/* internal working copy of mallinfo */
156440c85557Swdenkstatic struct mallinfo current_mallinfo = {  0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
156540c85557Swdenk
156640c85557Swdenk/* The total memory obtained from system via sbrk */
156740c85557Swdenk#define sbrked_mem  (current_mallinfo.arena)
156840c85557Swdenk
156940c85557Swdenk/* Tracking mmaps */
157040c85557Swdenk
157140c85557Swdenkstatic unsigned int n_mmaps = 0;
157240c85557Swdenkstatic unsigned int max_n_mmaps = 0;
157340c85557Swdenkstatic unsigned long mmapped_mem = 0;
157440c85557Swdenkstatic unsigned long max_mmapped_mem = 0;
157540c85557Swdenk
157640c85557Swdenk
157740c85557Swdenk
157840c85557Swdenk/*
157940c85557Swdenk  Debugging support
158040c85557Swdenk*/
158140c85557Swdenk
158240c85557Swdenk#if DEBUG
158340c85557Swdenk
158440c85557Swdenk
158540c85557Swdenk/*
158640c85557Swdenk  These routines make a number of assertions about the states
158740c85557Swdenk  of data structures that should be true at all times. If any
158840c85557Swdenk  are not true, it's very likely that a user program has somehow
158940c85557Swdenk  trashed memory. (It's also possible that there is a coding error
159040c85557Swdenk  in malloc. In which case, please report it!)
159140c85557Swdenk*/
159240c85557Swdenk
159340c85557Swdenk#if __STD_C
159440c85557Swdenkstatic void do_check_chunk(mchunkptr p)
159540c85557Swdenk#else
159640c85557Swdenkstatic void do_check_chunk(p) mchunkptr p;
159740c85557Swdenk#endif
159840c85557Swdenk{
159940c85557Swdenk  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
160040c85557Swdenk
160140c85557Swdenk  /* No checkable chunk is mmapped */
160240c85557Swdenk  assert(!chunk_is_mmapped(p));
160340c85557Swdenk
160440c85557Swdenk  /* Check for legal address ... */
160540c85557Swdenk  assert((char*)p >= sbrk_base);
160640c85557Swdenk  if (p != top)
160740c85557Swdenk    assert((char*)p + sz <= (char*)top);
160840c85557Swdenk  else
160940c85557Swdenk    assert((char*)p + sz <= sbrk_base + sbrked_mem);
161040c85557Swdenk
161140c85557Swdenk}
161240c85557Swdenk
161340c85557Swdenk
161440c85557Swdenk#if __STD_C
161540c85557Swdenkstatic void do_check_free_chunk(mchunkptr p)
161640c85557Swdenk#else
161740c85557Swdenkstatic void do_check_free_chunk(p) mchunkptr p;
161840c85557Swdenk#endif
161940c85557Swdenk{
162040c85557Swdenk  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
162140c85557Swdenk  mchunkptr next = chunk_at_offset(p, sz);
162240c85557Swdenk
162340c85557Swdenk  do_check_chunk(p);
162440c85557Swdenk
162540c85557Swdenk  /* Check whether it claims to be free ... */
162640c85557Swdenk  assert(!inuse(p));
162740c85557Swdenk
162840c85557Swdenk  /* Unless a special marker, must have OK fields */
162940c85557Swdenk  if ((long)sz >= (long)MINSIZE)
163040c85557Swdenk  {
163140c85557Swdenk    assert((sz & MALLOC_ALIGN_MASK) == 0);
163240c85557Swdenk    assert(aligned_OK(chunk2mem(p)));
163340c85557Swdenk    /* ... matching footer field */
163440c85557Swdenk    assert(next->prev_size == sz);
163540c85557Swdenk    /* ... and is fully consolidated */
163640c85557Swdenk    assert(prev_inuse(p));
163740c85557Swdenk    assert (next == top || inuse(next));
163840c85557Swdenk
163940c85557Swdenk    /* ... and has minimally sane links */
164040c85557Swdenk    assert(p->fd->bk == p);
164140c85557Swdenk    assert(p->bk->fd == p);
164240c85557Swdenk  }
164340c85557Swdenk  else /* markers are always of size SIZE_SZ */
164440c85557Swdenk    assert(sz == SIZE_SZ);
164540c85557Swdenk}
164640c85557Swdenk
164740c85557Swdenk#if __STD_C
164840c85557Swdenkstatic void do_check_inuse_chunk(mchunkptr p)
164940c85557Swdenk#else
165040c85557Swdenkstatic void do_check_inuse_chunk(p) mchunkptr p;
165140c85557Swdenk#endif
165240c85557Swdenk{
165340c85557Swdenk  mchunkptr next = next_chunk(p);
165440c85557Swdenk  do_check_chunk(p);
165540c85557Swdenk
165640c85557Swdenk  /* Check whether it claims to be in use ... */
165740c85557Swdenk  assert(inuse(p));
165840c85557Swdenk
165940c85557Swdenk  /* ... and is surrounded by OK chunks.
166040c85557Swdenk    Since more things can be checked with free chunks than inuse ones,
166140c85557Swdenk    if an inuse chunk borders them and debug is on, it's worth doing them.
166240c85557Swdenk  */
166340c85557Swdenk  if (!prev_inuse(p))
166440c85557Swdenk  {
166540c85557Swdenk    mchunkptr prv = prev_chunk(p);
166640c85557Swdenk    assert(next_chunk(prv) == p);
166740c85557Swdenk    do_check_free_chunk(prv);
166840c85557Swdenk  }
166940c85557Swdenk  if (next == top)
167040c85557Swdenk  {
167140c85557Swdenk    assert(prev_inuse(next));
167240c85557Swdenk    assert(chunksize(next) >= MINSIZE);
167340c85557Swdenk  }
167440c85557Swdenk  else if (!inuse(next))
167540c85557Swdenk    do_check_free_chunk(next);
167640c85557Swdenk
167740c85557Swdenk}
167840c85557Swdenk
167940c85557Swdenk#if __STD_C
168040c85557Swdenkstatic void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)
168140c85557Swdenk#else
168240c85557Swdenkstatic void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
168340c85557Swdenk#endif
168440c85557Swdenk{
168540c85557Swdenk  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
168640c85557Swdenk  long room = sz - s;
168740c85557Swdenk
168840c85557Swdenk  do_check_inuse_chunk(p);
168940c85557Swdenk
169040c85557Swdenk  /* Legal size ... */
169140c85557Swdenk  assert((long)sz >= (long)MINSIZE);
169240c85557Swdenk  assert((sz & MALLOC_ALIGN_MASK) == 0);
169340c85557Swdenk  assert(room >= 0);
169440c85557Swdenk  assert(room < (long)MINSIZE);
169540c85557Swdenk
169640c85557Swdenk  /* ... and alignment */
169740c85557Swdenk  assert(aligned_OK(chunk2mem(p)));
169840c85557Swdenk
169940c85557Swdenk
170040c85557Swdenk  /* ... and was allocated at front of an available chunk */
170140c85557Swdenk  assert(prev_inuse(p));
170240c85557Swdenk
170340c85557Swdenk}
170440c85557Swdenk
170540c85557Swdenk
170640c85557Swdenk#define check_free_chunk(P)  do_check_free_chunk(P)
170740c85557Swdenk#define check_inuse_chunk(P) do_check_inuse_chunk(P)
170840c85557Swdenk#define check_chunk(P) do_check_chunk(P)
170940c85557Swdenk#define check_malloced_chunk(P,N) do_check_malloced_chunk(P,N)
171040c85557Swdenk#else
171140c85557Swdenk#define check_free_chunk(P)
171240c85557Swdenk#define check_inuse_chunk(P)
171340c85557Swdenk#define check_chunk(P)
171440c85557Swdenk#define check_malloced_chunk(P,N)
171540c85557Swdenk#endif
171640c85557Swdenk
171740c85557Swdenk
171840c85557Swdenk
171940c85557Swdenk/*
172040c85557Swdenk  Macro-based internal utilities
172140c85557Swdenk*/
172240c85557Swdenk
172340c85557Swdenk
172440c85557Swdenk/*
172540c85557Swdenk  Linking chunks in bin lists.
172640c85557Swdenk  Call these only with variables, not arbitrary expressions, as arguments.
172740c85557Swdenk*/
172840c85557Swdenk
172940c85557Swdenk/*
173040c85557Swdenk  Place chunk p of size s in its bin, in size order,
173140c85557Swdenk  putting it ahead of others of same size.
173240c85557Swdenk*/
173340c85557Swdenk
173440c85557Swdenk
173540c85557Swdenk#define frontlink(P, S, IDX, BK, FD)                                          \
173640c85557Swdenk{                                                                             \
173740c85557Swdenk  if (S < MAX_SMALLBIN_SIZE)                                                  \
173840c85557Swdenk  {                                                                           \
173940c85557Swdenk    IDX = smallbin_index(S);                                                  \
174040c85557Swdenk    mark_binblock(IDX);                                                       \
174140c85557Swdenk    BK = bin_at(IDX);                                                         \
174240c85557Swdenk    FD = BK->fd;                                                              \
174340c85557Swdenk    P->bk = BK;                                                               \
174440c85557Swdenk    P->fd = FD;                                                               \
174540c85557Swdenk    FD->bk = BK->fd = P;                                                      \
174640c85557Swdenk  }                                                                           \
174740c85557Swdenk  else                                                                        \
174840c85557Swdenk  {                                                                           \
174940c85557Swdenk    IDX = bin_index(S);                                                       \
175040c85557Swdenk    BK = bin_at(IDX);                                                         \
175140c85557Swdenk    FD = BK->fd;                                                              \
175240c85557Swdenk    if (FD == BK) mark_binblock(IDX);                                         \
175340c85557Swdenk    else                                                                      \
175440c85557Swdenk    {                                                                         \
175540c85557Swdenk      while (FD != BK && S < chunksize(FD)) FD = FD->fd;                      \
175640c85557Swdenk      BK = FD->bk;                                                            \
175740c85557Swdenk    }                                                                         \
175840c85557Swdenk    P->bk = BK;                                                               \
175940c85557Swdenk    P->fd = FD;                                                               \
176040c85557Swdenk    FD->bk = BK->fd = P;                                                      \
176140c85557Swdenk  }                                                                           \
176240c85557Swdenk}
176340c85557Swdenk
176440c85557Swdenk
176540c85557Swdenk/* take a chunk off a list */
176640c85557Swdenk
176740c85557Swdenk#define unlink(P, BK, FD)                                                     \
176840c85557Swdenk{                                                                             \
176940c85557Swdenk  BK = P->bk;                                                                 \
177040c85557Swdenk  FD = P->fd;                                                                 \
177140c85557Swdenk  FD->bk = BK;                                                                \
177240c85557Swdenk  BK->fd = FD;                                                                \
177340c85557Swdenk}                                                                             \
177440c85557Swdenk
177540c85557Swdenk/* Place p as the last remainder */
177640c85557Swdenk
177740c85557Swdenk#define link_last_remainder(P)                                                \
177840c85557Swdenk{                                                                             \
177940c85557Swdenk  last_remainder->fd = last_remainder->bk =  P;                               \
178040c85557Swdenk  P->fd = P->bk = last_remainder;                                             \
178140c85557Swdenk}
178240c85557Swdenk
178340c85557Swdenk/* Clear the last_remainder bin */
178440c85557Swdenk
178540c85557Swdenk#define clear_last_remainder \
178640c85557Swdenk  (last_remainder->fd = last_remainder->bk = last_remainder)
178740c85557Swdenk
178840c85557Swdenk
178940c85557Swdenk
179040c85557Swdenk
179140c85557Swdenk
179240c85557Swdenk/* Routines dealing with mmap(). */
179340c85557Swdenk
179440c85557Swdenk#if HAVE_MMAP
179540c85557Swdenk
179640c85557Swdenk#if __STD_C
179740c85557Swdenkstatic mchunkptr mmap_chunk(size_t size)
179840c85557Swdenk#else
179940c85557Swdenkstatic mchunkptr mmap_chunk(size) size_t size;
180040c85557Swdenk#endif
180140c85557Swdenk{
180240c85557Swdenk  size_t page_mask = malloc_getpagesize - 1;
180340c85557Swdenk  mchunkptr p;
180440c85557Swdenk
180540c85557Swdenk#ifndef MAP_ANONYMOUS
180640c85557Swdenk  static int fd = -1;
180740c85557Swdenk#endif
180840c85557Swdenk
180940c85557Swdenk  if(n_mmaps >= n_mmaps_max) return 0; /* too many regions */
181040c85557Swdenk
181140c85557Swdenk  /* For mmapped chunks, the overhead is one SIZE_SZ unit larger, because
181240c85557Swdenk   * there is no following chunk whose prev_size field could be used.
181340c85557Swdenk   */
181440c85557Swdenk  size = (size + SIZE_SZ + page_mask) & ~page_mask;
181540c85557Swdenk
181640c85557Swdenk#ifdef MAP_ANONYMOUS
181740c85557Swdenk  p = (mchunkptr)mmap(0, size, PROT_READ|PROT_WRITE,
181840c85557Swdenk		      MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
181940c85557Swdenk#else /* !MAP_ANONYMOUS */
182040c85557Swdenk  if (fd < 0)
182140c85557Swdenk  {
182240c85557Swdenk    fd = open("/dev/zero", O_RDWR);
182340c85557Swdenk    if(fd < 0) return 0;
182440c85557Swdenk  }
182540c85557Swdenk  p = (mchunkptr)mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
182640c85557Swdenk#endif
182740c85557Swdenk
182840c85557Swdenk  if(p == (mchunkptr)-1) return 0;
182940c85557Swdenk
183040c85557Swdenk  n_mmaps++;
183140c85557Swdenk  if (n_mmaps > max_n_mmaps) max_n_mmaps = n_mmaps;
183240c85557Swdenk
183340c85557Swdenk  /* We demand that eight bytes into a page must be 8-byte aligned. */
183440c85557Swdenk  assert(aligned_OK(chunk2mem(p)));
183540c85557Swdenk
183640c85557Swdenk  /* The offset to the start of the mmapped region is stored
183740c85557Swdenk   * in the prev_size field of the chunk; normally it is zero,
183840c85557Swdenk   * but that can be changed in memalign().
183940c85557Swdenk   */
184040c85557Swdenk  p->prev_size = 0;
184140c85557Swdenk  set_head(p, size|IS_MMAPPED);
184240c85557Swdenk
184340c85557Swdenk  mmapped_mem += size;
184440c85557Swdenk  if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem)
184540c85557Swdenk    max_mmapped_mem = mmapped_mem;
184640c85557Swdenk  if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
184740c85557Swdenk    max_total_mem = mmapped_mem + sbrked_mem;
184840c85557Swdenk  return p;
184940c85557Swdenk}
185040c85557Swdenk
185140c85557Swdenk#if __STD_C
185240c85557Swdenkstatic void munmap_chunk(mchunkptr p)
185340c85557Swdenk#else
185440c85557Swdenkstatic void munmap_chunk(p) mchunkptr p;
185540c85557Swdenk#endif
185640c85557Swdenk{
185740c85557Swdenk  INTERNAL_SIZE_T size = chunksize(p);
185840c85557Swdenk  int ret;
185940c85557Swdenk
186040c85557Swdenk  assert (chunk_is_mmapped(p));
186140c85557Swdenk  assert(! ((char*)p >= sbrk_base && (char*)p < sbrk_base + sbrked_mem));
186240c85557Swdenk  assert((n_mmaps > 0));
186340c85557Swdenk  assert(((p->prev_size + size) & (malloc_getpagesize-1)) == 0);
186440c85557Swdenk
186540c85557Swdenk  n_mmaps--;
186640c85557Swdenk  mmapped_mem -= (size + p->prev_size);
186740c85557Swdenk
186840c85557Swdenk  ret = munmap((char *)p - p->prev_size, size + p->prev_size);
186940c85557Swdenk
187040c85557Swdenk  /* munmap returns non-zero on failure */
187140c85557Swdenk  assert(ret == 0);
187240c85557Swdenk}
187340c85557Swdenk
187440c85557Swdenk#if HAVE_MREMAP
187540c85557Swdenk
187640c85557Swdenk#if __STD_C
187740c85557Swdenkstatic mchunkptr mremap_chunk(mchunkptr p, size_t new_size)
187840c85557Swdenk#else
187940c85557Swdenkstatic mchunkptr mremap_chunk(p, new_size) mchunkptr p; size_t new_size;
188040c85557Swdenk#endif
188140c85557Swdenk{
188240c85557Swdenk  size_t page_mask = malloc_getpagesize - 1;
188340c85557Swdenk  INTERNAL_SIZE_T offset = p->prev_size;
188440c85557Swdenk  INTERNAL_SIZE_T size = chunksize(p);
188540c85557Swdenk  char *cp;
188640c85557Swdenk
188740c85557Swdenk  assert (chunk_is_mmapped(p));
188840c85557Swdenk  assert(! ((char*)p >= sbrk_base && (char*)p < sbrk_base + sbrked_mem));
188940c85557Swdenk  assert((n_mmaps > 0));
189040c85557Swdenk  assert(((size + offset) & (malloc_getpagesize-1)) == 0);
189140c85557Swdenk
189240c85557Swdenk  /* Note the extra SIZE_SZ overhead as in mmap_chunk(). */
189340c85557Swdenk  new_size = (new_size + offset + SIZE_SZ + page_mask) & ~page_mask;
189440c85557Swdenk
189540c85557Swdenk  cp = (char *)mremap((char *)p - offset, size + offset, new_size, 1);
189640c85557Swdenk
189740c85557Swdenk  if (cp == (char *)-1) return 0;
189840c85557Swdenk
189940c85557Swdenk  p = (mchunkptr)(cp + offset);
190040c85557Swdenk
190140c85557Swdenk  assert(aligned_OK(chunk2mem(p)));
190240c85557Swdenk
190340c85557Swdenk  assert((p->prev_size == offset));
190440c85557Swdenk  set_head(p, (new_size - offset)|IS_MMAPPED);
190540c85557Swdenk
190640c85557Swdenk  mmapped_mem -= size + offset;
190740c85557Swdenk  mmapped_mem += new_size;
190840c85557Swdenk  if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem)
190940c85557Swdenk    max_mmapped_mem = mmapped_mem;
191040c85557Swdenk  if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
191140c85557Swdenk    max_total_mem = mmapped_mem + sbrked_mem;
191240c85557Swdenk  return p;
191340c85557Swdenk}
191440c85557Swdenk
191540c85557Swdenk#endif /* HAVE_MREMAP */
191640c85557Swdenk
191740c85557Swdenk#endif /* HAVE_MMAP */
191840c85557Swdenk
191940c85557Swdenk
192040c85557Swdenk
192140c85557Swdenk
192240c85557Swdenk/*
192340c85557Swdenk  Extend the top-most chunk by obtaining memory from system.
192440c85557Swdenk  Main interface to sbrk (but see also malloc_trim).
192540c85557Swdenk*/
192640c85557Swdenk
192740c85557Swdenk#if __STD_C
192840c85557Swdenkstatic void malloc_extend_top(INTERNAL_SIZE_T nb)
192940c85557Swdenk#else
193040c85557Swdenkstatic void malloc_extend_top(nb) INTERNAL_SIZE_T nb;
193140c85557Swdenk#endif
193240c85557Swdenk{
193340c85557Swdenk  char*     brk;                  /* return value from sbrk */
193440c85557Swdenk  INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of sbrked space */
193540c85557Swdenk  INTERNAL_SIZE_T correction;     /* bytes for 2nd sbrk call */
193640c85557Swdenk  char*     new_brk;              /* return of 2nd sbrk call */
193740c85557Swdenk  INTERNAL_SIZE_T top_size;       /* new size of top chunk */
193840c85557Swdenk
193940c85557Swdenk  mchunkptr old_top     = top;  /* Record state of old top */
194040c85557Swdenk  INTERNAL_SIZE_T old_top_size = chunksize(old_top);
194140c85557Swdenk  char*     old_end      = (char*)(chunk_at_offset(old_top, old_top_size));
194240c85557Swdenk
194340c85557Swdenk  /* Pad request with top_pad plus minimal overhead */
194440c85557Swdenk
194540c85557Swdenk  INTERNAL_SIZE_T    sbrk_size     = nb + top_pad + MINSIZE;
194640c85557Swdenk  unsigned long pagesz    = malloc_getpagesize;
194740c85557Swdenk
194840c85557Swdenk  /* If not the first time through, round to preserve page boundary */
194940c85557Swdenk  /* Otherwise, we need to correct to a page size below anyway. */
195040c85557Swdenk  /* (We also correct below if an intervening foreign sbrk call.) */
195140c85557Swdenk
195240c85557Swdenk  if (sbrk_base != (char*)(-1))
195340c85557Swdenk    sbrk_size = (sbrk_size + (pagesz - 1)) & ~(pagesz - 1);
195440c85557Swdenk
195540c85557Swdenk  brk = (char*)(MORECORE (sbrk_size));
195640c85557Swdenk
195740c85557Swdenk  /* Fail if sbrk failed or if a foreign sbrk call killed our space */
195840c85557Swdenk  if (brk == (char*)(MORECORE_FAILURE) ||
195940c85557Swdenk      (brk < old_end && old_top != initial_top))
196040c85557Swdenk    return;
196140c85557Swdenk
196240c85557Swdenk  sbrked_mem += sbrk_size;
196340c85557Swdenk
196440c85557Swdenk  if (brk == old_end) /* can just add bytes to current top */
196540c85557Swdenk  {
196640c85557Swdenk    top_size = sbrk_size + old_top_size;
196740c85557Swdenk    set_head(top, top_size | PREV_INUSE);
196840c85557Swdenk  }
196940c85557Swdenk  else
197040c85557Swdenk  {
197140c85557Swdenk    if (sbrk_base == (char*)(-1))  /* First time through. Record base */
197240c85557Swdenk      sbrk_base = brk;
197340c85557Swdenk    else  /* Someone else called sbrk().  Count those bytes as sbrked_mem. */
197440c85557Swdenk      sbrked_mem += brk - (char*)old_end;
197540c85557Swdenk
197640c85557Swdenk    /* Guarantee alignment of first new chunk made from this space */
197740c85557Swdenk    front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK;
197840c85557Swdenk    if (front_misalign > 0)
197940c85557Swdenk    {
198040c85557Swdenk      correction = (MALLOC_ALIGNMENT) - front_misalign;
198140c85557Swdenk      brk += correction;
198240c85557Swdenk    }
198340c85557Swdenk    else
198440c85557Swdenk      correction = 0;
198540c85557Swdenk
198640c85557Swdenk    /* Guarantee the next brk will be at a page boundary */
198740c85557Swdenk
198840c85557Swdenk    correction += ((((unsigned long)(brk + sbrk_size))+(pagesz-1)) &
198940c85557Swdenk		   ~(pagesz - 1)) - ((unsigned long)(brk + sbrk_size));
199040c85557Swdenk
199140c85557Swdenk    /* Allocate correction */
199240c85557Swdenk    new_brk = (char*)(MORECORE (correction));
199340c85557Swdenk    if (new_brk == (char*)(MORECORE_FAILURE)) return;
199440c85557Swdenk
199540c85557Swdenk    sbrked_mem += correction;
199640c85557Swdenk
199740c85557Swdenk    top = (mchunkptr)brk;
199840c85557Swdenk    top_size = new_brk - brk + correction;
199940c85557Swdenk    set_head(top, top_size | PREV_INUSE);
200040c85557Swdenk
200140c85557Swdenk    if (old_top != initial_top)
200240c85557Swdenk    {
200340c85557Swdenk
200440c85557Swdenk      /* There must have been an intervening foreign sbrk call. */
200540c85557Swdenk      /* A double fencepost is necessary to prevent consolidation */
200640c85557Swdenk
200740c85557Swdenk      /* If not enough space to do this, then user did something very wrong */
200840c85557Swdenk      if (old_top_size < MINSIZE)
200940c85557Swdenk      {
201040c85557Swdenk	set_head(top, PREV_INUSE); /* will force null return from malloc */
201140c85557Swdenk	return;
201240c85557Swdenk      }
201340c85557Swdenk
201440c85557Swdenk      /* Also keep size a multiple of MALLOC_ALIGNMENT */
201540c85557Swdenk      old_top_size = (old_top_size - 3*SIZE_SZ) & ~MALLOC_ALIGN_MASK;
201640c85557Swdenk      set_head_size(old_top, old_top_size);
201740c85557Swdenk      chunk_at_offset(old_top, old_top_size          )->size =
201840c85557Swdenk	SIZE_SZ|PREV_INUSE;
201940c85557Swdenk      chunk_at_offset(old_top, old_top_size + SIZE_SZ)->size =
202040c85557Swdenk	SIZE_SZ|PREV_INUSE;
202140c85557Swdenk      /* If possible, release the rest. */
202240c85557Swdenk      if (old_top_size >= MINSIZE)
202340c85557Swdenk	fREe(chunk2mem(old_top));
202440c85557Swdenk    }
202540c85557Swdenk  }
202640c85557Swdenk
202740c85557Swdenk  if ((unsigned long)sbrked_mem > (unsigned long)max_sbrked_mem)
202840c85557Swdenk    max_sbrked_mem = sbrked_mem;
202940c85557Swdenk  if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
203040c85557Swdenk    max_total_mem = mmapped_mem + sbrked_mem;
203140c85557Swdenk
203240c85557Swdenk  /* We always land on a page boundary */
203340c85557Swdenk  assert(((unsigned long)((char*)top + top_size) & (pagesz - 1)) == 0);
203440c85557Swdenk}
203540c85557Swdenk
203640c85557Swdenk
203740c85557Swdenk
203840c85557Swdenk
203940c85557Swdenk/* Main public routines */
204040c85557Swdenk
204140c85557Swdenk
204240c85557Swdenk/*
204340c85557Swdenk  Malloc Algorthim:
204440c85557Swdenk
204540c85557Swdenk    The requested size is first converted into a usable form, `nb'.
204640c85557Swdenk    This currently means to add 4 bytes overhead plus possibly more to
204740c85557Swdenk    obtain 8-byte alignment and/or to obtain a size of at least
204840c85557Swdenk    MINSIZE (currently 16 bytes), the smallest allocatable size.
204940c85557Swdenk    (All fits are considered `exact' if they are within MINSIZE bytes.)
205040c85557Swdenk
205140c85557Swdenk    From there, the first successful of the following steps is taken:
205240c85557Swdenk
205340c85557Swdenk      1. The bin corresponding to the request size is scanned, and if
205440c85557Swdenk	 a chunk of exactly the right size is found, it is taken.
205540c85557Swdenk
205640c85557Swdenk      2. The most recently remaindered chunk is used if it is big
205740c85557Swdenk	 enough.  This is a form of (roving) first fit, used only in
205840c85557Swdenk	 the absence of exact fits. Runs of consecutive requests use
205940c85557Swdenk	 the remainder of the chunk used for the previous such request
206040c85557Swdenk	 whenever possible. This limited use of a first-fit style
206140c85557Swdenk	 allocation strategy tends to give contiguous chunks
206240c85557Swdenk	 coextensive lifetimes, which improves locality and can reduce
206340c85557Swdenk	 fragmentation in the long run.
206440c85557Swdenk
206540c85557Swdenk      3. Other bins are scanned in increasing size order, using a
206640c85557Swdenk	 chunk big enough to fulfill the request, and splitting off
206740c85557Swdenk	 any remainder.  This search is strictly by best-fit; i.e.,
206840c85557Swdenk	 the smallest (with ties going to approximately the least
206940c85557Swdenk	 recently used) chunk that fits is selected.
207040c85557Swdenk
207140c85557Swdenk      4. If large enough, the chunk bordering the end of memory
207240c85557Swdenk	 (`top') is split off. (This use of `top' is in accord with
207340c85557Swdenk	 the best-fit search rule.  In effect, `top' is treated as
207440c85557Swdenk	 larger (and thus less well fitting) than any other available
207540c85557Swdenk	 chunk since it can be extended to be as large as necessary
207640c85557Swdenk	 (up to system limitations).
207740c85557Swdenk
207840c85557Swdenk      5. If the request size meets the mmap threshold and the
207940c85557Swdenk	 system supports mmap, and there are few enough currently
208040c85557Swdenk	 allocated mmapped regions, and a call to mmap succeeds,
208140c85557Swdenk	 the request is allocated via direct memory mapping.
208240c85557Swdenk
208340c85557Swdenk      6. Otherwise, the top of memory is extended by
208440c85557Swdenk	 obtaining more space from the system (normally using sbrk,
208540c85557Swdenk	 but definable to anything else via the MORECORE macro).
208640c85557Swdenk	 Memory is gathered from the system (in system page-sized
208740c85557Swdenk	 units) in a way that allows chunks obtained across different
208840c85557Swdenk	 sbrk calls to be consolidated, but does not require
208940c85557Swdenk	 contiguous memory. Thus, it should be safe to intersperse
209040c85557Swdenk	 mallocs with other sbrk calls.
209140c85557Swdenk
209240c85557Swdenk
209340c85557Swdenk      All allocations are made from the the `lowest' part of any found
209440c85557Swdenk      chunk. (The implementation invariant is that prev_inuse is
209540c85557Swdenk      always true of any allocated chunk; i.e., that each allocated
209640c85557Swdenk      chunk borders either a previously allocated and still in-use chunk,
209740c85557Swdenk      or the base of its memory arena.)
209840c85557Swdenk
209940c85557Swdenk*/
210040c85557Swdenk
210140c85557Swdenk#if __STD_C
210240c85557SwdenkVoid_t* mALLOc(size_t bytes)
210340c85557Swdenk#else
210440c85557SwdenkVoid_t* mALLOc(bytes) size_t bytes;
210540c85557Swdenk#endif
210640c85557Swdenk{
210740c85557Swdenk  mchunkptr victim;                  /* inspected/selected chunk */
210840c85557Swdenk  INTERNAL_SIZE_T victim_size;       /* its size */
210940c85557Swdenk  int       idx;                     /* index for bin traversal */
211040c85557Swdenk  mbinptr   bin;                     /* associated bin */
211140c85557Swdenk  mchunkptr remainder;               /* remainder from a split */
211240c85557Swdenk  long      remainder_size;          /* its size */
211340c85557Swdenk  int       remainder_index;         /* its bin index */
211440c85557Swdenk  unsigned long block;               /* block traverser bit */
211540c85557Swdenk  int       startidx;                /* first bin of a traversed block */
211640c85557Swdenk  mchunkptr fwd;                     /* misc temp for linking */
211740c85557Swdenk  mchunkptr bck;                     /* misc temp for linking */
211840c85557Swdenk  mbinptr q;                         /* misc temp */
211940c85557Swdenk
212040c85557Swdenk  INTERNAL_SIZE_T nb;
212140c85557Swdenk
212240c85557Swdenk  if ((long)bytes < 0) return 0;
212340c85557Swdenk
212440c85557Swdenk  nb = request2size(bytes);  /* padded request size; */
212540c85557Swdenk
212640c85557Swdenk  /* Check for exact match in a bin */
212740c85557Swdenk
212840c85557Swdenk  if (is_small_request(nb))  /* Faster version for small requests */
212940c85557Swdenk  {
213040c85557Swdenk    idx = smallbin_index(nb);
213140c85557Swdenk
213240c85557Swdenk    /* No traversal or size check necessary for small bins.  */
213340c85557Swdenk
213440c85557Swdenk    q = bin_at(idx);
213540c85557Swdenk    victim = last(q);
213640c85557Swdenk
213740c85557Swdenk    /* Also scan the next one, since it would have a remainder < MINSIZE */
213840c85557Swdenk    if (victim == q)
213940c85557Swdenk    {
214040c85557Swdenk      q = next_bin(q);
214140c85557Swdenk      victim = last(q);
214240c85557Swdenk    }
214340c85557Swdenk    if (victim != q)
214440c85557Swdenk    {
214540c85557Swdenk      victim_size = chunksize(victim);
214640c85557Swdenk      unlink(victim, bck, fwd);
214740c85557Swdenk      set_inuse_bit_at_offset(victim, victim_size);
214840c85557Swdenk      check_malloced_chunk(victim, nb);
214940c85557Swdenk      return chunk2mem(victim);
215040c85557Swdenk    }
215140c85557Swdenk
215240c85557Swdenk    idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */
215340c85557Swdenk
215440c85557Swdenk  }
215540c85557Swdenk  else
215640c85557Swdenk  {
215740c85557Swdenk    idx = bin_index(nb);
215840c85557Swdenk    bin = bin_at(idx);
215940c85557Swdenk
216040c85557Swdenk    for (victim = last(bin); victim != bin; victim = victim->bk)
216140c85557Swdenk    {
216240c85557Swdenk      victim_size = chunksize(victim);
216340c85557Swdenk      remainder_size = victim_size - nb;
216440c85557Swdenk
216540c85557Swdenk      if (remainder_size >= (long)MINSIZE) /* too big */
216640c85557Swdenk      {
216740c85557Swdenk	--idx; /* adjust to rescan below after checking last remainder */
216840c85557Swdenk	break;
216940c85557Swdenk      }
217040c85557Swdenk
217140c85557Swdenk      else if (remainder_size >= 0) /* exact fit */
217240c85557Swdenk      {
217340c85557Swdenk	unlink(victim, bck, fwd);
217440c85557Swdenk	set_inuse_bit_at_offset(victim, victim_size);
217540c85557Swdenk	check_malloced_chunk(victim, nb);
217640c85557Swdenk	return chunk2mem(victim);
217740c85557Swdenk      }
217840c85557Swdenk    }
217940c85557Swdenk
218040c85557Swdenk    ++idx;
218140c85557Swdenk
218240c85557Swdenk  }
218340c85557Swdenk
218440c85557Swdenk  /* Try to use the last split-off remainder */
218540c85557Swdenk
218640c85557Swdenk  if ( (victim = last_remainder->fd) != last_remainder)
218740c85557Swdenk  {
218840c85557Swdenk    victim_size = chunksize(victim);
218940c85557Swdenk    remainder_size = victim_size - nb;
219040c85557Swdenk
219140c85557Swdenk    if (remainder_size >= (long)MINSIZE) /* re-split */
219240c85557Swdenk    {
219340c85557Swdenk      remainder = chunk_at_offset(victim, nb);
219440c85557Swdenk      set_head(victim, nb | PREV_INUSE);
219540c85557Swdenk      link_last_remainder(remainder);
219640c85557Swdenk      set_head(remainder, remainder_size | PREV_INUSE);
219740c85557Swdenk      set_foot(remainder, remainder_size);
219840c85557Swdenk      check_malloced_chunk(victim, nb);
219940c85557Swdenk      return chunk2mem(victim);
220040c85557Swdenk    }
220140c85557Swdenk
220240c85557Swdenk    clear_last_remainder;
220340c85557Swdenk
220440c85557Swdenk    if (remainder_size >= 0)  /* exhaust */
220540c85557Swdenk    {
220640c85557Swdenk      set_inuse_bit_at_offset(victim, victim_size);
220740c85557Swdenk      check_malloced_chunk(victim, nb);
220840c85557Swdenk      return chunk2mem(victim);
220940c85557Swdenk    }
221040c85557Swdenk
221140c85557Swdenk    /* Else place in bin */
221240c85557Swdenk
221340c85557Swdenk    frontlink(victim, victim_size, remainder_index, bck, fwd);
221440c85557Swdenk  }
221540c85557Swdenk
221640c85557Swdenk  /*
221740c85557Swdenk     If there are any possibly nonempty big-enough blocks,
221840c85557Swdenk     search for best fitting chunk by scanning bins in blockwidth units.
221940c85557Swdenk  */
222040c85557Swdenk
222140c85557Swdenk  if ( (block = idx2binblock(idx)) <= binblocks)
222240c85557Swdenk  {
222340c85557Swdenk
222440c85557Swdenk    /* Get to the first marked block */
222540c85557Swdenk
222640c85557Swdenk    if ( (block & binblocks) == 0)
222740c85557Swdenk    {
222840c85557Swdenk      /* force to an even block boundary */
222940c85557Swdenk      idx = (idx & ~(BINBLOCKWIDTH - 1)) + BINBLOCKWIDTH;
223040c85557Swdenk      block <<= 1;
223140c85557Swdenk      while ((block & binblocks) == 0)
223240c85557Swdenk      {
223340c85557Swdenk	idx += BINBLOCKWIDTH;
223440c85557Swdenk	block <<= 1;
223540c85557Swdenk      }
223640c85557Swdenk    }
223740c85557Swdenk
223840c85557Swdenk    /* For each possibly nonempty block ... */
223940c85557Swdenk    for (;;)
224040c85557Swdenk    {
224140c85557Swdenk      startidx = idx;          /* (track incomplete blocks) */
224240c85557Swdenk      q = bin = bin_at(idx);
224340c85557Swdenk
224440c85557Swdenk      /* For each bin in this block ... */
224540c85557Swdenk      do
224640c85557Swdenk      {
224740c85557Swdenk	/* Find and use first big enough chunk ... */
224840c85557Swdenk
224940c85557Swdenk	for (victim = last(bin); victim != bin; victim = victim->bk)
225040c85557Swdenk	{
225140c85557Swdenk	  victim_size = chunksize(victim);
225240c85557Swdenk	  remainder_size = victim_size - nb;
225340c85557Swdenk
225440c85557Swdenk	  if (remainder_size >= (long)MINSIZE) /* split */
225540c85557Swdenk	  {
225640c85557Swdenk	    remainder = chunk_at_offset(victim, nb);
225740c85557Swdenk	    set_head(victim, nb | PREV_INUSE);
225840c85557Swdenk	    unlink(victim, bck, fwd);
225940c85557Swdenk	    link_last_remainder(remainder);
226040c85557Swdenk	    set_head(remainder, remainder_size | PREV_INUSE);
226140c85557Swdenk	    set_foot(remainder, remainder_size);
226240c85557Swdenk	    check_malloced_chunk(victim, nb);
226340c85557Swdenk	    return chunk2mem(victim);
226440c85557Swdenk	  }
226540c85557Swdenk
226640c85557Swdenk	  else if (remainder_size >= 0)  /* take */
226740c85557Swdenk	  {
226840c85557Swdenk	    set_inuse_bit_at_offset(victim, victim_size);
226940c85557Swdenk	    unlink(victim, bck, fwd);
227040c85557Swdenk	    check_malloced_chunk(victim, nb);
227140c85557Swdenk	    return chunk2mem(victim);
227240c85557Swdenk	  }
227340c85557Swdenk
227440c85557Swdenk	}
227540c85557Swdenk
227640c85557Swdenk       bin = next_bin(bin);
227740c85557Swdenk
227840c85557Swdenk      } while ((++idx & (BINBLOCKWIDTH - 1)) != 0);
227940c85557Swdenk
228040c85557Swdenk      /* Clear out the block bit. */
228140c85557Swdenk
228240c85557Swdenk      do   /* Possibly backtrack to try to clear a partial block */
228340c85557Swdenk      {
228440c85557Swdenk	if ((startidx & (BINBLOCKWIDTH - 1)) == 0)
228540c85557Swdenk	{
228640c85557Swdenk	  binblocks &= ~block;
228740c85557Swdenk	  break;
228840c85557Swdenk	}
228940c85557Swdenk	--startidx;
229040c85557Swdenk       q = prev_bin(q);
229140c85557Swdenk      } while (first(q) == q);
229240c85557Swdenk
229340c85557Swdenk      /* Get to the next possibly nonempty block */
229440c85557Swdenk
229540c85557Swdenk      if ( (block <<= 1) <= binblocks && (block != 0) )
229640c85557Swdenk      {
229740c85557Swdenk	while ((block & binblocks) == 0)
229840c85557Swdenk	{
229940c85557Swdenk	  idx += BINBLOCKWIDTH;
230040c85557Swdenk	  block <<= 1;
230140c85557Swdenk	}
230240c85557Swdenk      }
230340c85557Swdenk      else
230440c85557Swdenk	break;
230540c85557Swdenk    }
230640c85557Swdenk  }
230740c85557Swdenk
230840c85557Swdenk
230940c85557Swdenk  /* Try to use top chunk */
231040c85557Swdenk
231140c85557Swdenk  /* Require that there be a remainder, ensuring top always exists  */
231240c85557Swdenk  if ( (remainder_size = chunksize(top) - nb) < (long)MINSIZE)
231340c85557Swdenk  {
231440c85557Swdenk
231540c85557Swdenk#if HAVE_MMAP
231640c85557Swdenk    /* If big and would otherwise need to extend, try to use mmap instead */
231740c85557Swdenk    if ((unsigned long)nb >= (unsigned long)mmap_threshold &&
231840c85557Swdenk	(victim = mmap_chunk(nb)) != 0)
231940c85557Swdenk      return chunk2mem(victim);
232040c85557Swdenk#endif
232140c85557Swdenk
232240c85557Swdenk    /* Try to extend */
232340c85557Swdenk    malloc_extend_top(nb);
232440c85557Swdenk    if ( (remainder_size = chunksize(top) - nb) < (long)MINSIZE)
232540c85557Swdenk      return 0; /* propagate failure */
232640c85557Swdenk  }
232740c85557Swdenk
232840c85557Swdenk  victim = top;
232940c85557Swdenk  set_head(victim, nb | PREV_INUSE);
233040c85557Swdenk  top = chunk_at_offset(victim, nb);
233140c85557Swdenk  set_head(top, remainder_size | PREV_INUSE);
233240c85557Swdenk  check_malloced_chunk(victim, nb);
233340c85557Swdenk  return chunk2mem(victim);
233440c85557Swdenk
233540c85557Swdenk}
233640c85557Swdenk
233740c85557Swdenk
233840c85557Swdenk
233940c85557Swdenk
234040c85557Swdenk/*
234140c85557Swdenk
234240c85557Swdenk  free() algorithm :
234340c85557Swdenk
234440c85557Swdenk    cases:
234540c85557Swdenk
234640c85557Swdenk       1. free(0) has no effect.
234740c85557Swdenk
234840c85557Swdenk       2. If the chunk was allocated via mmap, it is release via munmap().
234940c85557Swdenk
235040c85557Swdenk       3. If a returned chunk borders the current high end of memory,
235140c85557Swdenk	  it is consolidated into the top, and if the total unused
235240c85557Swdenk	  topmost memory exceeds the trim threshold, malloc_trim is
235340c85557Swdenk	  called.
235440c85557Swdenk
235540c85557Swdenk       4. Other chunks are consolidated as they arrive, and
235640c85557Swdenk	  placed in corresponding bins. (This includes the case of
235740c85557Swdenk	  consolidating with the current `last_remainder').
235840c85557Swdenk
235940c85557Swdenk*/
236040c85557Swdenk
236140c85557Swdenk
236240c85557Swdenk#if __STD_C
236340c85557Swdenkvoid fREe(Void_t* mem)
236440c85557Swdenk#else
236540c85557Swdenkvoid fREe(mem) Void_t* mem;
236640c85557Swdenk#endif
236740c85557Swdenk{
236840c85557Swdenk  mchunkptr p;         /* chunk corresponding to mem */
236940c85557Swdenk  INTERNAL_SIZE_T hd;  /* its head field */
237040c85557Swdenk  INTERNAL_SIZE_T sz;  /* its size */
237140c85557Swdenk  int       idx;       /* its bin index */
237240c85557Swdenk  mchunkptr next;      /* next contiguous chunk */
237340c85557Swdenk  INTERNAL_SIZE_T nextsz; /* its size */
237440c85557Swdenk  INTERNAL_SIZE_T prevsz; /* size of previous contiguous chunk */
237540c85557Swdenk  mchunkptr bck;       /* misc temp for linking */
237640c85557Swdenk  mchunkptr fwd;       /* misc temp for linking */
237740c85557Swdenk  int       islr;      /* track whether merging with last_remainder */
237840c85557Swdenk
237940c85557Swdenk  if (mem == 0)                              /* free(0) has no effect */
238040c85557Swdenk    return;
238140c85557Swdenk
238240c85557Swdenk  p = mem2chunk(mem);
238340c85557Swdenk  hd = p->size;
238440c85557Swdenk
238540c85557Swdenk#if HAVE_MMAP
238640c85557Swdenk  if (hd & IS_MMAPPED)                       /* release mmapped memory. */
238740c85557Swdenk  {
238840c85557Swdenk    munmap_chunk(p);
238940c85557Swdenk    return;
239040c85557Swdenk  }
239140c85557Swdenk#endif
239240c85557Swdenk
239340c85557Swdenk  check_inuse_chunk(p);
239440c85557Swdenk
239540c85557Swdenk  sz = hd & ~PREV_INUSE;
239640c85557Swdenk  next = chunk_at_offset(p, sz);
239740c85557Swdenk  nextsz = chunksize(next);
239840c85557Swdenk
239940c85557Swdenk  if (next == top)                            /* merge with top */
240040c85557Swdenk  {
240140c85557Swdenk    sz += nextsz;
240240c85557Swdenk
240340c85557Swdenk    if (!(hd & PREV_INUSE))                    /* consolidate backward */
240440c85557Swdenk    {
240540c85557Swdenk      prevsz = p->prev_size;
240640c85557Swdenk      p = chunk_at_offset(p, -((long) prevsz));
240740c85557Swdenk      sz += prevsz;
240840c85557Swdenk      unlink(p, bck, fwd);
240940c85557Swdenk    }
241040c85557Swdenk
241140c85557Swdenk    set_head(p, sz | PREV_INUSE);
241240c85557Swdenk    top = p;
241340c85557Swdenk    if ((unsigned long)(sz) >= (unsigned long)trim_threshold)
241440c85557Swdenk      malloc_trim(top_pad);
241540c85557Swdenk    return;
241640c85557Swdenk  }
241740c85557Swdenk
241840c85557Swdenk  set_head(next, nextsz);                    /* clear inuse bit */
241940c85557Swdenk
242040c85557Swdenk  islr = 0;
242140c85557Swdenk
242240c85557Swdenk  if (!(hd & PREV_INUSE))                    /* consolidate backward */
242340c85557Swdenk  {
242440c85557Swdenk    prevsz = p->prev_size;
242540c85557Swdenk    p = chunk_at_offset(p, -((long) prevsz));
242640c85557Swdenk    sz += prevsz;
242740c85557Swdenk
242840c85557Swdenk    if (p->fd == last_remainder)             /* keep as last_remainder */
242940c85557Swdenk      islr = 1;
243040c85557Swdenk    else
243140c85557Swdenk      unlink(p, bck, fwd);
243240c85557Swdenk  }
243340c85557Swdenk
243440c85557Swdenk  if (!(inuse_bit_at_offset(next, nextsz)))   /* consolidate forward */
243540c85557Swdenk  {
243640c85557Swdenk    sz += nextsz;
243740c85557Swdenk
243840c85557Swdenk    if (!islr && next->fd == last_remainder)  /* re-insert last_remainder */
243940c85557Swdenk    {
244040c85557Swdenk      islr = 1;
244140c85557Swdenk      link_last_remainder(p);
244240c85557Swdenk    }
244340c85557Swdenk    else
244440c85557Swdenk      unlink(next, bck, fwd);
244540c85557Swdenk  }
244640c85557Swdenk
244740c85557Swdenk
244840c85557Swdenk  set_head(p, sz | PREV_INUSE);
244940c85557Swdenk  set_foot(p, sz);
245040c85557Swdenk  if (!islr)
245140c85557Swdenk    frontlink(p, sz, idx, bck, fwd);
245240c85557Swdenk}
245340c85557Swdenk
245440c85557Swdenk
245540c85557Swdenk
245640c85557Swdenk
245740c85557Swdenk
245840c85557Swdenk/*
245940c85557Swdenk
246040c85557Swdenk  Realloc algorithm:
246140c85557Swdenk
246240c85557Swdenk    Chunks that were obtained via mmap cannot be extended or shrunk
246340c85557Swdenk    unless HAVE_MREMAP is defined, in which case mremap is used.
246440c85557Swdenk    Otherwise, if their reallocation is for additional space, they are
246540c85557Swdenk    copied.  If for less, they are just left alone.
246640c85557Swdenk
246740c85557Swdenk    Otherwise, if the reallocation is for additional space, and the
246840c85557Swdenk    chunk can be extended, it is, else a malloc-copy-free sequence is
246940c85557Swdenk    taken.  There are several different ways that a chunk could be
247040c85557Swdenk    extended. All are tried:
247140c85557Swdenk
247240c85557Swdenk       * Extending forward into following adjacent free chunk.
247340c85557Swdenk       * Shifting backwards, joining preceding adjacent space
247440c85557Swdenk       * Both shifting backwards and extending forward.
247540c85557Swdenk       * Extending into newly sbrked space
247640c85557Swdenk
247740c85557Swdenk    Unless the #define REALLOC_ZERO_BYTES_FREES is set, realloc with a
247840c85557Swdenk    size argument of zero (re)allocates a minimum-sized chunk.
247940c85557Swdenk
248040c85557Swdenk    If the reallocation is for less space, and the new request is for
248140c85557Swdenk    a `small' (<512 bytes) size, then the newly unused space is lopped
248240c85557Swdenk    off and freed.
248340c85557Swdenk
248440c85557Swdenk    The old unix realloc convention of allowing the last-free'd chunk
248540c85557Swdenk    to be used as an argument to realloc is no longer supported.
248640c85557Swdenk    I don't know of any programs still relying on this feature,
248740c85557Swdenk    and allowing it would also allow too many other incorrect
248840c85557Swdenk    usages of realloc to be sensible.
248940c85557Swdenk
249040c85557Swdenk
249140c85557Swdenk*/
249240c85557Swdenk
249340c85557Swdenk
249440c85557Swdenk#if __STD_C
249540c85557SwdenkVoid_t* rEALLOc(Void_t* oldmem, size_t bytes)
249640c85557Swdenk#else
249740c85557SwdenkVoid_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
249840c85557Swdenk#endif
249940c85557Swdenk{
250040c85557Swdenk  INTERNAL_SIZE_T    nb;      /* padded request size */
250140c85557Swdenk
250240c85557Swdenk  mchunkptr oldp;             /* chunk corresponding to oldmem */
250340c85557Swdenk  INTERNAL_SIZE_T    oldsize; /* its size */
250440c85557Swdenk
250540c85557Swdenk  mchunkptr newp;             /* chunk to return */
250640c85557Swdenk  INTERNAL_SIZE_T    newsize; /* its size */
250740c85557Swdenk  Void_t*   newmem;           /* corresponding user mem */
250840c85557Swdenk
250940c85557Swdenk  mchunkptr next;             /* next contiguous chunk after oldp */
251040c85557Swdenk  INTERNAL_SIZE_T  nextsize;  /* its size */
251140c85557Swdenk
251240c85557Swdenk  mchunkptr prev;             /* previous contiguous chunk before oldp */
251340c85557Swdenk  INTERNAL_SIZE_T  prevsize;  /* its size */
251440c85557Swdenk
251540c85557Swdenk  mchunkptr remainder;        /* holds split off extra space from newp */
251640c85557Swdenk  INTERNAL_SIZE_T  remainder_size;   /* its size */
251740c85557Swdenk
251840c85557Swdenk  mchunkptr bck;              /* misc temp for linking */
251940c85557Swdenk  mchunkptr fwd;              /* misc temp for linking */
252040c85557Swdenk
252140c85557Swdenk#ifdef REALLOC_ZERO_BYTES_FREES
252240c85557Swdenk  if (bytes == 0) { fREe(oldmem); return 0; }
252340c85557Swdenk#endif
252440c85557Swdenk
252540c85557Swdenk  if ((long)bytes < 0) return 0;
252640c85557Swdenk
252740c85557Swdenk  /* realloc of null is supposed to be same as malloc */
252840c85557Swdenk  if (oldmem == 0) return mALLOc(bytes);
252940c85557Swdenk
253040c85557Swdenk  newp    = oldp    = mem2chunk(oldmem);
253140c85557Swdenk  newsize = oldsize = chunksize(oldp);
253240c85557Swdenk
253340c85557Swdenk
253440c85557Swdenk  nb = request2size(bytes);
253540c85557Swdenk
253640c85557Swdenk#if HAVE_MMAP
253740c85557Swdenk  if (chunk_is_mmapped(oldp))
253840c85557Swdenk  {
253940c85557Swdenk#if HAVE_MREMAP
254040c85557Swdenk    newp = mremap_chunk(oldp, nb);
254140c85557Swdenk    if(newp) return chunk2mem(newp);
254240c85557Swdenk#endif
254340c85557Swdenk    /* Note the extra SIZE_SZ overhead. */
254440c85557Swdenk    if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */
254540c85557Swdenk    /* Must alloc, copy, free. */
254640c85557Swdenk    newmem = mALLOc(bytes);
254740c85557Swdenk    if (newmem == 0) return 0; /* propagate failure */
254840c85557Swdenk    MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ);
254940c85557Swdenk    munmap_chunk(oldp);
255040c85557Swdenk    return newmem;
255140c85557Swdenk  }
255240c85557Swdenk#endif
255340c85557Swdenk
255440c85557Swdenk  check_inuse_chunk(oldp);
255540c85557Swdenk
255640c85557Swdenk  if ((long)(oldsize) < (long)(nb))
255740c85557Swdenk  {
255840c85557Swdenk
255940c85557Swdenk    /* Try expanding forward */
256040c85557Swdenk
256140c85557Swdenk    next = chunk_at_offset(oldp, oldsize);
256240c85557Swdenk    if (next == top || !inuse(next))
256340c85557Swdenk    {
256440c85557Swdenk      nextsize = chunksize(next);
256540c85557Swdenk
256640c85557Swdenk      /* Forward into top only if a remainder */
256740c85557Swdenk      if (next == top)
256840c85557Swdenk      {
256940c85557Swdenk	if ((long)(nextsize + newsize) >= (long)(nb + MINSIZE))
257040c85557Swdenk	{
257140c85557Swdenk	  newsize += nextsize;
257240c85557Swdenk	  top = chunk_at_offset(oldp, nb);
257340c85557Swdenk	  set_head(top, (newsize - nb) | PREV_INUSE);
257440c85557Swdenk	  set_head_size(oldp, nb);
257540c85557Swdenk	  return chunk2mem(oldp);
257640c85557Swdenk	}
257740c85557Swdenk      }
257840c85557Swdenk
257940c85557Swdenk      /* Forward into next chunk */
258040c85557Swdenk      else if (((long)(nextsize + newsize) >= (long)(nb)))
258140c85557Swdenk      {
258240c85557Swdenk	unlink(next, bck, fwd);
258340c85557Swdenk	newsize  += nextsize;
258440c85557Swdenk	goto split;
258540c85557Swdenk      }
258640c85557Swdenk    }
258740c85557Swdenk    else
258840c85557Swdenk    {
258940c85557Swdenk      next = 0;
259040c85557Swdenk      nextsize = 0;
259140c85557Swdenk    }
259240c85557Swdenk
259340c85557Swdenk    /* Try shifting backwards. */
259440c85557Swdenk
259540c85557Swdenk    if (!prev_inuse(oldp))
259640c85557Swdenk    {
259740c85557Swdenk      prev = prev_chunk(oldp);
259840c85557Swdenk      prevsize = chunksize(prev);
259940c85557Swdenk
260040c85557Swdenk      /* try forward + backward first to save a later consolidation */
260140c85557Swdenk
260240c85557Swdenk      if (next != 0)
260340c85557Swdenk      {
260440c85557Swdenk	/* into top */
260540c85557Swdenk	if (next == top)
260640c85557Swdenk	{
260740c85557Swdenk	  if ((long)(nextsize + prevsize + newsize) >= (long)(nb + MINSIZE))
260840c85557Swdenk	  {
260940c85557Swdenk	    unlink(prev, bck, fwd);
261040c85557Swdenk	    newp = prev;
261140c85557Swdenk	    newsize += prevsize + nextsize;
261240c85557Swdenk	    newmem = chunk2mem(newp);
261340c85557Swdenk	    MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
261440c85557Swdenk	    top = chunk_at_offset(newp, nb);
261540c85557Swdenk	    set_head(top, (newsize - nb) | PREV_INUSE);
261640c85557Swdenk	    set_head_size(newp, nb);
261740c85557Swdenk	    return newmem;
261840c85557Swdenk	  }
261940c85557Swdenk	}
262040c85557Swdenk
262140c85557Swdenk	/* into next chunk */
262240c85557Swdenk	else if (((long)(nextsize + prevsize + newsize) >= (long)(nb)))
262340c85557Swdenk	{
262440c85557Swdenk	  unlink(next, bck, fwd);
262540c85557Swdenk	  unlink(prev, bck, fwd);
262640c85557Swdenk	  newp = prev;
262740c85557Swdenk	  newsize += nextsize + prevsize;
262840c85557Swdenk	  newmem = chunk2mem(newp);
262940c85557Swdenk	  MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
263040c85557Swdenk	  goto split;
263140c85557Swdenk	}
263240c85557Swdenk      }
263340c85557Swdenk
263440c85557Swdenk      /* backward only */
263540c85557Swdenk      if (prev != 0 && (long)(prevsize + newsize) >= (long)nb)
263640c85557Swdenk      {
263740c85557Swdenk	unlink(prev, bck, fwd);
263840c85557Swdenk	newp = prev;
263940c85557Swdenk	newsize += prevsize;
264040c85557Swdenk	newmem = chunk2mem(newp);
264140c85557Swdenk	MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
264240c85557Swdenk	goto split;
264340c85557Swdenk      }
264440c85557Swdenk    }
264540c85557Swdenk
264640c85557Swdenk    /* Must allocate */
264740c85557Swdenk
264840c85557Swdenk    newmem = mALLOc (bytes);
264940c85557Swdenk
265040c85557Swdenk    if (newmem == 0)  /* propagate failure */
265140c85557Swdenk      return 0;
265240c85557Swdenk
265340c85557Swdenk    /* Avoid copy if newp is next chunk after oldp. */
265440c85557Swdenk    /* (This can only happen when new chunk is sbrk'ed.) */
265540c85557Swdenk
265640c85557Swdenk    if ( (newp = mem2chunk(newmem)) == next_chunk(oldp))
265740c85557Swdenk    {
265840c85557Swdenk      newsize += chunksize(newp);
265940c85557Swdenk      newp = oldp;
266040c85557Swdenk      goto split;
266140c85557Swdenk    }
266240c85557Swdenk
266340c85557Swdenk    /* Otherwise copy, free, and exit */
266440c85557Swdenk    MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
266540c85557Swdenk    fREe(oldmem);
266640c85557Swdenk    return newmem;
266740c85557Swdenk  }
266840c85557Swdenk
266940c85557Swdenk
267040c85557Swdenk split:  /* split off extra room in old or expanded chunk */
267140c85557Swdenk
267240c85557Swdenk  if (newsize - nb >= MINSIZE) /* split off remainder */
267340c85557Swdenk  {
267440c85557Swdenk    remainder = chunk_at_offset(newp, nb);
267540c85557Swdenk    remainder_size = newsize - nb;
267640c85557Swdenk    set_head_size(newp, nb);
267740c85557Swdenk    set_head(remainder, remainder_size | PREV_INUSE);
267840c85557Swdenk    set_inuse_bit_at_offset(remainder, remainder_size);
267940c85557Swdenk    fREe(chunk2mem(remainder)); /* let free() deal with it */
268040c85557Swdenk  }
268140c85557Swdenk  else
268240c85557Swdenk  {
268340c85557Swdenk    set_head_size(newp, newsize);
268440c85557Swdenk    set_inuse_bit_at_offset(newp, newsize);
268540c85557Swdenk  }
268640c85557Swdenk
268740c85557Swdenk  check_inuse_chunk(newp);
268840c85557Swdenk  return chunk2mem(newp);
268940c85557Swdenk}
269040c85557Swdenk
269140c85557Swdenk
269240c85557Swdenk
269340c85557Swdenk
269440c85557Swdenk/*
269540c85557Swdenk
269640c85557Swdenk  memalign algorithm:
269740c85557Swdenk
269840c85557Swdenk    memalign requests more than enough space from malloc, finds a spot
269940c85557Swdenk    within that chunk that meets the alignment request, and then
270040c85557Swdenk    possibly frees the leading and trailing space.
270140c85557Swdenk
270240c85557Swdenk    The alignment argument must be a power of two. This property is not
270340c85557Swdenk    checked by memalign, so misuse may result in random runtime errors.
270440c85557Swdenk
270540c85557Swdenk    8-byte alignment is guaranteed by normal malloc calls, so don't
270640c85557Swdenk    bother calling memalign with an argument of 8 or less.
270740c85557Swdenk
270840c85557Swdenk    Overreliance on memalign is a sure way to fragment space.
270940c85557Swdenk
271040c85557Swdenk*/
271140c85557Swdenk
271240c85557Swdenk
271340c85557Swdenk#if __STD_C
271440c85557SwdenkVoid_t* mEMALIGn(size_t alignment, size_t bytes)
271540c85557Swdenk#else
271640c85557SwdenkVoid_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
271740c85557Swdenk#endif
271840c85557Swdenk{
271940c85557Swdenk  INTERNAL_SIZE_T    nb;      /* padded  request size */
272040c85557Swdenk  char*     m;                /* memory returned by malloc call */
272140c85557Swdenk  mchunkptr p;                /* corresponding chunk */
272240c85557Swdenk  char*     brk;              /* alignment point within p */
272340c85557Swdenk  mchunkptr newp;             /* chunk to return */
272440c85557Swdenk  INTERNAL_SIZE_T  newsize;   /* its size */
272540c85557Swdenk  INTERNAL_SIZE_T  leadsize;  /* leading space befor alignment point */
272640c85557Swdenk  mchunkptr remainder;        /* spare room at end to split off */
272740c85557Swdenk  long      remainder_size;   /* its size */
272840c85557Swdenk
272940c85557Swdenk  if ((long)bytes < 0) return 0;
273040c85557Swdenk
273140c85557Swdenk  /* If need less alignment than we give anyway, just relay to malloc */
273240c85557Swdenk
273340c85557Swdenk  if (alignment <= MALLOC_ALIGNMENT) return mALLOc(bytes);
273440c85557Swdenk
273540c85557Swdenk  /* Otherwise, ensure that it is at least a minimum chunk size */
273640c85557Swdenk
273740c85557Swdenk  if (alignment <  MINSIZE) alignment = MINSIZE;
273840c85557Swdenk
273940c85557Swdenk  /* Call malloc with worst case padding to hit alignment. */
274040c85557Swdenk
274140c85557Swdenk  nb = request2size(bytes);
274240c85557Swdenk  m  = (char*)(mALLOc(nb + alignment + MINSIZE));
274340c85557Swdenk
274440c85557Swdenk  if (m == 0) return 0; /* propagate failure */
274540c85557Swdenk
274640c85557Swdenk  p = mem2chunk(m);
274740c85557Swdenk
274840c85557Swdenk  if ((((unsigned long)(m)) % alignment) == 0) /* aligned */
274940c85557Swdenk  {
275040c85557Swdenk#if HAVE_MMAP
275140c85557Swdenk    if(chunk_is_mmapped(p))
275240c85557Swdenk      return chunk2mem(p); /* nothing more to do */
275340c85557Swdenk#endif
275440c85557Swdenk  }
275540c85557Swdenk  else /* misaligned */
275640c85557Swdenk  {
275740c85557Swdenk    /*
275840c85557Swdenk      Find an aligned spot inside chunk.
275940c85557Swdenk      Since we need to give back leading space in a chunk of at
276040c85557Swdenk      least MINSIZE, if the first calculation places us at
276140c85557Swdenk      a spot with less than MINSIZE leader, we can move to the
276240c85557Swdenk      next aligned spot -- we've allocated enough total room so that
276340c85557Swdenk      this is always possible.
276440c85557Swdenk    */
276540c85557Swdenk
276640c85557Swdenk    brk = (char*)mem2chunk(((unsigned long)(m + alignment - 1)) & -((signed) alignment));
276740c85557Swdenk    if ((long)(brk - (char*)(p)) < MINSIZE) brk = brk + alignment;
276840c85557Swdenk
276940c85557Swdenk    newp = (mchunkptr)brk;
277040c85557Swdenk    leadsize = brk - (char*)(p);
277140c85557Swdenk    newsize = chunksize(p) - leadsize;
277240c85557Swdenk
277340c85557Swdenk#if HAVE_MMAP
277440c85557Swdenk    if(chunk_is_mmapped(p))
277540c85557Swdenk    {
277640c85557Swdenk      newp->prev_size = p->prev_size + leadsize;
277740c85557Swdenk      set_head(newp, newsize|IS_MMAPPED);
277840c85557Swdenk      return chunk2mem(newp);
277940c85557Swdenk    }
278040c85557Swdenk#endif
278140c85557Swdenk
278240c85557Swdenk    /* give back leader, use the rest */
278340c85557Swdenk
278440c85557Swdenk    set_head(newp, newsize | PREV_INUSE);
278540c85557Swdenk    set_inuse_bit_at_offset(newp, newsize);
278640c85557Swdenk    set_head_size(p, leadsize);
278740c85557Swdenk    fREe(chunk2mem(p));
278840c85557Swdenk    p = newp;
278940c85557Swdenk
279040c85557Swdenk    assert (newsize >= nb && (((unsigned long)(chunk2mem(p))) % alignment) == 0);
279140c85557Swdenk  }
279240c85557Swdenk
279340c85557Swdenk  /* Also give back spare room at the end */
279440c85557Swdenk
279540c85557Swdenk  remainder_size = chunksize(p) - nb;
279640c85557Swdenk
279740c85557Swdenk  if (remainder_size >= (long)MINSIZE)
279840c85557Swdenk  {
279940c85557Swdenk    remainder = chunk_at_offset(p, nb);
280040c85557Swdenk    set_head(remainder, remainder_size | PREV_INUSE);
280140c85557Swdenk    set_head_size(p, nb);
280240c85557Swdenk    fREe(chunk2mem(remainder));
280340c85557Swdenk  }
280440c85557Swdenk
280540c85557Swdenk  check_inuse_chunk(p);
280640c85557Swdenk  return chunk2mem(p);
280740c85557Swdenk
280840c85557Swdenk}
280940c85557Swdenk
281040c85557Swdenk
281140c85557Swdenk
281240c85557Swdenk
281340c85557Swdenk/*
281440c85557Swdenk    valloc just invokes memalign with alignment argument equal
281540c85557Swdenk    to the page size of the system (or as near to this as can
281640c85557Swdenk    be figured out from all the includes/defines above.)
281740c85557Swdenk*/
281840c85557Swdenk
281940c85557Swdenk#if __STD_C
282040c85557SwdenkVoid_t* vALLOc(size_t bytes)
282140c85557Swdenk#else
282240c85557SwdenkVoid_t* vALLOc(bytes) size_t bytes;
282340c85557Swdenk#endif
282440c85557Swdenk{
282540c85557Swdenk  return mEMALIGn (malloc_getpagesize, bytes);
282640c85557Swdenk}
282740c85557Swdenk
282840c85557Swdenk/*
282940c85557Swdenk  pvalloc just invokes valloc for the nearest pagesize
283040c85557Swdenk  that will accommodate request
283140c85557Swdenk*/
283240c85557Swdenk
283340c85557Swdenk
283440c85557Swdenk#if __STD_C
283540c85557SwdenkVoid_t* pvALLOc(size_t bytes)
283640c85557Swdenk#else
283740c85557SwdenkVoid_t* pvALLOc(bytes) size_t bytes;
283840c85557Swdenk#endif
283940c85557Swdenk{
284040c85557Swdenk  size_t pagesize = malloc_getpagesize;
284140c85557Swdenk  return mEMALIGn (pagesize, (bytes + pagesize - 1) & ~(pagesize - 1));
284240c85557Swdenk}
284340c85557Swdenk
284440c85557Swdenk/*
284540c85557Swdenk
284640c85557Swdenk  calloc calls malloc, then zeroes out the allocated chunk.
284740c85557Swdenk
284840c85557Swdenk*/
284940c85557Swdenk
285040c85557Swdenk#if __STD_C
285140c85557SwdenkVoid_t* cALLOc(size_t n, size_t elem_size)
285240c85557Swdenk#else
285340c85557SwdenkVoid_t* cALLOc(n, elem_size) size_t n; size_t elem_size;
285440c85557Swdenk#endif
285540c85557Swdenk{
285640c85557Swdenk  mchunkptr p;
285740c85557Swdenk  INTERNAL_SIZE_T csz;
285840c85557Swdenk
285940c85557Swdenk  INTERNAL_SIZE_T sz = n * elem_size;
286040c85557Swdenk
286140c85557Swdenk
286240c85557Swdenk  /* check if expand_top called, in which case don't need to clear */
286340c85557Swdenk#if MORECORE_CLEARS
286440c85557Swdenk  mchunkptr oldtop = top;
286540c85557Swdenk  INTERNAL_SIZE_T oldtopsize = chunksize(top);
286640c85557Swdenk#endif
286740c85557Swdenk  Void_t* mem = mALLOc (sz);
286840c85557Swdenk
286940c85557Swdenk  if ((long)n < 0) return 0;
287040c85557Swdenk
287140c85557Swdenk  if (mem == 0)
287240c85557Swdenk    return 0;
287340c85557Swdenk  else
287440c85557Swdenk  {
287540c85557Swdenk    p = mem2chunk(mem);
287640c85557Swdenk
287740c85557Swdenk    /* Two optional cases in which clearing not necessary */
287840c85557Swdenk
287940c85557Swdenk
288040c85557Swdenk#if HAVE_MMAP
288140c85557Swdenk    if (chunk_is_mmapped(p)) return mem;
288240c85557Swdenk#endif
288340c85557Swdenk
288440c85557Swdenk    csz = chunksize(p);
288540c85557Swdenk
288640c85557Swdenk#if MORECORE_CLEARS
288740c85557Swdenk    if (p == oldtop && csz > oldtopsize)
288840c85557Swdenk    {
288940c85557Swdenk      /* clear only the bytes from non-freshly-sbrked memory */
289040c85557Swdenk      csz = oldtopsize;
289140c85557Swdenk    }
289240c85557Swdenk#endif
289340c85557Swdenk
289440c85557Swdenk    MALLOC_ZERO(mem, csz - SIZE_SZ);
289540c85557Swdenk    return mem;
289640c85557Swdenk  }
289740c85557Swdenk}
289840c85557Swdenk
289940c85557Swdenk/*
290040c85557Swdenk
290140c85557Swdenk  cfree just calls free. It is needed/defined on some systems
290240c85557Swdenk  that pair it with calloc, presumably for odd historical reasons.
290340c85557Swdenk
290440c85557Swdenk*/
290540c85557Swdenk
290640c85557Swdenk#if !defined(INTERNAL_LINUX_C_LIB) || !defined(__ELF__)
290740c85557Swdenk#if __STD_C
290840c85557Swdenkvoid cfree(Void_t *mem)
290940c85557Swdenk#else
291040c85557Swdenkvoid cfree(mem) Void_t *mem;
291140c85557Swdenk#endif
291240c85557Swdenk{
291340c85557Swdenk  fREe(mem);
291440c85557Swdenk}
291540c85557Swdenk#endif
291640c85557Swdenk
291740c85557Swdenk
291840c85557Swdenk
291940c85557Swdenk/*
292040c85557Swdenk
292140c85557Swdenk    Malloc_trim gives memory back to the system (via negative
292240c85557Swdenk    arguments to sbrk) if there is unused memory at the `high' end of
292340c85557Swdenk    the malloc pool. You can call this after freeing large blocks of
292440c85557Swdenk    memory to potentially reduce the system-level memory requirements
292540c85557Swdenk    of a program. However, it cannot guarantee to reduce memory. Under
292640c85557Swdenk    some allocation patterns, some large free blocks of memory will be
292740c85557Swdenk    locked between two used chunks, so they cannot be given back to
292840c85557Swdenk    the system.
292940c85557Swdenk
293040c85557Swdenk    The `pad' argument to malloc_trim represents the amount of free
293140c85557Swdenk    trailing space to leave untrimmed. If this argument is zero,
293240c85557Swdenk    only the minimum amount of memory to maintain internal data
293340c85557Swdenk    structures will be left (one page or less). Non-zero arguments
293440c85557Swdenk    can be supplied to maintain enough trailing space to service
293540c85557Swdenk    future expected allocations without having to re-obtain memory
293640c85557Swdenk    from the system.
293740c85557Swdenk
293840c85557Swdenk    Malloc_trim returns 1 if it actually released any memory, else 0.
293940c85557Swdenk
294040c85557Swdenk*/
294140c85557Swdenk
294240c85557Swdenk#if __STD_C
294340c85557Swdenkint malloc_trim(size_t pad)
294440c85557Swdenk#else
294540c85557Swdenkint malloc_trim(pad) size_t pad;
294640c85557Swdenk#endif
294740c85557Swdenk{
294840c85557Swdenk  long  top_size;        /* Amount of top-most memory */
294940c85557Swdenk  long  extra;           /* Amount to release */
295040c85557Swdenk  char* current_brk;     /* address returned by pre-check sbrk call */
295140c85557Swdenk  char* new_brk;         /* address returned by negative sbrk call */
295240c85557Swdenk
295340c85557Swdenk  unsigned long pagesz = malloc_getpagesize;
295440c85557Swdenk
295540c85557Swdenk  top_size = chunksize(top);
295640c85557Swdenk  extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz;
295740c85557Swdenk
295840c85557Swdenk  if (extra < (long)pagesz)  /* Not enough memory to release */
295940c85557Swdenk    return 0;
296040c85557Swdenk
296140c85557Swdenk  else
296240c85557Swdenk  {
296340c85557Swdenk    /* Test to make sure no one else called sbrk */
296440c85557Swdenk    current_brk = (char*)(MORECORE (0));
296540c85557Swdenk    if (current_brk != (char*)(top) + top_size)
296640c85557Swdenk      return 0;     /* Apparently we don't own memory; must fail */
296740c85557Swdenk
296840c85557Swdenk    else
296940c85557Swdenk    {
297040c85557Swdenk      new_brk = (char*)(MORECORE (-extra));
297140c85557Swdenk
297240c85557Swdenk      if (new_brk == (char*)(MORECORE_FAILURE)) /* sbrk failed? */
297340c85557Swdenk      {
297440c85557Swdenk	/* Try to figure out what we have */
297540c85557Swdenk	current_brk = (char*)(MORECORE (0));
297640c85557Swdenk	top_size = current_brk - (char*)top;
297740c85557Swdenk	if (top_size >= (long)MINSIZE) /* if not, we are very very dead! */
297840c85557Swdenk	{
297940c85557Swdenk	  sbrked_mem = current_brk - sbrk_base;
298040c85557Swdenk	  set_head(top, top_size | PREV_INUSE);
298140c85557Swdenk	}
298240c85557Swdenk	check_chunk(top);
298340c85557Swdenk	return 0;
298440c85557Swdenk      }
298540c85557Swdenk
298640c85557Swdenk      else
298740c85557Swdenk      {
298840c85557Swdenk	/* Success. Adjust top accordingly. */
298940c85557Swdenk	set_head(top, (top_size - extra) | PREV_INUSE);
299040c85557Swdenk	sbrked_mem -= extra;
299140c85557Swdenk	check_chunk(top);
299240c85557Swdenk	return 1;
299340c85557Swdenk      }
299440c85557Swdenk    }
299540c85557Swdenk  }
299640c85557Swdenk}
299740c85557Swdenk
299840c85557Swdenk
299940c85557Swdenk
300040c85557Swdenk/*
300140c85557Swdenk  malloc_usable_size:
300240c85557Swdenk
300340c85557Swdenk    This routine tells you how many bytes you can actually use in an
300440c85557Swdenk    allocated chunk, which may be more than you requested (although
300540c85557Swdenk    often not). You can use this many bytes without worrying about
300640c85557Swdenk    overwriting other allocated objects. Not a particularly great
300740c85557Swdenk    programming practice, but still sometimes useful.
300840c85557Swdenk
300940c85557Swdenk*/
301040c85557Swdenk
301140c85557Swdenk#if __STD_C
301240c85557Swdenksize_t malloc_usable_size(Void_t* mem)
301340c85557Swdenk#else
301440c85557Swdenksize_t malloc_usable_size(mem) Void_t* mem;
301540c85557Swdenk#endif
301640c85557Swdenk{
301740c85557Swdenk  mchunkptr p;
301840c85557Swdenk  if (mem == 0)
301940c85557Swdenk    return 0;
302040c85557Swdenk  else
302140c85557Swdenk  {
302240c85557Swdenk    p = mem2chunk(mem);
302340c85557Swdenk    if(!chunk_is_mmapped(p))
302440c85557Swdenk    {
302540c85557Swdenk      if (!inuse(p)) return 0;
302640c85557Swdenk      check_inuse_chunk(p);
302740c85557Swdenk      return chunksize(p) - SIZE_SZ;
302840c85557Swdenk    }
302940c85557Swdenk    return chunksize(p) - 2*SIZE_SZ;
303040c85557Swdenk  }
303140c85557Swdenk}
303240c85557Swdenk
303340c85557Swdenk
303440c85557Swdenk
303540c85557Swdenk
303640c85557Swdenk/* Utility to update current_mallinfo for malloc_stats and mallinfo() */
303740c85557Swdenk
303840c85557Swdenkstatic void malloc_update_mallinfo()
303940c85557Swdenk{
304040c85557Swdenk  int i;
304140c85557Swdenk  mbinptr b;
304240c85557Swdenk  mchunkptr p;
304340c85557Swdenk#if DEBUG
304440c85557Swdenk  mchunkptr q;
304540c85557Swdenk#endif
304640c85557Swdenk
304740c85557Swdenk  INTERNAL_SIZE_T avail = chunksize(top);
304840c85557Swdenk  int   navail = ((long)(avail) >= (long)MINSIZE)? 1 : 0;
304940c85557Swdenk
305040c85557Swdenk  for (i = 1; i < NAV; ++i)
305140c85557Swdenk  {
305240c85557Swdenk    b = bin_at(i);
305340c85557Swdenk    for (p = last(b); p != b; p = p->bk)
305440c85557Swdenk    {
305540c85557Swdenk#if DEBUG
305640c85557Swdenk      check_free_chunk(p);
305740c85557Swdenk      for (q = next_chunk(p);
305840c85557Swdenk	   q < top && inuse(q) && (long)(chunksize(q)) >= (long)MINSIZE;
305940c85557Swdenk	   q = next_chunk(q))
306040c85557Swdenk	check_inuse_chunk(q);
306140c85557Swdenk#endif
306240c85557Swdenk      avail += chunksize(p);
306340c85557Swdenk      navail++;
306440c85557Swdenk    }
306540c85557Swdenk  }
306640c85557Swdenk
306740c85557Swdenk  current_mallinfo.ordblks = navail;
306840c85557Swdenk  current_mallinfo.uordblks = sbrked_mem - avail;
306940c85557Swdenk  current_mallinfo.fordblks = avail;
307040c85557Swdenk  current_mallinfo.hblks = n_mmaps;
307140c85557Swdenk  current_mallinfo.hblkhd = mmapped_mem;
307240c85557Swdenk  current_mallinfo.keepcost = chunksize(top);
307340c85557Swdenk
307440c85557Swdenk}
307540c85557Swdenk
307640c85557Swdenk
307740c85557Swdenk
307840c85557Swdenk/*
307940c85557Swdenk
308040c85557Swdenk  malloc_stats:
308140c85557Swdenk
308240c85557Swdenk    Prints on stderr the amount of space obtain from the system (both
308340c85557Swdenk    via sbrk and mmap), the maximum amount (which may be more than
308440c85557Swdenk    current if malloc_trim and/or munmap got called), the maximum
308540c85557Swdenk    number of simultaneous mmap regions used, and the current number
308640c85557Swdenk    of bytes allocated via malloc (or realloc, etc) but not yet
308740c85557Swdenk    freed. (Note that this is the number of bytes allocated, not the
308840c85557Swdenk    number requested. It will be larger than the number requested
308940c85557Swdenk    because of alignment and bookkeeping overhead.)
309040c85557Swdenk
309140c85557Swdenk*/
309240c85557Swdenk
309340c85557Swdenkvoid malloc_stats()
309440c85557Swdenk{
309540c85557Swdenk  malloc_update_mallinfo();
309640c85557Swdenk  fprintf(stderr, "max system bytes = %10u\n",
309740c85557Swdenk	  (unsigned int)(max_total_mem));
309840c85557Swdenk  fprintf(stderr, "system bytes     = %10u\n",
309940c85557Swdenk	  (unsigned int)(sbrked_mem + mmapped_mem));
310040c85557Swdenk  fprintf(stderr, "in use bytes     = %10u\n",
310140c85557Swdenk	  (unsigned int)(current_mallinfo.uordblks + mmapped_mem));
310240c85557Swdenk#if HAVE_MMAP
310340c85557Swdenk  fprintf(stderr, "max mmap regions = %10u\n",
310440c85557Swdenk	  (unsigned int)max_n_mmaps);
310540c85557Swdenk#endif
310640c85557Swdenk}
310740c85557Swdenk
310840c85557Swdenk/*
310940c85557Swdenk  mallinfo returns a copy of updated current mallinfo.
311040c85557Swdenk*/
311140c85557Swdenk
311240c85557Swdenkstruct mallinfo mALLINFo()
311340c85557Swdenk{
311440c85557Swdenk  malloc_update_mallinfo();
311540c85557Swdenk  return current_mallinfo;
311640c85557Swdenk}
311740c85557Swdenk
311840c85557Swdenk
311940c85557Swdenk
312040c85557Swdenk
312140c85557Swdenk/*
312240c85557Swdenk  mallopt:
312340c85557Swdenk
312440c85557Swdenk    mallopt is the general SVID/XPG interface to tunable parameters.
312540c85557Swdenk    The format is to provide a (parameter-number, parameter-value) pair.
312640c85557Swdenk    mallopt then sets the corresponding parameter to the argument
312740c85557Swdenk    value if it can (i.e., so long as the value is meaningful),
312840c85557Swdenk    and returns 1 if successful else 0.
312940c85557Swdenk
313040c85557Swdenk    See descriptions of tunable parameters above.
313140c85557Swdenk
313240c85557Swdenk*/
313340c85557Swdenk
313440c85557Swdenk#if __STD_C
313540c85557Swdenkint mALLOPt(int param_number, int value)
313640c85557Swdenk#else
313740c85557Swdenkint mALLOPt(param_number, value) int param_number; int value;
313840c85557Swdenk#endif
313940c85557Swdenk{
314040c85557Swdenk  switch(param_number)
314140c85557Swdenk  {
314240c85557Swdenk    case M_TRIM_THRESHOLD:
314340c85557Swdenk      trim_threshold = value; return 1;
314440c85557Swdenk    case M_TOP_PAD:
314540c85557Swdenk      top_pad = value; return 1;
314640c85557Swdenk    case M_MMAP_THRESHOLD:
314740c85557Swdenk      mmap_threshold = value; return 1;
314840c85557Swdenk    case M_MMAP_MAX:
314940c85557Swdenk#if HAVE_MMAP
315040c85557Swdenk      n_mmaps_max = value; return 1;
315140c85557Swdenk#else
315240c85557Swdenk      if (value != 0) return 0; else  n_mmaps_max = value; return 1;
315340c85557Swdenk#endif
315440c85557Swdenk
315540c85557Swdenk    default:
315640c85557Swdenk      return 0;
315740c85557Swdenk  }
315840c85557Swdenk}
315940c85557Swdenk
316040c85557Swdenk/*
316140c85557Swdenk
316240c85557SwdenkHistory:
316340c85557Swdenk
316440c85557Swdenk    V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
316540c85557Swdenk      * return null for negative arguments
316640c85557Swdenk      * Added Several WIN32 cleanups from Martin C. Fong <mcfong@yahoo.com>
316740c85557Swdenk	 * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
316840c85557Swdenk	  (e.g. WIN32 platforms)
316940c85557Swdenk	 * Cleanup up header file inclusion for WIN32 platforms
317040c85557Swdenk	 * Cleanup code to avoid Microsoft Visual C++ compiler complaints
317140c85557Swdenk	 * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
317240c85557Swdenk	   memory allocation routines
317340c85557Swdenk	 * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
317440c85557Swdenk	 * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
317540c85557Swdenk	   usage of 'assert' in non-WIN32 code
317640c85557Swdenk	 * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
317740c85557Swdenk	   avoid infinite loop
317840c85557Swdenk      * Always call 'fREe()' rather than 'free()'
317940c85557Swdenk
318040c85557Swdenk    V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
318140c85557Swdenk      * Fixed ordering problem with boundary-stamping
318240c85557Swdenk
318340c85557Swdenk    V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
318440c85557Swdenk      * Added pvalloc, as recommended by H.J. Liu
318540c85557Swdenk      * Added 64bit pointer support mainly from Wolfram Gloger
318640c85557Swdenk      * Added anonymously donated WIN32 sbrk emulation
318740c85557Swdenk      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
318840c85557Swdenk      * malloc_extend_top: fix mask error that caused wastage after
318940c85557Swdenk	foreign sbrks
319040c85557Swdenk      * Add linux mremap support code from HJ Liu
319140c85557Swdenk
319240c85557Swdenk    V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
319340c85557Swdenk      * Integrated most documentation with the code.
319440c85557Swdenk      * Add support for mmap, with help from
319540c85557Swdenk	Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
319640c85557Swdenk      * Use last_remainder in more cases.
319740c85557Swdenk      * Pack bins using idea from  colin@nyx10.cs.du.edu
319840c85557Swdenk      * Use ordered bins instead of best-fit threshhold
319940c85557Swdenk      * Eliminate block-local decls to simplify tracing and debugging.
320040c85557Swdenk      * Support another case of realloc via move into top
320140c85557Swdenk      * Fix error occuring when initial sbrk_base not word-aligned.
320240c85557Swdenk      * Rely on page size for units instead of SBRK_UNIT to
320340c85557Swdenk	avoid surprises about sbrk alignment conventions.
320440c85557Swdenk      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
320540c85557Swdenk	(raymond@es.ele.tue.nl) for the suggestion.
320640c85557Swdenk      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
320740c85557Swdenk      * More precautions for cases where other routines call sbrk,
320840c85557Swdenk	courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
320940c85557Swdenk      * Added macros etc., allowing use in linux libc from
321040c85557Swdenk	H.J. Lu (hjl@gnu.ai.mit.edu)
321140c85557Swdenk      * Inverted this history list
321240c85557Swdenk
321340c85557Swdenk    V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
321440c85557Swdenk      * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
321540c85557Swdenk      * Removed all preallocation code since under current scheme
321640c85557Swdenk	the work required to undo bad preallocations exceeds
321740c85557Swdenk	the work saved in good cases for most test programs.
321840c85557Swdenk      * No longer use return list or unconsolidated bins since
321940c85557Swdenk	no scheme using them consistently outperforms those that don't
322040c85557Swdenk	given above changes.
322140c85557Swdenk      * Use best fit for very large chunks to prevent some worst-cases.
322240c85557Swdenk      * Added some support for debugging
322340c85557Swdenk
322440c85557Swdenk    V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
322540c85557Swdenk      * Removed footers when chunks are in use. Thanks to
322640c85557Swdenk	Paul Wilson (wilson@cs.texas.edu) for the suggestion.
322740c85557Swdenk
322840c85557Swdenk    V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
322940c85557Swdenk      * Added malloc_trim, with help from Wolfram Gloger
323040c85557Swdenk	(wmglo@Dent.MED.Uni-Muenchen.DE).
323140c85557Swdenk
323240c85557Swdenk    V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
323340c85557Swdenk
323440c85557Swdenk    V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
323540c85557Swdenk      * realloc: try to expand in both directions
323640c85557Swdenk      * malloc: swap order of clean-bin strategy;
323740c85557Swdenk      * realloc: only conditionally expand backwards
323840c85557Swdenk      * Try not to scavenge used bins
323940c85557Swdenk      * Use bin counts as a guide to preallocation
324040c85557Swdenk      * Occasionally bin return list chunks in first scan
324140c85557Swdenk      * Add a few optimizations from colin@nyx10.cs.du.edu
324240c85557Swdenk
324340c85557Swdenk    V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
324440c85557Swdenk      * faster bin computation & slightly different binning
324540c85557Swdenk      * merged all consolidations to one part of malloc proper
324640c85557Swdenk	 (eliminating old malloc_find_space & malloc_clean_bin)
324740c85557Swdenk      * Scan 2 returns chunks (not just 1)
324840c85557Swdenk      * Propagate failure in realloc if malloc returns 0
324940c85557Swdenk      * Add stuff to allow compilation on non-ANSI compilers
325040c85557Swdenk	  from kpv@research.att.com
325140c85557Swdenk
325240c85557Swdenk    V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
325340c85557Swdenk      * removed potential for odd address access in prev_chunk
325440c85557Swdenk      * removed dependency on getpagesize.h
325540c85557Swdenk      * misc cosmetics and a bit more internal documentation
325640c85557Swdenk      * anticosmetics: mangled names in macros to evade debugger strangeness
325740c85557Swdenk      * tested on sparc, hp-700, dec-mips, rs6000
325840c85557Swdenk	  with gcc & native cc (hp, dec only) allowing
325940c85557Swdenk	  Detlefs & Zorn comparison study (in SIGPLAN Notices.)
326040c85557Swdenk
326140c85557Swdenk    Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
326240c85557Swdenk      * Based loosely on libg++-1.2X malloc. (It retains some of the overall
326340c85557Swdenk	 structure of old version,  but most details differ.)
326440c85557Swdenk
326540c85557Swdenk*/
3266