The R Project SVN R

Rev

Rev 40801 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 40801 Rev 50907
1
/* R changes:
1
/* R changes:
2
 
2
 
3
 - use Rm_malloc, Rm_calloc, Rm_realloc, Rm_free to ensure this is only
3
 - use Rm_malloc, Rm_calloc, Rm_realloc, Rm_free to ensure this is only
4
   used from memory.c.
4
   used from memory.c.
5
 
5
 
6
 - make attempt for maximum footprint to exceed limit a failure.
6
 - make attempt for maximum footprint to exceed limit a failure.
7
 
7
 
8
 - MinGW does have unistd and does not need VC++ pragma.
8
 - MinGW does have unistd and does not need VC++ pragma.
9
*/
9
*/
10
 
10
 
11
/*
11
/*
12
  This is a version (aka dlmalloc) of malloc/free/realloc written by
12
  This is a version (aka dlmalloc) of malloc/free/realloc written by
13
  Doug Lea and released to the public domain, as explained at
13
  Doug Lea and released to the public domain, as explained at
14
  http://creativecommons.org/licenses/publicdomain.  Send questions,
14
  http://creativecommons.org/licenses/publicdomain.  Send questions,
15
  comments, complaints, performance data, etc to dl@cs.oswego.edu
15
  comments, complaints, performance data, etc to dl@cs.oswego.edu
16
 
16
 
17
* Version 2.8.3 Thu Sep 22 11:16:15 2005  Doug Lea  (dl at gee)
17
* Version 2.8.3 Thu Sep 22 11:16:15 2005  Doug Lea  (dl at gee)
18
 
18
 
19
   Note: There may be an updated version of this malloc obtainable at
19
   Note: There may be an updated version of this malloc obtainable at
20
           ftp://gee.cs.oswego.edu/pub/misc/malloc.c
20
           ftp://gee.cs.oswego.edu/pub/misc/malloc.c
21
         Check before installing!
21
         Check before installing!
22
 
22
 
23
* Quickstart
23
* Quickstart
24
 
24
 
25
  This library is all in one file to simplify the most common usage:
25
  This library is all in one file to simplify the most common usage:
26
  ftp it, compile it (-O3), and link it into another program. All of
26
  ftp it, compile it (-O3), and link it into another program. All of
27
  the compile-time options default to reasonable values for use on
27
  the compile-time options default to reasonable values for use on
28
  most platforms.  You might later want to step through various
28
  most platforms.  You might later want to step through various
29
  compile-time and dynamic tuning options.
29
  compile-time and dynamic tuning options.
30
 
30
 
31
  For convenience, an include file for code using this malloc is at:
31
  For convenience, an include file for code using this malloc is at:
32
     ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h
32
     ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h
33
  You don't really need this .h file unless you call functions not
33
  You don't really need this .h file unless you call functions not
34
  defined in your system include files.  The .h file contains only the
34
  defined in your system include files.  The .h file contains only the
35
  excerpts from this file needed for using this malloc on ANSI C/C++
35
  excerpts from this file needed for using this malloc on ANSI C/C++
36
  systems, so long as you haven't changed compile-time options about
36
  systems, so long as you haven't changed compile-time options about
37
  naming and tuning parameters.  If you do, then you can create your
37
  naming and tuning parameters.  If you do, then you can create your
38
  own malloc.h that does include all settings by cutting at the point
38
  own malloc.h that does include all settings by cutting at the point
39
  indicated below. Note that you may already by default be using a C
39
  indicated below. Note that you may already by default be using a C
40
  library containing a malloc that is based on some version of this
40
  library containing a malloc that is based on some version of this
41
  malloc (for example in linux). You might still want to use the one
41
  malloc (for example in linux). You might still want to use the one
42
  in this file to customize settings or to avoid overheads associated
42
  in this file to customize settings or to avoid overheads associated
43
  with library versions.
43
  with library versions.
44
 
44
 
45
* Vital statistics:
45
* Vital statistics:
46
 
46
 
47
  Supported pointer/size_t representation:       4 or 8 bytes
47
  Supported pointer/size_t representation:       4 or 8 bytes
48
       size_t MUST be an unsigned type of the same width as
48
       size_t MUST be an unsigned type of the same width as
49
       pointers. (If you are using an ancient system that declares
49
       pointers. (If you are using an ancient system that declares
50
       size_t as a signed type, or need it to be a different width
50
       size_t as a signed type, or need it to be a different width
51
       than pointers, you can use a previous release of this malloc
51
       than pointers, you can use a previous release of this malloc
52
       (e.g. 2.7.2) supporting these.)
52
       (e.g. 2.7.2) supporting these.)
53
 
53
 
54
  Alignment:                                     8 bytes (default)
54
  Alignment:                                     8 bytes (default)
55
       This suffices for nearly all current machines and C compilers.
55
       This suffices for nearly all current machines and C compilers.
56
       However, you can define MALLOC_ALIGNMENT to be wider than this
56
       However, you can define MALLOC_ALIGNMENT to be wider than this
57
       if necessary (up to 128bytes), at the expense of using more space.
57
       if necessary (up to 128bytes), at the expense of using more space.
58
 
58
 
59
  Minimum overhead per allocated chunk:   4 or  8 bytes (if 4byte sizes)
59
  Minimum overhead per allocated chunk:   4 or  8 bytes (if 4byte sizes)
60
                                          8 or 16 bytes (if 8byte sizes)
60
                                          8 or 16 bytes (if 8byte sizes)
61
       Each malloced chunk has a hidden word of overhead holding size
61
       Each malloced chunk has a hidden word of overhead holding size
62
       and status information, and additional cross-check word
62
       and status information, and additional cross-check word
63
       if FOOTERS is defined.
63
       if FOOTERS is defined.
64
 
64
 
65
  Minimum allocated size: 4-byte ptrs:  16 bytes    (including overhead)
65
  Minimum allocated size: 4-byte ptrs:  16 bytes    (including overhead)
66
                          8-byte ptrs:  32 bytes    (including overhead)
66
                          8-byte ptrs:  32 bytes    (including overhead)
67
 
67
 
68
       Even a request for zero bytes (i.e., malloc(0)) returns a
68
       Even a request for zero bytes (i.e., malloc(0)) returns a
69
       pointer to something of the minimum allocatable size.
69
       pointer to something of the minimum allocatable size.
70
       The maximum overhead wastage (i.e., number of extra bytes
70
       The maximum overhead wastage (i.e., number of extra bytes
71
       allocated than were requested in malloc) is less than or equal
71
       allocated than were requested in malloc) is less than or equal
72
       to the minimum size, except for requests >= mmap_threshold that
72
       to the minimum size, except for requests >= mmap_threshold that
73
       are serviced via mmap(), where the worst case wastage is about
73
       are serviced via mmap(), where the worst case wastage is about
74
       32 bytes plus the remainder from a system page (the minimal
74
       32 bytes plus the remainder from a system page (the minimal
75
       mmap unit); typically 4096 or 8192 bytes.
75
       mmap unit); typically 4096 or 8192 bytes.
76
 
76
 
77
  Security: static-safe; optionally more or less
77
  Security: static-safe; optionally more or less
78
       The "security" of malloc refers to the ability of malicious
78
       The "security" of malloc refers to the ability of malicious
79
       code to accentuate the effects of errors (for example, freeing
79
       code to accentuate the effects of errors (for example, freeing
80
       space that is not currently malloc'ed or overwriting past the
80
       space that is not currently malloc'ed or overwriting past the
81
       ends of chunks) in code that calls malloc.  This malloc
81
       ends of chunks) in code that calls malloc.  This malloc
82
       guarantees not to modify any memory locations below the base of
82
       guarantees not to modify any memory locations below the base of
83
       heap, i.e., static variables, even in the presence of usage
83
       heap, i.e., static variables, even in the presence of usage
84
       errors.  The routines additionally detect most improper frees
84
       errors.  The routines additionally detect most improper frees
85
       and reallocs.  All this holds as long as the static bookkeeping
85
       and reallocs.  All this holds as long as the static bookkeeping
86
       for malloc itself is not corrupted by some other means.  This
86
       for malloc itself is not corrupted by some other means.  This
87
       is only one aspect of security -- these checks do not, and
87
       is only one aspect of security -- these checks do not, and
88
       cannot, detect all possible programming errors.
88
       cannot, detect all possible programming errors.
89
 
89
 
90
       If FOOTERS is defined nonzero, then each allocated chunk
90
       If FOOTERS is defined nonzero, then each allocated chunk
91
       carries an additional check word to verify that it was malloced
91
       carries an additional check word to verify that it was malloced
92
       from its space.  These check words are the same within each
92
       from its space.  These check words are the same within each
93
       execution of a program using malloc, but differ across
93
       execution of a program using malloc, but differ across
94
       executions, so externally crafted fake chunks cannot be
94
       executions, so externally crafted fake chunks cannot be
95
       freed. This improves security by rejecting frees/reallocs that
95
       freed. This improves security by rejecting frees/reallocs that
96
       could corrupt heap memory, in addition to the checks preventing
96
       could corrupt heap memory, in addition to the checks preventing
97
       writes to statics that are always on.  This may further improve
97
       writes to statics that are always on.  This may further improve
98
       security at the expense of time and space overhead.  (Note that
98
       security at the expense of time and space overhead.  (Note that
99
       FOOTERS may also be worth using with MSPACES.)
99
       FOOTERS may also be worth using with MSPACES.)
100
 
100
 
101
       By default detected errors cause the program to abort (calling
101
       By default detected errors cause the program to abort (calling
102
       "abort()"). You can override this to instead proceed past
102
       "abort()"). You can override this to instead proceed past
103
       errors by defining PROCEED_ON_ERROR.  In this case, a bad free
103
       errors by defining PROCEED_ON_ERROR.  In this case, a bad free
104
       has no effect, and a malloc that encounters a bad address
104
       has no effect, and a malloc that encounters a bad address
105
       caused by user overwrites will ignore the bad address by
105
       caused by user overwrites will ignore the bad address by
106
       dropping pointers and indices to all known memory. This may
106
       dropping pointers and indices to all known memory. This may
107
       be appropriate for programs that should continue if at all
107
       be appropriate for programs that should continue if at all
108
       possible in the face of programming errors, although they may
108
       possible in the face of programming errors, although they may
109
       run out of memory because dropped memory is never reclaimed.
109
       run out of memory because dropped memory is never reclaimed.
110
 
110
 
111
       If you don't like either of these options, you can define
111
       If you don't like either of these options, you can define
112
       CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
112
       CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
113
       else. And if if you are sure that your program using malloc has
113
       else. And if if you are sure that your program using malloc has
114
       no errors or vulnerabilities, you can define INSECURE to 1,
114
       no errors or vulnerabilities, you can define INSECURE to 1,
115
       which might (or might not) provide a small performance improvement.
115
       which might (or might not) provide a small performance improvement.
116
 
116
 
117
  Thread-safety: NOT thread-safe unless USE_LOCKS defined
117
  Thread-safety: NOT thread-safe unless USE_LOCKS defined
118
       When USE_LOCKS is defined, each public call to malloc, free,
118
       When USE_LOCKS is defined, each public call to malloc, free,
119
       etc is surrounded with either a pthread mutex or a win32
119
       etc is surrounded with either a pthread mutex or a win32
120
       spinlock (depending on WIN32). This is not especially fast, and
120
       spinlock (depending on WIN32). This is not especially fast, and
121
       can be a major bottleneck.  It is designed only to provide
121
       can be a major bottleneck.  It is designed only to provide
122
       minimal protection in concurrent environments, and to provide a
122
       minimal protection in concurrent environments, and to provide a
123
       basis for extensions.  If you are using malloc in a concurrent
123
       basis for extensions.  If you are using malloc in a concurrent
124
       program, consider instead using ptmalloc, which is derived from
124
       program, consider instead using ptmalloc, which is derived from
125
       a version of this malloc. (See http://www.malloc.de).
125
       a version of this malloc. (See http://www.malloc.de).
126
 
126
 
127
  System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
127
  System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
128
       This malloc can use unix sbrk or any emulation (invoked using
128
       This malloc can use unix sbrk or any emulation (invoked using
129
       the CALL_MORECORE macro) and/or mmap/munmap or any emulation
129
       the CALL_MORECORE macro) and/or mmap/munmap or any emulation
130
       (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
130
       (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
131
       memory.  On most unix systems, it tends to work best if both
131
       memory.  On most unix systems, it tends to work best if both
132
       MORECORE and MMAP are enabled.  On Win32, it uses emulations
132
       MORECORE and MMAP are enabled.  On Win32, it uses emulations
133
       based on VirtualAlloc. It also uses common C library functions
133
       based on VirtualAlloc. It also uses common C library functions
134
       like memset.
134
       like memset.
135
 
135
 
136
  Compliance: I believe it is compliant with the Single Unix Specification
136
  Compliance: I believe it is compliant with the Single Unix Specification
137
       (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
137
       (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
138
       others as well.
138
       others as well.
139
 
139
 
140
* Overview of algorithms
140
* Overview of algorithms
141
 
141
 
142
  This is not the fastest, most space-conserving, most portable, or
142
  This is not the fastest, most space-conserving, most portable, or
143
  most tunable malloc ever written. However it is among the fastest
143
  most tunable malloc ever written. However it is among the fastest
144
  while also being among the most space-conserving, portable and
144
  while also being among the most space-conserving, portable and
145
  tunable.  Consistent balance across these factors results in a good
145
  tunable.  Consistent balance across these factors results in a good
146
  general-purpose allocator for malloc-intensive programs.
146
  general-purpose allocator for malloc-intensive programs.
147
 
147
 
148
  In most ways, this malloc is a best-fit allocator. Generally, it
148
  In most ways, this malloc is a best-fit allocator. Generally, it
149
  chooses the best-fitting existing chunk for a request, with ties
149
  chooses the best-fitting existing chunk for a request, with ties
150
  broken in approximately least-recently-used order. (This strategy
150
  broken in approximately least-recently-used order. (This strategy
151
  normally maintains low fragmentation.) However, for requests less
151
  normally maintains low fragmentation.) However, for requests less
152
  than 256bytes, it deviates from best-fit when there is not an
152
  than 256bytes, it deviates from best-fit when there is not an
153
  exactly fitting available chunk by preferring to use space adjacent
153
  exactly fitting available chunk by preferring to use space adjacent
154
  to that used for the previous small request, as well as by breaking
154
  to that used for the previous small request, as well as by breaking
155
  ties in approximately most-recently-used order. (These enhance
155
  ties in approximately most-recently-used order. (These enhance
156
  locality of series of small allocations.)  And for very large requests
156
  locality of series of small allocations.)  And for very large requests
157
  (>= 256Kb by default), it relies on system memory mapping
157
  (>= 256Kb by default), it relies on system memory mapping
158
  facilities, if supported.  (This helps avoid carrying around and
158
  facilities, if supported.  (This helps avoid carrying around and
159
  possibly fragmenting memory used only for large chunks.)
159
  possibly fragmenting memory used only for large chunks.)
160
 
160
 
161
  All operations (except malloc_stats and mallinfo) have execution
161
  All operations (except malloc_stats and mallinfo) have execution
162
  times that are bounded by a constant factor of the number of bits in
162
  times that are bounded by a constant factor of the number of bits in
163
  a size_t, not counting any clearing in calloc or copying in realloc,
163
  a size_t, not counting any clearing in calloc or copying in realloc,
164
  or actions surrounding MORECORE and MMAP that have times
164
  or actions surrounding MORECORE and MMAP that have times
165
  proportional to the number of non-contiguous regions returned by
165
  proportional to the number of non-contiguous regions returned by
166
  system allocation routines, which is often just 1.
166
  system allocation routines, which is often just 1.
167
 
167
 
168
  The implementation is not very modular and seriously overuses
168
  The implementation is not very modular and seriously overuses
169
  macros. Perhaps someday all C compilers will do as good a job
169
  macros. Perhaps someday all C compilers will do as good a job
170
  inlining modular code as can now be done by brute-force expansion,
170
  inlining modular code as can now be done by brute-force expansion,
171
  but now, enough of them seem not to.
171
  but now, enough of them seem not to.
172
 
172
 
173
  Some compilers issue a lot of warnings about code that is
173
  Some compilers issue a lot of warnings about code that is
174
  dead/unreachable only on some platforms, and also about intentional
174
  dead/unreachable only on some platforms, and also about intentional
175
  uses of negation on unsigned types. All known cases of each can be
175
  uses of negation on unsigned types. All known cases of each can be
176
  ignored.
176
  ignored.
177
 
177
 
178
  For a longer but out of date high-level description, see
178
  For a longer but out of date high-level description, see
179
     http://gee.cs.oswego.edu/dl/html/malloc.html
179
     http://gee.cs.oswego.edu/dl/html/malloc.html
180
 
180
 
181
* MSPACES
181
* MSPACES
182
  If MSPACES is defined, then in addition to malloc, free, etc.,
182
  If MSPACES is defined, then in addition to malloc, free, etc.,
183
  this file also defines mspace_malloc, mspace_free, etc. These
183
  this file also defines mspace_malloc, mspace_free, etc. These
184
  are versions of malloc routines that take an "mspace" argument
184
  are versions of malloc routines that take an "mspace" argument
185
  obtained using create_mspace, to control all internal bookkeeping.
185
  obtained using create_mspace, to control all internal bookkeeping.
186
  If ONLY_MSPACES is defined, only these versions are compiled.
186
  If ONLY_MSPACES is defined, only these versions are compiled.
187
  So if you would like to use this allocator for only some allocations,
187
  So if you would like to use this allocator for only some allocations,
188
  and your system malloc for others, you can compile with
188
  and your system malloc for others, you can compile with
189
  ONLY_MSPACES and then do something like...
189
  ONLY_MSPACES and then do something like...
190
    static mspace mymspace = create_mspace(0,0); // for example
190
    static mspace mymspace = create_mspace(0,0); // for example
191
    #define mymalloc(bytes)  mspace_malloc(mymspace, bytes)
191
    #define mymalloc(bytes)  mspace_malloc(mymspace, bytes)
192
 
192
 
193
  (Note: If you only need one instance of an mspace, you can instead
193
  (Note: If you only need one instance of an mspace, you can instead
194
  use "USE_DL_PREFIX" to relabel the global malloc.)
194
  use "USE_DL_PREFIX" to relabel the global malloc.)
195
 
195
 
196
  You can similarly create thread-local allocators by storing
196
  You can similarly create thread-local allocators by storing
197
  mspaces as thread-locals. For example:
197
  mspaces as thread-locals. For example:
198
    static __thread mspace tlms = 0;
198
    static __thread mspace tlms = 0;
199
    void*  tlmalloc(size_t bytes) {
199
    void*  tlmalloc(size_t bytes) {
200
      if (tlms == 0) tlms = create_mspace(0, 0);
200
      if (tlms == 0) tlms = create_mspace(0, 0);
201
      return mspace_malloc(tlms, bytes);
201
      return mspace_malloc(tlms, bytes);
202
    }
202
    }
203
    void  tlfree(void* mem) { mspace_free(tlms, mem); }
203
    void  tlfree(void* mem) { mspace_free(tlms, mem); }
204
 
204
 
205
  Unless FOOTERS is defined, each mspace is completely independent.
205
  Unless FOOTERS is defined, each mspace is completely independent.
206
  You cannot allocate from one and free to another (although
206
  You cannot allocate from one and free to another (although
207
  conformance is only weakly checked, so usage errors are not always
207
  conformance is only weakly checked, so usage errors are not always
208
  caught). If FOOTERS is defined, then each chunk carries around a tag
208
  caught). If FOOTERS is defined, then each chunk carries around a tag
209
  indicating its originating mspace, and frees are directed to their
209
  indicating its originating mspace, and frees are directed to their
210
  originating spaces.
210
  originating spaces.
211
 
211
 
212
 -------------------------  Compile-time options ---------------------------
212
 -------------------------  Compile-time options ---------------------------
213
 
213
 
214
Be careful in setting #define values for numerical constants of type
214
Be careful in setting #define values for numerical constants of type
215
size_t. On some systems, literal values are not automatically extended
215
size_t. On some systems, literal values are not automatically extended
216
to size_t precision unless they are explicitly casted.
216
to size_t precision unless they are explicitly casted.
217
 
217
 
218
WIN32                    default: defined if _WIN32 defined
218
WIN32                    default: defined if _WIN32 defined
219
  Defining WIN32 sets up defaults for MS environment and compilers.
219
  Defining WIN32 sets up defaults for MS environment and compilers.
220
  Otherwise defaults are for unix.
220
  Otherwise defaults are for unix.
221
 
221
 
222
MALLOC_ALIGNMENT         default: (size_t)8
222
MALLOC_ALIGNMENT         default: (size_t)8
223
  Controls the minimum alignment for malloc'ed chunks.  It must be a
223
  Controls the minimum alignment for malloc'ed chunks.  It must be a
224
  power of two and at least 8, even on machines for which smaller
224
  power of two and at least 8, even on machines for which smaller
225
  alignments would suffice. It may be defined as larger than this
225
  alignments would suffice. It may be defined as larger than this
226
  though. Note however that code and data structures are optimized for
226
  though. Note however that code and data structures are optimized for
227
  the case of 8-byte alignment.
227
  the case of 8-byte alignment.
228
 
228
 
229
MSPACES                  default: 0 (false)
229
MSPACES                  default: 0 (false)
230
  If true, compile in support for independent allocation spaces.
230
  If true, compile in support for independent allocation spaces.
231
  This is only supported if HAVE_MMAP is true.
231
  This is only supported if HAVE_MMAP is true.
232
 
232
 
233
ONLY_MSPACES             default: 0 (false)
233
ONLY_MSPACES             default: 0 (false)
234
  If true, only compile in mspace versions, not regular versions.
234
  If true, only compile in mspace versions, not regular versions.
235
 
235
 
236
USE_LOCKS                default: 0 (false)
236
USE_LOCKS                default: 0 (false)
237
  Causes each call to each public routine to be surrounded with
237
  Causes each call to each public routine to be surrounded with
238
  pthread or WIN32 mutex lock/unlock. (If set true, this can be
238
  pthread or WIN32 mutex lock/unlock. (If set true, this can be
239
  overridden on a per-mspace basis for mspace versions.)
239
  overridden on a per-mspace basis for mspace versions.)
240
 
240
 
241
FOOTERS                  default: 0
241
FOOTERS                  default: 0
242
  If true, provide extra checking and dispatching by placing
242
  If true, provide extra checking and dispatching by placing
243
  information in the footers of allocated chunks. This adds
243
  information in the footers of allocated chunks. This adds
244
  space and time overhead.
244
  space and time overhead.
245
 
245
 
246
INSECURE                 default: 0
246
INSECURE                 default: 0
247
  If true, omit checks for usage errors and heap space overwrites.
247
  If true, omit checks for usage errors and heap space overwrites.
248
 
248
 
249
USE_DL_PREFIX            default: NOT defined
249
USE_DL_PREFIX            default: NOT defined
250
  Causes compiler to prefix all public routines with the string 'dl'.
250
  Causes compiler to prefix all public routines with the string 'dl'.
251
  This can be useful when you only want to use this malloc in one part
251
  This can be useful when you only want to use this malloc in one part
252
  of a program, using your regular system malloc elsewhere.
252
  of a program, using your regular system malloc elsewhere.
253
 
253
 
254
ABORT                    default: defined as abort()
254
ABORT                    default: defined as abort()
255
  Defines how to abort on failed checks.  On most systems, a failed
255
  Defines how to abort on failed checks.  On most systems, a failed
256
  check cannot die with an "assert" or even print an informative
256
  check cannot die with an "assert" or even print an informative
257
  message, because the underlying print routines in turn call malloc,
257
  message, because the underlying print routines in turn call malloc,
258
  which will fail again.  Generally, the best policy is to simply call
258
  which will fail again.  Generally, the best policy is to simply call
259
  abort(). It's not very useful to do more than this because many
259
  abort(). It's not very useful to do more than this because many
260
  errors due to overwriting will show up as address faults (null, odd
260
  errors due to overwriting will show up as address faults (null, odd
261
  addresses etc) rather than malloc-triggered checks, so will also
261
  addresses etc) rather than malloc-triggered checks, so will also
262
  abort.  Also, most compilers know that abort() does not return, so
262
  abort.  Also, most compilers know that abort() does not return, so
263
  can better optimize code conditionally calling it.
263
  can better optimize code conditionally calling it.
264
 
264
 
265
PROCEED_ON_ERROR           default: defined as 0 (false)
265
PROCEED_ON_ERROR           default: defined as 0 (false)
266
  Controls whether detected bad addresses cause them to bypassed
266
  Controls whether detected bad addresses cause them to bypassed
267
  rather than aborting. If set, detected bad arguments to free and
267
  rather than aborting. If set, detected bad arguments to free and
268
  realloc are ignored. And all bookkeeping information is zeroed out
268
  realloc are ignored. And all bookkeeping information is zeroed out
269
  upon a detected overwrite of freed heap space, thus losing the
269
  upon a detected overwrite of freed heap space, thus losing the
270
  ability to ever return it from malloc again, but enabling the
270
  ability to ever return it from malloc again, but enabling the
271
  application to proceed. If PROCEED_ON_ERROR is defined, the
271
  application to proceed. If PROCEED_ON_ERROR is defined, the
272
  static variable malloc_corruption_error_count is compiled in
272
  static variable malloc_corruption_error_count is compiled in
273
  and can be examined to see if errors have occurred. This option
273
  and can be examined to see if errors have occurred. This option
274
  generates slower code than the default abort policy.
274
  generates slower code than the default abort policy.
275
 
275
 
276
DEBUG                    default: NOT defined
276
DEBUG                    default: NOT defined
277
  The DEBUG setting is mainly intended for people trying to modify
277
  The DEBUG setting is mainly intended for people trying to modify
278
  this code or diagnose problems when porting to new platforms.
278
  this code or diagnose problems when porting to new platforms.
279
  However, it may also be able to better isolate user errors than just
279
  However, it may also be able to better isolate user errors than just
280
  using runtime checks.  The assertions in the check routines spell
280
  using runtime checks.  The assertions in the check routines spell
281
  out in more detail the assumptions and invariants underlying the
281
  out in more detail the assumptions and invariants underlying the
282
  algorithms.  The checking is fairly extensive, and will slow down
282
  algorithms.  The checking is fairly extensive, and will slow down
283
  execution noticeably. Calling malloc_stats or mallinfo with DEBUG
283
  execution noticeably. Calling malloc_stats or mallinfo with DEBUG
284
  set will attempt to check every non-mmapped allocated and free chunk
284
  set will attempt to check every non-mmapped allocated and free chunk
285
  in the course of computing the summaries.
285
  in the course of computing the summaries.
286
 
286
 
287
ABORT_ON_ASSERT_FAILURE   default: defined as 1 (true)
287
ABORT_ON_ASSERT_FAILURE   default: defined as 1 (true)
288
  Debugging assertion failures can be nearly impossible if your
288
  Debugging assertion failures can be nearly impossible if your
289
  version of the assert macro causes malloc to be called, which will
289
  version of the assert macro causes malloc to be called, which will
290
  lead to a cascade of further failures, blowing the runtime stack.
290
  lead to a cascade of further failures, blowing the runtime stack.
291
  ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),
291
  ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),
292
  which will usually make debugging easier.
292
  which will usually make debugging easier.
293
 
293
 
294
MALLOC_FAILURE_ACTION     default: sets errno to ENOMEM, or no-op on win32
294
MALLOC_FAILURE_ACTION     default: sets errno to ENOMEM, or no-op on win32
295
  The action to take before "return 0" when malloc fails to be able to
295
  The action to take before "return 0" when malloc fails to be able to
296
  return memory because there is none available.
296
  return memory because there is none available.
297
 
297
 
298
HAVE_MORECORE             default: 1 (true) unless win32 or ONLY_MSPACES
298
HAVE_MORECORE             default: 1 (true) unless win32 or ONLY_MSPACES
299
  True if this system supports sbrk or an emulation of it.
299
  True if this system supports sbrk or an emulation of it.
300
 
300
 
301
MORECORE                  default: sbrk
301
MORECORE                  default: sbrk
302
  The name of the sbrk-style system routine to call to obtain more
302
  The name of the sbrk-style system routine to call to obtain more
303
  memory.  See below for guidance on writing custom MORECORE
303
  memory.  See below for guidance on writing custom MORECORE
304
  functions. The type of the argument to sbrk/MORECORE varies across
304
  functions. The type of the argument to sbrk/MORECORE varies across
305
  systems.  It cannot be size_t, because it supports negative
305
  systems.  It cannot be size_t, because it supports negative
306
  arguments, so it is normally the signed type of the same width as
306
  arguments, so it is normally the signed type of the same width as
307
  size_t (sometimes declared as "intptr_t").  It doesn't much matter
307
  size_t (sometimes declared as "intptr_t").  It doesn't much matter
308
  though. Internally, we only call it with arguments less than half
308
  though. Internally, we only call it with arguments less than half
309
  the max value of a size_t, which should work across all reasonable
309
  the max value of a size_t, which should work across all reasonable
310
  possibilities, although sometimes generating compiler warnings.  See
310
  possibilities, although sometimes generating compiler warnings.  See
311
  near the end of this file for guidelines for creating a custom
311
  near the end of this file for guidelines for creating a custom
312
  version of MORECORE.
312
  version of MORECORE.
313
 
313
 
314
MORECORE_CONTIGUOUS       default: 1 (true)
314
MORECORE_CONTIGUOUS       default: 1 (true)
315
  If true, take advantage of fact that consecutive calls to MORECORE
315
  If true, take advantage of fact that consecutive calls to MORECORE
316
  with positive arguments always return contiguous increasing
316
  with positive arguments always return contiguous increasing
317
  addresses.  This is true of unix sbrk. It does not hurt too much to
317
  addresses.  This is true of unix sbrk. It does not hurt too much to
318
  set it true anyway, since malloc copes with non-contiguities.
318
  set it true anyway, since malloc copes with non-contiguities.
319
  Setting it false when definitely non-contiguous saves time
319
  Setting it false when definitely non-contiguous saves time
320
  and possibly wasted space it would take to discover this though.
320
  and possibly wasted space it would take to discover this though.
321
 
321
 
322
MORECORE_CANNOT_TRIM      default: NOT defined
322
MORECORE_CANNOT_TRIM      default: NOT defined
323
  True if MORECORE cannot release space back to the system when given
323
  True if MORECORE cannot release space back to the system when given
324
  negative arguments. This is generally necessary only if you are
324
  negative arguments. This is generally necessary only if you are
325
  using a hand-crafted MORECORE function that cannot handle negative
325
  using a hand-crafted MORECORE function that cannot handle negative
326
  arguments.
326
  arguments.
327
 
327
 
328
HAVE_MMAP                 default: 1 (true)
328
HAVE_MMAP                 default: 1 (true)
329
  True if this system supports mmap or an emulation of it.  If so, and
329
  True if this system supports mmap or an emulation of it.  If so, and
330
  HAVE_MORECORE is not true, MMAP is used for all system
330
  HAVE_MORECORE is not true, MMAP is used for all system
331
  allocation. If set and HAVE_MORECORE is true as well, MMAP is
331
  allocation. If set and HAVE_MORECORE is true as well, MMAP is
332
  primarily used to directly allocate very large blocks. It is also
332
  primarily used to directly allocate very large blocks. It is also
333
  used as a backup strategy in cases where MORECORE fails to provide
333
  used as a backup strategy in cases where MORECORE fails to provide
334
  space from system. Note: A single call to MUNMAP is assumed to be
334
  space from system. Note: A single call to MUNMAP is assumed to be
335
  able to unmap memory that may have be allocated using multiple calls
335
  able to unmap memory that may have be allocated using multiple calls
336
  to MMAP, so long as they are adjacent.
336
  to MMAP, so long as they are adjacent.
337
 
337
 
338
HAVE_MREMAP               default: 1 on linux, else 0
338
HAVE_MREMAP               default: 1 on linux, else 0
339
  If true realloc() uses mremap() to re-allocate large blocks and
339
  If true realloc() uses mremap() to re-allocate large blocks and
340
  extend or shrink allocation spaces.
340
  extend or shrink allocation spaces.
341
 
341
 
342
MMAP_CLEARS               default: 1 on unix
342
MMAP_CLEARS               default: 1 on unix
343
  True if mmap clears memory so calloc doesn't need to. This is true
343
  True if mmap clears memory so calloc doesn't need to. This is true
344
  for standard unix mmap using /dev/zero.
344
  for standard unix mmap using /dev/zero.
345
 
345
 
346
USE_BUILTIN_FFS            default: 0 (i.e., not used)
346
USE_BUILTIN_FFS            default: 0 (i.e., not used)
347
  Causes malloc to use the builtin ffs() function to compute indices.
347
  Causes malloc to use the builtin ffs() function to compute indices.
348
  Some compilers may recognize and intrinsify ffs to be faster than the
348
  Some compilers may recognize and intrinsify ffs to be faster than the
349
  supplied C version. Also, the case of x86 using gcc is special-cased
349
  supplied C version. Also, the case of x86 using gcc is special-cased
350
  to an asm instruction, so is already as fast as it can be, and so
350
  to an asm instruction, so is already as fast as it can be, and so
351
  this setting has no effect. (On most x86s, the asm version is only
351
  this setting has no effect. (On most x86s, the asm version is only
352
  slightly faster than the C version.)
352
  slightly faster than the C version.)
353
 
353
 
354
malloc_getpagesize         default: derive from system includes, or 4096.
354
malloc_getpagesize         default: derive from system includes, or 4096.
355
  The system page size. To the extent possible, this malloc manages
355
  The system page size. To the extent possible, this malloc manages
356
  memory from the system in page-size units.  This may be (and
356
  memory from the system in page-size units.  This may be (and
357
  usually is) a function rather than a constant. This is ignored
357
  usually is) a function rather than a constant. This is ignored
358
  if WIN32, where page size is determined using getSystemInfo during
358
  if WIN32, where page size is determined using getSystemInfo during
359
  initialization.
359
  initialization.
360
 
360
 
361
USE_DEV_RANDOM             default: 0 (i.e., not used)
361
USE_DEV_RANDOM             default: 0 (i.e., not used)
362
  Causes malloc to use /dev/random to initialize secure magic seed for
362
  Causes malloc to use /dev/random to initialize secure magic seed for
363
  stamping footers. Otherwise, the current time is used.
363
  stamping footers. Otherwise, the current time is used.
364
 
364
 
365
NO_MALLINFO                default: 0
365
NO_MALLINFO                default: 0
366
  If defined, don't compile "mallinfo". This can be a simple way
366
  If defined, don't compile "mallinfo". This can be a simple way
367
  of dealing with mismatches between system declarations and
367
  of dealing with mismatches between system declarations and
368
  those in this file.
368
  those in this file.
369
 
369
 
370
MALLINFO_FIELD_TYPE        default: size_t
370
MALLINFO_FIELD_TYPE        default: size_t
371
  The type of the fields in the mallinfo struct. This was originally
371
  The type of the fields in the mallinfo struct. This was originally
372
  defined as "int" in SVID etc, but is more usefully defined as
372
  defined as "int" in SVID etc, but is more usefully defined as
373
  size_t. The value is used only if  HAVE_USR_INCLUDE_MALLOC_H is not set
373
  size_t. The value is used only if  HAVE_USR_INCLUDE_MALLOC_H is not set
374
 
374
 
375
REALLOC_ZERO_BYTES_FREES    default: not defined
375
REALLOC_ZERO_BYTES_FREES    default: not defined
376
  This should be set if a call to realloc with zero bytes should 
376
  This should be set if a call to realloc with zero bytes should 
377
  be the same as a call to free. Some people think it should. Otherwise, 
377
  be the same as a call to free. Some people think it should. Otherwise, 
378
  since this malloc returns a unique pointer for malloc(0), so does 
378
  since this malloc returns a unique pointer for malloc(0), so does 
379
  realloc(p, 0).
379
  realloc(p, 0).
380
 
380
 
381
LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H
381
LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H
382
LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H,  LACKS_ERRNO_H
382
LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H,  LACKS_ERRNO_H
383
LACKS_STDLIB_H                default: NOT defined unless on WIN32
383
LACKS_STDLIB_H                default: NOT defined unless on WIN32
384
  Define these if your system does not have these header files.
384
  Define these if your system does not have these header files.
385
  You might need to manually insert some of the declarations they provide.
385
  You might need to manually insert some of the declarations they provide.
386
 
386
 
387
DEFAULT_GRANULARITY        default: page size if MORECORE_CONTIGUOUS,
387
DEFAULT_GRANULARITY        default: page size if MORECORE_CONTIGUOUS,
388
                                system_info.dwAllocationGranularity in WIN32,
388
                                system_info.dwAllocationGranularity in WIN32,
389
                                otherwise 64K.
389
                                otherwise 64K.
390
      Also settable using mallopt(M_GRANULARITY, x)
390
      Also settable using mallopt(M_GRANULARITY, x)
391
  The unit for allocating and deallocating memory from the system.  On
391
  The unit for allocating and deallocating memory from the system.  On
392
  most systems with contiguous MORECORE, there is no reason to
392
  most systems with contiguous MORECORE, there is no reason to
393
  make this more than a page. However, systems with MMAP tend to
393
  make this more than a page. However, systems with MMAP tend to
394
  either require or encourage larger granularities.  You can increase
394
  either require or encourage larger granularities.  You can increase
395
  this value to prevent system allocation functions to be called so
395
  this value to prevent system allocation functions to be called so
396
  often, especially if they are slow.  The value must be at least one
396
  often, especially if they are slow.  The value must be at least one
397
  page and must be a power of two.  Setting to 0 causes initialization
397
  page and must be a power of two.  Setting to 0 causes initialization
398
  to either page size or win32 region size.  (Note: In previous
398
  to either page size or win32 region size.  (Note: In previous
399
  versions of malloc, the equivalent of this option was called
399
  versions of malloc, the equivalent of this option was called
400
  "TOP_PAD")
400
  "TOP_PAD")
401
 
401
 
402
DEFAULT_TRIM_THRESHOLD    default: 2MB
402
DEFAULT_TRIM_THRESHOLD    default: 2MB
403
      Also settable using mallopt(M_TRIM_THRESHOLD, x)
403
      Also settable using mallopt(M_TRIM_THRESHOLD, x)
404
  The maximum amount of unused top-most memory to keep before
404
  The maximum amount of unused top-most memory to keep before
405
  releasing via malloc_trim in free().  Automatic trimming is mainly
405
  releasing via malloc_trim in free().  Automatic trimming is mainly
406
  useful in long-lived programs using contiguous MORECORE.  Because
406
  useful in long-lived programs using contiguous MORECORE.  Because
407
  trimming via sbrk can be slow on some systems, and can sometimes be
407
  trimming via sbrk can be slow on some systems, and can sometimes be
408
  wasteful (in cases where programs immediately afterward allocate
408
  wasteful (in cases where programs immediately afterward allocate
409
  more large chunks) the value should be high enough so that your
409
  more large chunks) the value should be high enough so that your
410
  overall system performance would improve by releasing this much
410
  overall system performance would improve by releasing this much
411
  memory.  As a rough guide, you might set to a value close to the
411
  memory.  As a rough guide, you might set to a value close to the
412
  average size of a process (program) running on your system.
412
  average size of a process (program) running on your system.
413
  Releasing this much memory would allow such a process to run in
413
  Releasing this much memory would allow such a process to run in
414
  memory.  Generally, it is worth tuning trim thresholds when a
414
  memory.  Generally, it is worth tuning trim thresholds when a
415
  program undergoes phases where several large chunks are allocated
415
  program undergoes phases where several large chunks are allocated
416
  and released in ways that can reuse each other's storage, perhaps
416
  and released in ways that can reuse each other's storage, perhaps
417
  mixed with phases where there are no such chunks at all. The trim
417
  mixed with phases where there are no such chunks at all. The trim
418
  value must be greater than page size to have any useful effect.  To
418
  value must be greater than page size to have any useful effect.  To
419
  disable trimming completely, you can set to MAX_SIZE_T. Note that the trick
419
  disable trimming completely, you can set to MAX_SIZE_T. Note that the trick
420
  some people use of mallocing a huge space and then freeing it at
420
  some people use of mallocing a huge space and then freeing it at
421
  program startup, in an attempt to reserve system memory, doesn't
421
  program startup, in an attempt to reserve system memory, doesn't
422
  have the intended effect under automatic trimming, since that memory
422
  have the intended effect under automatic trimming, since that memory
423
  will immediately be returned to the system.
423
  will immediately be returned to the system.
424
 
424
 
425
DEFAULT_MMAP_THRESHOLD       default: 256K
425
DEFAULT_MMAP_THRESHOLD       default: 256K
426
      Also settable using mallopt(M_MMAP_THRESHOLD, x)
426
      Also settable using mallopt(M_MMAP_THRESHOLD, x)
427
  The request size threshold for using MMAP to directly service a
427
  The request size threshold for using MMAP to directly service a
428
  request. Requests of at least this size that cannot be allocated
428
  request. Requests of at least this size that cannot be allocated
429
  using already-existing space will be serviced via mmap.  (If enough
429
  using already-existing space will be serviced via mmap.  (If enough
430
  normal freed space already exists it is used instead.)  Using mmap
430
  normal freed space already exists it is used instead.)  Using mmap
431
  segregates relatively large chunks of memory so that they can be
431
  segregates relatively large chunks of memory so that they can be
432
  individually obtained and released from the host system. A request
432
  individually obtained and released from the host system. A request
433
  serviced through mmap is never reused by any other request (at least
433
  serviced through mmap is never reused by any other request (at least
434
  not directly; the system may just so happen to remap successive
434
  not directly; the system may just so happen to remap successive
435
  requests to the same locations).  Segregating space in this way has
435
  requests to the same locations).  Segregating space in this way has
436
  the benefits that: Mmapped space can always be individually released
436
  the benefits that: Mmapped space can always be individually released
437
  back to the system, which helps keep the system level memory demands
437
  back to the system, which helps keep the system level memory demands
438
  of a long-lived program low.  Also, mapped memory doesn't become
438
  of a long-lived program low.  Also, mapped memory doesn't become
439
  `locked' between other chunks, as can happen with normally allocated
439
  `locked' between other chunks, as can happen with normally allocated
440
  chunks, which means that even trimming via malloc_trim would not
440
  chunks, which means that even trimming via malloc_trim would not
441
  release them.  However, it has the disadvantage that the space
441
  release them.  However, it has the disadvantage that the space
442
  cannot be reclaimed, consolidated, and then used to service later
442
  cannot be reclaimed, consolidated, and then used to service later
443
  requests, as happens with normal chunks.  The advantages of mmap
443
  requests, as happens with normal chunks.  The advantages of mmap
444
  nearly always outweigh disadvantages for "large" chunks, but the
444
  nearly always outweigh disadvantages for "large" chunks, but the
445
  value of "large" may vary across systems.  The default is an
445
  value of "large" may vary across systems.  The default is an
446
  empirically derived value that works well in most systems. You can
446
  empirically derived value that works well in most systems. You can
447
  disable mmap by setting to MAX_SIZE_T.
447
  disable mmap by setting to MAX_SIZE_T.
448
 
448
 
449
*/
449
*/
450
 
450
 
451
#ifndef WIN32
451
#ifndef WIN32
452
#ifdef _WIN32
452
#ifdef _WIN32
453
#define WIN32 1
453
#define WIN32 1
454
#endif  /* _WIN32 */
454
#endif  /* _WIN32 */
455
#endif  /* WIN32 */
455
#endif  /* WIN32 */
456
#ifdef WIN32
456
#ifdef WIN32
457
#define WIN32_LEAN_AND_MEAN
457
#define WIN32_LEAN_AND_MEAN
458
#include <windows.h>
458
#include <windows.h>
459
#define HAVE_MMAP 1
459
#define HAVE_MMAP 1
460
#define HAVE_MORECORE 0
460
#define HAVE_MORECORE 0
461
/* #define LACKS_UNISTD_H */
461
/* #define LACKS_UNISTD_H */
462
#define LACKS_SYS_PARAM_H
462
#define LACKS_SYS_PARAM_H
463
#define LACKS_SYS_MMAN_H
463
#define LACKS_SYS_MMAN_H
464
#define LACKS_STRING_H
464
#define LACKS_STRING_H
465
#define LACKS_STRINGS_H
465
#define LACKS_STRINGS_H
466
#define LACKS_SYS_TYPES_H
466
#define LACKS_SYS_TYPES_H
467
#define LACKS_ERRNO_H
467
#define LACKS_ERRNO_H
468
#define MALLOC_FAILURE_ACTION
468
#define MALLOC_FAILURE_ACTION
469
#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */
469
#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */
470
#endif  /* WIN32 */
470
#endif  /* WIN32 */
471
 
471
 
472
#if defined(DARWIN) || defined(_DARWIN)
472
#if defined(DARWIN) || defined(_DARWIN)
473
/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
473
/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
474
#ifndef HAVE_MORECORE
474
#ifndef HAVE_MORECORE
475
#define HAVE_MORECORE 0
475
#define HAVE_MORECORE 0
476
#define HAVE_MMAP 1
476
#define HAVE_MMAP 1
477
#endif  /* HAVE_MORECORE */
477
#endif  /* HAVE_MORECORE */
478
#endif  /* DARWIN */
478
#endif  /* DARWIN */
479
 
479
 
480
#ifndef LACKS_SYS_TYPES_H
480
#ifndef LACKS_SYS_TYPES_H
481
#include <sys/types.h>  /* For size_t */
481
#include <sys/types.h>  /* For size_t */
482
#endif  /* LACKS_SYS_TYPES_H */
482
#endif  /* LACKS_SYS_TYPES_H */
483
 
483
 
484
/* The maximum possible size_t value has all bits set */
484
/* The maximum possible size_t value has all bits set */
485
#define MAX_SIZE_T           (~(size_t)0)
485
#define MAX_SIZE_T           (~(size_t)0)
486
 
486
 
487
#ifndef ONLY_MSPACES
487
#ifndef ONLY_MSPACES
488
#define ONLY_MSPACES 0
488
#define ONLY_MSPACES 0
489
#endif  /* ONLY_MSPACES */
489
#endif  /* ONLY_MSPACES */
490
#ifndef MSPACES
490
#ifndef MSPACES
491
#if ONLY_MSPACES
491
#if ONLY_MSPACES
492
#define MSPACES 1
492
#define MSPACES 1
493
#else   /* ONLY_MSPACES */
493
#else   /* ONLY_MSPACES */
494
#define MSPACES 0
494
#define MSPACES 0
495
#endif  /* ONLY_MSPACES */
495
#endif  /* ONLY_MSPACES */
496
#endif  /* MSPACES */
496
#endif  /* MSPACES */
497
#ifndef MALLOC_ALIGNMENT
497
#ifndef MALLOC_ALIGNMENT
498
#define MALLOC_ALIGNMENT ((size_t)8U)
498
#define MALLOC_ALIGNMENT ((size_t)8U)
499
#endif  /* MALLOC_ALIGNMENT */
499
#endif  /* MALLOC_ALIGNMENT */
500
#ifndef FOOTERS
500
#ifndef FOOTERS
501
#define FOOTERS 0
501
#define FOOTERS 0
502
#endif  /* FOOTERS */
502
#endif  /* FOOTERS */
503
#ifndef ABORT
503
#ifndef ABORT
504
#define ABORT  abort()
504
#define ABORT  abort()
505
#endif  /* ABORT */
505
#endif  /* ABORT */
506
#ifndef ABORT_ON_ASSERT_FAILURE
506
#ifndef ABORT_ON_ASSERT_FAILURE
507
#define ABORT_ON_ASSERT_FAILURE 1
507
#define ABORT_ON_ASSERT_FAILURE 1
508
#endif  /* ABORT_ON_ASSERT_FAILURE */
508
#endif  /* ABORT_ON_ASSERT_FAILURE */
509
#ifndef PROCEED_ON_ERROR
509
#ifndef PROCEED_ON_ERROR
510
#define PROCEED_ON_ERROR 0
510
#define PROCEED_ON_ERROR 0
511
#endif  /* PROCEED_ON_ERROR */
511
#endif  /* PROCEED_ON_ERROR */
512
#ifndef USE_LOCKS
512
#ifndef USE_LOCKS
513
#define USE_LOCKS 0
513
#define USE_LOCKS 0
514
#endif  /* USE_LOCKS */
514
#endif  /* USE_LOCKS */
515
#ifndef INSECURE
515
#ifndef INSECURE
516
#define INSECURE 0
516
#define INSECURE 0
517
#endif  /* INSECURE */
517
#endif  /* INSECURE */
518
#ifndef HAVE_MMAP
518
#ifndef HAVE_MMAP
519
#define HAVE_MMAP 1
519
#define HAVE_MMAP 1
520
#endif  /* HAVE_MMAP */
520
#endif  /* HAVE_MMAP */
521
#ifndef MMAP_CLEARS
521
#ifndef MMAP_CLEARS
522
#define MMAP_CLEARS 1
522
#define MMAP_CLEARS 1
523
#endif  /* MMAP_CLEARS */
523
#endif  /* MMAP_CLEARS */
524
#ifndef HAVE_MREMAP
524
#ifndef HAVE_MREMAP
525
#ifdef linux
525
#ifdef linux
526
#define HAVE_MREMAP 1
526
#define HAVE_MREMAP 1
527
#else   /* linux */
527
#else   /* linux */
528
#define HAVE_MREMAP 0
528
#define HAVE_MREMAP 0
529
#endif  /* linux */
529
#endif  /* linux */
530
#endif  /* HAVE_MREMAP */
530
#endif  /* HAVE_MREMAP */
531
#ifndef MALLOC_FAILURE_ACTION
531
#ifndef MALLOC_FAILURE_ACTION
532
#define MALLOC_FAILURE_ACTION  errno = ENOMEM;
532
#define MALLOC_FAILURE_ACTION  errno = ENOMEM;
533
#endif  /* MALLOC_FAILURE_ACTION */
533
#endif  /* MALLOC_FAILURE_ACTION */
534
#ifndef HAVE_MORECORE
534
#ifndef HAVE_MORECORE
535
#if ONLY_MSPACES
535
#if ONLY_MSPACES
536
#define HAVE_MORECORE 0
536
#define HAVE_MORECORE 0
537
#else   /* ONLY_MSPACES */
537
#else   /* ONLY_MSPACES */
538
#define HAVE_MORECORE 1
538
#define HAVE_MORECORE 1
539
#endif  /* ONLY_MSPACES */
539
#endif  /* ONLY_MSPACES */
540
#endif  /* HAVE_MORECORE */
540
#endif  /* HAVE_MORECORE */
541
#if !HAVE_MORECORE
541
#if !HAVE_MORECORE
542
#define MORECORE_CONTIGUOUS 0
542
#define MORECORE_CONTIGUOUS 0
543
#else   /* !HAVE_MORECORE */
543
#else   /* !HAVE_MORECORE */
544
#ifndef MORECORE
544
#ifndef MORECORE
545
#define MORECORE sbrk
545
#define MORECORE sbrk
546
#endif  /* MORECORE */
546
#endif  /* MORECORE */
547
#ifndef MORECORE_CONTIGUOUS
547
#ifndef MORECORE_CONTIGUOUS
548
#define MORECORE_CONTIGUOUS 1
548
#define MORECORE_CONTIGUOUS 1
549
#endif  /* MORECORE_CONTIGUOUS */
549
#endif  /* MORECORE_CONTIGUOUS */
550
#endif  /* HAVE_MORECORE */
550
#endif  /* HAVE_MORECORE */
551
#ifndef DEFAULT_GRANULARITY
551
#ifndef DEFAULT_GRANULARITY
552
#if MORECORE_CONTIGUOUS
552
#if MORECORE_CONTIGUOUS
553
#define DEFAULT_GRANULARITY (0)  /* 0 means to compute in init_mparams */
553
#define DEFAULT_GRANULARITY (0)  /* 0 means to compute in init_mparams */
554
#else   /* MORECORE_CONTIGUOUS */
554
#else   /* MORECORE_CONTIGUOUS */
555
#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
555
#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
556
#endif  /* MORECORE_CONTIGUOUS */
556
#endif  /* MORECORE_CONTIGUOUS */
557
#endif  /* DEFAULT_GRANULARITY */
557
#endif  /* DEFAULT_GRANULARITY */
558
#ifndef DEFAULT_TRIM_THRESHOLD
558
#ifndef DEFAULT_TRIM_THRESHOLD
559
#ifndef MORECORE_CANNOT_TRIM
559
#ifndef MORECORE_CANNOT_TRIM
560
#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
560
#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
561
#else   /* MORECORE_CANNOT_TRIM */
561
#else   /* MORECORE_CANNOT_TRIM */
562
#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
562
#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
563
#endif  /* MORECORE_CANNOT_TRIM */
563
#endif  /* MORECORE_CANNOT_TRIM */
564
#endif  /* DEFAULT_TRIM_THRESHOLD */
564
#endif  /* DEFAULT_TRIM_THRESHOLD */
565
#ifndef DEFAULT_MMAP_THRESHOLD
565
#ifndef DEFAULT_MMAP_THRESHOLD
566
#if HAVE_MMAP
566
#if HAVE_MMAP
567
#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
567
#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
568
#else   /* HAVE_MMAP */
568
#else   /* HAVE_MMAP */
569
#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
569
#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
570
#endif  /* HAVE_MMAP */
570
#endif  /* HAVE_MMAP */
571
#endif  /* DEFAULT_MMAP_THRESHOLD */
571
#endif  /* DEFAULT_MMAP_THRESHOLD */
572
#ifndef USE_BUILTIN_FFS
572
#ifndef USE_BUILTIN_FFS
573
#define USE_BUILTIN_FFS 0
573
#define USE_BUILTIN_FFS 0
574
#endif  /* USE_BUILTIN_FFS */
574
#endif  /* USE_BUILTIN_FFS */
575
#ifndef USE_DEV_RANDOM
575
#ifndef USE_DEV_RANDOM
576
#define USE_DEV_RANDOM 0
576
#define USE_DEV_RANDOM 0
577
#endif  /* USE_DEV_RANDOM */
577
#endif  /* USE_DEV_RANDOM */
578
#ifndef NO_MALLINFO
578
#ifndef NO_MALLINFO
579
#define NO_MALLINFO 0
579
#define NO_MALLINFO 0
580
#endif  /* NO_MALLINFO */
580
#endif  /* NO_MALLINFO */
581
#ifndef MALLINFO_FIELD_TYPE
581
#ifndef MALLINFO_FIELD_TYPE
582
#define MALLINFO_FIELD_TYPE size_t
582
#define MALLINFO_FIELD_TYPE size_t
583
#endif  /* MALLINFO_FIELD_TYPE */
583
#endif  /* MALLINFO_FIELD_TYPE */
584
 
584
 
585
/*
585
/*
586
  mallopt tuning options.  SVID/XPG defines four standard parameter
586
  mallopt tuning options.  SVID/XPG defines four standard parameter
587
  numbers for mallopt, normally defined in malloc.h.  None of these
587
  numbers for mallopt, normally defined in malloc.h.  None of these
588
  are used in this malloc, so setting them has no effect. But this
588
  are used in this malloc, so setting them has no effect. But this
589
  malloc does support the following options.
589
  malloc does support the following options.
590
*/
590
*/
591
 
591
 
592
#define M_TRIM_THRESHOLD     (-1)
592
#define M_TRIM_THRESHOLD     (-1)
593
#define M_GRANULARITY        (-2)
593
#define M_GRANULARITY        (-2)
594
#define M_MMAP_THRESHOLD     (-3)
594
#define M_MMAP_THRESHOLD     (-3)
595
 
595
 
596
/* ------------------------ Mallinfo declarations ------------------------ */
596
/* ------------------------ Mallinfo declarations ------------------------ */
597
 
597
 
598
#if !NO_MALLINFO
598
#if !NO_MALLINFO
599
/*
599
/*
600
  This version of malloc supports the standard SVID/XPG mallinfo
600
  This version of malloc supports the standard SVID/XPG mallinfo
601
  routine that returns a struct containing usage properties and
601
  routine that returns a struct containing usage properties and
602
  statistics. It should work on any system that has a
602
  statistics. It should work on any system that has a
603
  /usr/include/malloc.h defining struct mallinfo.  The main
603
  /usr/include/malloc.h defining struct mallinfo.  The main
604
  declaration needed is the mallinfo struct that is returned (by-copy)
604
  declaration needed is the mallinfo struct that is returned (by-copy)
605
  by mallinfo().  The malloinfo struct contains a bunch of fields that
605
  by mallinfo().  The malloinfo struct contains a bunch of fields that
606
  are not even meaningful in this version of malloc.  These fields are
606
  are not even meaningful in this version of malloc.  These fields are
607
  are instead filled by mallinfo() with other numbers that might be of
607
  are instead filled by mallinfo() with other numbers that might be of
608
  interest.
608
  interest.
609
 
609
 
610
  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
610
  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
611
  /usr/include/malloc.h file that includes a declaration of struct
611
  /usr/include/malloc.h file that includes a declaration of struct
612
  mallinfo.  If so, it is included; else a compliant version is
612
  mallinfo.  If so, it is included; else a compliant version is
613
  declared below.  These must be precisely the same for mallinfo() to
613
  declared below.  These must be precisely the same for mallinfo() to
614
  work.  The original SVID version of this struct, defined on most
614
  work.  The original SVID version of this struct, defined on most
615
  systems with mallinfo, declares all fields as ints. But some others
615
  systems with mallinfo, declares all fields as ints. But some others
616
  define as unsigned long. If your system defines the fields using a
616
  define as unsigned long. If your system defines the fields using a
617
  type of different width than listed here, you MUST #include your
617
  type of different width than listed here, you MUST #include your
618
  system version and #define HAVE_USR_INCLUDE_MALLOC_H.
618
  system version and #define HAVE_USR_INCLUDE_MALLOC_H.
619
*/
619
*/
620
 
620
 
621
/* #define HAVE_USR_INCLUDE_MALLOC_H */
621
/* #define HAVE_USR_INCLUDE_MALLOC_H */
622
 
622
 
623
#ifdef HAVE_USR_INCLUDE_MALLOC_H
623
#ifdef HAVE_USR_INCLUDE_MALLOC_H
624
#include "/usr/include/malloc.h"
624
#include "/usr/include/malloc.h"
625
#else /* HAVE_USR_INCLUDE_MALLOC_H */
625
#else /* HAVE_USR_INCLUDE_MALLOC_H */
626
 
626
 
627
struct mallinfo {
627
struct mallinfo {
628
  MALLINFO_FIELD_TYPE arena;    /* non-mmapped space allocated from system */
628
  MALLINFO_FIELD_TYPE arena;    /* non-mmapped space allocated from system */
629
  MALLINFO_FIELD_TYPE ordblks;  /* number of free chunks */
629
  MALLINFO_FIELD_TYPE ordblks;  /* number of free chunks */
630
  MALLINFO_FIELD_TYPE smblks;   /* always 0 */
630
  MALLINFO_FIELD_TYPE smblks;   /* always 0 */
631
  MALLINFO_FIELD_TYPE hblks;    /* always 0 */
631
  MALLINFO_FIELD_TYPE hblks;    /* always 0 */
632
  MALLINFO_FIELD_TYPE hblkhd;   /* space in mmapped regions */
632
  MALLINFO_FIELD_TYPE hblkhd;   /* space in mmapped regions */
633
  MALLINFO_FIELD_TYPE usmblks;  /* maximum total allocated space */
633
  MALLINFO_FIELD_TYPE usmblks;  /* maximum total allocated space */
634
  MALLINFO_FIELD_TYPE fsmblks;  /* always 0 */
634
  MALLINFO_FIELD_TYPE fsmblks;  /* always 0 */
635
  MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
635
  MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
636
  MALLINFO_FIELD_TYPE fordblks; /* total free space */
636
  MALLINFO_FIELD_TYPE fordblks; /* total free space */
637
  MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
637
  MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
638
};
638
};
639
 
639
 
640
#endif /* HAVE_USR_INCLUDE_MALLOC_H */
640
#endif /* HAVE_USR_INCLUDE_MALLOC_H */
641
#endif /* NO_MALLINFO */
641
#endif /* NO_MALLINFO */
642
 
642
 
643
#ifdef __cplusplus
643
#ifdef __cplusplus
644
extern "C" {
644
extern "C" {
645
#endif /* __cplusplus */
645
#endif /* __cplusplus */
646
 
646
 
647
/* R Specific declarations here */
647
/* R Specific declarations here */
648
 
648
 
649
    extern unsigned int R_max_memory;
649
extern size_t R_max_memory;
650
extern int R_Is_Running;
650
extern int R_Is_Running;
651
static size_t R_used = 0;
651
static size_t R_used = 0;
652
void Rf_warning(const char *, ...);
652
void Rf_warning(const char *, ...);
653
 
653
 
654
#if !ONLY_MSPACES
654
#if !ONLY_MSPACES
655
 
655
 
656
/* ------------------- Declarations of public routines ------------------- */
656
/* ------------------- Declarations of public routines ------------------- */
657
 
657
 
658
#ifndef USE_DL_PREFIX
658
#ifndef USE_DL_PREFIX
659
#define dlcalloc               Rm_calloc
659
#define dlcalloc               Rm_calloc
660
#define dlfree                 Rm_free
660
#define dlfree                 Rm_free
661
#define dlmalloc               Rm_malloc
661
#define dlmalloc               Rm_malloc
662
#define dlmemalign             memalign
662
#define dlmemalign             memalign
663
#define dlrealloc              Rm_realloc
663
#define dlrealloc              Rm_realloc
664
#define dlvalloc               valloc
664
#define dlvalloc               valloc
665
#define dlpvalloc              pvalloc
665
#define dlpvalloc              pvalloc
666
#define dlmallinfo             mallinfo
666
#define dlmallinfo             mallinfo
667
#define dlmallopt              mallopt
667
#define dlmallopt              mallopt
668
#define dlmalloc_trim          malloc_trim
668
#define dlmalloc_trim          malloc_trim
669
#define dlmalloc_stats         malloc_stats
669
#define dlmalloc_stats         malloc_stats
670
#define dlmalloc_usable_size   malloc_usable_size
670
#define dlmalloc_usable_size   malloc_usable_size
671
#define dlmalloc_footprint     malloc_footprint
671
#define dlmalloc_footprint     malloc_footprint
672
#define dlmalloc_max_footprint malloc_max_footprint
672
#define dlmalloc_max_footprint malloc_max_footprint
673
#define dlindependent_calloc   independent_calloc
673
#define dlindependent_calloc   independent_calloc
674
#define dlindependent_comalloc independent_comalloc
674
#define dlindependent_comalloc independent_comalloc
675
#endif /* USE_DL_PREFIX */
675
#endif /* USE_DL_PREFIX */
676
 
676
 
677
/*
677
/*
678
  malloc(size_t n)
678
  malloc(size_t n)
679
  Returns a pointer to a newly allocated chunk of at least n bytes, or
679
  Returns a pointer to a newly allocated chunk of at least n bytes, or
680
  null if no space is available, in which case errno is set to ENOMEM
680
  null if no space is available, in which case errno is set to ENOMEM
681
  on ANSI C systems.
681
  on ANSI C systems.
682
 
682
 
683
  If n is zero, malloc returns a minimum-sized chunk. (The minimum
683
  If n is zero, malloc returns a minimum-sized chunk. (The minimum
684
  size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
684
  size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
685
  systems.)  Note that size_t is an unsigned type, so calls with
685
  systems.)  Note that size_t is an unsigned type, so calls with
686
  arguments that would be negative if signed are interpreted as
686
  arguments that would be negative if signed are interpreted as
687
  requests for huge amounts of space, which will often fail. The
687
  requests for huge amounts of space, which will often fail. The
688
  maximum supported value of n differs across systems, but is in all
688
  maximum supported value of n differs across systems, but is in all
689
  cases less than the maximum representable value of a size_t.
689
  cases less than the maximum representable value of a size_t.
690
*/
690
*/
691
void* dlmalloc(size_t);
691
void* dlmalloc(size_t);
692
 
692
 
693
/*
693
/*
694
  free(void* p)
694
  free(void* p)
695
  Releases the chunk of memory pointed to by p, that had been previously
695
  Releases the chunk of memory pointed to by p, that had been previously
696
  allocated using malloc or a related routine such as realloc.
696
  allocated using malloc or a related routine such as realloc.
697
  It has no effect if p is null. If p was not malloced or already
697
  It has no effect if p is null. If p was not malloced or already
698
  freed, free(p) will by default cause the current program to abort.
698
  freed, free(p) will by default cause the current program to abort.
699
*/
699
*/
700
void  dlfree(void*);
700
void  dlfree(void*);
701
 
701
 
702
/*
702
/*
703
  calloc(size_t n_elements, size_t element_size);
703
  calloc(size_t n_elements, size_t element_size);
704
  Returns a pointer to n_elements * element_size bytes, with all locations
704
  Returns a pointer to n_elements * element_size bytes, with all locations
705
  set to zero.
705
  set to zero.
706
*/
706
*/
707
void* dlcalloc(size_t, size_t);
707
void* dlcalloc(size_t, size_t);
708
 
708
 
709
/*
709
/*
710
  realloc(void* p, size_t n)
710
  realloc(void* p, size_t n)
711
  Returns a pointer to a chunk of size n that contains the same data
711
  Returns a pointer to a chunk of size n that contains the same data
712
  as does chunk p up to the minimum of (n, p's size) bytes, or null
712
  as does chunk p up to the minimum of (n, p's size) bytes, or null
713
  if no space is available.
713
  if no space is available.
714
 
714
 
715
  The returned pointer may or may not be the same as p. The algorithm
715
  The returned pointer may or may not be the same as p. The algorithm
716
  prefers extending p in most cases when possible, otherwise it
716
  prefers extending p in most cases when possible, otherwise it
717
  employs the equivalent of a malloc-copy-free sequence.
717
  employs the equivalent of a malloc-copy-free sequence.
718
 
718
 
719
  If p is null, realloc is equivalent to malloc.
719
  If p is null, realloc is equivalent to malloc.
720
 
720
 
721
  If space is not available, realloc returns null, errno is set (if on
721
  If space is not available, realloc returns null, errno is set (if on
722
  ANSI) and p is NOT freed.
722
  ANSI) and p is NOT freed.
723
 
723
 
724
  if n is for fewer bytes than already held by p, the newly unused
724
  if n is for fewer bytes than already held by p, the newly unused
725
  space is lopped off and freed if possible.  realloc with a size
725
  space is lopped off and freed if possible.  realloc with a size
726
  argument of zero (re)allocates a minimum-sized chunk.
726
  argument of zero (re)allocates a minimum-sized chunk.
727
 
727
 
728
  The old unix realloc convention of allowing the last-free'd chunk
728
  The old unix realloc convention of allowing the last-free'd chunk
729
  to be used as an argument to realloc is not supported.
729
  to be used as an argument to realloc is not supported.
730
*/
730
*/
731
 
731
 
732
void* dlrealloc(void*, size_t);
732
void* dlrealloc(void*, size_t);
733
 
733
 
734
/*
734
/*
735
  memalign(size_t alignment, size_t n);
735
  memalign(size_t alignment, size_t n);
736
  Returns a pointer to a newly allocated chunk of n bytes, aligned
736
  Returns a pointer to a newly allocated chunk of n bytes, aligned
737
  in accord with the alignment argument.
737
  in accord with the alignment argument.
738
 
738
 
739
  The alignment argument should be a power of two. If the argument is
739
  The alignment argument should be a power of two. If the argument is
740
  not a power of two, the nearest greater power is used.
740
  not a power of two, the nearest greater power is used.
741
  8-byte alignment is guaranteed by normal malloc calls, so don't
741
  8-byte alignment is guaranteed by normal malloc calls, so don't
742
  bother calling memalign with an argument of 8 or less.
742
  bother calling memalign with an argument of 8 or less.
743
 
743
 
744
  Overreliance on memalign is a sure way to fragment space.
744
  Overreliance on memalign is a sure way to fragment space.
745
*/
745
*/
746
void* dlmemalign(size_t, size_t);
746
void* dlmemalign(size_t, size_t);
747
 
747
 
748
/*
748
/*
749
  valloc(size_t n);
749
  valloc(size_t n);
750
  Equivalent to memalign(pagesize, n), where pagesize is the page
750
  Equivalent to memalign(pagesize, n), where pagesize is the page
751
  size of the system. If the pagesize is unknown, 4096 is used.
751
  size of the system. If the pagesize is unknown, 4096 is used.
752
*/
752
*/
753
void* dlvalloc(size_t);
753
void* dlvalloc(size_t);
754
 
754
 
755
/*
755
/*
756
  mallopt(int parameter_number, int parameter_value)
756
  mallopt(int parameter_number, int parameter_value)
757
  Sets tunable parameters The format is to provide a
757
  Sets tunable parameters The format is to provide a
758
  (parameter-number, parameter-value) pair.  mallopt then sets the
758
  (parameter-number, parameter-value) pair.  mallopt then sets the
759
  corresponding parameter to the argument value if it can (i.e., so
759
  corresponding parameter to the argument value if it can (i.e., so
760
  long as the value is meaningful), and returns 1 if successful else
760
  long as the value is meaningful), and returns 1 if successful else
761
  0.  SVID/XPG/ANSI defines four standard param numbers for mallopt,
761
  0.  SVID/XPG/ANSI defines four standard param numbers for mallopt,
762
  normally defined in malloc.h.  None of these are use in this malloc,
762
  normally defined in malloc.h.  None of these are use in this malloc,
763
  so setting them has no effect. But this malloc also supports other
763
  so setting them has no effect. But this malloc also supports other
764
  options in mallopt. See below for details.  Briefly, supported
764
  options in mallopt. See below for details.  Briefly, supported
765
  parameters are as follows (listed defaults are for "typical"
765
  parameters are as follows (listed defaults are for "typical"
766
  configurations).
766
  configurations).
767
 
767
 
768
  Symbol            param #  default    allowed param values
768
  Symbol            param #  default    allowed param values
769
  M_TRIM_THRESHOLD     -1   2*1024*1024   any   (MAX_SIZE_T disables)
769
  M_TRIM_THRESHOLD     -1   2*1024*1024   any   (MAX_SIZE_T disables)
770
  M_GRANULARITY        -2     page size   any power of 2 >= page size
770
  M_GRANULARITY        -2     page size   any power of 2 >= page size
771
  M_MMAP_THRESHOLD     -3      256*1024   any   (or 0 if no MMAP support)
771
  M_MMAP_THRESHOLD     -3      256*1024   any   (or 0 if no MMAP support)
772
*/
772
*/
773
int dlmallopt(int, int);
773
int dlmallopt(int, int);
774
 
774
 
775
/*
775
/*
776
  malloc_footprint();
776
  malloc_footprint();
777
  Returns the number of bytes obtained from the system.  The total
777
  Returns the number of bytes obtained from the system.  The total
778
  number of bytes allocated by malloc, realloc etc., is less than this
778
  number of bytes allocated by malloc, realloc etc., is less than this
779
  value. Unlike mallinfo, this function returns only a precomputed
779
  value. Unlike mallinfo, this function returns only a precomputed
780
  result, so can be called frequently to monitor memory consumption.
780
  result, so can be called frequently to monitor memory consumption.
781
  Even if locks are otherwise defined, this function does not use them,
781
  Even if locks are otherwise defined, this function does not use them,
782
  so results might not be up to date.
782
  so results might not be up to date.
783
*/
783
*/
784
size_t dlmalloc_footprint(void);
784
size_t dlmalloc_footprint(void);
785
 
785
 
786
/*
786
/*
787
  malloc_max_footprint();
787
  malloc_max_footprint();
788
  Returns the maximum number of bytes obtained from the system. This
788
  Returns the maximum number of bytes obtained from the system. This
789
  value will be greater than current footprint if deallocated space
789
  value will be greater than current footprint if deallocated space
790
  has been reclaimed by the system. The peak number of bytes allocated
790
  has been reclaimed by the system. The peak number of bytes allocated
791
  by malloc, realloc etc., is less than this value. Unlike mallinfo,
791
  by malloc, realloc etc., is less than this value. Unlike mallinfo,
792
  this function returns only a precomputed result, so can be called
792
  this function returns only a precomputed result, so can be called
793
  frequently to monitor memory consumption.  Even if locks are
793
  frequently to monitor memory consumption.  Even if locks are
794
  otherwise defined, this function does not use them, so results might
794
  otherwise defined, this function does not use them, so results might
795
  not be up to date.
795
  not be up to date.
796
*/
796
*/
797
size_t dlmalloc_max_footprint(void);
797
size_t dlmalloc_max_footprint(void);
798
 
798
 
799
#if !NO_MALLINFO
799
#if !NO_MALLINFO
800
/*
800
/*
801
  mallinfo()
801
  mallinfo()
802
  Returns (by copy) a struct containing various summary statistics:
802
  Returns (by copy) a struct containing various summary statistics:
803
 
803
 
804
  arena:     current total non-mmapped bytes allocated from system
804
  arena:     current total non-mmapped bytes allocated from system
805
  ordblks:   the number of free chunks
805
  ordblks:   the number of free chunks
806
  smblks:    always zero.
806
  smblks:    always zero.
807
  hblks:     current number of mmapped regions
807
  hblks:     current number of mmapped regions
808
  hblkhd:    total bytes held in mmapped regions
808
  hblkhd:    total bytes held in mmapped regions
809
  usmblks:   the maximum total allocated space. This will be greater
809
  usmblks:   the maximum total allocated space. This will be greater
810
                than current total if trimming has occurred.
810
                than current total if trimming has occurred.
811
  fsmblks:   always zero
811
  fsmblks:   always zero
812
  uordblks:  current total allocated space (normal or mmapped)
812
  uordblks:  current total allocated space (normal or mmapped)
813
  fordblks:  total free space
813
  fordblks:  total free space
814
  keepcost:  the maximum number of bytes that could ideally be released
814
  keepcost:  the maximum number of bytes that could ideally be released
815
               back to system via malloc_trim. ("ideally" means that
815
               back to system via malloc_trim. ("ideally" means that
816
               it ignores page restrictions etc.)
816
               it ignores page restrictions etc.)
817
 
817
 
818
  Because these fields are ints, but internal bookkeeping may
818
  Because these fields are ints, but internal bookkeeping may
819
  be kept as longs, the reported values may wrap around zero and
819
  be kept as longs, the reported values may wrap around zero and
820
  thus be inaccurate.
820
  thus be inaccurate.
821
*/
821
*/
822
struct mallinfo dlmallinfo(void);
822
struct mallinfo dlmallinfo(void);
823
#endif /* NO_MALLINFO */
823
#endif /* NO_MALLINFO */
824
 
824
 
825
/*
825
/*
826
  independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
826
  independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
827
 
827
 
828
  independent_calloc is similar to calloc, but instead of returning a
828
  independent_calloc is similar to calloc, but instead of returning a
829
  single cleared space, it returns an array of pointers to n_elements
829
  single cleared space, it returns an array of pointers to n_elements
830
  independent elements that can hold contents of size elem_size, each
830
  independent elements that can hold contents of size elem_size, each
831
  of which starts out cleared, and can be independently freed,
831
  of which starts out cleared, and can be independently freed,
832
  realloc'ed etc. The elements are guaranteed to be adjacently
832
  realloc'ed etc. The elements are guaranteed to be adjacently
833
  allocated (this is not guaranteed to occur with multiple callocs or
833
  allocated (this is not guaranteed to occur with multiple callocs or
834
  mallocs), which may also improve cache locality in some
834
  mallocs), which may also improve cache locality in some
835
  applications.
835
  applications.
836
 
836
 
837
  The "chunks" argument is optional (i.e., may be null, which is
837
  The "chunks" argument is optional (i.e., may be null, which is
838
  probably the most typical usage). If it is null, the returned array
838
  probably the most typical usage). If it is null, the returned array
839
  is itself dynamically allocated and should also be freed when it is
839
  is itself dynamically allocated and should also be freed when it is
840
  no longer needed. Otherwise, the chunks array must be of at least
840
  no longer needed. Otherwise, the chunks array must be of at least
841
  n_elements in length. It is filled in with the pointers to the
841
  n_elements in length. It is filled in with the pointers to the
842
  chunks.
842
  chunks.
843
 
843
 
844
  In either case, independent_calloc returns this pointer array, or
844
  In either case, independent_calloc returns this pointer array, or
845
  null if the allocation failed.  If n_elements is zero and "chunks"
845
  null if the allocation failed.  If n_elements is zero and "chunks"
846
  is null, it returns a chunk representing an array with zero elements
846
  is null, it returns a chunk representing an array with zero elements
847
  (which should be freed if not wanted).
847
  (which should be freed if not wanted).
848
 
848
 
849
  Each element must be individually freed when it is no longer
849
  Each element must be individually freed when it is no longer
850
  needed. If you'd like to instead be able to free all at once, you
850
  needed. If you'd like to instead be able to free all at once, you
851
  should instead use regular calloc and assign pointers into this
851
  should instead use regular calloc and assign pointers into this
852
  space to represent elements.  (In this case though, you cannot
852
  space to represent elements.  (In this case though, you cannot
853
  independently free elements.)
853
  independently free elements.)
854
 
854
 
855
  independent_calloc simplifies and speeds up implementations of many
855
  independent_calloc simplifies and speeds up implementations of many
856
  kinds of pools.  It may also be useful when constructing large data
856
  kinds of pools.  It may also be useful when constructing large data
857
  structures that initially have a fixed number of fixed-sized nodes,
857
  structures that initially have a fixed number of fixed-sized nodes,
858
  but the number is not known at compile time, and some of the nodes
858
  but the number is not known at compile time, and some of the nodes
859
  may later need to be freed. For example:
859
  may later need to be freed. For example:
860
 
860
 
861
  struct Node { int item; struct Node* next; };
861
  struct Node { int item; struct Node* next; };
862
 
862
 
863
  struct Node* build_list() {
863
  struct Node* build_list() {
864
    struct Node** pool;
864
    struct Node** pool;
865
    int n = read_number_of_nodes_needed();
865
    int n = read_number_of_nodes_needed();
866
    if (n <= 0) return 0;
866
    if (n <= 0) return 0;
867
    pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
867
    pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
868
    if (pool == 0) die();
868
    if (pool == 0) die();
869
    // organize into a linked list...
869
    // organize into a linked list...
870
    struct Node* first = pool[0];
870
    struct Node* first = pool[0];
871
    for (i = 0; i < n-1; ++i)
871
    for (i = 0; i < n-1; ++i)
872
      pool[i]->next = pool[i+1];
872
      pool[i]->next = pool[i+1];
873
    free(pool);     // Can now free the array (or not, if it is needed later)
873
    free(pool);     // Can now free the array (or not, if it is needed later)
874
    return first;
874
    return first;
875
  }
875
  }
876
*/
876
*/
877
void** dlindependent_calloc(size_t, size_t, void**);
877
void** dlindependent_calloc(size_t, size_t, void**);
878
 
878
 
879
/*
879
/*
880
  independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
880
  independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
881
 
881
 
882
  independent_comalloc allocates, all at once, a set of n_elements
882
  independent_comalloc allocates, all at once, a set of n_elements
883
  chunks with sizes indicated in the "sizes" array.    It returns
883
  chunks with sizes indicated in the "sizes" array.    It returns
884
  an array of pointers to these elements, each of which can be
884
  an array of pointers to these elements, each of which can be
885
  independently freed, realloc'ed etc. The elements are guaranteed to
885
  independently freed, realloc'ed etc. The elements are guaranteed to
886
  be adjacently allocated (this is not guaranteed to occur with
886
  be adjacently allocated (this is not guaranteed to occur with
887
  multiple callocs or mallocs), which may also improve cache locality
887
  multiple callocs or mallocs), which may also improve cache locality
888
  in some applications.
888
  in some applications.
889
 
889
 
890
  The "chunks" argument is optional (i.e., may be null). If it is null
890
  The "chunks" argument is optional (i.e., may be null). If it is null
891
  the returned array is itself dynamically allocated and should also
891
  the returned array is itself dynamically allocated and should also
892
  be freed when it is no longer needed. Otherwise, the chunks array
892
  be freed when it is no longer needed. Otherwise, the chunks array
893
  must be of at least n_elements in length. It is filled in with the
893
  must be of at least n_elements in length. It is filled in with the
894
  pointers to the chunks.
894
  pointers to the chunks.
895
 
895
 
896
  In either case, independent_comalloc returns this pointer array, or
896
  In either case, independent_comalloc returns this pointer array, or
897
  null if the allocation failed.  If n_elements is zero and chunks is
897
  null if the allocation failed.  If n_elements is zero and chunks is
898
  null, it returns a chunk representing an array with zero elements
898
  null, it returns a chunk representing an array with zero elements
899
  (which should be freed if not wanted).
899
  (which should be freed if not wanted).
900
 
900
 
901
  Each element must be individually freed when it is no longer
901
  Each element must be individually freed when it is no longer
902
  needed. If you'd like to instead be able to free all at once, you
902
  needed. If you'd like to instead be able to free all at once, you
903
  should instead use a single regular malloc, and assign pointers at
903
  should instead use a single regular malloc, and assign pointers at
904
  particular offsets in the aggregate space. (In this case though, you
904
  particular offsets in the aggregate space. (In this case though, you
905
  cannot independently free elements.)
905
  cannot independently free elements.)
906
 
906
 
907
  independent_comallac differs from independent_calloc in that each
907
  independent_comallac differs from independent_calloc in that each
908
  element may have a different size, and also that it does not
908
  element may have a different size, and also that it does not
909
  automatically clear elements.
909
  automatically clear elements.
910
 
910
 
911
  independent_comalloc can be used to speed up allocation in cases
911
  independent_comalloc can be used to speed up allocation in cases
912
  where several structs or objects must always be allocated at the
912
  where several structs or objects must always be allocated at the
913
  same time.  For example:
913
  same time.  For example:
914
 
914
 
915
  struct Head { ... }
915
  struct Head { ... }
916
  struct Foot { ... }
916
  struct Foot { ... }
917
 
917
 
918
  void send_message(char* msg) {
918
  void send_message(char* msg) {
919
    int msglen = strlen(msg);
919
    int msglen = strlen(msg);
920
    size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
920
    size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
921
    void* chunks[3];
921
    void* chunks[3];
922
    if (independent_comalloc(3, sizes, chunks) == 0)
922
    if (independent_comalloc(3, sizes, chunks) == 0)
923
      die();
923
      die();
924
    struct Head* head = (struct Head*)(chunks[0]);
924
    struct Head* head = (struct Head*)(chunks[0]);
925
    char*        body = (char*)(chunks[1]);
925
    char*        body = (char*)(chunks[1]);
926
    struct Foot* foot = (struct Foot*)(chunks[2]);
926
    struct Foot* foot = (struct Foot*)(chunks[2]);
927
    // ...
927
    // ...
928
  }
928
  }
929
 
929
 
930
  In general though, independent_comalloc is worth using only for
930
  In general though, independent_comalloc is worth using only for
931
  larger values of n_elements. For small values, you probably won't
931
  larger values of n_elements. For small values, you probably won't
932
  detect enough difference from series of malloc calls to bother.
932
  detect enough difference from series of malloc calls to bother.
933
 
933
 
934
  Overuse of independent_comalloc can increase overall memory usage,
934
  Overuse of independent_comalloc can increase overall memory usage,
935
  since it cannot reuse existing noncontiguous small chunks that
935
  since it cannot reuse existing noncontiguous small chunks that
936
  might be available for some of the elements.
936
  might be available for some of the elements.
937
*/
937
*/
938
void** dlindependent_comalloc(size_t, size_t*, void**);
938
void** dlindependent_comalloc(size_t, size_t*, void**);
939
 
939
 
940
 
940
 
941
/*
941
/*
942
  pvalloc(size_t n);
942
  pvalloc(size_t n);
943
  Equivalent to valloc(minimum-page-that-holds(n)), that is,
943
  Equivalent to valloc(minimum-page-that-holds(n)), that is,
944
  round up n to nearest pagesize.
944
  round up n to nearest pagesize.
945
 */
945
 */
946
void*  dlpvalloc(size_t);
946
void*  dlpvalloc(size_t);
947
 
947
 
948
/*
948
/*
949
  malloc_trim(size_t pad);
949
  malloc_trim(size_t pad);
950
 
950
 
951
  If possible, gives memory back to the system (via negative arguments
951
  If possible, gives memory back to the system (via negative arguments
952
  to sbrk) if there is unused memory at the `high' end of the malloc
952
  to sbrk) if there is unused memory at the `high' end of the malloc
953
  pool or in unused MMAP segments. You can call this after freeing
953
  pool or in unused MMAP segments. You can call this after freeing
954
  large blocks of memory to potentially reduce the system-level memory
954
  large blocks of memory to potentially reduce the system-level memory
955
  requirements of a program. However, it cannot guarantee to reduce
955
  requirements of a program. However, it cannot guarantee to reduce
956
  memory. Under some allocation patterns, some large free blocks of
956
  memory. Under some allocation patterns, some large free blocks of
957
  memory will be locked between two used chunks, so they cannot be
957
  memory will be locked between two used chunks, so they cannot be
958
  given back to the system.
958
  given back to the system.
959
 
959
 
960
  The `pad' argument to malloc_trim represents the amount of free
960
  The `pad' argument to malloc_trim represents the amount of free
961
  trailing space to leave untrimmed. If this argument is zero, only
961
  trailing space to leave untrimmed. If this argument is zero, only
962
  the minimum amount of memory to maintain internal data structures
962
  the minimum amount of memory to maintain internal data structures
963
  will be left. Non-zero arguments can be supplied to maintain enough
963
  will be left. Non-zero arguments can be supplied to maintain enough
964
  trailing space to service future expected allocations without having
964
  trailing space to service future expected allocations without having
965
  to re-obtain memory from the system.
965
  to re-obtain memory from the system.
966
 
966
 
967
  Malloc_trim returns 1 if it actually released any memory, else 0.
967
  Malloc_trim returns 1 if it actually released any memory, else 0.
968
*/
968
*/
969
int  dlmalloc_trim(size_t);
969
int  dlmalloc_trim(size_t);
970
 
970
 
971
/*
971
/*
972
  malloc_usable_size(void* p);
972
  malloc_usable_size(void* p);
973
 
973
 
974
  Returns the number of bytes you can actually use in
974
  Returns the number of bytes you can actually use in
975
  an allocated chunk, which may be more than you requested (although
975
  an allocated chunk, which may be more than you requested (although
976
  often not) due to alignment and minimum size constraints.
976
  often not) due to alignment and minimum size constraints.
977
  You can use this many bytes without worrying about
977
  You can use this many bytes without worrying about
978
  overwriting other allocated objects. This is not a particularly great
978
  overwriting other allocated objects. This is not a particularly great
979
  programming practice. malloc_usable_size can be more useful in
979
  programming practice. malloc_usable_size can be more useful in
980
  debugging and assertions, for example:
980
  debugging and assertions, for example:
981
 
981
 
982
  p = malloc(n);
982
  p = malloc(n);
983
  assert(malloc_usable_size(p) >= 256);
983
  assert(malloc_usable_size(p) >= 256);
984
*/
984
*/
985
size_t dlmalloc_usable_size(void*);
985
size_t dlmalloc_usable_size(void*);
986
 
986
 
987
/*
987
/*
988
  malloc_stats();
988
  malloc_stats();
989
  Prints on stderr the amount of space obtained from the system (both
989
  Prints on stderr the amount of space obtained from the system (both
990
  via sbrk and mmap), the maximum amount (which may be more than
990
  via sbrk and mmap), the maximum amount (which may be more than
991
  current if malloc_trim and/or munmap got called), and the current
991
  current if malloc_trim and/or munmap got called), and the current
992
  number of bytes allocated via malloc (or realloc, etc) but not yet
992
  number of bytes allocated via malloc (or realloc, etc) but not yet
993
  freed. Note that this is the number of bytes allocated, not the
993
  freed. Note that this is the number of bytes allocated, not the
994
  number requested. It will be larger than the number requested
994
  number requested. It will be larger than the number requested
995
  because of alignment and bookkeeping overhead. Because it includes
995
  because of alignment and bookkeeping overhead. Because it includes
996
  alignment wastage as being in use, this figure may be greater than
996
  alignment wastage as being in use, this figure may be greater than
997
  zero even when no user-level chunks are allocated.
997
  zero even when no user-level chunks are allocated.
998
 
998
 
999
  The reported current and maximum system memory can be inaccurate if
999
  The reported current and maximum system memory can be inaccurate if
1000
  a program makes other calls to system memory allocation functions
1000
  a program makes other calls to system memory allocation functions
1001
  (normally sbrk) outside of malloc.
1001
  (normally sbrk) outside of malloc.
1002
 
1002
 
1003
  malloc_stats prints only the most commonly interesting statistics.
1003
  malloc_stats prints only the most commonly interesting statistics.
1004
  More information can be obtained by calling mallinfo.
1004
  More information can be obtained by calling mallinfo.
1005
*/
1005
*/
1006
void  dlmalloc_stats(void);
1006
void  dlmalloc_stats(void);
1007
 
1007
 
1008
#endif /* ONLY_MSPACES */
1008
#endif /* ONLY_MSPACES */
1009
 
1009
 
1010
#if MSPACES
1010
#if MSPACES
1011
 
1011
 
1012
/*
1012
/*
1013
  mspace is an opaque type representing an independent
1013
  mspace is an opaque type representing an independent
1014
  region of space that supports mspace_malloc, etc.
1014
  region of space that supports mspace_malloc, etc.
1015
*/
1015
*/
1016
typedef void* mspace;
1016
typedef void* mspace;
1017
 
1017
 
1018
/*
1018
/*
1019
  create_mspace creates and returns a new independent space with the
1019
  create_mspace creates and returns a new independent space with the
1020
  given initial capacity, or, if 0, the default granularity size.  It
1020
  given initial capacity, or, if 0, the default granularity size.  It
1021
  returns null if there is no system memory available to create the
1021
  returns null if there is no system memory available to create the
1022
  space.  If argument locked is non-zero, the space uses a separate
1022
  space.  If argument locked is non-zero, the space uses a separate
1023
  lock to control access. The capacity of the space will grow
1023
  lock to control access. The capacity of the space will grow
1024
  dynamically as needed to service mspace_malloc requests.  You can
1024
  dynamically as needed to service mspace_malloc requests.  You can
1025
  control the sizes of incremental increases of this space by
1025
  control the sizes of incremental increases of this space by
1026
  compiling with a different DEFAULT_GRANULARITY or dynamically
1026
  compiling with a different DEFAULT_GRANULARITY or dynamically
1027
  setting with mallopt(M_GRANULARITY, value).
1027
  setting with mallopt(M_GRANULARITY, value).
1028
*/
1028
*/
1029
mspace create_mspace(size_t capacity, int locked);
1029
mspace create_mspace(size_t capacity, int locked);
1030
 
1030
 
1031
/*
1031
/*
1032
  destroy_mspace destroys the given space, and attempts to return all
1032
  destroy_mspace destroys the given space, and attempts to return all
1033
  of its memory back to the system, returning the total number of
1033
  of its memory back to the system, returning the total number of
1034
  bytes freed. After destruction, the results of access to all memory
1034
  bytes freed. After destruction, the results of access to all memory
1035
  used by the space become undefined.
1035
  used by the space become undefined.
1036
*/
1036
*/
1037
size_t destroy_mspace(mspace msp);
1037
size_t destroy_mspace(mspace msp);
1038
 
1038
 
1039
/*
1039
/*
1040
  create_mspace_with_base uses the memory supplied as the initial base
1040
  create_mspace_with_base uses the memory supplied as the initial base
1041
  of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
1041
  of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
1042
  space is used for bookkeeping, so the capacity must be at least this
1042
  space is used for bookkeeping, so the capacity must be at least this
1043
  large. (Otherwise 0 is returned.) When this initial space is
1043
  large. (Otherwise 0 is returned.) When this initial space is
1044
  exhausted, additional memory will be obtained from the system.
1044
  exhausted, additional memory will be obtained from the system.
1045
  Destroying this space will deallocate all additionally allocated
1045
  Destroying this space will deallocate all additionally allocated
1046
  space (if possible) but not the initial base.
1046
  space (if possible) but not the initial base.
1047
*/
1047
*/
1048
mspace create_mspace_with_base(void* base, size_t capacity, int locked);
1048
mspace create_mspace_with_base(void* base, size_t capacity, int locked);
1049
 
1049
 
1050
/*
1050
/*
1051
  mspace_malloc behaves as malloc, but operates within
1051
  mspace_malloc behaves as malloc, but operates within
1052
  the given space.
1052
  the given space.
1053
*/
1053
*/
1054
void* mspace_malloc(mspace msp, size_t bytes);
1054
void* mspace_malloc(mspace msp, size_t bytes);
1055
 
1055
 
1056
/*
1056
/*
1057
  mspace_free behaves as free, but operates within
1057
  mspace_free behaves as free, but operates within
1058
  the given space.
1058
  the given space.
1059
 
1059
 
1060
  If compiled with FOOTERS==1, mspace_free is not actually needed.
1060
  If compiled with FOOTERS==1, mspace_free is not actually needed.
1061
  free may be called instead of mspace_free because freed chunks from
1061
  free may be called instead of mspace_free because freed chunks from
1062
  any space are handled by their originating spaces.
1062
  any space are handled by their originating spaces.
1063
*/
1063
*/
1064
void mspace_free(mspace msp, void* mem);
1064
void mspace_free(mspace msp, void* mem);
1065
 
1065
 
1066
/*
1066
/*
1067
  mspace_realloc behaves as realloc, but operates within
1067
  mspace_realloc behaves as realloc, but operates within
1068
  the given space.
1068
  the given space.
1069
 
1069
 
1070
  If compiled with FOOTERS==1, mspace_realloc is not actually
1070
  If compiled with FOOTERS==1, mspace_realloc is not actually
1071
  needed.  realloc may be called instead of mspace_realloc because
1071
  needed.  realloc may be called instead of mspace_realloc because
1072
  realloced chunks from any space are handled by their originating
1072
  realloced chunks from any space are handled by their originating
1073
  spaces.
1073
  spaces.
1074
*/
1074
*/
1075
void* mspace_realloc(mspace msp, void* mem, size_t newsize);
1075
void* mspace_realloc(mspace msp, void* mem, size_t newsize);
1076
 
1076
 
1077
/*
1077
/*
1078
  mspace_calloc behaves as calloc, but operates within
1078
  mspace_calloc behaves as calloc, but operates within
1079
  the given space.
1079
  the given space.
1080
*/
1080
*/
1081
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
1081
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
1082
 
1082
 
1083
/*
1083
/*
1084
  mspace_memalign behaves as memalign, but operates within
1084
  mspace_memalign behaves as memalign, but operates within
1085
  the given space.
1085
  the given space.
1086
*/
1086
*/
1087
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
1087
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
1088
 
1088
 
1089
/*
1089
/*
1090
  mspace_independent_calloc behaves as independent_calloc, but
1090
  mspace_independent_calloc behaves as independent_calloc, but
1091
  operates within the given space.
1091
  operates within the given space.
1092
*/
1092
*/
1093
void** mspace_independent_calloc(mspace msp, size_t n_elements,
1093
void** mspace_independent_calloc(mspace msp, size_t n_elements,
1094
                                 size_t elem_size, void* chunks[]);
1094
                                 size_t elem_size, void* chunks[]);
1095
 
1095
 
1096
/*
1096
/*
1097
  mspace_independent_comalloc behaves as independent_comalloc, but
1097
  mspace_independent_comalloc behaves as independent_comalloc, but
1098
  operates within the given space.
1098
  operates within the given space.
1099
*/
1099
*/
1100
void** mspace_independent_comalloc(mspace msp, size_t n_elements,
1100
void** mspace_independent_comalloc(mspace msp, size_t n_elements,
1101
                                   size_t sizes[], void* chunks[]);
1101
                                   size_t sizes[], void* chunks[]);
1102
 
1102
 
1103
/*
1103
/*
1104
  mspace_footprint() returns the number of bytes obtained from the
1104
  mspace_footprint() returns the number of bytes obtained from the
1105
  system for this space.
1105
  system for this space.
1106
*/
1106
*/
1107
size_t mspace_footprint(mspace msp);
1107
size_t mspace_footprint(mspace msp);
1108
 
1108
 
1109
/*
1109
/*
1110
  mspace_max_footprint() returns the peak number of bytes obtained from the
1110
  mspace_max_footprint() returns the peak number of bytes obtained from the
1111
  system for this space.
1111
  system for this space.
1112
*/
1112
*/
1113
size_t mspace_max_footprint(mspace msp);
1113
size_t mspace_max_footprint(mspace msp);
1114
 
1114
 
1115
 
1115
 
1116
#if !NO_MALLINFO
1116
#if !NO_MALLINFO
1117
/*
1117
/*
1118
  mspace_mallinfo behaves as mallinfo, but reports properties of
1118
  mspace_mallinfo behaves as mallinfo, but reports properties of
1119
  the given space.
1119
  the given space.
1120
*/
1120
*/
1121
struct mallinfo mspace_mallinfo(mspace msp);
1121
struct mallinfo mspace_mallinfo(mspace msp);
1122
#endif /* NO_MALLINFO */
1122
#endif /* NO_MALLINFO */
1123
 
1123
 
1124
/*
1124
/*
1125
  mspace_malloc_stats behaves as malloc_stats, but reports
1125
  mspace_malloc_stats behaves as malloc_stats, but reports
1126
  properties of the given space.
1126
  properties of the given space.
1127
*/
1127
*/
1128
void mspace_malloc_stats(mspace msp);
1128
void mspace_malloc_stats(mspace msp);
1129
 
1129
 
1130
/*
1130
/*
1131
  mspace_trim behaves as malloc_trim, but
1131
  mspace_trim behaves as malloc_trim, but
1132
  operates within the given space.
1132
  operates within the given space.
1133
*/
1133
*/
1134
int mspace_trim(mspace msp, size_t pad);
1134
int mspace_trim(mspace msp, size_t pad);
1135
 
1135
 
1136
/*
1136
/*
1137
  An alias for mallopt.
1137
  An alias for mallopt.
1138
*/
1138
*/
1139
int mspace_mallopt(int, int);
1139
int mspace_mallopt(int, int);
1140
 
1140
 
1141
#endif /* MSPACES */
1141
#endif /* MSPACES */
1142
 
1142
 
1143
#ifdef __cplusplus
1143
#ifdef __cplusplus
1144
};  /* end of extern "C" */
1144
};  /* end of extern "C" */
1145
#endif /* __cplusplus */
1145
#endif /* __cplusplus */
1146
 
1146
 
1147
/*
1147
/*
1148
  ========================================================================
1148
  ========================================================================
1149
  To make a fully customizable malloc.h header file, cut everything
1149
  To make a fully customizable malloc.h header file, cut everything
1150
  above this line, put into file malloc.h, edit to suit, and #include it
1150
  above this line, put into file malloc.h, edit to suit, and #include it
1151
  on the next line, as well as in programs that use this malloc.
1151
  on the next line, as well as in programs that use this malloc.
1152
  ========================================================================
1152
  ========================================================================
1153
*/
1153
*/
1154
 
1154
 
1155
/* #include "malloc.h" */
1155
/* #include "malloc.h" */
1156
 
1156
 
1157
/*------------------------------ internal #includes ---------------------- */
1157
/*------------------------------ internal #includes ---------------------- */
1158
 
1158
 
1159
#if 0
1159
#if 0
1160
#ifdef WIN32
1160
#ifdef WIN32
1161
#pragma warning( disable : 4146 ) /* no "unsigned" warnings */
1161
#pragma warning( disable : 4146 ) /* no "unsigned" warnings */
1162
#endif /* WIN32 */
1162
#endif /* WIN32 */
1163
#endif
1163
#endif
1164
 
1164
 
1165
#include <stdio.h>       /* for printing in malloc_stats */
1165
#include <stdio.h>       /* for printing in malloc_stats */
1166
 
1166
 
1167
#ifndef LACKS_ERRNO_H
1167
#ifndef LACKS_ERRNO_H
1168
#include <errno.h>       /* for MALLOC_FAILURE_ACTION */
1168
#include <errno.h>       /* for MALLOC_FAILURE_ACTION */
1169
#endif /* LACKS_ERRNO_H */
1169
#endif /* LACKS_ERRNO_H */
1170
#if FOOTERS
1170
#if FOOTERS
1171
#include <time.h>        /* for magic initialization */
1171
#include <time.h>        /* for magic initialization */
1172
#endif /* FOOTERS */
1172
#endif /* FOOTERS */
1173
#ifndef LACKS_STDLIB_H
1173
#ifndef LACKS_STDLIB_H
1174
#include <stdlib.h>      /* for abort() */
1174
#include <stdlib.h>      /* for abort() */
1175
#endif /* LACKS_STDLIB_H */
1175
#endif /* LACKS_STDLIB_H */
1176
#ifdef DEBUG
1176
#ifdef DEBUG
1177
#if ABORT_ON_ASSERT_FAILURE
1177
#if ABORT_ON_ASSERT_FAILURE
1178
#define assert(x) if(!(x)) ABORT
1178
#define assert(x) if(!(x)) ABORT
1179
#else /* ABORT_ON_ASSERT_FAILURE */
1179
#else /* ABORT_ON_ASSERT_FAILURE */
1180
#include <assert.h>
1180
#include <assert.h>
1181
#endif /* ABORT_ON_ASSERT_FAILURE */
1181
#endif /* ABORT_ON_ASSERT_FAILURE */
1182
#else  /* DEBUG */
1182
#else  /* DEBUG */
1183
#define assert(x)
1183
#define assert(x)
1184
#endif /* DEBUG */
1184
#endif /* DEBUG */
1185
#ifndef LACKS_STRING_H
1185
#ifndef LACKS_STRING_H
1186
#include <string.h>      /* for memset etc */
1186
#include <string.h>      /* for memset etc */
1187
#endif  /* LACKS_STRING_H */
1187
#endif  /* LACKS_STRING_H */
1188
#if USE_BUILTIN_FFS
1188
#if USE_BUILTIN_FFS
1189
#ifndef LACKS_STRINGS_H
1189
#ifndef LACKS_STRINGS_H
1190
#include <strings.h>     /* for ffs */
1190
#include <strings.h>     /* for ffs */
1191
#endif /* LACKS_STRINGS_H */
1191
#endif /* LACKS_STRINGS_H */
1192
#endif /* USE_BUILTIN_FFS */
1192
#endif /* USE_BUILTIN_FFS */
1193
#if HAVE_MMAP
1193
#if HAVE_MMAP
1194
#ifndef LACKS_SYS_MMAN_H
1194
#ifndef LACKS_SYS_MMAN_H
1195
#include <sys/mman.h>    /* for mmap */
1195
#include <sys/mman.h>    /* for mmap */
1196
#endif /* LACKS_SYS_MMAN_H */
1196
#endif /* LACKS_SYS_MMAN_H */
1197
#ifndef LACKS_FCNTL_H
1197
#ifndef LACKS_FCNTL_H
1198
#include <fcntl.h>
1198
#include <fcntl.h>
1199
#endif /* LACKS_FCNTL_H */
1199
#endif /* LACKS_FCNTL_H */
1200
#endif /* HAVE_MMAP */
1200
#endif /* HAVE_MMAP */
1201
#if HAVE_MORECORE
1201
#if HAVE_MORECORE
1202
#ifndef LACKS_UNISTD_H
1202
#ifndef LACKS_UNISTD_H
1203
#include <unistd.h>     /* for sbrk */
1203
#include <unistd.h>     /* for sbrk */
1204
#else /* LACKS_UNISTD_H */
1204
#else /* LACKS_UNISTD_H */
1205
#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
1205
#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
1206
extern void*     sbrk(ptrdiff_t);
1206
extern void*     sbrk(ptrdiff_t);
1207
#endif /* FreeBSD etc */
1207
#endif /* FreeBSD etc */
1208
#endif /* LACKS_UNISTD_H */
1208
#endif /* LACKS_UNISTD_H */
1209
#endif /* HAVE_MMAP */
1209
#endif /* HAVE_MMAP */
1210
 
1210
 
1211
#ifndef WIN32
1211
#ifndef WIN32
1212
#ifndef malloc_getpagesize
1212
#ifndef malloc_getpagesize
1213
#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
1213
#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
1214
#    ifndef _SC_PAGE_SIZE
1214
#    ifndef _SC_PAGE_SIZE
1215
#      define _SC_PAGE_SIZE _SC_PAGESIZE
1215
#      define _SC_PAGE_SIZE _SC_PAGESIZE
1216
#    endif
1216
#    endif
1217
#  endif
1217
#  endif
1218
#  ifdef _SC_PAGE_SIZE
1218
#  ifdef _SC_PAGE_SIZE
1219
#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
1219
#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
1220
#  else
1220
#  else
1221
#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
1221
#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
1222
       extern size_t getpagesize();
1222
       extern size_t getpagesize();
1223
#      define malloc_getpagesize getpagesize()
1223
#      define malloc_getpagesize getpagesize()
1224
#    else
1224
#    else
1225
#      ifdef WIN32 /* use supplied emulation of getpagesize */
1225
#      ifdef WIN32 /* use supplied emulation of getpagesize */
1226
#        define malloc_getpagesize getpagesize()
1226
#        define malloc_getpagesize getpagesize()
1227
#      else
1227
#      else
1228
#        ifndef LACKS_SYS_PARAM_H
1228
#        ifndef LACKS_SYS_PARAM_H
1229
#          include <sys/param.h>
1229
#          include <sys/param.h>
1230
#        endif
1230
#        endif
1231
#        ifdef EXEC_PAGESIZE
1231
#        ifdef EXEC_PAGESIZE
1232
#          define malloc_getpagesize EXEC_PAGESIZE
1232
#          define malloc_getpagesize EXEC_PAGESIZE
1233
#        else
1233
#        else
1234
#          ifdef NBPG
1234
#          ifdef NBPG
1235
#            ifndef CLSIZE
1235
#            ifndef CLSIZE
1236
#              define malloc_getpagesize NBPG
1236
#              define malloc_getpagesize NBPG
1237
#            else
1237
#            else
1238
#              define malloc_getpagesize (NBPG * CLSIZE)
1238
#              define malloc_getpagesize (NBPG * CLSIZE)
1239
#            endif
1239
#            endif
1240
#          else
1240
#          else
1241
#            ifdef NBPC
1241
#            ifdef NBPC
1242
#              define malloc_getpagesize NBPC
1242
#              define malloc_getpagesize NBPC
1243
#            else
1243
#            else
1244
#              ifdef PAGESIZE
1244
#              ifdef PAGESIZE
1245
#                define malloc_getpagesize PAGESIZE
1245
#                define malloc_getpagesize PAGESIZE
1246
#              else /* just guess */
1246
#              else /* just guess */
1247
#                define malloc_getpagesize ((size_t)4096U)
1247
#                define malloc_getpagesize ((size_t)4096U)
1248
#              endif
1248
#              endif
1249
#            endif
1249
#            endif
1250
#          endif
1250
#          endif
1251
#        endif
1251
#        endif
1252
#      endif
1252
#      endif
1253
#    endif
1253
#    endif
1254
#  endif
1254
#  endif
1255
#endif
1255
#endif
1256
#endif
1256
#endif
1257
 
1257
 
1258
/* ------------------- size_t and alignment properties -------------------- */
1258
/* ------------------- size_t and alignment properties -------------------- */
1259
 
1259
 
1260
/* The byte and bit size of a size_t */
1260
/* The byte and bit size of a size_t */
1261
#define SIZE_T_SIZE         (sizeof(size_t))
1261
#define SIZE_T_SIZE         (sizeof(size_t))
1262
#define SIZE_T_BITSIZE      (sizeof(size_t) << 3)
1262
#define SIZE_T_BITSIZE      (sizeof(size_t) << 3)
1263
 
1263
 
1264
/* Some constants coerced to size_t */
1264
/* Some constants coerced to size_t */
1265
/* Annoying but necessary to avoid errors on some plaftorms */
1265
/* Annoying but necessary to avoid errors on some plaftorms */
1266
#define SIZE_T_ZERO         ((size_t)0)
1266
#define SIZE_T_ZERO         ((size_t)0)
1267
#define SIZE_T_ONE          ((size_t)1)
1267
#define SIZE_T_ONE          ((size_t)1)
1268
#define SIZE_T_TWO          ((size_t)2)
1268
#define SIZE_T_TWO          ((size_t)2)
1269
#define TWO_SIZE_T_SIZES    (SIZE_T_SIZE<<1)
1269
#define TWO_SIZE_T_SIZES    (SIZE_T_SIZE<<1)
1270
#define FOUR_SIZE_T_SIZES   (SIZE_T_SIZE<<2)
1270
#define FOUR_SIZE_T_SIZES   (SIZE_T_SIZE<<2)
1271
#define SIX_SIZE_T_SIZES    (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
1271
#define SIX_SIZE_T_SIZES    (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
1272
#define HALF_MAX_SIZE_T     (MAX_SIZE_T / 2U)
1272
#define HALF_MAX_SIZE_T     (MAX_SIZE_T / 2U)
1273
 
1273
 
1274
/* The bit mask value corresponding to MALLOC_ALIGNMENT */
1274
/* The bit mask value corresponding to MALLOC_ALIGNMENT */
1275
#define CHUNK_ALIGN_MASK    (MALLOC_ALIGNMENT - SIZE_T_ONE)
1275
#define CHUNK_ALIGN_MASK    (MALLOC_ALIGNMENT - SIZE_T_ONE)
1276
 
1276
 
1277
/* True if address a has acceptable alignment */
1277
/* True if address a has acceptable alignment */
1278
#define is_aligned(A)       (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
1278
#define is_aligned(A)       (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
1279
 
1279
 
1280
/* the number of bytes to offset an address to align it */
1280
/* the number of bytes to offset an address to align it */
1281
#define align_offset(A)\
1281
#define align_offset(A)\
1282
 ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
1282
 ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
1283
  ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
1283
  ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
1284
 
1284
 
1285
/* -------------------------- MMAP preliminaries ------------------------- */
1285
/* -------------------------- MMAP preliminaries ------------------------- */
1286
 
1286
 
1287
/*
1287
/*
1288
   If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
1288
   If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
1289
   checks to fail so compiler optimizer can delete code rather than
1289
   checks to fail so compiler optimizer can delete code rather than
1290
   using so many "#if"s.
1290
   using so many "#if"s.
1291
*/
1291
*/
1292
 
1292
 
1293
 
1293
 
1294
/* MORECORE and MMAP must return MFAIL on failure */
1294
/* MORECORE and MMAP must return MFAIL on failure */
1295
#define MFAIL                ((void*)(MAX_SIZE_T))
1295
#define MFAIL                ((void*)(MAX_SIZE_T))
1296
#define CMFAIL               ((char*)(MFAIL)) /* defined for convenience */
1296
#define CMFAIL               ((char*)(MFAIL)) /* defined for convenience */
1297
 
1297
 
1298
#if !HAVE_MMAP
1298
#if !HAVE_MMAP
1299
#define IS_MMAPPED_BIT       (SIZE_T_ZERO)
1299
#define IS_MMAPPED_BIT       (SIZE_T_ZERO)
1300
#define USE_MMAP_BIT         (SIZE_T_ZERO)
1300
#define USE_MMAP_BIT         (SIZE_T_ZERO)
1301
#define CALL_MMAP(s)         MFAIL
1301
#define CALL_MMAP(s)         MFAIL
1302
#define CALL_MUNMAP(a, s)    (-1)
1302
#define CALL_MUNMAP(a, s)    (-1)
1303
#define DIRECT_MMAP(s)       MFAIL
1303
#define DIRECT_MMAP(s)       MFAIL
1304
 
1304
 
1305
#else /* HAVE_MMAP */
1305
#else /* HAVE_MMAP */
1306
#define IS_MMAPPED_BIT       (SIZE_T_ONE)
1306
#define IS_MMAPPED_BIT       (SIZE_T_ONE)
1307
#define USE_MMAP_BIT         (SIZE_T_ONE)
1307
#define USE_MMAP_BIT         (SIZE_T_ONE)
1308
 
1308
 
1309
#ifndef WIN32
1309
#ifndef WIN32
1310
#define CALL_MUNMAP(a, s)    munmap((a), (s))
1310
#define CALL_MUNMAP(a, s)    munmap((a), (s))
1311
#define MMAP_PROT            (PROT_READ|PROT_WRITE)
1311
#define MMAP_PROT            (PROT_READ|PROT_WRITE)
1312
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
1312
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
1313
#define MAP_ANONYMOUS        MAP_ANON
1313
#define MAP_ANONYMOUS        MAP_ANON
1314
#endif /* MAP_ANON */
1314
#endif /* MAP_ANON */
1315
#ifdef MAP_ANONYMOUS
1315
#ifdef MAP_ANONYMOUS
1316
#define MMAP_FLAGS           (MAP_PRIVATE|MAP_ANONYMOUS)
1316
#define MMAP_FLAGS           (MAP_PRIVATE|MAP_ANONYMOUS)
1317
#define CALL_MMAP(s)         mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
1317
#define CALL_MMAP(s)         mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
1318
#else /* MAP_ANONYMOUS */
1318
#else /* MAP_ANONYMOUS */
1319
/*
1319
/*
1320
   Nearly all versions of mmap support MAP_ANONYMOUS, so the following
1320
   Nearly all versions of mmap support MAP_ANONYMOUS, so the following
1321
   is unlikely to be needed, but is supplied just in case.
1321
   is unlikely to be needed, but is supplied just in case.
1322
*/
1322
*/
1323
#define MMAP_FLAGS           (MAP_PRIVATE)
1323
#define MMAP_FLAGS           (MAP_PRIVATE)
1324
static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
1324
static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
1325
#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
1325
#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
1326
           (dev_zero_fd = open("/dev/zero", O_RDWR), \
1326
           (dev_zero_fd = open("/dev/zero", O_RDWR), \
1327
            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
1327
            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
1328
            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
1328
            mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
1329
#endif /* MAP_ANONYMOUS */
1329
#endif /* MAP_ANONYMOUS */
1330
 
1330
 
1331
#define DIRECT_MMAP(s)       CALL_MMAP(s)
1331
#define DIRECT_MMAP(s)       CALL_MMAP(s)
1332
#else /* WIN32 */
1332
#else /* WIN32 */
1333
 
1333
 
1334
/* Win32 MMAP via VirtualAlloc */
1334
/* Win32 MMAP via VirtualAlloc */
1335
static void* win32mmap(size_t size) {
1335
static void* win32mmap(size_t size) {
1336
  void* ptr;
1336
  void* ptr;
1337
  /* printf("current %0.1f, asking %0.1f\n", R_used/1048576., size/1048576.);*/
1337
  /* printf("current %0.1f, asking %0.1f\n", R_used/1048576., size/1048576.);*/
1338
  if (R_used + size > R_max_memory) {
1338
  if (R_used + size > R_max_memory) {
1339
      if(R_Is_Running) 
1339
      if(R_Is_Running) 
1340
	  Rf_warning("Reached total allocation of %dMb: see help(memory.size)",
1340
	  Rf_warning("Reached total allocation of %dMb: see help(memory.size)",
1341
		     R_max_memory/1048576);
1341
		     R_max_memory/1048576);
1342
      return MFAIL;
1342
      return MFAIL;
1343
  }
1343
  }
1344
  ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
1344
  ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
1345
  R_used += (ptr != 0)? size: 0;
1345
  R_used += (ptr != 0)? size: 0;
1346
  return (ptr != 0)? ptr: MFAIL;
1346
  return (ptr != 0)? ptr: MFAIL;
1347
}
1347
}
1348
 
1348
 
1349
/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
1349
/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
1350
static void* win32direct_mmap(size_t size) {
1350
static void* win32direct_mmap(size_t size) {
1351
  void* ptr;
1351
  void* ptr;
1352
  /* printf("current %0.1f, asking %0.1f\n", R_used/1048576., size/1048576.);*/
1352
  /* printf("current %0.1f, asking %0.1f\n", R_used/1048576., size/1048576.);*/
1353
  if (R_used + size > R_max_memory) {
1353
  if (R_used + size > R_max_memory) {
1354
      if(R_Is_Running) 
1354
      if(R_Is_Running) 
1355
	  Rf_warning("Reached total allocation of %dMb: see help(memory.size)",
1355
	  Rf_warning("Reached total allocation of %dMb: see help(memory.size)",
1356
		     R_max_memory/1048576);
1356
		     R_max_memory/1048576);
1357
      return MFAIL;
1357
      return MFAIL;
1358
  }
1358
  }
1359
  ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
1359
  ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
1360
                           PAGE_READWRITE);
1360
                           PAGE_READWRITE);
1361
  R_used += (ptr != 0)? size: 0;
1361
  R_used += (ptr != 0)? size: 0;
1362
  return (ptr != 0)? ptr: MFAIL;
1362
  return (ptr != 0)? ptr: MFAIL;
1363
}
1363
}
1364
 
1364
 
1365
/* This function supports releasing coalesed segments */
1365
/* This function supports releasing coalesed segments */
1366
static int win32munmap(void* ptr, size_t size) {
1366
static int win32munmap(void* ptr, size_t size) {
1367
  MEMORY_BASIC_INFORMATION minfo;
1367
  MEMORY_BASIC_INFORMATION minfo;
1368
  char* cptr = ptr;
1368
  char* cptr = ptr;
1369
  while (size) {
1369
  while (size) {
1370
    if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
1370
    if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
1371
      return -1;
1371
      return -1;
1372
    if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
1372
    if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
1373
        minfo.State != MEM_COMMIT || minfo.RegionSize > size)
1373
        minfo.State != MEM_COMMIT || minfo.RegionSize > size)
1374
      return -1;
1374
      return -1;
1375
    if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
1375
    if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
1376
      return -1;
1376
      return -1;
1377
    cptr += minfo.RegionSize;
1377
    cptr += minfo.RegionSize;
1378
    size -= minfo.RegionSize;
1378
    size -= minfo.RegionSize;
1379
    /* printf("current %0.1f, releasing %0.1f\n", 
1379
    /* printf("current %0.1f, releasing %0.1f\n", 
1380
       R_used/1048576., minfo.RegionSize/1048576.); */
1380
       R_used/1048576., minfo.RegionSize/1048576.); */
1381
    R_used -= minfo.RegionSize;
1381
    R_used -= minfo.RegionSize;
1382
  }
1382
  }
1383
  return 0;
1383
  return 0;
1384
}
1384
}
1385
 
1385
 
1386
#define CALL_MMAP(s)         win32mmap(s)
1386
#define CALL_MMAP(s)         win32mmap(s)
1387
#define CALL_MUNMAP(a, s)    win32munmap((a), (s))
1387
#define CALL_MUNMAP(a, s)    win32munmap((a), (s))
1388
#define DIRECT_MMAP(s)       win32direct_mmap(s)
1388
#define DIRECT_MMAP(s)       win32direct_mmap(s)
1389
#endif /* WIN32 */
1389
#endif /* WIN32 */
1390
#endif /* HAVE_MMAP */
1390
#endif /* HAVE_MMAP */
1391
 
1391
 
1392
#if HAVE_MMAP && HAVE_MREMAP
1392
#if HAVE_MMAP && HAVE_MREMAP
1393
#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
1393
#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
1394
#else  /* HAVE_MMAP && HAVE_MREMAP */
1394
#else  /* HAVE_MMAP && HAVE_MREMAP */
1395
#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
1395
#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
1396
#endif /* HAVE_MMAP && HAVE_MREMAP */
1396
#endif /* HAVE_MMAP && HAVE_MREMAP */
1397
 
1397
 
1398
#if HAVE_MORECORE
1398
#if HAVE_MORECORE
1399
#define CALL_MORECORE(S)     MORECORE(S)
1399
#define CALL_MORECORE(S)     MORECORE(S)
1400
#else  /* HAVE_MORECORE */
1400
#else  /* HAVE_MORECORE */
1401
#define CALL_MORECORE(S)     MFAIL
1401
#define CALL_MORECORE(S)     MFAIL
1402
#endif /* HAVE_MORECORE */
1402
#endif /* HAVE_MORECORE */
1403
 
1403
 
1404
/* mstate bit set if continguous morecore disabled or failed */
1404
/* mstate bit set if continguous morecore disabled or failed */
1405
#define USE_NONCONTIGUOUS_BIT (4U)
1405
#define USE_NONCONTIGUOUS_BIT (4U)
1406
 
1406
 
1407
/* segment bit set in create_mspace_with_base */
1407
/* segment bit set in create_mspace_with_base */
1408
#define EXTERN_BIT            (8U)
1408
#define EXTERN_BIT            (8U)
1409
 
1409
 
1410
 
1410
 
1411
/* --------------------------- Lock preliminaries ------------------------ */
1411
/* --------------------------- Lock preliminaries ------------------------ */
1412
 
1412
 
1413
#if USE_LOCKS
1413
#if USE_LOCKS
1414
 
1414
 
1415
/*
1415
/*
1416
  When locks are defined, there are up to two global locks:
1416
  When locks are defined, there are up to two global locks:
1417
 
1417
 
1418
  * If HAVE_MORECORE, morecore_mutex protects sequences of calls to
1418
  * If HAVE_MORECORE, morecore_mutex protects sequences of calls to
1419
    MORECORE.  In many cases sys_alloc requires two calls, that should
1419
    MORECORE.  In many cases sys_alloc requires two calls, that should
1420
    not be interleaved with calls by other threads.  This does not
1420
    not be interleaved with calls by other threads.  This does not
1421
    protect against direct calls to MORECORE by other threads not
1421
    protect against direct calls to MORECORE by other threads not
1422
    using this lock, so there is still code to cope the best we can on
1422
    using this lock, so there is still code to cope the best we can on
1423
    interference.
1423
    interference.
1424
 
1424
 
1425
  * magic_init_mutex ensures that mparams.magic and other
1425
  * magic_init_mutex ensures that mparams.magic and other
1426
    unique mparams values are initialized only once.
1426
    unique mparams values are initialized only once.
1427
*/
1427
*/
1428
 
1428
 
1429
#ifndef WIN32
1429
#ifndef WIN32
1430
/* By default use posix locks */
1430
/* By default use posix locks */
1431
#include <pthread.h>
1431
#include <pthread.h>
1432
#define MLOCK_T pthread_mutex_t
1432
#define MLOCK_T pthread_mutex_t
1433
#define INITIAL_LOCK(l)      pthread_mutex_init(l, NULL)
1433
#define INITIAL_LOCK(l)      pthread_mutex_init(l, NULL)
1434
#define ACQUIRE_LOCK(l)      pthread_mutex_lock(l)
1434
#define ACQUIRE_LOCK(l)      pthread_mutex_lock(l)
1435
#define RELEASE_LOCK(l)      pthread_mutex_unlock(l)
1435
#define RELEASE_LOCK(l)      pthread_mutex_unlock(l)
1436
 
1436
 
1437
#if HAVE_MORECORE
1437
#if HAVE_MORECORE
1438
static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER;
1438
static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER;
1439
#endif /* HAVE_MORECORE */
1439
#endif /* HAVE_MORECORE */
1440
 
1440
 
1441
static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER;
1441
static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER;
1442
 
1442
 
1443
#else /* WIN32 */
1443
#else /* WIN32 */
1444
/*
1444
/*
1445
   Because lock-protected regions have bounded times, and there
1445
   Because lock-protected regions have bounded times, and there
1446
   are no recursive lock calls, we can use simple spinlocks.
1446
   are no recursive lock calls, we can use simple spinlocks.
1447
*/
1447
*/
1448
 
1448
 
1449
#define MLOCK_T long
1449
#define MLOCK_T long
1450
static int win32_acquire_lock (MLOCK_T *sl) {
1450
static int win32_acquire_lock (MLOCK_T *sl) {
1451
  for (;;) {
1451
  for (;;) {
1452
#ifdef InterlockedCompareExchangePointer
1452
#ifdef InterlockedCompareExchangePointer
1453
    if (!InterlockedCompareExchange(sl, 1, 0))
1453
    if (!InterlockedCompareExchange(sl, 1, 0))
1454
      return 0;
1454
      return 0;
1455
#else  /* Use older void* version */
1455
#else  /* Use older void* version */
1456
    if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0))
1456
    if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0))
1457
      return 0;
1457
      return 0;
1458
#endif /* InterlockedCompareExchangePointer */
1458
#endif /* InterlockedCompareExchangePointer */
1459
    Sleep (0);
1459
    Sleep (0);
1460
  }
1460
  }
1461
}
1461
}
1462
 
1462
 
1463
static void win32_release_lock (MLOCK_T *sl) {
1463
static void win32_release_lock (MLOCK_T *sl) {
1464
  InterlockedExchange (sl, 0);
1464
  InterlockedExchange (sl, 0);
1465
}
1465
}
1466
 
1466
 
1467
#define INITIAL_LOCK(l)      *(l)=0
1467
#define INITIAL_LOCK(l)      *(l)=0
1468
#define ACQUIRE_LOCK(l)      win32_acquire_lock(l)
1468
#define ACQUIRE_LOCK(l)      win32_acquire_lock(l)
1469
#define RELEASE_LOCK(l)      win32_release_lock(l)
1469
#define RELEASE_LOCK(l)      win32_release_lock(l)
1470
#if HAVE_MORECORE
1470
#if HAVE_MORECORE
1471
static MLOCK_T morecore_mutex;
1471
static MLOCK_T morecore_mutex;
1472
#endif /* HAVE_MORECORE */
1472
#endif /* HAVE_MORECORE */
1473
static MLOCK_T magic_init_mutex;
1473
static MLOCK_T magic_init_mutex;
1474
#endif /* WIN32 */
1474
#endif /* WIN32 */
1475
 
1475
 
1476
#define USE_LOCK_BIT               (2U)
1476
#define USE_LOCK_BIT               (2U)
1477
#else  /* USE_LOCKS */
1477
#else  /* USE_LOCKS */
1478
#define USE_LOCK_BIT               (0U)
1478
#define USE_LOCK_BIT               (0U)
1479
#define INITIAL_LOCK(l)
1479
#define INITIAL_LOCK(l)
1480
#endif /* USE_LOCKS */
1480
#endif /* USE_LOCKS */
1481
 
1481
 
1482
#if USE_LOCKS && HAVE_MORECORE
1482
#if USE_LOCKS && HAVE_MORECORE
1483
#define ACQUIRE_MORECORE_LOCK()    ACQUIRE_LOCK(&morecore_mutex);
1483
#define ACQUIRE_MORECORE_LOCK()    ACQUIRE_LOCK(&morecore_mutex);
1484
#define RELEASE_MORECORE_LOCK()    RELEASE_LOCK(&morecore_mutex);
1484
#define RELEASE_MORECORE_LOCK()    RELEASE_LOCK(&morecore_mutex);
1485
#else /* USE_LOCKS && HAVE_MORECORE */
1485
#else /* USE_LOCKS && HAVE_MORECORE */
1486
#define ACQUIRE_MORECORE_LOCK()
1486
#define ACQUIRE_MORECORE_LOCK()
1487
#define RELEASE_MORECORE_LOCK()
1487
#define RELEASE_MORECORE_LOCK()
1488
#endif /* USE_LOCKS && HAVE_MORECORE */
1488
#endif /* USE_LOCKS && HAVE_MORECORE */
1489
 
1489
 
1490
#if USE_LOCKS
1490
#if USE_LOCKS
1491
#define ACQUIRE_MAGIC_INIT_LOCK()  ACQUIRE_LOCK(&magic_init_mutex);
1491
#define ACQUIRE_MAGIC_INIT_LOCK()  ACQUIRE_LOCK(&magic_init_mutex);
1492
#define RELEASE_MAGIC_INIT_LOCK()  RELEASE_LOCK(&magic_init_mutex);
1492
#define RELEASE_MAGIC_INIT_LOCK()  RELEASE_LOCK(&magic_init_mutex);
1493
#else  /* USE_LOCKS */
1493
#else  /* USE_LOCKS */
1494
#define ACQUIRE_MAGIC_INIT_LOCK()
1494
#define ACQUIRE_MAGIC_INIT_LOCK()
1495
#define RELEASE_MAGIC_INIT_LOCK()
1495
#define RELEASE_MAGIC_INIT_LOCK()
1496
#endif /* USE_LOCKS */
1496
#endif /* USE_LOCKS */
1497
 
1497
 
1498
 
1498
 
1499
/* -----------------------  Chunk representations ------------------------ */
1499
/* -----------------------  Chunk representations ------------------------ */
1500
 
1500
 
1501
/*
1501
/*
1502
  (The following includes lightly edited explanations by Colin Plumb.)
1502
  (The following includes lightly edited explanations by Colin Plumb.)
1503
 
1503
 
1504
  The malloc_chunk declaration below is misleading (but accurate and
1504
  The malloc_chunk declaration below is misleading (but accurate and
1505
  necessary).  It declares a "view" into memory allowing access to
1505
  necessary).  It declares a "view" into memory allowing access to
1506
  necessary fields at known offsets from a given base.
1506
  necessary fields at known offsets from a given base.
1507
 
1507
 
1508
  Chunks of memory are maintained using a `boundary tag' method as
1508
  Chunks of memory are maintained using a `boundary tag' method as
1509
  originally described by Knuth.  (See the paper by Paul Wilson
1509
  originally described by Knuth.  (See the paper by Paul Wilson
1510
  ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
1510
  ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
1511
  techniques.)  Sizes of free chunks are stored both in the front of
1511
  techniques.)  Sizes of free chunks are stored both in the front of
1512
  each chunk and at the end.  This makes consolidating fragmented
1512
  each chunk and at the end.  This makes consolidating fragmented
1513
  chunks into bigger chunks fast.  The head fields also hold bits
1513
  chunks into bigger chunks fast.  The head fields also hold bits
1514
  representing whether chunks are free or in use.
1514
  representing whether chunks are free or in use.
1515
 
1515
 
1516
  Here are some pictures to make it clearer.  They are "exploded" to
1516
  Here are some pictures to make it clearer.  They are "exploded" to
1517
  show that the state of a chunk can be thought of as extending from
1517
  show that the state of a chunk can be thought of as extending from
1518
  the high 31 bits of the head field of its header through the
1518
  the high 31 bits of the head field of its header through the
1519
  prev_foot and PINUSE_BIT bit of the following chunk header.
1519
  prev_foot and PINUSE_BIT bit of the following chunk header.
1520
 
1520
 
1521
  A chunk that's in use looks like:
1521
  A chunk that's in use looks like:
1522
 
1522
 
1523
   chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1523
   chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1524
           | Size of previous chunk (if P = 1)                             |
1524
           | Size of previous chunk (if P = 1)                             |
1525
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1525
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1526
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
1526
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
1527
         | Size of this chunk                                         1| +-+
1527
         | Size of this chunk                                         1| +-+
1528
   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1528
   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1529
         |                                                               |
1529
         |                                                               |
1530
         +-                                                             -+
1530
         +-                                                             -+
1531
         |                                                               |
1531
         |                                                               |
1532
         +-                                                             -+
1532
         +-                                                             -+
1533
         |                                                               :
1533
         |                                                               :
1534
         +-      size - sizeof(size_t) available payload bytes          -+
1534
         +-      size - sizeof(size_t) available payload bytes          -+
1535
         :                                                               |
1535
         :                                                               |
1536
 chunk-> +-                                                             -+
1536
 chunk-> +-                                                             -+
1537
         |                                                               |
1537
         |                                                               |
1538
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1538
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1539
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
1539
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
1540
       | Size of next chunk (may or may not be in use)               | +-+
1540
       | Size of next chunk (may or may not be in use)               | +-+
1541
 mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1541
 mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1542
 
1542
 
1543
    And if it's free, it looks like this:
1543
    And if it's free, it looks like this:
1544
 
1544
 
1545
   chunk-> +-                                                             -+
1545
   chunk-> +-                                                             -+
1546
           | User payload (must be in use, or we would have merged!)       |
1546
           | User payload (must be in use, or we would have merged!)       |
1547
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1547
           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1548
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
1548
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
1549
         | Size of this chunk                                         0| +-+
1549
         | Size of this chunk                                         0| +-+
1550
   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1550
   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1551
         | Next pointer                                                  |
1551
         | Next pointer                                                  |
1552
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1552
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1553
         | Prev pointer                                                  |
1553
         | Prev pointer                                                  |
1554
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1554
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1555
         |                                                               :
1555
         |                                                               :
1556
         +-      size - sizeof(struct chunk) unused bytes               -+
1556
         +-      size - sizeof(struct chunk) unused bytes               -+
1557
         :                                                               |
1557
         :                                                               |
1558
 chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1558
 chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1559
         | Size of this chunk                                            |
1559
         | Size of this chunk                                            |
1560
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1560
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1561
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
1561
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
1562
       | Size of next chunk (must be in use, or we would have merged)| +-+
1562
       | Size of next chunk (must be in use, or we would have merged)| +-+
1563
 mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1563
 mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1564
       |                                                               :
1564
       |                                                               :
1565
       +- User payload                                                -+
1565
       +- User payload                                                -+
1566
       :                                                               |
1566
       :                                                               |
1567
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1567
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1568
                                                                     |0|
1568
                                                                     |0|
1569
                                                                     +-+
1569
                                                                     +-+
1570
  Note that since we always merge adjacent free chunks, the chunks
1570
  Note that since we always merge adjacent free chunks, the chunks
1571
  adjacent to a free chunk must be in use.
1571
  adjacent to a free chunk must be in use.
1572
 
1572
 
1573
  Given a pointer to a chunk (which can be derived trivially from the
1573
  Given a pointer to a chunk (which can be derived trivially from the
1574
  payload pointer) we can, in O(1) time, find out whether the adjacent
1574
  payload pointer) we can, in O(1) time, find out whether the adjacent
1575
  chunks are free, and if so, unlink them from the lists that they
1575
  chunks are free, and if so, unlink them from the lists that they
1576
  are on and merge them with the current chunk.
1576
  are on and merge them with the current chunk.
1577
 
1577
 
1578
  Chunks always begin on even word boundaries, so the mem portion
1578
  Chunks always begin on even word boundaries, so the mem portion
1579
  (which is returned to the user) is also on an even word boundary, and
1579
  (which is returned to the user) is also on an even word boundary, and
1580
  thus at least double-word aligned.
1580
  thus at least double-word aligned.
1581
 
1581
 
1582
  The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
1582
  The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
1583
  chunk size (which is always a multiple of two words), is an in-use
1583
  chunk size (which is always a multiple of two words), is an in-use
1584
  bit for the *previous* chunk.  If that bit is *clear*, then the
1584
  bit for the *previous* chunk.  If that bit is *clear*, then the
1585
  word before the current chunk size contains the previous chunk
1585
  word before the current chunk size contains the previous chunk
1586
  size, and can be used to find the front of the previous chunk.
1586
  size, and can be used to find the front of the previous chunk.
1587
  The very first chunk allocated always has this bit set, preventing
1587
  The very first chunk allocated always has this bit set, preventing
1588
  access to non-existent (or non-owned) memory. If pinuse is set for
1588
  access to non-existent (or non-owned) memory. If pinuse is set for
1589
  any given chunk, then you CANNOT determine the size of the
1589
  any given chunk, then you CANNOT determine the size of the
1590
  previous chunk, and might even get a memory addressing fault when
1590
  previous chunk, and might even get a memory addressing fault when
1591
  trying to do so.
1591
  trying to do so.
1592
 
1592
 
1593
  The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
1593
  The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
1594
  the chunk size redundantly records whether the current chunk is
1594
  the chunk size redundantly records whether the current chunk is
1595
  inuse. This redundancy enables usage checks within free and realloc,
1595
  inuse. This redundancy enables usage checks within free and realloc,
1596
  and reduces indirection when freeing and consolidating chunks.
1596
  and reduces indirection when freeing and consolidating chunks.
1597
 
1597
 
1598
  Each freshly allocated chunk must have both cinuse and pinuse set.
1598
  Each freshly allocated chunk must have both cinuse and pinuse set.
1599
  That is, each allocated chunk borders either a previously allocated
1599
  That is, each allocated chunk borders either a previously allocated
1600
  and still in-use chunk, or the base of its memory arena. This is
1600
  and still in-use chunk, or the base of its memory arena. This is
1601
  ensured by making all allocations from the the `lowest' part of any
1601
  ensured by making all allocations from the the `lowest' part of any
1602
  found chunk.  Further, no free chunk physically borders another one,
1602
  found chunk.  Further, no free chunk physically borders another one,
1603
  so each free chunk is known to be preceded and followed by either
1603
  so each free chunk is known to be preceded and followed by either
1604
  inuse chunks or the ends of memory.
1604
  inuse chunks or the ends of memory.
1605
 
1605
 
1606
  Note that the `foot' of the current chunk is actually represented
1606
  Note that the `foot' of the current chunk is actually represented
1607
  as the prev_foot of the NEXT chunk. This makes it easier to
1607
  as the prev_foot of the NEXT chunk. This makes it easier to
1608
  deal with alignments etc but can be very confusing when trying
1608
  deal with alignments etc but can be very confusing when trying
1609
  to extend or adapt this code.
1609
  to extend or adapt this code.
1610
 
1610
 
1611
  The exceptions to all this are
1611
  The exceptions to all this are
1612
 
1612
 
1613
     1. The special chunk `top' is the top-most available chunk (i.e.,
1613
     1. The special chunk `top' is the top-most available chunk (i.e.,
1614
        the one bordering the end of available memory). It is treated
1614
        the one bordering the end of available memory). It is treated
1615
        specially.  Top is never included in any bin, is used only if
1615
        specially.  Top is never included in any bin, is used only if
1616
        no other chunk is available, and is released back to the
1616
        no other chunk is available, and is released back to the
1617
        system if it is very large (see M_TRIM_THRESHOLD).  In effect,
1617
        system if it is very large (see M_TRIM_THRESHOLD).  In effect,
1618
        the top chunk is treated as larger (and thus less well
1618
        the top chunk is treated as larger (and thus less well
1619
        fitting) than any other available chunk.  The top chunk
1619
        fitting) than any other available chunk.  The top chunk
1620
        doesn't update its trailing size field since there is no next
1620
        doesn't update its trailing size field since there is no next
1621
        contiguous chunk that would have to index off it. However,
1621
        contiguous chunk that would have to index off it. However,
1622
        space is still allocated for it (TOP_FOOT_SIZE) to enable
1622
        space is still allocated for it (TOP_FOOT_SIZE) to enable
1623
        separation or merging when space is extended.
1623
        separation or merging when space is extended.
1624
 
1624
 
1625
     3. Chunks allocated via mmap, which have the lowest-order bit
1625
     3. Chunks allocated via mmap, which have the lowest-order bit
1626
        (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set
1626
        (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set
1627
        PINUSE_BIT in their head fields.  Because they are allocated
1627
        PINUSE_BIT in their head fields.  Because they are allocated
1628
        one-by-one, each must carry its own prev_foot field, which is
1628
        one-by-one, each must carry its own prev_foot field, which is
1629
        also used to hold the offset this chunk has within its mmapped
1629
        also used to hold the offset this chunk has within its mmapped
1630
        region, which is needed to preserve alignment. Each mmapped
1630
        region, which is needed to preserve alignment. Each mmapped
1631
        chunk is trailed by the first two fields of a fake next-chunk
1631
        chunk is trailed by the first two fields of a fake next-chunk
1632
        for sake of usage checks.
1632
        for sake of usage checks.
1633
 
1633
 
1634
*/
1634
*/
1635
 
1635
 
1636
struct malloc_chunk {
1636
struct malloc_chunk {
1637
  size_t               prev_foot;  /* Size of previous chunk (if free).  */
1637
  size_t               prev_foot;  /* Size of previous chunk (if free).  */
1638
  size_t               head;       /* Size and inuse bits. */
1638
  size_t               head;       /* Size and inuse bits. */
1639
  struct malloc_chunk* fd;         /* double links -- used only if free. */
1639
  struct malloc_chunk* fd;         /* double links -- used only if free. */
1640
  struct malloc_chunk* bk;
1640
  struct malloc_chunk* bk;
1641
};
1641
};
1642
 
1642
 
1643
typedef struct malloc_chunk  mchunk;
1643
typedef struct malloc_chunk  mchunk;
1644
typedef struct malloc_chunk* mchunkptr;
1644
typedef struct malloc_chunk* mchunkptr;
1645
typedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */
1645
typedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */
1646
typedef unsigned int bindex_t;         /* Described below */
1646
typedef unsigned int bindex_t;         /* Described below */
1647
typedef unsigned int binmap_t;         /* Described below */
1647
typedef unsigned int binmap_t;         /* Described below */
1648
typedef unsigned int flag_t;           /* The type of various bit flag sets */
1648
typedef unsigned int flag_t;           /* The type of various bit flag sets */
1649
 
1649
 
1650
/* ------------------- Chunks sizes and alignments ----------------------- */
1650
/* ------------------- Chunks sizes and alignments ----------------------- */
1651
 
1651
 
1652
#define MCHUNK_SIZE         (sizeof(mchunk))
1652
#define MCHUNK_SIZE         (sizeof(mchunk))
1653
 
1653
 
1654
#if FOOTERS
1654
#if FOOTERS
1655
#define CHUNK_OVERHEAD      (TWO_SIZE_T_SIZES)
1655
#define CHUNK_OVERHEAD      (TWO_SIZE_T_SIZES)
1656
#else /* FOOTERS */
1656
#else /* FOOTERS */
1657
#define CHUNK_OVERHEAD      (SIZE_T_SIZE)
1657
#define CHUNK_OVERHEAD      (SIZE_T_SIZE)
1658
#endif /* FOOTERS */
1658
#endif /* FOOTERS */
1659
 
1659
 
1660
/* MMapped chunks need a second word of overhead ... */
1660
/* MMapped chunks need a second word of overhead ... */
1661
#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
1661
#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
1662
/* ... and additional padding for fake next-chunk at foot */
1662
/* ... and additional padding for fake next-chunk at foot */
1663
#define MMAP_FOOT_PAD       (FOUR_SIZE_T_SIZES)
1663
#define MMAP_FOOT_PAD       (FOUR_SIZE_T_SIZES)
1664
 
1664
 
1665
/* The smallest size we can malloc is an aligned minimal chunk */
1665
/* The smallest size we can malloc is an aligned minimal chunk */
1666
#define MIN_CHUNK_SIZE\
1666
#define MIN_CHUNK_SIZE\
1667
  ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
1667
  ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
1668
 
1668
 
1669
/* conversion from malloc headers to user pointers, and back */
1669
/* conversion from malloc headers to user pointers, and back */
1670
#define chunk2mem(p)        ((void*)((char*)(p)       + TWO_SIZE_T_SIZES))
1670
#define chunk2mem(p)        ((void*)((char*)(p)       + TWO_SIZE_T_SIZES))
1671
#define mem2chunk(mem)      ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
1671
#define mem2chunk(mem)      ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
1672
/* chunk associated with aligned address A */
1672
/* chunk associated with aligned address A */
1673
#define align_as_chunk(A)   (mchunkptr)((A) + align_offset(chunk2mem(A)))
1673
#define align_as_chunk(A)   (mchunkptr)((A) + align_offset(chunk2mem(A)))
1674
 
1674
 
1675
/* Bounds on request (not chunk) sizes. */
1675
/* Bounds on request (not chunk) sizes. */
1676
#define MAX_REQUEST         ((-MIN_CHUNK_SIZE) << 2)
1676
#define MAX_REQUEST         ((-MIN_CHUNK_SIZE) << 2)
1677
#define MIN_REQUEST         (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
1677
#define MIN_REQUEST         (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
1678
 
1678
 
1679
/* pad request bytes into a usable size */
1679
/* pad request bytes into a usable size */
1680
#define pad_request(req) \
1680
#define pad_request(req) \
1681
   (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
1681
   (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
1682
 
1682
 
1683
/* pad request, checking for minimum (but not maximum) */
1683
/* pad request, checking for minimum (but not maximum) */
1684
#define request2size(req) \
1684
#define request2size(req) \
1685
  (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
1685
  (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
1686
 
1686
 
1687
 
1687
 
1688
/* ------------------ Operations on head and foot fields ----------------- */
1688
/* ------------------ Operations on head and foot fields ----------------- */
1689
 
1689
 
1690
/*
1690
/*
1691
  The head field of a chunk is or'ed with PINUSE_BIT when previous
1691
  The head field of a chunk is or'ed with PINUSE_BIT when previous
1692
  adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
1692
  adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
1693
  use. If the chunk was obtained with mmap, the prev_foot field has
1693
  use. If the chunk was obtained with mmap, the prev_foot field has
1694
  IS_MMAPPED_BIT set, otherwise holding the offset of the base of the
1694
  IS_MMAPPED_BIT set, otherwise holding the offset of the base of the
1695
  mmapped region to the base of the chunk.
1695
  mmapped region to the base of the chunk.
1696
*/
1696
*/
1697
 
1697
 
1698
#define PINUSE_BIT          (SIZE_T_ONE)
1698
#define PINUSE_BIT          (SIZE_T_ONE)
1699
#define CINUSE_BIT          (SIZE_T_TWO)
1699
#define CINUSE_BIT          (SIZE_T_TWO)
1700
#define INUSE_BITS          (PINUSE_BIT|CINUSE_BIT)
1700
#define INUSE_BITS          (PINUSE_BIT|CINUSE_BIT)
1701
 
1701
 
1702
/* Head value for fenceposts */
1702
/* Head value for fenceposts */
1703
#define FENCEPOST_HEAD      (INUSE_BITS|SIZE_T_SIZE)
1703
#define FENCEPOST_HEAD      (INUSE_BITS|SIZE_T_SIZE)
1704
 
1704
 
1705
/* extraction of fields from head words */
1705
/* extraction of fields from head words */
1706
#define cinuse(p)           ((p)->head & CINUSE_BIT)
1706
#define cinuse(p)           ((p)->head & CINUSE_BIT)
1707
#define pinuse(p)           ((p)->head & PINUSE_BIT)
1707
#define pinuse(p)           ((p)->head & PINUSE_BIT)
1708
#define chunksize(p)        ((p)->head & ~(INUSE_BITS))
1708
#define chunksize(p)        ((p)->head & ~(INUSE_BITS))
1709
 
1709
 
1710
#define clear_pinuse(p)     ((p)->head &= ~PINUSE_BIT)
1710
#define clear_pinuse(p)     ((p)->head &= ~PINUSE_BIT)
1711
#define clear_cinuse(p)     ((p)->head &= ~CINUSE_BIT)
1711
#define clear_cinuse(p)     ((p)->head &= ~CINUSE_BIT)
1712
 
1712
 
1713
/* Treat space at ptr +/- offset as a chunk */
1713
/* Treat space at ptr +/- offset as a chunk */
1714
#define chunk_plus_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
1714
#define chunk_plus_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
1715
#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
1715
#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
1716
 
1716
 
1717
/* Ptr to next or previous physical malloc_chunk. */
1717
/* Ptr to next or previous physical malloc_chunk. */
1718
#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS)))
1718
#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS)))
1719
#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
1719
#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
1720
 
1720
 
1721
/* extract next chunk's pinuse bit */
1721
/* extract next chunk's pinuse bit */
1722
#define next_pinuse(p)  ((next_chunk(p)->head) & PINUSE_BIT)
1722
#define next_pinuse(p)  ((next_chunk(p)->head) & PINUSE_BIT)
1723
 
1723
 
1724
/* Get/set size at footer */
1724
/* Get/set size at footer */
1725
#define get_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot)
1725
#define get_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot)
1726
#define set_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
1726
#define set_foot(p, s)  (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
1727
 
1727
 
1728
/* Set size, pinuse bit, and foot */
1728
/* Set size, pinuse bit, and foot */
1729
#define set_size_and_pinuse_of_free_chunk(p, s)\
1729
#define set_size_and_pinuse_of_free_chunk(p, s)\
1730
  ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
1730
  ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
1731
 
1731
 
1732
/* Set size, pinuse bit, foot, and clear next pinuse */
1732
/* Set size, pinuse bit, foot, and clear next pinuse */
1733
#define set_free_with_pinuse(p, s, n)\
1733
#define set_free_with_pinuse(p, s, n)\
1734
  (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
1734
  (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
1735
 
1735
 
1736
#define is_mmapped(p)\
1736
#define is_mmapped(p)\
1737
  (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT))
1737
  (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT))
1738
 
1738
 
1739
/* Get the internal overhead associated with chunk p */
1739
/* Get the internal overhead associated with chunk p */
1740
#define overhead_for(p)\
1740
#define overhead_for(p)\
1741
 (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
1741
 (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
1742
 
1742
 
1743
/* Return true if malloced space is not necessarily cleared */
1743
/* Return true if malloced space is not necessarily cleared */
1744
#if MMAP_CLEARS
1744
#if MMAP_CLEARS
1745
#define calloc_must_clear(p) (!is_mmapped(p))
1745
#define calloc_must_clear(p) (!is_mmapped(p))
1746
#else /* MMAP_CLEARS */
1746
#else /* MMAP_CLEARS */
1747
#define calloc_must_clear(p) (1)
1747
#define calloc_must_clear(p) (1)
1748
#endif /* MMAP_CLEARS */
1748
#endif /* MMAP_CLEARS */
1749
 
1749
 
1750
/* ---------------------- Overlaid data structures ----------------------- */
1750
/* ---------------------- Overlaid data structures ----------------------- */
1751
 
1751
 
1752
/*
1752
/*
1753
  When chunks are not in use, they are treated as nodes of either
1753
  When chunks are not in use, they are treated as nodes of either
1754
  lists or trees.
1754
  lists or trees.
1755
 
1755
 
1756
  "Small"  chunks are stored in circular doubly-linked lists, and look
1756
  "Small"  chunks are stored in circular doubly-linked lists, and look
1757
  like this:
1757
  like this:
1758
 
1758
 
1759
    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1759
    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1760
            |             Size of previous chunk                            |
1760
            |             Size of previous chunk                            |
1761
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1761
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1762
    `head:' |             Size of chunk, in bytes                         |P|
1762
    `head:' |             Size of chunk, in bytes                         |P|
1763
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1763
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1764
            |             Forward pointer to next chunk in list             |
1764
            |             Forward pointer to next chunk in list             |
1765
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1765
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1766
            |             Back pointer to previous chunk in list            |
1766
            |             Back pointer to previous chunk in list            |
1767
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1767
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1768
            |             Unused space (may be 0 bytes long)                .
1768
            |             Unused space (may be 0 bytes long)                .
1769
            .                                                               .
1769
            .                                                               .
1770
            .                                                               |
1770
            .                                                               |
1771
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1771
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1772
    `foot:' |             Size of chunk, in bytes                           |
1772
    `foot:' |             Size of chunk, in bytes                           |
1773
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1773
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1774
 
1774
 
1775
  Larger chunks are kept in a form of bitwise digital trees (aka
1775
  Larger chunks are kept in a form of bitwise digital trees (aka
1776
  tries) keyed on chunksizes.  Because malloc_tree_chunks are only for
1776
  tries) keyed on chunksizes.  Because malloc_tree_chunks are only for
1777
  free chunks greater than 256 bytes, their size doesn't impose any
1777
  free chunks greater than 256 bytes, their size doesn't impose any
1778
  constraints on user chunk sizes.  Each node looks like:
1778
  constraints on user chunk sizes.  Each node looks like:
1779
 
1779
 
1780
    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1780
    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1781
            |             Size of previous chunk                            |
1781
            |             Size of previous chunk                            |
1782
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1782
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1783
    `head:' |             Size of chunk, in bytes                         |P|
1783
    `head:' |             Size of chunk, in bytes                         |P|
1784
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1784
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1785
            |             Forward pointer to next chunk of same size        |
1785
            |             Forward pointer to next chunk of same size        |
1786
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1786
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1787
            |             Back pointer to previous chunk of same size       |
1787
            |             Back pointer to previous chunk of same size       |
1788
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1788
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1789
            |             Pointer to left child (child[0])                  |
1789
            |             Pointer to left child (child[0])                  |
1790
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1790
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1791
            |             Pointer to right child (child[1])                 |
1791
            |             Pointer to right child (child[1])                 |
1792
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1792
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1793
            |             Pointer to parent                                 |
1793
            |             Pointer to parent                                 |
1794
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1794
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1795
            |             bin index of this chunk                           |
1795
            |             bin index of this chunk                           |
1796
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1796
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1797
            |             Unused space                                      .
1797
            |             Unused space                                      .
1798
            .                                                               |
1798
            .                                                               |
1799
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1799
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1800
    `foot:' |             Size of chunk, in bytes                           |
1800
    `foot:' |             Size of chunk, in bytes                           |
1801
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1801
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1802
 
1802
 
1803
  Each tree holding treenodes is a tree of unique chunk sizes.  Chunks
1803
  Each tree holding treenodes is a tree of unique chunk sizes.  Chunks
1804
  of the same size are arranged in a circularly-linked list, with only
1804
  of the same size are arranged in a circularly-linked list, with only
1805
  the oldest chunk (the next to be used, in our FIFO ordering)
1805
  the oldest chunk (the next to be used, in our FIFO ordering)
1806
  actually in the tree.  (Tree members are distinguished by a non-null
1806
  actually in the tree.  (Tree members are distinguished by a non-null
1807
  parent pointer.)  If a chunk with the same size an an existing node
1807
  parent pointer.)  If a chunk with the same size an an existing node
1808
  is inserted, it is linked off the existing node using pointers that
1808
  is inserted, it is linked off the existing node using pointers that
1809
  work in the same way as fd/bk pointers of small chunks.
1809
  work in the same way as fd/bk pointers of small chunks.
1810
 
1810
 
1811
  Each tree contains a power of 2 sized range of chunk sizes (the
1811
  Each tree contains a power of 2 sized range of chunk sizes (the
1812
  smallest is 0x100 <= x < 0x180), which is is divided in half at each
1812
  smallest is 0x100 <= x < 0x180), which is is divided in half at each
1813
  tree level, with the chunks in the smaller half of the range (0x100
1813
  tree level, with the chunks in the smaller half of the range (0x100
1814
  <= x < 0x140 for the top nose) in the left subtree and the larger
1814
  <= x < 0x140 for the top nose) in the left subtree and the larger
1815
  half (0x140 <= x < 0x180) in the right subtree.  This is, of course,
1815
  half (0x140 <= x < 0x180) in the right subtree.  This is, of course,
1816
  done by inspecting individual bits.
1816
  done by inspecting individual bits.
1817
 
1817
 
1818
  Using these rules, each node's left subtree contains all smaller
1818
  Using these rules, each node's left subtree contains all smaller
1819
  sizes than its right subtree.  However, the node at the root of each
1819
  sizes than its right subtree.  However, the node at the root of each
1820
  subtree has no particular ordering relationship to either.  (The
1820
  subtree has no particular ordering relationship to either.  (The
1821
  dividing line between the subtree sizes is based on trie relation.)
1821
  dividing line between the subtree sizes is based on trie relation.)
1822
  If we remove the last chunk of a given size from the interior of the
1822
  If we remove the last chunk of a given size from the interior of the
1823
  tree, we need to replace it with a leaf node.  The tree ordering
1823
  tree, we need to replace it with a leaf node.  The tree ordering
1824
  rules permit a node to be replaced by any leaf below it.
1824
  rules permit a node to be replaced by any leaf below it.
1825
 
1825
 
1826
  The smallest chunk in a tree (a common operation in a best-fit
1826
  The smallest chunk in a tree (a common operation in a best-fit
1827
  allocator) can be found by walking a path to the leftmost leaf in
1827
  allocator) can be found by walking a path to the leftmost leaf in
1828
  the tree.  Unlike a usual binary tree, where we follow left child
1828
  the tree.  Unlike a usual binary tree, where we follow left child
1829
  pointers until we reach a null, here we follow the right child
1829
  pointers until we reach a null, here we follow the right child
1830
  pointer any time the left one is null, until we reach a leaf with
1830
  pointer any time the left one is null, until we reach a leaf with
1831
  both child pointers null. The smallest chunk in the tree will be
1831
  both child pointers null. The smallest chunk in the tree will be
1832
  somewhere along that path.
1832
  somewhere along that path.
1833
 
1833
 
1834
  The worst case number of steps to add, find, or remove a node is
1834
  The worst case number of steps to add, find, or remove a node is
1835
  bounded by the number of bits differentiating chunks within
1835
  bounded by the number of bits differentiating chunks within
1836
  bins. Under current bin calculations, this ranges from 6 up to 21
1836
  bins. Under current bin calculations, this ranges from 6 up to 21
1837
  (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
1837
  (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
1838
  is of course much better.
1838
  is of course much better.
1839
*/
1839
*/
1840
 
1840
 
1841
struct malloc_tree_chunk {
1841
struct malloc_tree_chunk {
1842
  /* The first four fields must be compatible with malloc_chunk */
1842
  /* The first four fields must be compatible with malloc_chunk */
1843
  size_t                    prev_foot;
1843
  size_t                    prev_foot;
1844
  size_t                    head;
1844
  size_t                    head;
1845
  struct malloc_tree_chunk* fd;
1845
  struct malloc_tree_chunk* fd;
1846
  struct malloc_tree_chunk* bk;
1846
  struct malloc_tree_chunk* bk;
1847
 
1847
 
1848
  struct malloc_tree_chunk* child[2];
1848
  struct malloc_tree_chunk* child[2];
1849
  struct malloc_tree_chunk* parent;
1849
  struct malloc_tree_chunk* parent;
1850
  bindex_t                  index;
1850
  bindex_t                  index;
1851
};
1851
};
1852
 
1852
 
1853
typedef struct malloc_tree_chunk  tchunk;
1853
typedef struct malloc_tree_chunk  tchunk;
1854
typedef struct malloc_tree_chunk* tchunkptr;
1854
typedef struct malloc_tree_chunk* tchunkptr;
1855
typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
1855
typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
1856
 
1856
 
1857
/* A little helper macro for trees */
1857
/* A little helper macro for trees */
1858
#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
1858
#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
1859
 
1859
 
1860
/* ----------------------------- Segments -------------------------------- */
1860
/* ----------------------------- Segments -------------------------------- */
1861
 
1861
 
1862
/*
1862
/*
1863
  Each malloc space may include non-contiguous segments, held in a
1863
  Each malloc space may include non-contiguous segments, held in a
1864
  list headed by an embedded malloc_segment record representing the
1864
  list headed by an embedded malloc_segment record representing the
1865
  top-most space. Segments also include flags holding properties of
1865
  top-most space. Segments also include flags holding properties of
1866
  the space. Large chunks that are directly allocated by mmap are not
1866
  the space. Large chunks that are directly allocated by mmap are not
1867
  included in this list. They are instead independently created and
1867
  included in this list. They are instead independently created and
1868
  destroyed without otherwise keeping track of them.
1868
  destroyed without otherwise keeping track of them.
1869
 
1869
 
1870
  Segment management mainly comes into play for spaces allocated by
1870
  Segment management mainly comes into play for spaces allocated by
1871
  MMAP.  Any call to MMAP might or might not return memory that is
1871
  MMAP.  Any call to MMAP might or might not return memory that is
1872
  adjacent to an existing segment.  MORECORE normally contiguously
1872
  adjacent to an existing segment.  MORECORE normally contiguously
1873
  extends the current space, so this space is almost always adjacent,
1873
  extends the current space, so this space is almost always adjacent,
1874
  which is simpler and faster to deal with. (This is why MORECORE is
1874
  which is simpler and faster to deal with. (This is why MORECORE is
1875
  used preferentially to MMAP when both are available -- see
1875
  used preferentially to MMAP when both are available -- see
1876
  sys_alloc.)  When allocating using MMAP, we don't use any of the
1876
  sys_alloc.)  When allocating using MMAP, we don't use any of the
1877
  hinting mechanisms (inconsistently) supported in various
1877
  hinting mechanisms (inconsistently) supported in various
1878
  implementations of unix mmap, or distinguish reserving from
1878
  implementations of unix mmap, or distinguish reserving from
1879
  committing memory. Instead, we just ask for space, and exploit
1879
  committing memory. Instead, we just ask for space, and exploit
1880
  contiguity when we get it.  It is probably possible to do
1880
  contiguity when we get it.  It is probably possible to do
1881
  better than this on some systems, but no general scheme seems
1881
  better than this on some systems, but no general scheme seems
1882
  to be significantly better.
1882
  to be significantly better.
1883
 
1883
 
1884
  Management entails a simpler variant of the consolidation scheme
1884
  Management entails a simpler variant of the consolidation scheme
1885
  used for chunks to reduce fragmentation -- new adjacent memory is
1885
  used for chunks to reduce fragmentation -- new adjacent memory is
1886
  normally prepended or appended to an existing segment. However,
1886
  normally prepended or appended to an existing segment. However,
1887
  there are limitations compared to chunk consolidation that mostly
1887
  there are limitations compared to chunk consolidation that mostly
1888
  reflect the fact that segment processing is relatively infrequent
1888
  reflect the fact that segment processing is relatively infrequent
1889
  (occurring only when getting memory from system) and that we
1889
  (occurring only when getting memory from system) and that we
1890
  don't expect to have huge numbers of segments:
1890
  don't expect to have huge numbers of segments:
1891
 
1891
 
1892
  * Segments are not indexed, so traversal requires linear scans.  (It
1892
  * Segments are not indexed, so traversal requires linear scans.  (It
1893
    would be possible to index these, but is not worth the extra
1893
    would be possible to index these, but is not worth the extra
1894
    overhead and complexity for most programs on most platforms.)
1894
    overhead and complexity for most programs on most platforms.)
1895
  * New segments are only appended to old ones when holding top-most
1895
  * New segments are only appended to old ones when holding top-most
1896
    memory; if they cannot be prepended to others, they are held in
1896
    memory; if they cannot be prepended to others, they are held in
1897
    different segments.
1897
    different segments.
1898
 
1898
 
1899
  Except for the top-most segment of an mstate, each segment record
1899
  Except for the top-most segment of an mstate, each segment record
1900
  is kept at the tail of its segment. Segments are added by pushing
1900
  is kept at the tail of its segment. Segments are added by pushing
1901
  segment records onto the list headed by &mstate.seg for the
1901
  segment records onto the list headed by &mstate.seg for the
1902
  containing mstate.
1902
  containing mstate.
1903
 
1903
 
1904
  Segment flags control allocation/merge/deallocation policies:
1904
  Segment flags control allocation/merge/deallocation policies:
1905
  * If EXTERN_BIT set, then we did not allocate this segment,
1905
  * If EXTERN_BIT set, then we did not allocate this segment,
1906
    and so should not try to deallocate or merge with others.
1906
    and so should not try to deallocate or merge with others.
1907
    (This currently holds only for the initial segment passed
1907
    (This currently holds only for the initial segment passed
1908
    into create_mspace_with_base.)
1908
    into create_mspace_with_base.)
1909
  * If IS_MMAPPED_BIT set, the segment may be merged with
1909
  * If IS_MMAPPED_BIT set, the segment may be merged with
1910
    other surrounding mmapped segments and trimmed/de-allocated
1910
    other surrounding mmapped segments and trimmed/de-allocated
1911
    using munmap.
1911
    using munmap.
1912
  * If neither bit is set, then the segment was obtained using
1912
  * If neither bit is set, then the segment was obtained using
1913
    MORECORE so can be merged with surrounding MORECORE'd segments
1913
    MORECORE so can be merged with surrounding MORECORE'd segments
1914
    and deallocated/trimmed using MORECORE with negative arguments.
1914
    and deallocated/trimmed using MORECORE with negative arguments.
1915
*/
1915
*/
1916
 
1916
 
1917
struct malloc_segment {
1917
struct malloc_segment {
1918
  char*        base;             /* base address */
1918
  char*        base;             /* base address */
1919
  size_t       size;             /* allocated size */
1919
  size_t       size;             /* allocated size */
1920
  struct malloc_segment* next;   /* ptr to next segment */
1920
  struct malloc_segment* next;   /* ptr to next segment */
1921
  flag_t       sflags;           /* mmap and extern flag */
1921
  flag_t       sflags;           /* mmap and extern flag */
1922
};
1922
};
1923
 
1923
 
1924
#define is_mmapped_segment(S)  ((S)->sflags & IS_MMAPPED_BIT)
1924
#define is_mmapped_segment(S)  ((S)->sflags & IS_MMAPPED_BIT)
1925
#define is_extern_segment(S)   ((S)->sflags & EXTERN_BIT)
1925
#define is_extern_segment(S)   ((S)->sflags & EXTERN_BIT)
1926
 
1926
 
1927
typedef struct malloc_segment  msegment;
1927
typedef struct malloc_segment  msegment;
1928
typedef struct malloc_segment* msegmentptr;
1928
typedef struct malloc_segment* msegmentptr;
1929
 
1929
 
1930
/* ---------------------------- malloc_state ----------------------------- */
1930
/* ---------------------------- malloc_state ----------------------------- */
1931
 
1931
 
1932
/*
1932
/*
1933
   A malloc_state holds all of the bookkeeping for a space.
1933
   A malloc_state holds all of the bookkeeping for a space.
1934
   The main fields are:
1934
   The main fields are:
1935
 
1935
 
1936
  Top
1936
  Top
1937
    The topmost chunk of the currently active segment. Its size is
1937
    The topmost chunk of the currently active segment. Its size is
1938
    cached in topsize.  The actual size of topmost space is
1938
    cached in topsize.  The actual size of topmost space is
1939
    topsize+TOP_FOOT_SIZE, which includes space reserved for adding
1939
    topsize+TOP_FOOT_SIZE, which includes space reserved for adding
1940
    fenceposts and segment records if necessary when getting more
1940
    fenceposts and segment records if necessary when getting more
1941
    space from the system.  The size at which to autotrim top is
1941
    space from the system.  The size at which to autotrim top is
1942
    cached from mparams in trim_check, except that it is disabled if
1942
    cached from mparams in trim_check, except that it is disabled if
1943
    an autotrim fails.
1943
    an autotrim fails.
1944
 
1944
 
1945
  Designated victim (dv)
1945
  Designated victim (dv)
1946
    This is the preferred chunk for servicing small requests that
1946
    This is the preferred chunk for servicing small requests that
1947
    don't have exact fits.  It is normally the chunk split off most
1947
    don't have exact fits.  It is normally the chunk split off most
1948
    recently to service another small request.  Its size is cached in
1948
    recently to service another small request.  Its size is cached in
1949
    dvsize. The link fields of this chunk are not maintained since it
1949
    dvsize. The link fields of this chunk are not maintained since it
1950
    is not kept in a bin.
1950
    is not kept in a bin.
1951
 
1951
 
1952
  SmallBins
1952
  SmallBins
1953
    An array of bin headers for free chunks.  These bins hold chunks
1953
    An array of bin headers for free chunks.  These bins hold chunks
1954
    with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
1954
    with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
1955
    chunks of all the same size, spaced 8 bytes apart.  To simplify
1955
    chunks of all the same size, spaced 8 bytes apart.  To simplify
1956
    use in double-linked lists, each bin header acts as a malloc_chunk
1956
    use in double-linked lists, each bin header acts as a malloc_chunk
1957
    pointing to the real first node, if it exists (else pointing to
1957
    pointing to the real first node, if it exists (else pointing to
1958
    itself).  This avoids special-casing for headers.  But to avoid
1958
    itself).  This avoids special-casing for headers.  But to avoid
1959
    waste, we allocate only the fd/bk pointers of bins, and then use
1959
    waste, we allocate only the fd/bk pointers of bins, and then use
1960
    repositioning tricks to treat these as the fields of a chunk.
1960
    repositioning tricks to treat these as the fields of a chunk.
1961
 
1961
 
1962
  TreeBins
1962
  TreeBins
1963
    Treebins are pointers to the roots of trees holding a range of
1963
    Treebins are pointers to the roots of trees holding a range of
1964
    sizes. There are 2 equally spaced treebins for each power of two
1964
    sizes. There are 2 equally spaced treebins for each power of two
1965
    from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
1965
    from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
1966
    larger.
1966
    larger.
1967
 
1967
 
1968
  Bin maps
1968
  Bin maps
1969
    There is one bit map for small bins ("smallmap") and one for
1969
    There is one bit map for small bins ("smallmap") and one for
1970
    treebins ("treemap).  Each bin sets its bit when non-empty, and
1970
    treebins ("treemap).  Each bin sets its bit when non-empty, and
1971
    clears the bit when empty.  Bit operations are then used to avoid
1971
    clears the bit when empty.  Bit operations are then used to avoid
1972
    bin-by-bin searching -- nearly all "search" is done without ever
1972
    bin-by-bin searching -- nearly all "search" is done without ever
1973
    looking at bins that won't be selected.  The bit maps
1973
    looking at bins that won't be selected.  The bit maps
1974
    conservatively use 32 bits per map word, even if on 64bit system.
1974
    conservatively use 32 bits per map word, even if on 64bit system.
1975
    For a good description of some of the bit-based techniques used
1975
    For a good description of some of the bit-based techniques used
1976
    here, see Henry S. Warren Jr's book "Hacker's Delight" (and
1976
    here, see Henry S. Warren Jr's book "Hacker's Delight" (and
1977
    supplement at http://hackersdelight.org/). Many of these are
1977
    supplement at http://hackersdelight.org/). Many of these are
1978
    intended to reduce the branchiness of paths through malloc etc, as
1978
    intended to reduce the branchiness of paths through malloc etc, as
1979
    well as to reduce the number of memory locations read or written.
1979
    well as to reduce the number of memory locations read or written.
1980
 
1980
 
1981
  Segments
1981
  Segments
1982
    A list of segments headed by an embedded malloc_segment record
1982
    A list of segments headed by an embedded malloc_segment record
1983
    representing the initial space.
1983
    representing the initial space.
1984
 
1984
 
1985
  Address check support
1985
  Address check support
1986
    The least_addr field is the least address ever obtained from
1986
    The least_addr field is the least address ever obtained from
1987
    MORECORE or MMAP. Attempted frees and reallocs of any address less
1987
    MORECORE or MMAP. Attempted frees and reallocs of any address less
1988
    than this are trapped (unless INSECURE is defined).
1988
    than this are trapped (unless INSECURE is defined).
1989
 
1989
 
1990
  Magic tag
1990
  Magic tag
1991
    A cross-check field that should always hold same value as mparams.magic.
1991
    A cross-check field that should always hold same value as mparams.magic.
1992
 
1992
 
1993
  Flags
1993
  Flags
1994
    Bits recording whether to use MMAP, locks, or contiguous MORECORE
1994
    Bits recording whether to use MMAP, locks, or contiguous MORECORE
1995
 
1995
 
1996
  Statistics
1996
  Statistics
1997
    Each space keeps track of current and maximum system memory
1997
    Each space keeps track of current and maximum system memory
1998
    obtained via MORECORE or MMAP.
1998
    obtained via MORECORE or MMAP.
1999
 
1999
 
2000
  Locking
2000
  Locking
2001
    If USE_LOCKS is defined, the "mutex" lock is acquired and released
2001
    If USE_LOCKS is defined, the "mutex" lock is acquired and released
2002
    around every public call using this mspace.
2002
    around every public call using this mspace.
2003
*/
2003
*/
2004
 
2004
 
2005
/* Bin types, widths and sizes */
2005
/* Bin types, widths and sizes */
2006
#define NSMALLBINS        (32U)
2006
#define NSMALLBINS        (32U)
2007
#define NTREEBINS         (32U)
2007
#define NTREEBINS         (32U)
2008
#define SMALLBIN_SHIFT    (3U)
2008
#define SMALLBIN_SHIFT    (3U)
2009
#define SMALLBIN_WIDTH    (SIZE_T_ONE << SMALLBIN_SHIFT)
2009
#define SMALLBIN_WIDTH    (SIZE_T_ONE << SMALLBIN_SHIFT)
2010
#define TREEBIN_SHIFT     (8U)
2010
#define TREEBIN_SHIFT     (8U)
2011
#define MIN_LARGE_SIZE    (SIZE_T_ONE << TREEBIN_SHIFT)
2011
#define MIN_LARGE_SIZE    (SIZE_T_ONE << TREEBIN_SHIFT)
2012
#define MAX_SMALL_SIZE    (MIN_LARGE_SIZE - SIZE_T_ONE)
2012
#define MAX_SMALL_SIZE    (MIN_LARGE_SIZE - SIZE_T_ONE)
2013
#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
2013
#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
2014
 
2014
 
2015
struct malloc_state {
2015
struct malloc_state {
2016
  binmap_t   smallmap;
2016
  binmap_t   smallmap;
2017
  binmap_t   treemap;
2017
  binmap_t   treemap;
2018
  size_t     dvsize;
2018
  size_t     dvsize;
2019
  size_t     topsize;
2019
  size_t     topsize;
2020
  char*      least_addr;
2020
  char*      least_addr;
2021
  mchunkptr  dv;
2021
  mchunkptr  dv;
2022
  mchunkptr  top;
2022
  mchunkptr  top;
2023
  size_t     trim_check;
2023
  size_t     trim_check;
2024
  size_t     magic;
2024
  size_t     magic;
2025
  mchunkptr  smallbins[(NSMALLBINS+1)*2];
2025
  mchunkptr  smallbins[(NSMALLBINS+1)*2];
2026
  tbinptr    treebins[NTREEBINS];
2026
  tbinptr    treebins[NTREEBINS];
2027
  size_t     footprint;
2027
  size_t     footprint;
2028
  size_t     max_footprint;
2028
  size_t     max_footprint;
2029
  flag_t     mflags;
2029
  flag_t     mflags;
2030
#if USE_LOCKS
2030
#if USE_LOCKS
2031
  MLOCK_T    mutex;     /* locate lock among fields that rarely change */
2031
  MLOCK_T    mutex;     /* locate lock among fields that rarely change */
2032
#endif /* USE_LOCKS */
2032
#endif /* USE_LOCKS */
2033
  msegment   seg;
2033
  msegment   seg;
2034
};
2034
};
2035
 
2035
 
2036
typedef struct malloc_state*    mstate;
2036
typedef struct malloc_state*    mstate;
2037
 
2037
 
2038
/* ------------- Global malloc_state and malloc_params ------------------- */
2038
/* ------------- Global malloc_state and malloc_params ------------------- */
2039
 
2039
 
2040
/*
2040
/*
2041
  malloc_params holds global properties, including those that can be
2041
  malloc_params holds global properties, including those that can be
2042
  dynamically set using mallopt. There is a single instance, mparams,
2042
  dynamically set using mallopt. There is a single instance, mparams,
2043
  initialized in init_mparams.
2043
  initialized in init_mparams.
2044
*/
2044
*/
2045
 
2045
 
2046
struct malloc_params {
2046
struct malloc_params {
2047
  size_t magic;
2047
  size_t magic;
2048
  size_t page_size;
2048
  size_t page_size;
2049
  size_t granularity;
2049
  size_t granularity;
2050
  size_t mmap_threshold;
2050
  size_t mmap_threshold;
2051
  size_t trim_threshold;
2051
  size_t trim_threshold;
2052
  flag_t default_mflags;
2052
  flag_t default_mflags;
2053
};
2053
};
2054
 
2054
 
2055
static struct malloc_params mparams;
2055
static struct malloc_params mparams;
2056
 
2056
 
2057
/* The global malloc_state used for all non-"mspace" calls */
2057
/* The global malloc_state used for all non-"mspace" calls */
2058
static struct malloc_state _gm_;
2058
static struct malloc_state _gm_;
2059
#define gm                 (&_gm_)
2059
#define gm                 (&_gm_)
2060
#define is_global(M)       ((M) == &_gm_)
2060
#define is_global(M)       ((M) == &_gm_)
2061
#define is_initialized(M)  ((M)->top != 0)
2061
#define is_initialized(M)  ((M)->top != 0)
2062
 
2062
 
2063
/* -------------------------- system alloc setup ------------------------- */
2063
/* -------------------------- system alloc setup ------------------------- */
2064
 
2064
 
2065
/* Operations on mflags */
2065
/* Operations on mflags */
2066
 
2066
 
2067
#define use_lock(M)           ((M)->mflags &   USE_LOCK_BIT)
2067
#define use_lock(M)           ((M)->mflags &   USE_LOCK_BIT)
2068
#define enable_lock(M)        ((M)->mflags |=  USE_LOCK_BIT)
2068
#define enable_lock(M)        ((M)->mflags |=  USE_LOCK_BIT)
2069
#define disable_lock(M)       ((M)->mflags &= ~USE_LOCK_BIT)
2069
#define disable_lock(M)       ((M)->mflags &= ~USE_LOCK_BIT)
2070
 
2070
 
2071
#define use_mmap(M)           ((M)->mflags &   USE_MMAP_BIT)
2071
#define use_mmap(M)           ((M)->mflags &   USE_MMAP_BIT)
2072
#define enable_mmap(M)        ((M)->mflags |=  USE_MMAP_BIT)
2072
#define enable_mmap(M)        ((M)->mflags |=  USE_MMAP_BIT)
2073
#define disable_mmap(M)       ((M)->mflags &= ~USE_MMAP_BIT)
2073
#define disable_mmap(M)       ((M)->mflags &= ~USE_MMAP_BIT)
2074
 
2074
 
2075
#define use_noncontiguous(M)  ((M)->mflags &   USE_NONCONTIGUOUS_BIT)
2075
#define use_noncontiguous(M)  ((M)->mflags &   USE_NONCONTIGUOUS_BIT)
2076
#define disable_contiguous(M) ((M)->mflags |=  USE_NONCONTIGUOUS_BIT)
2076
#define disable_contiguous(M) ((M)->mflags |=  USE_NONCONTIGUOUS_BIT)
2077
 
2077
 
2078
#define set_lock(M,L)\
2078
#define set_lock(M,L)\
2079
 ((M)->mflags = (L)?\
2079
 ((M)->mflags = (L)?\
2080
  ((M)->mflags | USE_LOCK_BIT) :\
2080
  ((M)->mflags | USE_LOCK_BIT) :\
2081
  ((M)->mflags & ~USE_LOCK_BIT))
2081
  ((M)->mflags & ~USE_LOCK_BIT))
2082
 
2082
 
2083
/* page-align a size */
2083
/* page-align a size */
2084
#define page_align(S)\
2084
#define page_align(S)\
2085
 (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))
2085
 (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))
2086
 
2086
 
2087
/* granularity-align a size */
2087
/* granularity-align a size */
2088
#define granularity_align(S)\
2088
#define granularity_align(S)\
2089
  (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))
2089
  (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))
2090
 
2090
 
2091
#define is_page_aligned(S)\
2091
#define is_page_aligned(S)\
2092
   (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
2092
   (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
2093
#define is_granularity_aligned(S)\
2093
#define is_granularity_aligned(S)\
2094
   (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
2094
   (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
2095
 
2095
 
2096
/*  True if segment S holds address A */
2096
/*  True if segment S holds address A */
2097
#define segment_holds(S, A)\
2097
#define segment_holds(S, A)\
2098
  ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
2098
  ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
2099
 
2099
 
2100
/* Return segment holding given address */
2100
/* Return segment holding given address */
2101
static msegmentptr segment_holding(mstate m, char* addr) {
2101
static msegmentptr segment_holding(mstate m, char* addr) {
2102
  msegmentptr sp = &m->seg;
2102
  msegmentptr sp = &m->seg;
2103
  for (;;) {
2103
  for (;;) {
2104
    if (addr >= sp->base && addr < sp->base + sp->size)
2104
    if (addr >= sp->base && addr < sp->base + sp->size)
2105
      return sp;
2105
      return sp;
2106
    if ((sp = sp->next) == 0)
2106
    if ((sp = sp->next) == 0)
2107
      return 0;
2107
      return 0;
2108
  }
2108
  }
2109
}
2109
}
2110
 
2110
 
2111
/* Return true if segment contains a segment link */
2111
/* Return true if segment contains a segment link */
2112
static int has_segment_link(mstate m, msegmentptr ss) {
2112
static int has_segment_link(mstate m, msegmentptr ss) {
2113
  msegmentptr sp = &m->seg;
2113
  msegmentptr sp = &m->seg;
2114
  for (;;) {
2114
  for (;;) {
2115
    if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
2115
    if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
2116
      return 1;
2116
      return 1;
2117
    if ((sp = sp->next) == 0)
2117
    if ((sp = sp->next) == 0)
2118
      return 0;
2118
      return 0;
2119
  }
2119
  }
2120
}
2120
}
2121
 
2121
 
2122
#ifndef MORECORE_CANNOT_TRIM
2122
#ifndef MORECORE_CANNOT_TRIM
2123
#define should_trim(M,s)  ((s) > (M)->trim_check)
2123
#define should_trim(M,s)  ((s) > (M)->trim_check)
2124
#else  /* MORECORE_CANNOT_TRIM */
2124
#else  /* MORECORE_CANNOT_TRIM */
2125
#define should_trim(M,s)  (0)
2125
#define should_trim(M,s)  (0)
2126
#endif /* MORECORE_CANNOT_TRIM */
2126
#endif /* MORECORE_CANNOT_TRIM */
2127
 
2127
 
2128
/*
2128
/*
2129
  TOP_FOOT_SIZE is padding at the end of a segment, including space
2129
  TOP_FOOT_SIZE is padding at the end of a segment, including space
2130
  that may be needed to place segment records and fenceposts when new
2130
  that may be needed to place segment records and fenceposts when new
2131
  noncontiguous segments are added.
2131
  noncontiguous segments are added.
2132
*/
2132
*/
2133
#define TOP_FOOT_SIZE\
2133
#define TOP_FOOT_SIZE\
2134
  (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
2134
  (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
2135
 
2135
 
2136
 
2136
 
2137
/* -------------------------------  Hooks -------------------------------- */
2137
/* -------------------------------  Hooks -------------------------------- */
2138
 
2138
 
2139
/*
2139
/*
2140
  PREACTION should be defined to return 0 on success, and nonzero on
2140
  PREACTION should be defined to return 0 on success, and nonzero on
2141
  failure. If you are not using locking, you can redefine these to do
2141
  failure. If you are not using locking, you can redefine these to do
2142
  anything you like.
2142
  anything you like.
2143
*/
2143
*/
2144
 
2144
 
2145
#if USE_LOCKS
2145
#if USE_LOCKS
2146
 
2146
 
2147
/* Ensure locks are initialized */
2147
/* Ensure locks are initialized */
2148
#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())
2148
#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())
2149
 
2149
 
2150
#define PREACTION(M)  ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
2150
#define PREACTION(M)  ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
2151
#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
2151
#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
2152
#else /* USE_LOCKS */
2152
#else /* USE_LOCKS */
2153
 
2153
 
2154
#ifndef PREACTION
2154
#ifndef PREACTION
2155
#define PREACTION(M) (0)
2155
#define PREACTION(M) (0)
2156
#endif  /* PREACTION */
2156
#endif  /* PREACTION */
2157
 
2157
 
2158
#ifndef POSTACTION
2158
#ifndef POSTACTION
2159
#define POSTACTION(M)
2159
#define POSTACTION(M)
2160
#endif  /* POSTACTION */
2160
#endif  /* POSTACTION */
2161
 
2161
 
2162
#endif /* USE_LOCKS */
2162
#endif /* USE_LOCKS */
2163
 
2163
 
2164
/*
2164
/*
2165
  CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
2165
  CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
2166
  USAGE_ERROR_ACTION is triggered on detected bad frees and
2166
  USAGE_ERROR_ACTION is triggered on detected bad frees and
2167
  reallocs. The argument p is an address that might have triggered the
2167
  reallocs. The argument p is an address that might have triggered the
2168
  fault. It is ignored by the two predefined actions, but might be
2168
  fault. It is ignored by the two predefined actions, but might be
2169
  useful in custom actions that try to help diagnose errors.
2169
  useful in custom actions that try to help diagnose errors.
2170
*/
2170
*/
2171
 
2171
 
2172
#if PROCEED_ON_ERROR
2172
#if PROCEED_ON_ERROR
2173
 
2173
 
2174
/* A count of the number of corruption errors causing resets */
2174
/* A count of the number of corruption errors causing resets */
2175
int malloc_corruption_error_count;
2175
int malloc_corruption_error_count;
2176
 
2176
 
2177
/* default corruption action */
2177
/* default corruption action */
2178
static void reset_on_error(mstate m);
2178
static void reset_on_error(mstate m);
2179
 
2179
 
2180
#define CORRUPTION_ERROR_ACTION(m)  reset_on_error(m)
2180
#define CORRUPTION_ERROR_ACTION(m)  reset_on_error(m)
2181
#define USAGE_ERROR_ACTION(m, p)
2181
#define USAGE_ERROR_ACTION(m, p)
2182
 
2182
 
2183
#else /* PROCEED_ON_ERROR */
2183
#else /* PROCEED_ON_ERROR */
2184
 
2184
 
2185
#ifndef CORRUPTION_ERROR_ACTION
2185
#ifndef CORRUPTION_ERROR_ACTION
2186
#define CORRUPTION_ERROR_ACTION(m) ABORT
2186
#define CORRUPTION_ERROR_ACTION(m) ABORT
2187
#endif /* CORRUPTION_ERROR_ACTION */
2187
#endif /* CORRUPTION_ERROR_ACTION */
2188
 
2188
 
2189
#ifndef USAGE_ERROR_ACTION
2189
#ifndef USAGE_ERROR_ACTION
2190
#define USAGE_ERROR_ACTION(m,p) ABORT
2190
#define USAGE_ERROR_ACTION(m,p) ABORT
2191
#endif /* USAGE_ERROR_ACTION */
2191
#endif /* USAGE_ERROR_ACTION */
2192
 
2192
 
2193
#endif /* PROCEED_ON_ERROR */
2193
#endif /* PROCEED_ON_ERROR */
2194
 
2194
 
2195
/* -------------------------- Debugging setup ---------------------------- */
2195
/* -------------------------- Debugging setup ---------------------------- */
2196
 
2196
 
2197
#if ! DEBUG
2197
#if ! DEBUG
2198
 
2198
 
2199
#define check_free_chunk(M,P)
2199
#define check_free_chunk(M,P)
2200
#define check_inuse_chunk(M,P)
2200
#define check_inuse_chunk(M,P)
2201
#define check_malloced_chunk(M,P,N)
2201
#define check_malloced_chunk(M,P,N)
2202
#define check_mmapped_chunk(M,P)
2202
#define check_mmapped_chunk(M,P)
2203
#define check_malloc_state(M)
2203
#define check_malloc_state(M)
2204
#define check_top_chunk(M,P)
2204
#define check_top_chunk(M,P)
2205
 
2205
 
2206
#else /* DEBUG */
2206
#else /* DEBUG */
2207
#define check_free_chunk(M,P)       do_check_free_chunk(M,P)
2207
#define check_free_chunk(M,P)       do_check_free_chunk(M,P)
2208
#define check_inuse_chunk(M,P)      do_check_inuse_chunk(M,P)
2208
#define check_inuse_chunk(M,P)      do_check_inuse_chunk(M,P)
2209
#define check_top_chunk(M,P)        do_check_top_chunk(M,P)
2209
#define check_top_chunk(M,P)        do_check_top_chunk(M,P)
2210
#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
2210
#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
2211
#define check_mmapped_chunk(M,P)    do_check_mmapped_chunk(M,P)
2211
#define check_mmapped_chunk(M,P)    do_check_mmapped_chunk(M,P)
2212
#define check_malloc_state(M)       do_check_malloc_state(M)
2212
#define check_malloc_state(M)       do_check_malloc_state(M)
2213
 
2213
 
2214
static void   do_check_any_chunk(mstate m, mchunkptr p);
2214
static void   do_check_any_chunk(mstate m, mchunkptr p);
2215
static void   do_check_top_chunk(mstate m, mchunkptr p);
2215
static void   do_check_top_chunk(mstate m, mchunkptr p);
2216
static void   do_check_mmapped_chunk(mstate m, mchunkptr p);
2216
static void   do_check_mmapped_chunk(mstate m, mchunkptr p);
2217
static void   do_check_inuse_chunk(mstate m, mchunkptr p);
2217
static void   do_check_inuse_chunk(mstate m, mchunkptr p);
2218
static void   do_check_free_chunk(mstate m, mchunkptr p);
2218
static void   do_check_free_chunk(mstate m, mchunkptr p);
2219
static void   do_check_malloced_chunk(mstate m, void* mem, size_t s);
2219
static void   do_check_malloced_chunk(mstate m, void* mem, size_t s);
2220
static void   do_check_tree(mstate m, tchunkptr t);
2220
static void   do_check_tree(mstate m, tchunkptr t);
2221
static void   do_check_treebin(mstate m, bindex_t i);
2221
static void   do_check_treebin(mstate m, bindex_t i);
2222
static void   do_check_smallbin(mstate m, bindex_t i);
2222
static void   do_check_smallbin(mstate m, bindex_t i);
2223
static void   do_check_malloc_state(mstate m);
2223
static void   do_check_malloc_state(mstate m);
2224
static int    bin_find(mstate m, mchunkptr x);
2224
static int    bin_find(mstate m, mchunkptr x);
2225
static size_t traverse_and_check(mstate m);
2225
static size_t traverse_and_check(mstate m);
2226
#endif /* DEBUG */
2226
#endif /* DEBUG */
2227
 
2227
 
2228
/* ---------------------------- Indexing Bins ---------------------------- */
2228
/* ---------------------------- Indexing Bins ---------------------------- */
2229
 
2229
 
2230
#define is_small(s)         (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
2230
#define is_small(s)         (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
2231
#define small_index(s)      ((s)  >> SMALLBIN_SHIFT)
2231
#define small_index(s)      ((s)  >> SMALLBIN_SHIFT)
2232
#define small_index2size(i) ((i)  << SMALLBIN_SHIFT)
2232
#define small_index2size(i) ((i)  << SMALLBIN_SHIFT)
2233
#define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))
2233
#define MIN_SMALL_INDEX     (small_index(MIN_CHUNK_SIZE))
2234
 
2234
 
2235
/* addressing by index. See above about smallbin repositioning */
2235
/* addressing by index. See above about smallbin repositioning */
2236
#define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
2236
#define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
2237
#define treebin_at(M,i)     (&((M)->treebins[i]))
2237
#define treebin_at(M,i)     (&((M)->treebins[i]))
2238
 
2238
 
2239
/* assign tree index for size S to variable I */
2239
/* assign tree index for size S to variable I */
2240
#if defined(__GNUC__) && defined(i386)
2240
#if defined(__GNUC__) && defined(i386)
2241
#define compute_tree_index(S, I)\
2241
#define compute_tree_index(S, I)\
2242
{\
2242
{\
2243
  size_t X = S >> TREEBIN_SHIFT;\
2243
  size_t X = S >> TREEBIN_SHIFT;\
2244
  if (X == 0)\
2244
  if (X == 0)\
2245
    I = 0;\
2245
    I = 0;\
2246
  else if (X > 0xFFFF)\
2246
  else if (X > 0xFFFF)\
2247
    I = NTREEBINS-1;\
2247
    I = NTREEBINS-1;\
2248
  else {\
2248
  else {\
2249
    unsigned int K;\
2249
    unsigned int K;\
2250
    __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm"  (X));\
2250
    __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm"  (X));\
2251
    I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
2251
    I =  (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
2252
  }\
2252
  }\
2253
}
2253
}
2254
#else /* GNUC */
2254
#else /* GNUC */
2255
#define compute_tree_index(S, I)\
2255
#define compute_tree_index(S, I)\
2256
{\
2256
{\
2257
  size_t X = S >> TREEBIN_SHIFT;\
2257
  size_t X = S >> TREEBIN_SHIFT;\
2258
  if (X == 0)\
2258
  if (X == 0)\
2259
    I = 0;\
2259
    I = 0;\
2260
  else if (X > 0xFFFF)\
2260
  else if (X > 0xFFFF)\
2261
    I = NTREEBINS-1;\
2261
    I = NTREEBINS-1;\
2262
  else {\
2262
  else {\
2263
    unsigned int Y = (unsigned int)X;\
2263
    unsigned int Y = (unsigned int)X;\
2264
    unsigned int N = ((Y - 0x100) >> 16) & 8;\
2264
    unsigned int N = ((Y - 0x100) >> 16) & 8;\
2265
    unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
2265
    unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
2266
    N += K;\
2266
    N += K;\
2267
    N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
2267
    N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
2268
    K = 14 - N + ((Y <<= K) >> 15);\
2268
    K = 14 - N + ((Y <<= K) >> 15);\
2269
    I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
2269
    I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
2270
  }\
2270
  }\
2271
}
2271
}
2272
#endif /* GNUC */
2272
#endif /* GNUC */
2273
 
2273
 
2274
/* Bit representing maximum resolved size in a treebin at i */
2274
/* Bit representing maximum resolved size in a treebin at i */
2275
#define bit_for_tree_index(i) \
2275
#define bit_for_tree_index(i) \
2276
   (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
2276
   (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
2277
 
2277
 
2278
/* Shift placing maximum resolved bit in a treebin at i as sign bit */
2278
/* Shift placing maximum resolved bit in a treebin at i as sign bit */
2279
#define leftshift_for_tree_index(i) \
2279
#define leftshift_for_tree_index(i) \
2280
   ((i == NTREEBINS-1)? 0 : \
2280
   ((i == NTREEBINS-1)? 0 : \
2281
    ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
2281
    ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
2282
 
2282
 
2283
/* The size of the smallest chunk held in bin with index i */
2283
/* The size of the smallest chunk held in bin with index i */
2284
#define minsize_for_tree_index(i) \
2284
#define minsize_for_tree_index(i) \
2285
   ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) |  \
2285
   ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) |  \
2286
   (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
2286
   (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
2287
 
2287
 
2288
 
2288
 
2289
/* ------------------------ Operations on bin maps ----------------------- */
2289
/* ------------------------ Operations on bin maps ----------------------- */
2290
 
2290
 
2291
/* bit corresponding to given index */
2291
/* bit corresponding to given index */
2292
#define idx2bit(i)              ((binmap_t)(1) << (i))
2292
#define idx2bit(i)              ((binmap_t)(1) << (i))
2293
 
2293
 
2294
/* Mark/Clear bits with given index */
2294
/* Mark/Clear bits with given index */
2295
#define mark_smallmap(M,i)      ((M)->smallmap |=  idx2bit(i))
2295
#define mark_smallmap(M,i)      ((M)->smallmap |=  idx2bit(i))
2296
#define clear_smallmap(M,i)     ((M)->smallmap &= ~idx2bit(i))
2296
#define clear_smallmap(M,i)     ((M)->smallmap &= ~idx2bit(i))
2297
#define smallmap_is_marked(M,i) ((M)->smallmap &   idx2bit(i))
2297
#define smallmap_is_marked(M,i) ((M)->smallmap &   idx2bit(i))
2298
 
2298
 
2299
#define mark_treemap(M,i)       ((M)->treemap  |=  idx2bit(i))
2299
#define mark_treemap(M,i)       ((M)->treemap  |=  idx2bit(i))
2300
#define clear_treemap(M,i)      ((M)->treemap  &= ~idx2bit(i))
2300
#define clear_treemap(M,i)      ((M)->treemap  &= ~idx2bit(i))
2301
#define treemap_is_marked(M,i)  ((M)->treemap  &   idx2bit(i))
2301
#define treemap_is_marked(M,i)  ((M)->treemap  &   idx2bit(i))
2302
 
2302
 
2303
/* index corresponding to given bit */
2303
/* index corresponding to given bit */
2304
 
2304
 
2305
#if defined(__GNUC__) && defined(i386)
2305
#if defined(__GNUC__) && defined(i386)
2306
#define compute_bit2idx(X, I)\
2306
#define compute_bit2idx(X, I)\
2307
{\
2307
{\
2308
  unsigned int J;\
2308
  unsigned int J;\
2309
  __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\
2309
  __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\
2310
  I = (bindex_t)J;\
2310
  I = (bindex_t)J;\
2311
}
2311
}
2312
 
2312
 
2313
#else /* GNUC */
2313
#else /* GNUC */
2314
#if  USE_BUILTIN_FFS
2314
#if  USE_BUILTIN_FFS
2315
#define compute_bit2idx(X, I) I = ffs(X)-1
2315
#define compute_bit2idx(X, I) I = ffs(X)-1
2316
 
2316
 
2317
#else /* USE_BUILTIN_FFS */
2317
#else /* USE_BUILTIN_FFS */
2318
#define compute_bit2idx(X, I)\
2318
#define compute_bit2idx(X, I)\
2319
{\
2319
{\
2320
  unsigned int Y = X - 1;\
2320
  unsigned int Y = X - 1;\
2321
  unsigned int K = Y >> (16-4) & 16;\
2321
  unsigned int K = Y >> (16-4) & 16;\
2322
  unsigned int N = K;        Y >>= K;\
2322
  unsigned int N = K;        Y >>= K;\
2323
  N += K = Y >> (8-3) &  8;  Y >>= K;\
2323
  N += K = Y >> (8-3) &  8;  Y >>= K;\
2324
  N += K = Y >> (4-2) &  4;  Y >>= K;\
2324
  N += K = Y >> (4-2) &  4;  Y >>= K;\
2325
  N += K = Y >> (2-1) &  2;  Y >>= K;\
2325
  N += K = Y >> (2-1) &  2;  Y >>= K;\
2326
  N += K = Y >> (1-0) &  1;  Y >>= K;\
2326
  N += K = Y >> (1-0) &  1;  Y >>= K;\
2327
  I = (bindex_t)(N + Y);\
2327
  I = (bindex_t)(N + Y);\
2328
}
2328
}
2329
#endif /* USE_BUILTIN_FFS */
2329
#endif /* USE_BUILTIN_FFS */
2330
#endif /* GNUC */
2330
#endif /* GNUC */
2331
 
2331
 
2332
/* isolate the least set bit of a bitmap */
2332
/* isolate the least set bit of a bitmap */
2333
#define least_bit(x)         ((x) & -(x))
2333
#define least_bit(x)         ((x) & -(x))
2334
 
2334
 
2335
/* mask with all bits to left of least bit of x on */
2335
/* mask with all bits to left of least bit of x on */
2336
#define left_bits(x)         ((x<<1) | -(x<<1))
2336
#define left_bits(x)         ((x<<1) | -(x<<1))
2337
 
2337
 
2338
/* mask with all bits to left of or equal to least bit of x on */
2338
/* mask with all bits to left of or equal to least bit of x on */
2339
#define same_or_left_bits(x) ((x) | -(x))
2339
#define same_or_left_bits(x) ((x) | -(x))
2340
 
2340
 
2341
 
2341
 
2342
/* ----------------------- Runtime Check Support ------------------------- */
2342
/* ----------------------- Runtime Check Support ------------------------- */
2343
 
2343
 
2344
/*
2344
/*
2345
  For security, the main invariant is that malloc/free/etc never
2345
  For security, the main invariant is that malloc/free/etc never
2346
  writes to a static address other than malloc_state, unless static
2346
  writes to a static address other than malloc_state, unless static
2347
  malloc_state itself has been corrupted, which cannot occur via
2347
  malloc_state itself has been corrupted, which cannot occur via
2348
  malloc (because of these checks). In essence this means that we
2348
  malloc (because of these checks). In essence this means that we
2349
  believe all pointers, sizes, maps etc held in malloc_state, but
2349
  believe all pointers, sizes, maps etc held in malloc_state, but
2350
  check all of those linked or offsetted from other embedded data
2350
  check all of those linked or offsetted from other embedded data
2351
  structures.  These checks are interspersed with main code in a way
2351
  structures.  These checks are interspersed with main code in a way
2352
  that tends to minimize their run-time cost.
2352
  that tends to minimize their run-time cost.
2353
 
2353
 
2354
  When FOOTERS is defined, in addition to range checking, we also
2354
  When FOOTERS is defined, in addition to range checking, we also
2355
  verify footer fields of inuse chunks, which can be used guarantee
2355
  verify footer fields of inuse chunks, which can be used guarantee
2356
  that the mstate controlling malloc/free is intact.  This is a
2356
  that the mstate controlling malloc/free is intact.  This is a
2357
  streamlined version of the approach described by William Robertson
2357
  streamlined version of the approach described by William Robertson
2358
  et al in "Run-time Detection of Heap-based Overflows" LISA'03
2358
  et al in "Run-time Detection of Heap-based Overflows" LISA'03
2359
  http://www.usenix.org/events/lisa03/tech/robertson.html The footer
2359
  http://www.usenix.org/events/lisa03/tech/robertson.html The footer
2360
  of an inuse chunk holds the xor of its mstate and a random seed,
2360
  of an inuse chunk holds the xor of its mstate and a random seed,
2361
  that is checked upon calls to free() and realloc().  This is
2361
  that is checked upon calls to free() and realloc().  This is
2362
  (probablistically) unguessable from outside the program, but can be
2362
  (probablistically) unguessable from outside the program, but can be
2363
  computed by any code successfully malloc'ing any chunk, so does not
2363
  computed by any code successfully malloc'ing any chunk, so does not
2364
  itself provide protection against code that has already broken
2364
  itself provide protection against code that has already broken
2365
  security through some other means.  Unlike Robertson et al, we
2365
  security through some other means.  Unlike Robertson et al, we
2366
  always dynamically check addresses of all offset chunks (previous,
2366
  always dynamically check addresses of all offset chunks (previous,
2367
  next, etc). This turns out to be cheaper than relying on hashes.
2367
  next, etc). This turns out to be cheaper than relying on hashes.
2368
*/
2368
*/
2369
 
2369
 
2370
#if !INSECURE
2370
#if !INSECURE
2371
/* Check if address a is at least as high as any from MORECORE or MMAP */
2371
/* Check if address a is at least as high as any from MORECORE or MMAP */
2372
#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
2372
#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
2373
/* Check if address of next chunk n is higher than base chunk p */
2373
/* Check if address of next chunk n is higher than base chunk p */
2374
#define ok_next(p, n)    ((char*)(p) < (char*)(n))
2374
#define ok_next(p, n)    ((char*)(p) < (char*)(n))
2375
/* Check if p has its cinuse bit on */
2375
/* Check if p has its cinuse bit on */
2376
#define ok_cinuse(p)     cinuse(p)
2376
#define ok_cinuse(p)     cinuse(p)
2377
/* Check if p has its pinuse bit on */
2377
/* Check if p has its pinuse bit on */
2378
#define ok_pinuse(p)     pinuse(p)
2378
#define ok_pinuse(p)     pinuse(p)
2379
 
2379
 
2380
#else /* !INSECURE */
2380
#else /* !INSECURE */
2381
#define ok_address(M, a) (1)
2381
#define ok_address(M, a) (1)
2382
#define ok_next(b, n)    (1)
2382
#define ok_next(b, n)    (1)
2383
#define ok_cinuse(p)     (1)
2383
#define ok_cinuse(p)     (1)
2384
#define ok_pinuse(p)     (1)
2384
#define ok_pinuse(p)     (1)
2385
#endif /* !INSECURE */
2385
#endif /* !INSECURE */
2386
 
2386
 
2387
#if (FOOTERS && !INSECURE)
2387
#if (FOOTERS && !INSECURE)
2388
/* Check if (alleged) mstate m has expected magic field */
2388
/* Check if (alleged) mstate m has expected magic field */
2389
#define ok_magic(M)      ((M)->magic == mparams.magic)
2389
#define ok_magic(M)      ((M)->magic == mparams.magic)
2390
#else  /* (FOOTERS && !INSECURE) */
2390
#else  /* (FOOTERS && !INSECURE) */
2391
#define ok_magic(M)      (1)
2391
#define ok_magic(M)      (1)
2392
#endif /* (FOOTERS && !INSECURE) */
2392
#endif /* (FOOTERS && !INSECURE) */
2393
 
2393
 
2394
 
2394
 
2395
/* In gcc, use __builtin_expect to minimize impact of checks */
2395
/* In gcc, use __builtin_expect to minimize impact of checks */
2396
#if !INSECURE
2396
#if !INSECURE
2397
#if defined(__GNUC__) && __GNUC__ >= 3
2397
#if defined(__GNUC__) && __GNUC__ >= 3
2398
#define RTCHECK(e)  __builtin_expect(e, 1)
2398
#define RTCHECK(e)  __builtin_expect(e, 1)
2399
#else /* GNUC */
2399
#else /* GNUC */
2400
#define RTCHECK(e)  (e)
2400
#define RTCHECK(e)  (e)
2401
#endif /* GNUC */
2401
#endif /* GNUC */
2402
#else /* !INSECURE */
2402
#else /* !INSECURE */
2403
#define RTCHECK(e)  (1)
2403
#define RTCHECK(e)  (1)
2404
#endif /* !INSECURE */
2404
#endif /* !INSECURE */
2405
 
2405
 
2406
/* macros to set up inuse chunks with or without footers */
2406
/* macros to set up inuse chunks with or without footers */
2407
 
2407
 
2408
#if !FOOTERS
2408
#if !FOOTERS
2409
 
2409
 
2410
#define mark_inuse_foot(M,p,s)
2410
#define mark_inuse_foot(M,p,s)
2411
 
2411
 
2412
/* Set cinuse bit and pinuse bit of next chunk */
2412
/* Set cinuse bit and pinuse bit of next chunk */
2413
#define set_inuse(M,p,s)\
2413
#define set_inuse(M,p,s)\
2414
  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
2414
  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
2415
  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
2415
  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
2416
 
2416
 
2417
/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
2417
/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
2418
#define set_inuse_and_pinuse(M,p,s)\
2418
#define set_inuse_and_pinuse(M,p,s)\
2419
  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
2419
  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
2420
  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
2420
  ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
2421
 
2421
 
2422
/* Set size, cinuse and pinuse bit of this chunk */
2422
/* Set size, cinuse and pinuse bit of this chunk */
2423
#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
2423
#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
2424
  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
2424
  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
2425
 
2425
 
2426
#else /* FOOTERS */
2426
#else /* FOOTERS */
2427
 
2427
 
2428
/* Set foot of inuse chunk to be xor of mstate and seed */
2428
/* Set foot of inuse chunk to be xor of mstate and seed */
2429
#define mark_inuse_foot(M,p,s)\
2429
#define mark_inuse_foot(M,p,s)\
2430
  (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
2430
  (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
2431
 
2431
 
2432
#define get_mstate_for(p)\
2432
#define get_mstate_for(p)\
2433
  ((mstate)(((mchunkptr)((char*)(p) +\
2433
  ((mstate)(((mchunkptr)((char*)(p) +\
2434
    (chunksize(p))))->prev_foot ^ mparams.magic))
2434
    (chunksize(p))))->prev_foot ^ mparams.magic))
2435
 
2435
 
2436
#define set_inuse(M,p,s)\
2436
#define set_inuse(M,p,s)\
2437
  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
2437
  ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
2438
  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
2438
  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
2439
  mark_inuse_foot(M,p,s))
2439
  mark_inuse_foot(M,p,s))
2440
 
2440
 
2441
#define set_inuse_and_pinuse(M,p,s)\
2441
#define set_inuse_and_pinuse(M,p,s)\
2442
  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
2442
  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
2443
  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
2443
  (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
2444
 mark_inuse_foot(M,p,s))
2444
 mark_inuse_foot(M,p,s))
2445
 
2445
 
2446
#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
2446
#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
2447
  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
2447
  ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
2448
  mark_inuse_foot(M, p, s))
2448
  mark_inuse_foot(M, p, s))
2449
 
2449
 
2450
#endif /* !FOOTERS */
2450
#endif /* !FOOTERS */
2451
 
2451
 
2452
/* ---------------------------- setting mparams -------------------------- */
2452
/* ---------------------------- setting mparams -------------------------- */
2453
 
2453
 
2454
/* Initialize mparams */
2454
/* Initialize mparams */
2455
static int init_mparams(void) {
2455
static int init_mparams(void) {
2456
  if (mparams.page_size == 0) {
2456
  if (mparams.page_size == 0) {
2457
    size_t s;
2457
    size_t s;
2458
 
2458
 
2459
    mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
2459
    mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
2460
    mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
2460
    mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
2461
#if MORECORE_CONTIGUOUS
2461
#if MORECORE_CONTIGUOUS
2462
    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
2462
    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
2463
#else  /* MORECORE_CONTIGUOUS */
2463
#else  /* MORECORE_CONTIGUOUS */
2464
    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
2464
    mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
2465
#endif /* MORECORE_CONTIGUOUS */
2465
#endif /* MORECORE_CONTIGUOUS */
2466
 
2466
 
2467
#if (FOOTERS && !INSECURE)
2467
#if (FOOTERS && !INSECURE)
2468
    {
2468
    {
2469
#if USE_DEV_RANDOM
2469
#if USE_DEV_RANDOM
2470
      int fd;
2470
      int fd;
2471
      unsigned char buf[sizeof(size_t)];
2471
      unsigned char buf[sizeof(size_t)];
2472
      /* Try to use /dev/urandom, else fall back on using time */
2472
      /* Try to use /dev/urandom, else fall back on using time */
2473
      if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
2473
      if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
2474
          read(fd, buf, sizeof(buf)) == sizeof(buf)) {
2474
          read(fd, buf, sizeof(buf)) == sizeof(buf)) {
2475
        s = *((size_t *) buf);
2475
        s = *((size_t *) buf);
2476
        close(fd);
2476
        close(fd);
2477
      }
2477
      }
2478
      else
2478
      else
2479
#endif /* USE_DEV_RANDOM */
2479
#endif /* USE_DEV_RANDOM */
2480
        s = (size_t)(time(0) ^ (size_t)0x55555555U);
2480
        s = (size_t)(time(0) ^ (size_t)0x55555555U);
2481
 
2481
 
2482
      s |= (size_t)8U;    /* ensure nonzero */
2482
      s |= (size_t)8U;    /* ensure nonzero */
2483
      s &= ~(size_t)7U;   /* improve chances of fault for bad values */
2483
      s &= ~(size_t)7U;   /* improve chances of fault for bad values */
2484
 
2484
 
2485
    }
2485
    }
2486
#else /* (FOOTERS && !INSECURE) */
2486
#else /* (FOOTERS && !INSECURE) */
2487
    s = (size_t)0x58585858U;
2487
    s = (size_t)0x58585858U;
2488
#endif /* (FOOTERS && !INSECURE) */
2488
#endif /* (FOOTERS && !INSECURE) */
2489
    ACQUIRE_MAGIC_INIT_LOCK();
2489
    ACQUIRE_MAGIC_INIT_LOCK();
2490
    if (mparams.magic == 0) {
2490
    if (mparams.magic == 0) {
2491
      mparams.magic = s;
2491
      mparams.magic = s;
2492
      /* Set up lock for main malloc area */
2492
      /* Set up lock for main malloc area */
2493
      INITIAL_LOCK(&gm->mutex);
2493
      INITIAL_LOCK(&gm->mutex);
2494
      gm->mflags = mparams.default_mflags;
2494
      gm->mflags = mparams.default_mflags;
2495
    }
2495
    }
2496
    RELEASE_MAGIC_INIT_LOCK();
2496
    RELEASE_MAGIC_INIT_LOCK();
2497
 
2497
 
2498
#ifndef WIN32
2498
#ifndef WIN32
2499
    mparams.page_size = malloc_getpagesize;
2499
    mparams.page_size = malloc_getpagesize;
2500
    mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
2500
    mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
2501
                           DEFAULT_GRANULARITY : mparams.page_size);
2501
                           DEFAULT_GRANULARITY : mparams.page_size);
2502
#else /* WIN32 */
2502
#else /* WIN32 */
2503
    {
2503
    {
2504
      SYSTEM_INFO system_info;
2504
      SYSTEM_INFO system_info;
2505
      GetSystemInfo(&system_info);
2505
      GetSystemInfo(&system_info);
2506
      mparams.page_size = system_info.dwPageSize;
2506
      mparams.page_size = system_info.dwPageSize;
2507
      mparams.granularity = system_info.dwAllocationGranularity;
2507
      mparams.granularity = system_info.dwAllocationGranularity;
2508
    }
2508
    }
2509
#endif /* WIN32 */
2509
#endif /* WIN32 */
2510
 
2510
 
2511
    /* Sanity-check configuration:
2511
    /* Sanity-check configuration:
2512
       size_t must be unsigned and as wide as pointer type.
2512
       size_t must be unsigned and as wide as pointer type.
2513
       ints must be at least 4 bytes.
2513
       ints must be at least 4 bytes.
2514
       alignment must be at least 8.
2514
       alignment must be at least 8.
2515
       Alignment, min chunk size, and page size must all be powers of 2.
2515
       Alignment, min chunk size, and page size must all be powers of 2.
2516
    */
2516
    */
2517
    if ((sizeof(size_t) != sizeof(char*)) ||
2517
    if ((sizeof(size_t) != sizeof(char*)) ||
2518
        (MAX_SIZE_T < MIN_CHUNK_SIZE)  ||
2518
        (MAX_SIZE_T < MIN_CHUNK_SIZE)  ||
2519
        (sizeof(int) < 4)  ||
2519
        (sizeof(int) < 4)  ||
2520
        (MALLOC_ALIGNMENT < (size_t)8U) ||
2520
        (MALLOC_ALIGNMENT < (size_t)8U) ||
2521
        ((MALLOC_ALIGNMENT    & (MALLOC_ALIGNMENT-SIZE_T_ONE))    != 0) ||
2521
        ((MALLOC_ALIGNMENT    & (MALLOC_ALIGNMENT-SIZE_T_ONE))    != 0) ||
2522
        ((MCHUNK_SIZE         & (MCHUNK_SIZE-SIZE_T_ONE))         != 0) ||
2522
        ((MCHUNK_SIZE         & (MCHUNK_SIZE-SIZE_T_ONE))         != 0) ||
2523
        ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||
2523
        ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||
2524
        ((mparams.page_size   & (mparams.page_size-SIZE_T_ONE))   != 0))
2524
        ((mparams.page_size   & (mparams.page_size-SIZE_T_ONE))   != 0))
2525
      ABORT;
2525
      ABORT;
2526
  }
2526
  }
2527
  return 0;
2527
  return 0;
2528
}
2528
}
2529
 
2529
 
2530
#if 0
2530
#if 0
2531
/* support for mallopt */
2531
/* support for mallopt */
2532
static int change_mparam(int param_number, int value) {
2532
static int change_mparam(int param_number, int value) {
2533
  size_t val = (size_t)value;
2533
  size_t val = (size_t)value;
2534
  init_mparams();
2534
  init_mparams();
2535
  switch(param_number) {
2535
  switch(param_number) {
2536
  case M_TRIM_THRESHOLD:
2536
  case M_TRIM_THRESHOLD:
2537
    mparams.trim_threshold = val;
2537
    mparams.trim_threshold = val;
2538
    return 1;
2538
    return 1;
2539
  case M_GRANULARITY:
2539
  case M_GRANULARITY:
2540
    if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
2540
    if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
2541
      mparams.granularity = val;
2541
      mparams.granularity = val;
2542
      return 1;
2542
      return 1;
2543
    }
2543
    }
2544
    else
2544
    else
2545
      return 0;
2545
      return 0;
2546
  case M_MMAP_THRESHOLD:
2546
  case M_MMAP_THRESHOLD:
2547
    mparams.mmap_threshold = val;
2547
    mparams.mmap_threshold = val;
2548
    return 1;
2548
    return 1;
2549
  default:
2549
  default:
2550
    return 0;
2550
    return 0;
2551
  }
2551
  }
2552
}
2552
}
2553
#endif
2553
#endif
2554
 
2554
 
2555
#if DEBUG
2555
#if DEBUG
2556
/* ------------------------- Debugging Support --------------------------- */
2556
/* ------------------------- Debugging Support --------------------------- */
2557
 
2557
 
2558
/* Check properties of any chunk, whether free, inuse, mmapped etc  */
2558
/* Check properties of any chunk, whether free, inuse, mmapped etc  */
2559
static void do_check_any_chunk(mstate m, mchunkptr p) {
2559
static void do_check_any_chunk(mstate m, mchunkptr p) {
2560
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2560
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2561
  assert(ok_address(m, p));
2561
  assert(ok_address(m, p));
2562
}
2562
}
2563
 
2563
 
2564
/* Check properties of top chunk */
2564
/* Check properties of top chunk */
2565
static void do_check_top_chunk(mstate m, mchunkptr p) {
2565
static void do_check_top_chunk(mstate m, mchunkptr p) {
2566
  msegmentptr sp = segment_holding(m, (char*)p);
2566
  msegmentptr sp = segment_holding(m, (char*)p);
2567
  size_t  sz = chunksize(p);
2567
  size_t  sz = chunksize(p);
2568
  assert(sp != 0);
2568
  assert(sp != 0);
2569
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2569
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2570
  assert(ok_address(m, p));
2570
  assert(ok_address(m, p));
2571
  assert(sz == m->topsize);
2571
  assert(sz == m->topsize);
2572
  assert(sz > 0);
2572
  assert(sz > 0);
2573
  assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
2573
  assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
2574
  assert(pinuse(p));
2574
  assert(pinuse(p));
2575
  assert(!next_pinuse(p));
2575
  assert(!next_pinuse(p));
2576
}
2576
}
2577
 
2577
 
2578
/* Check properties of (inuse) mmapped chunks */
2578
/* Check properties of (inuse) mmapped chunks */
2579
static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
2579
static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
2580
  size_t  sz = chunksize(p);
2580
  size_t  sz = chunksize(p);
2581
  size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD);
2581
  size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD);
2582
  assert(is_mmapped(p));
2582
  assert(is_mmapped(p));
2583
  assert(use_mmap(m));
2583
  assert(use_mmap(m));
2584
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2584
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2585
  assert(ok_address(m, p));
2585
  assert(ok_address(m, p));
2586
  assert(!is_small(sz));
2586
  assert(!is_small(sz));
2587
  assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
2587
  assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
2588
  assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
2588
  assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
2589
  assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
2589
  assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
2590
}
2590
}
2591
 
2591
 
2592
/* Check properties of inuse chunks */
2592
/* Check properties of inuse chunks */
2593
static void do_check_inuse_chunk(mstate m, mchunkptr p) {
2593
static void do_check_inuse_chunk(mstate m, mchunkptr p) {
2594
  do_check_any_chunk(m, p);
2594
  do_check_any_chunk(m, p);
2595
  assert(cinuse(p));
2595
  assert(cinuse(p));
2596
  assert(next_pinuse(p));
2596
  assert(next_pinuse(p));
2597
  /* If not pinuse and not mmapped, previous chunk has OK offset */
2597
  /* If not pinuse and not mmapped, previous chunk has OK offset */
2598
  assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
2598
  assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
2599
  if (is_mmapped(p))
2599
  if (is_mmapped(p))
2600
    do_check_mmapped_chunk(m, p);
2600
    do_check_mmapped_chunk(m, p);
2601
}
2601
}
2602
 
2602
 
2603
/* Check properties of free chunks */
2603
/* Check properties of free chunks */
2604
static void do_check_free_chunk(mstate m, mchunkptr p) {
2604
static void do_check_free_chunk(mstate m, mchunkptr p) {
2605
  size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
2605
  size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
2606
  mchunkptr next = chunk_plus_offset(p, sz);
2606
  mchunkptr next = chunk_plus_offset(p, sz);
2607
  do_check_any_chunk(m, p);
2607
  do_check_any_chunk(m, p);
2608
  assert(!cinuse(p));
2608
  assert(!cinuse(p));
2609
  assert(!next_pinuse(p));
2609
  assert(!next_pinuse(p));
2610
  assert (!is_mmapped(p));
2610
  assert (!is_mmapped(p));
2611
  if (p != m->dv && p != m->top) {
2611
  if (p != m->dv && p != m->top) {
2612
    if (sz >= MIN_CHUNK_SIZE) {
2612
    if (sz >= MIN_CHUNK_SIZE) {
2613
      assert((sz & CHUNK_ALIGN_MASK) == 0);
2613
      assert((sz & CHUNK_ALIGN_MASK) == 0);
2614
      assert(is_aligned(chunk2mem(p)));
2614
      assert(is_aligned(chunk2mem(p)));
2615
      assert(next->prev_foot == sz);
2615
      assert(next->prev_foot == sz);
2616
      assert(pinuse(p));
2616
      assert(pinuse(p));
2617
      assert (next == m->top || cinuse(next));
2617
      assert (next == m->top || cinuse(next));
2618
      assert(p->fd->bk == p);
2618
      assert(p->fd->bk == p);
2619
      assert(p->bk->fd == p);
2619
      assert(p->bk->fd == p);
2620
    }
2620
    }
2621
    else  /* markers are always of size SIZE_T_SIZE */
2621
    else  /* markers are always of size SIZE_T_SIZE */
2622
      assert(sz == SIZE_T_SIZE);
2622
      assert(sz == SIZE_T_SIZE);
2623
  }
2623
  }
2624
}
2624
}
2625
 
2625
 
2626
/* Check properties of malloced chunks at the point they are malloced */
2626
/* Check properties of malloced chunks at the point they are malloced */
2627
static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
2627
static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
2628
  if (mem != 0) {
2628
  if (mem != 0) {
2629
    mchunkptr p = mem2chunk(mem);
2629
    mchunkptr p = mem2chunk(mem);
2630
    size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
2630
    size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
2631
    do_check_inuse_chunk(m, p);
2631
    do_check_inuse_chunk(m, p);
2632
    assert((sz & CHUNK_ALIGN_MASK) == 0);
2632
    assert((sz & CHUNK_ALIGN_MASK) == 0);
2633
    assert(sz >= MIN_CHUNK_SIZE);
2633
    assert(sz >= MIN_CHUNK_SIZE);
2634
    assert(sz >= s);
2634
    assert(sz >= s);
2635
    /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
2635
    /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
2636
    assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
2636
    assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
2637
  }
2637
  }
2638
}
2638
}
2639
 
2639
 
2640
/* Check a tree and its subtrees.  */
2640
/* Check a tree and its subtrees.  */
2641
static void do_check_tree(mstate m, tchunkptr t) {
2641
static void do_check_tree(mstate m, tchunkptr t) {
2642
  tchunkptr head = 0;
2642
  tchunkptr head = 0;
2643
  tchunkptr u = t;
2643
  tchunkptr u = t;
2644
  bindex_t tindex = t->index;
2644
  bindex_t tindex = t->index;
2645
  size_t tsize = chunksize(t);
2645
  size_t tsize = chunksize(t);
2646
  bindex_t idx;
2646
  bindex_t idx;
2647
  compute_tree_index(tsize, idx);
2647
  compute_tree_index(tsize, idx);
2648
  assert(tindex == idx);
2648
  assert(tindex == idx);
2649
  assert(tsize >= MIN_LARGE_SIZE);
2649
  assert(tsize >= MIN_LARGE_SIZE);
2650
  assert(tsize >= minsize_for_tree_index(idx));
2650
  assert(tsize >= minsize_for_tree_index(idx));
2651
  assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
2651
  assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
2652
 
2652
 
2653
  do { /* traverse through chain of same-sized nodes */
2653
  do { /* traverse through chain of same-sized nodes */
2654
    do_check_any_chunk(m, ((mchunkptr)u));
2654
    do_check_any_chunk(m, ((mchunkptr)u));
2655
    assert(u->index == tindex);
2655
    assert(u->index == tindex);
2656
    assert(chunksize(u) == tsize);
2656
    assert(chunksize(u) == tsize);
2657
    assert(!cinuse(u));
2657
    assert(!cinuse(u));
2658
    assert(!next_pinuse(u));
2658
    assert(!next_pinuse(u));
2659
    assert(u->fd->bk == u);
2659
    assert(u->fd->bk == u);
2660
    assert(u->bk->fd == u);
2660
    assert(u->bk->fd == u);
2661
    if (u->parent == 0) {
2661
    if (u->parent == 0) {
2662
      assert(u->child[0] == 0);
2662
      assert(u->child[0] == 0);
2663
      assert(u->child[1] == 0);
2663
      assert(u->child[1] == 0);
2664
    }
2664
    }
2665
    else {
2665
    else {
2666
      assert(head == 0); /* only one node on chain has parent */
2666
      assert(head == 0); /* only one node on chain has parent */
2667
      head = u;
2667
      head = u;
2668
      assert(u->parent != u);
2668
      assert(u->parent != u);
2669
      assert (u->parent->child[0] == u ||
2669
      assert (u->parent->child[0] == u ||
2670
              u->parent->child[1] == u ||
2670
              u->parent->child[1] == u ||
2671
              *((tbinptr*)(u->parent)) == u);
2671
              *((tbinptr*)(u->parent)) == u);
2672
      if (u->child[0] != 0) {
2672
      if (u->child[0] != 0) {
2673
        assert(u->child[0]->parent == u);
2673
        assert(u->child[0]->parent == u);
2674
        assert(u->child[0] != u);
2674
        assert(u->child[0] != u);
2675
        do_check_tree(m, u->child[0]);
2675
        do_check_tree(m, u->child[0]);
2676
      }
2676
      }
2677
      if (u->child[1] != 0) {
2677
      if (u->child[1] != 0) {
2678
        assert(u->child[1]->parent == u);
2678
        assert(u->child[1]->parent == u);
2679
        assert(u->child[1] != u);
2679
        assert(u->child[1] != u);
2680
        do_check_tree(m, u->child[1]);
2680
        do_check_tree(m, u->child[1]);
2681
      }
2681
      }
2682
      if (u->child[0] != 0 && u->child[1] != 0) {
2682
      if (u->child[0] != 0 && u->child[1] != 0) {
2683
        assert(chunksize(u->child[0]) < chunksize(u->child[1]));
2683
        assert(chunksize(u->child[0]) < chunksize(u->child[1]));
2684
      }
2684
      }
2685
    }
2685
    }
2686
    u = u->fd;
2686
    u = u->fd;
2687
  } while (u != t);
2687
  } while (u != t);
2688
  assert(head != 0);
2688
  assert(head != 0);
2689
}
2689
}
2690
 
2690
 
2691
/*  Check all the chunks in a treebin.  */
2691
/*  Check all the chunks in a treebin.  */
2692
static void do_check_treebin(mstate m, bindex_t i) {
2692
static void do_check_treebin(mstate m, bindex_t i) {
2693
  tbinptr* tb = treebin_at(m, i);
2693
  tbinptr* tb = treebin_at(m, i);
2694
  tchunkptr t = *tb;
2694
  tchunkptr t = *tb;
2695
  int empty = (m->treemap & (1U << i)) == 0;
2695
  int empty = (m->treemap & (1U << i)) == 0;
2696
  if (t == 0)
2696
  if (t == 0)
2697
    assert(empty);
2697
    assert(empty);
2698
  if (!empty)
2698
  if (!empty)
2699
    do_check_tree(m, t);
2699
    do_check_tree(m, t);
2700
}
2700
}
2701
 
2701
 
2702
/*  Check all the chunks in a smallbin.  */
2702
/*  Check all the chunks in a smallbin.  */
2703
static void do_check_smallbin(mstate m, bindex_t i) {
2703
static void do_check_smallbin(mstate m, bindex_t i) {
2704
  sbinptr b = smallbin_at(m, i);
2704
  sbinptr b = smallbin_at(m, i);
2705
  mchunkptr p = b->bk;
2705
  mchunkptr p = b->bk;
2706
  unsigned int empty = (m->smallmap & (1U << i)) == 0;
2706
  unsigned int empty = (m->smallmap & (1U << i)) == 0;
2707
  if (p == b)
2707
  if (p == b)
2708
    assert(empty);
2708
    assert(empty);
2709
  if (!empty) {
2709
  if (!empty) {
2710
    for (; p != b; p = p->bk) {
2710
    for (; p != b; p = p->bk) {
2711
      size_t size = chunksize(p);
2711
      size_t size = chunksize(p);
2712
      mchunkptr q;
2712
      mchunkptr q;
2713
      /* each chunk claims to be free */
2713
      /* each chunk claims to be free */
2714
      do_check_free_chunk(m, p);
2714
      do_check_free_chunk(m, p);
2715
      /* chunk belongs in bin */
2715
      /* chunk belongs in bin */
2716
      assert(small_index(size) == i);
2716
      assert(small_index(size) == i);
2717
      assert(p->bk == b || chunksize(p->bk) == chunksize(p));
2717
      assert(p->bk == b || chunksize(p->bk) == chunksize(p));
2718
      /* chunk is followed by an inuse chunk */
2718
      /* chunk is followed by an inuse chunk */
2719
      q = next_chunk(p);
2719
      q = next_chunk(p);
2720
      if (q->head != FENCEPOST_HEAD)
2720
      if (q->head != FENCEPOST_HEAD)
2721
        do_check_inuse_chunk(m, q);
2721
        do_check_inuse_chunk(m, q);
2722
    }
2722
    }
2723
  }
2723
  }
2724
}
2724
}
2725
 
2725
 
2726
/* Find x in a bin. Used in other check functions. */
2726
/* Find x in a bin. Used in other check functions. */
2727
static int bin_find(mstate m, mchunkptr x) {
2727
static int bin_find(mstate m, mchunkptr x) {
2728
  size_t size = chunksize(x);
2728
  size_t size = chunksize(x);
2729
  if (is_small(size)) {
2729
  if (is_small(size)) {
2730
    bindex_t sidx = small_index(size);
2730
    bindex_t sidx = small_index(size);
2731
    sbinptr b = smallbin_at(m, sidx);
2731
    sbinptr b = smallbin_at(m, sidx);
2732
    if (smallmap_is_marked(m, sidx)) {
2732
    if (smallmap_is_marked(m, sidx)) {
2733
      mchunkptr p = b;
2733
      mchunkptr p = b;
2734
      do {
2734
      do {
2735
        if (p == x)
2735
        if (p == x)
2736
          return 1;
2736
          return 1;
2737
      } while ((p = p->fd) != b);
2737
      } while ((p = p->fd) != b);
2738
    }
2738
    }
2739
  }
2739
  }
2740
  else {
2740
  else {
2741
    bindex_t tidx;
2741
    bindex_t tidx;
2742
    compute_tree_index(size, tidx);
2742
    compute_tree_index(size, tidx);
2743
    if (treemap_is_marked(m, tidx)) {
2743
    if (treemap_is_marked(m, tidx)) {
2744
      tchunkptr t = *treebin_at(m, tidx);
2744
      tchunkptr t = *treebin_at(m, tidx);
2745
      size_t sizebits = size << leftshift_for_tree_index(tidx);
2745
      size_t sizebits = size << leftshift_for_tree_index(tidx);
2746
      while (t != 0 && chunksize(t) != size) {
2746
      while (t != 0 && chunksize(t) != size) {
2747
        t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
2747
        t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
2748
        sizebits <<= 1;
2748
        sizebits <<= 1;
2749
      }
2749
      }
2750
      if (t != 0) {
2750
      if (t != 0) {
2751
        tchunkptr u = t;
2751
        tchunkptr u = t;
2752
        do {
2752
        do {
2753
          if (u == (tchunkptr)x)
2753
          if (u == (tchunkptr)x)
2754
            return 1;
2754
            return 1;
2755
        } while ((u = u->fd) != t);
2755
        } while ((u = u->fd) != t);
2756
      }
2756
      }
2757
    }
2757
    }
2758
  }
2758
  }
2759
  return 0;
2759
  return 0;
2760
}
2760
}
2761
 
2761
 
2762
/* Traverse each chunk and check it; return total */
2762
/* Traverse each chunk and check it; return total */
2763
static size_t traverse_and_check(mstate m) {
2763
static size_t traverse_and_check(mstate m) {
2764
  size_t sum = 0;
2764
  size_t sum = 0;
2765
  if (is_initialized(m)) {
2765
  if (is_initialized(m)) {
2766
    msegmentptr s = &m->seg;
2766
    msegmentptr s = &m->seg;
2767
    sum += m->topsize + TOP_FOOT_SIZE;
2767
    sum += m->topsize + TOP_FOOT_SIZE;
2768
    while (s != 0) {
2768
    while (s != 0) {
2769
      mchunkptr q = align_as_chunk(s->base);
2769
      mchunkptr q = align_as_chunk(s->base);
2770
      mchunkptr lastq = 0;
2770
      mchunkptr lastq = 0;
2771
      assert(pinuse(q));
2771
      assert(pinuse(q));
2772
      while (segment_holds(s, q) &&
2772
      while (segment_holds(s, q) &&
2773
             q != m->top && q->head != FENCEPOST_HEAD) {
2773
             q != m->top && q->head != FENCEPOST_HEAD) {
2774
        sum += chunksize(q);
2774
        sum += chunksize(q);
2775
        if (cinuse(q)) {
2775
        if (cinuse(q)) {
2776
          assert(!bin_find(m, q));
2776
          assert(!bin_find(m, q));
2777
          do_check_inuse_chunk(m, q);
2777
          do_check_inuse_chunk(m, q);
2778
        }
2778
        }
2779
        else {
2779
        else {
2780
          assert(q == m->dv || bin_find(m, q));
2780
          assert(q == m->dv || bin_find(m, q));
2781
          assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */
2781
          assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */
2782
          do_check_free_chunk(m, q);
2782
          do_check_free_chunk(m, q);
2783
        }
2783
        }
2784
        lastq = q;
2784
        lastq = q;
2785
        q = next_chunk(q);
2785
        q = next_chunk(q);
2786
      }
2786
      }
2787
      s = s->next;
2787
      s = s->next;
2788
    }
2788
    }
2789
  }
2789
  }
2790
  return sum;
2790
  return sum;
2791
}
2791
}
2792
 
2792
 
2793
/* Check all properties of malloc_state. */
2793
/* Check all properties of malloc_state. */
2794
static void do_check_malloc_state(mstate m) {
2794
static void do_check_malloc_state(mstate m) {
2795
  bindex_t i;
2795
  bindex_t i;
2796
  size_t total;
2796
  size_t total;
2797
  /* check bins */
2797
  /* check bins */
2798
  for (i = 0; i < NSMALLBINS; ++i)
2798
  for (i = 0; i < NSMALLBINS; ++i)
2799
    do_check_smallbin(m, i);
2799
    do_check_smallbin(m, i);
2800
  for (i = 0; i < NTREEBINS; ++i)
2800
  for (i = 0; i < NTREEBINS; ++i)
2801
    do_check_treebin(m, i);
2801
    do_check_treebin(m, i);
2802
 
2802
 
2803
  if (m->dvsize != 0) { /* check dv chunk */
2803
  if (m->dvsize != 0) { /* check dv chunk */
2804
    do_check_any_chunk(m, m->dv);
2804
    do_check_any_chunk(m, m->dv);
2805
    assert(m->dvsize == chunksize(m->dv));
2805
    assert(m->dvsize == chunksize(m->dv));
2806
    assert(m->dvsize >= MIN_CHUNK_SIZE);
2806
    assert(m->dvsize >= MIN_CHUNK_SIZE);
2807
    assert(bin_find(m, m->dv) == 0);
2807
    assert(bin_find(m, m->dv) == 0);
2808
  }
2808
  }
2809
 
2809
 
2810
  if (m->top != 0) {   /* check top chunk */
2810
  if (m->top != 0) {   /* check top chunk */
2811
    do_check_top_chunk(m, m->top);
2811
    do_check_top_chunk(m, m->top);
2812
    assert(m->topsize == chunksize(m->top));
2812
    assert(m->topsize == chunksize(m->top));
2813
    assert(m->topsize > 0);
2813
    assert(m->topsize > 0);
2814
    assert(bin_find(m, m->top) == 0);
2814
    assert(bin_find(m, m->top) == 0);
2815
  }
2815
  }
2816
 
2816
 
2817
  total = traverse_and_check(m);
2817
  total = traverse_and_check(m);
2818
  assert(total <= m->footprint);
2818
  assert(total <= m->footprint);
2819
  assert(m->footprint <= m->max_footprint);
2819
  assert(m->footprint <= m->max_footprint);
2820
}
2820
}
2821
#endif /* DEBUG */
2821
#endif /* DEBUG */
2822
 
2822
 
2823
/* ----------------------------- statistics ------------------------------ */
2823
/* ----------------------------- statistics ------------------------------ */
2824
 
2824
 
2825
#if !NO_MALLINFO
2825
#if !NO_MALLINFO
2826
static struct mallinfo internal_mallinfo(mstate m) {
2826
static struct mallinfo internal_mallinfo(mstate m) {
2827
  struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2827
  struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2828
  if (!PREACTION(m)) {
2828
  if (!PREACTION(m)) {
2829
    check_malloc_state(m);
2829
    check_malloc_state(m);
2830
    if (is_initialized(m)) {
2830
    if (is_initialized(m)) {
2831
      size_t nfree = SIZE_T_ONE; /* top always free */
2831
      size_t nfree = SIZE_T_ONE; /* top always free */
2832
      size_t mfree = m->topsize + TOP_FOOT_SIZE;
2832
      size_t mfree = m->topsize + TOP_FOOT_SIZE;
2833
      size_t sum = mfree;
2833
      size_t sum = mfree;
2834
      msegmentptr s = &m->seg;
2834
      msegmentptr s = &m->seg;
2835
      while (s != 0) {
2835
      while (s != 0) {
2836
        mchunkptr q = align_as_chunk(s->base);
2836
        mchunkptr q = align_as_chunk(s->base);
2837
        while (segment_holds(s, q) &&
2837
        while (segment_holds(s, q) &&
2838
               q != m->top && q->head != FENCEPOST_HEAD) {
2838
               q != m->top && q->head != FENCEPOST_HEAD) {
2839
          size_t sz = chunksize(q);
2839
          size_t sz = chunksize(q);
2840
          sum += sz;
2840
          sum += sz;
2841
          if (!cinuse(q)) {
2841
          if (!cinuse(q)) {
2842
            mfree += sz;
2842
            mfree += sz;
2843
            ++nfree;
2843
            ++nfree;
2844
          }
2844
          }
2845
          q = next_chunk(q);
2845
          q = next_chunk(q);
2846
        }
2846
        }
2847
        s = s->next;
2847
        s = s->next;
2848
      }
2848
      }
2849
 
2849
 
2850
      nm.arena    = sum;
2850
      nm.arena    = sum;
2851
      nm.ordblks  = nfree;
2851
      nm.ordblks  = nfree;
2852
      nm.hblkhd   = m->footprint - sum;
2852
      nm.hblkhd   = m->footprint - sum;
2853
      nm.usmblks  = m->max_footprint;
2853
      nm.usmblks  = m->max_footprint;
2854
      nm.uordblks = m->footprint - mfree;
2854
      nm.uordblks = m->footprint - mfree;
2855
      nm.fordblks = mfree;
2855
      nm.fordblks = mfree;
2856
      nm.keepcost = m->topsize;
2856
      nm.keepcost = m->topsize;
2857
    }
2857
    }
2858
 
2858
 
2859
    POSTACTION(m);
2859
    POSTACTION(m);
2860
  }
2860
  }
2861
  return nm;
2861
  return nm;
2862
}
2862
}
2863
#endif /* !NO_MALLINFO */
2863
#endif /* !NO_MALLINFO */
2864
 
2864
 
2865
#if 0
2865
#if 0
2866
static void internal_malloc_stats(mstate m) {
2866
static void internal_malloc_stats(mstate m) {
2867
  if (!PREACTION(m)) {
2867
  if (!PREACTION(m)) {
2868
    size_t maxfp = 0;
2868
    size_t maxfp = 0;
2869
    size_t fp = 0;
2869
    size_t fp = 0;
2870
    size_t used = 0;
2870
    size_t used = 0;
2871
    check_malloc_state(m);
2871
    check_malloc_state(m);
2872
    if (is_initialized(m)) {
2872
    if (is_initialized(m)) {
2873
      msegmentptr s = &m->seg;
2873
      msegmentptr s = &m->seg;
2874
      maxfp = m->max_footprint;
2874
      maxfp = m->max_footprint;
2875
      fp = m->footprint;
2875
      fp = m->footprint;
2876
      used = fp - (m->topsize + TOP_FOOT_SIZE);
2876
      used = fp - (m->topsize + TOP_FOOT_SIZE);
2877
 
2877
 
2878
      while (s != 0) {
2878
      while (s != 0) {
2879
        mchunkptr q = align_as_chunk(s->base);
2879
        mchunkptr q = align_as_chunk(s->base);
2880
        while (segment_holds(s, q) &&
2880
        while (segment_holds(s, q) &&
2881
               q != m->top && q->head != FENCEPOST_HEAD) {
2881
               q != m->top && q->head != FENCEPOST_HEAD) {
2882
          if (!cinuse(q))
2882
          if (!cinuse(q))
2883
            used -= chunksize(q);
2883
            used -= chunksize(q);
2884
          q = next_chunk(q);
2884
          q = next_chunk(q);
2885
        }
2885
        }
2886
        s = s->next;
2886
        s = s->next;
2887
      }
2887
      }
2888
    }
2888
    }
2889
 
2889
 
2890
    fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
2890
    fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
2891
    fprintf(stderr, "system bytes     = %10lu\n", (unsigned long)(fp));
2891
    fprintf(stderr, "system bytes     = %10lu\n", (unsigned long)(fp));
2892
    fprintf(stderr, "in use bytes     = %10lu\n", (unsigned long)(used));
2892
    fprintf(stderr, "in use bytes     = %10lu\n", (unsigned long)(used));
2893
 
2893
 
2894
    POSTACTION(m);
2894
    POSTACTION(m);
2895
  }
2895
  }
2896
}
2896
}
2897
#endif
2897
#endif
2898
 
2898
 
2899
/* ----------------------- Operations on smallbins ----------------------- */
2899
/* ----------------------- Operations on smallbins ----------------------- */
2900
 
2900
 
2901
/*
2901
/*
2902
  Various forms of linking and unlinking are defined as macros.  Even
2902
  Various forms of linking and unlinking are defined as macros.  Even
2903
  the ones for trees, which are very long but have very short typical
2903
  the ones for trees, which are very long but have very short typical
2904
  paths.  This is ugly but reduces reliance on inlining support of
2904
  paths.  This is ugly but reduces reliance on inlining support of
2905
  compilers.
2905
  compilers.
2906
*/
2906
*/
2907
 
2907
 
2908
/* Link a free chunk into a smallbin  */
2908
/* Link a free chunk into a smallbin  */
2909
#define insert_small_chunk(M, P, S) {\
2909
#define insert_small_chunk(M, P, S) {\
2910
  bindex_t I  = small_index(S);\
2910
  bindex_t I  = small_index(S);\
2911
  mchunkptr B = smallbin_at(M, I);\
2911
  mchunkptr B = smallbin_at(M, I);\
2912
  mchunkptr F = B;\
2912
  mchunkptr F = B;\
2913
  assert(S >= MIN_CHUNK_SIZE);\
2913
  assert(S >= MIN_CHUNK_SIZE);\
2914
  if (!smallmap_is_marked(M, I))\
2914
  if (!smallmap_is_marked(M, I))\
2915
    mark_smallmap(M, I);\
2915
    mark_smallmap(M, I);\
2916
  else if (RTCHECK(ok_address(M, B->fd)))\
2916
  else if (RTCHECK(ok_address(M, B->fd)))\
2917
    F = B->fd;\
2917
    F = B->fd;\
2918
  else {\
2918
  else {\
2919
    CORRUPTION_ERROR_ACTION(M);\
2919
    CORRUPTION_ERROR_ACTION(M);\
2920
  }\
2920
  }\
2921
  B->fd = P;\
2921
  B->fd = P;\
2922
  F->bk = P;\
2922
  F->bk = P;\
2923
  P->fd = F;\
2923
  P->fd = F;\
2924
  P->bk = B;\
2924
  P->bk = B;\
2925
}
2925
}
2926
 
2926
 
2927
/* Unlink a chunk from a smallbin  */
2927
/* Unlink a chunk from a smallbin  */
2928
#define unlink_small_chunk(M, P, S) {\
2928
#define unlink_small_chunk(M, P, S) {\
2929
  mchunkptr F = P->fd;\
2929
  mchunkptr F = P->fd;\
2930
  mchunkptr B = P->bk;\
2930
  mchunkptr B = P->bk;\
2931
  bindex_t I = small_index(S);\
2931
  bindex_t I = small_index(S);\
2932
  assert(P != B);\
2932
  assert(P != B);\
2933
  assert(P != F);\
2933
  assert(P != F);\
2934
  assert(chunksize(P) == small_index2size(I));\
2934
  assert(chunksize(P) == small_index2size(I));\
2935
  if (F == B)\
2935
  if (F == B)\
2936
    clear_smallmap(M, I);\
2936
    clear_smallmap(M, I);\
2937
  else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
2937
  else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
2938
                   (B == smallbin_at(M,I) || ok_address(M, B)))) {\
2938
                   (B == smallbin_at(M,I) || ok_address(M, B)))) {\
2939
    F->bk = B;\
2939
    F->bk = B;\
2940
    B->fd = F;\
2940
    B->fd = F;\
2941
  }\
2941
  }\
2942
  else {\
2942
  else {\
2943
    CORRUPTION_ERROR_ACTION(M);\
2943
    CORRUPTION_ERROR_ACTION(M);\
2944
  }\
2944
  }\
2945
}
2945
}
2946
 
2946
 
2947
/* Unlink the first chunk from a smallbin */
2947
/* Unlink the first chunk from a smallbin */
2948
#define unlink_first_small_chunk(M, B, P, I) {\
2948
#define unlink_first_small_chunk(M, B, P, I) {\
2949
  mchunkptr F = P->fd;\
2949
  mchunkptr F = P->fd;\
2950
  assert(P != B);\
2950
  assert(P != B);\
2951
  assert(P != F);\
2951
  assert(P != F);\
2952
  assert(chunksize(P) == small_index2size(I));\
2952
  assert(chunksize(P) == small_index2size(I));\
2953
  if (B == F)\
2953
  if (B == F)\
2954
    clear_smallmap(M, I);\
2954
    clear_smallmap(M, I);\
2955
  else if (RTCHECK(ok_address(M, F))) {\
2955
  else if (RTCHECK(ok_address(M, F))) {\
2956
    B->fd = F;\
2956
    B->fd = F;\
2957
    F->bk = B;\
2957
    F->bk = B;\
2958
  }\
2958
  }\
2959
  else {\
2959
  else {\
2960
    CORRUPTION_ERROR_ACTION(M);\
2960
    CORRUPTION_ERROR_ACTION(M);\
2961
  }\
2961
  }\
2962
}
2962
}
2963
 
2963
 
2964
/* Replace dv node, binning the old one */
2964
/* Replace dv node, binning the old one */
2965
/* Used only when dvsize known to be small */
2965
/* Used only when dvsize known to be small */
2966
#define replace_dv(M, P, S) {\
2966
#define replace_dv(M, P, S) {\
2967
  size_t DVS = M->dvsize;\
2967
  size_t DVS = M->dvsize;\
2968
  if (DVS != 0) {\
2968
  if (DVS != 0) {\
2969
    mchunkptr DV = M->dv;\
2969
    mchunkptr DV = M->dv;\
2970
    assert(is_small(DVS));\
2970
    assert(is_small(DVS));\
2971
    insert_small_chunk(M, DV, DVS);\
2971
    insert_small_chunk(M, DV, DVS);\
2972
  }\
2972
  }\
2973
  M->dvsize = S;\
2973
  M->dvsize = S;\
2974
  M->dv = P;\
2974
  M->dv = P;\
2975
}
2975
}
2976
 
2976
 
2977
/* ------------------------- Operations on trees ------------------------- */
2977
/* ------------------------- Operations on trees ------------------------- */
2978
 
2978
 
2979
/* Insert chunk into tree */
2979
/* Insert chunk into tree */
2980
#define insert_large_chunk(M, X, S) {\
2980
#define insert_large_chunk(M, X, S) {\
2981
  tbinptr* H;\
2981
  tbinptr* H;\
2982
  bindex_t I;\
2982
  bindex_t I;\
2983
  compute_tree_index(S, I);\
2983
  compute_tree_index(S, I);\
2984
  H = treebin_at(M, I);\
2984
  H = treebin_at(M, I);\
2985
  X->index = I;\
2985
  X->index = I;\
2986
  X->child[0] = X->child[1] = 0;\
2986
  X->child[0] = X->child[1] = 0;\
2987
  if (!treemap_is_marked(M, I)) {\
2987
  if (!treemap_is_marked(M, I)) {\
2988
    mark_treemap(M, I);\
2988
    mark_treemap(M, I);\
2989
    *H = X;\
2989
    *H = X;\
2990
    X->parent = (tchunkptr)H;\
2990
    X->parent = (tchunkptr)H;\
2991
    X->fd = X->bk = X;\
2991
    X->fd = X->bk = X;\
2992
  }\
2992
  }\
2993
  else {\
2993
  else {\
2994
    tchunkptr T = *H;\
2994
    tchunkptr T = *H;\
2995
    size_t K = S << leftshift_for_tree_index(I);\
2995
    size_t K = S << leftshift_for_tree_index(I);\
2996
    for (;;) {\
2996
    for (;;) {\
2997
      if (chunksize(T) != S) {\
2997
      if (chunksize(T) != S) {\
2998
        tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
2998
        tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
2999
        K <<= 1;\
2999
        K <<= 1;\
3000
        if (*C != 0)\
3000
        if (*C != 0)\
3001
          T = *C;\
3001
          T = *C;\
3002
        else if (RTCHECK(ok_address(M, C))) {\
3002
        else if (RTCHECK(ok_address(M, C))) {\
3003
          *C = X;\
3003
          *C = X;\
3004
          X->parent = T;\
3004
          X->parent = T;\
3005
          X->fd = X->bk = X;\
3005
          X->fd = X->bk = X;\
3006
          break;\
3006
          break;\
3007
        }\
3007
        }\
3008
        else {\
3008
        else {\
3009
          CORRUPTION_ERROR_ACTION(M);\
3009
          CORRUPTION_ERROR_ACTION(M);\
3010
          break;\
3010
          break;\
3011
        }\
3011
        }\
3012
      }\
3012
      }\
3013
      else {\
3013
      else {\
3014
        tchunkptr F = T->fd;\
3014
        tchunkptr F = T->fd;\
3015
        if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
3015
        if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
3016
          T->fd = F->bk = X;\
3016
          T->fd = F->bk = X;\
3017
          X->fd = F;\
3017
          X->fd = F;\
3018
          X->bk = T;\
3018
          X->bk = T;\
3019
          X->parent = 0;\
3019
          X->parent = 0;\
3020
          break;\
3020
          break;\
3021
        }\
3021
        }\
3022
        else {\
3022
        else {\
3023
          CORRUPTION_ERROR_ACTION(M);\
3023
          CORRUPTION_ERROR_ACTION(M);\
3024
          break;\
3024
          break;\
3025
        }\
3025
        }\
3026
      }\
3026
      }\
3027
    }\
3027
    }\
3028
  }\
3028
  }\
3029
}
3029
}
3030
 
3030
 
3031
/*
3031
/*
3032
  Unlink steps:
3032
  Unlink steps:
3033
 
3033
 
3034
  1. If x is a chained node, unlink it from its same-sized fd/bk links
3034
  1. If x is a chained node, unlink it from its same-sized fd/bk links
3035
     and choose its bk node as its replacement.
3035
     and choose its bk node as its replacement.
3036
  2. If x was the last node of its size, but not a leaf node, it must
3036
  2. If x was the last node of its size, but not a leaf node, it must
3037
     be replaced with a leaf node (not merely one with an open left or
3037
     be replaced with a leaf node (not merely one with an open left or
3038
     right), to make sure that lefts and rights of descendents
3038
     right), to make sure that lefts and rights of descendents
3039
     correspond properly to bit masks.  We use the rightmost descendent
3039
     correspond properly to bit masks.  We use the rightmost descendent
3040
     of x.  We could use any other leaf, but this is easy to locate and
3040
     of x.  We could use any other leaf, but this is easy to locate and
3041
     tends to counteract removal of leftmosts elsewhere, and so keeps
3041
     tends to counteract removal of leftmosts elsewhere, and so keeps
3042
     paths shorter than minimally guaranteed.  This doesn't loop much
3042
     paths shorter than minimally guaranteed.  This doesn't loop much
3043
     because on average a node in a tree is near the bottom.
3043
     because on average a node in a tree is near the bottom.
3044
  3. If x is the base of a chain (i.e., has parent links) relink
3044
  3. If x is the base of a chain (i.e., has parent links) relink
3045
     x's parent and children to x's replacement (or null if none).
3045
     x's parent and children to x's replacement (or null if none).
3046
*/
3046
*/
3047
 
3047
 
3048
#define unlink_large_chunk(M, X) {\
3048
#define unlink_large_chunk(M, X) {\
3049
  tchunkptr XP = X->parent;\
3049
  tchunkptr XP = X->parent;\
3050
  tchunkptr R;\
3050
  tchunkptr R;\
3051
  if (X->bk != X) {\
3051
  if (X->bk != X) {\
3052
    tchunkptr F = X->fd;\
3052
    tchunkptr F = X->fd;\
3053
    R = X->bk;\
3053
    R = X->bk;\
3054
    if (RTCHECK(ok_address(M, F))) {\
3054
    if (RTCHECK(ok_address(M, F))) {\
3055
      F->bk = R;\
3055
      F->bk = R;\
3056
      R->fd = F;\
3056
      R->fd = F;\
3057
    }\
3057
    }\
3058
    else {\
3058
    else {\
3059
      CORRUPTION_ERROR_ACTION(M);\
3059
      CORRUPTION_ERROR_ACTION(M);\
3060
    }\
3060
    }\
3061
  }\
3061
  }\
3062
  else {\
3062
  else {\
3063
    tchunkptr* RP;\
3063
    tchunkptr* RP;\
3064
    if (((R = *(RP = &(X->child[1]))) != 0) ||\
3064
    if (((R = *(RP = &(X->child[1]))) != 0) ||\
3065
        ((R = *(RP = &(X->child[0]))) != 0)) {\
3065
        ((R = *(RP = &(X->child[0]))) != 0)) {\
3066
      tchunkptr* CP;\
3066
      tchunkptr* CP;\
3067
      while ((*(CP = &(R->child[1])) != 0) ||\
3067
      while ((*(CP = &(R->child[1])) != 0) ||\
3068
             (*(CP = &(R->child[0])) != 0)) {\
3068
             (*(CP = &(R->child[0])) != 0)) {\
3069
        R = *(RP = CP);\
3069
        R = *(RP = CP);\
3070
      }\
3070
      }\
3071
      if (RTCHECK(ok_address(M, RP)))\
3071
      if (RTCHECK(ok_address(M, RP)))\
3072
        *RP = 0;\
3072
        *RP = 0;\
3073
      else {\
3073
      else {\
3074
        CORRUPTION_ERROR_ACTION(M);\
3074
        CORRUPTION_ERROR_ACTION(M);\
3075
      }\
3075
      }\
3076
    }\
3076
    }\
3077
  }\
3077
  }\
3078
  if (XP != 0) {\
3078
  if (XP != 0) {\
3079
    tbinptr* H = treebin_at(M, X->index);\
3079
    tbinptr* H = treebin_at(M, X->index);\
3080
    if (X == *H) {\
3080
    if (X == *H) {\
3081
      if ((*H = R) == 0) \
3081
      if ((*H = R) == 0) \
3082
        clear_treemap(M, X->index);\
3082
        clear_treemap(M, X->index);\
3083
    }\
3083
    }\
3084
    else if (RTCHECK(ok_address(M, XP))) {\
3084
    else if (RTCHECK(ok_address(M, XP))) {\
3085
      if (XP->child[0] == X) \
3085
      if (XP->child[0] == X) \
3086
        XP->child[0] = R;\
3086
        XP->child[0] = R;\
3087
      else \
3087
      else \
3088
        XP->child[1] = R;\
3088
        XP->child[1] = R;\
3089
    }\
3089
    }\
3090
    else\
3090
    else\
3091
      CORRUPTION_ERROR_ACTION(M);\
3091
      CORRUPTION_ERROR_ACTION(M);\
3092
    if (R != 0) {\
3092
    if (R != 0) {\
3093
      if (RTCHECK(ok_address(M, R))) {\
3093
      if (RTCHECK(ok_address(M, R))) {\
3094
        tchunkptr C0, C1;\
3094
        tchunkptr C0, C1;\
3095
        R->parent = XP;\
3095
        R->parent = XP;\
3096
        if ((C0 = X->child[0]) != 0) {\
3096
        if ((C0 = X->child[0]) != 0) {\
3097
          if (RTCHECK(ok_address(M, C0))) {\
3097
          if (RTCHECK(ok_address(M, C0))) {\
3098
            R->child[0] = C0;\
3098
            R->child[0] = C0;\
3099
            C0->parent = R;\
3099
            C0->parent = R;\
3100
          }\
3100
          }\
3101
          else\
3101
          else\
3102
            CORRUPTION_ERROR_ACTION(M);\
3102
            CORRUPTION_ERROR_ACTION(M);\
3103
        }\
3103
        }\
3104
        if ((C1 = X->child[1]) != 0) {\
3104
        if ((C1 = X->child[1]) != 0) {\
3105
          if (RTCHECK(ok_address(M, C1))) {\
3105
          if (RTCHECK(ok_address(M, C1))) {\
3106
            R->child[1] = C1;\
3106
            R->child[1] = C1;\
3107
            C1->parent = R;\
3107
            C1->parent = R;\
3108
          }\
3108
          }\
3109
          else\
3109
          else\
3110
            CORRUPTION_ERROR_ACTION(M);\
3110
            CORRUPTION_ERROR_ACTION(M);\
3111
        }\
3111
        }\
3112
      }\
3112
      }\
3113
      else\
3113
      else\
3114
        CORRUPTION_ERROR_ACTION(M);\
3114
        CORRUPTION_ERROR_ACTION(M);\
3115
    }\
3115
    }\
3116
  }\
3116
  }\
3117
}
3117
}
3118
 
3118
 
3119
/* Relays to large vs small bin operations */
3119
/* Relays to large vs small bin operations */
3120
 
3120
 
3121
#define insert_chunk(M, P, S)\
3121
#define insert_chunk(M, P, S)\
3122
  if (is_small(S)) insert_small_chunk(M, P, S)\
3122
  if (is_small(S)) insert_small_chunk(M, P, S)\
3123
  else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
3123
  else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
3124
 
3124
 
3125
#define unlink_chunk(M, P, S)\
3125
#define unlink_chunk(M, P, S)\
3126
  if (is_small(S)) unlink_small_chunk(M, P, S)\
3126
  if (is_small(S)) unlink_small_chunk(M, P, S)\
3127
  else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
3127
  else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
3128
 
3128
 
3129
 
3129
 
3130
/* Relays to internal calls to malloc/free from realloc, memalign etc */
3130
/* Relays to internal calls to malloc/free from realloc, memalign etc */
3131
 
3131
 
3132
#if ONLY_MSPACES
3132
#if ONLY_MSPACES
3133
#define internal_malloc(m, b) mspace_malloc(m, b)
3133
#define internal_malloc(m, b) mspace_malloc(m, b)
3134
#define internal_free(m, mem) mspace_free(m,mem);
3134
#define internal_free(m, mem) mspace_free(m,mem);
3135
#else /* ONLY_MSPACES */
3135
#else /* ONLY_MSPACES */
3136
#if MSPACES
3136
#if MSPACES
3137
#define internal_malloc(m, b)\
3137
#define internal_malloc(m, b)\
3138
   (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
3138
   (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
3139
#define internal_free(m, mem)\
3139
#define internal_free(m, mem)\
3140
   if (m == gm) dlfree(mem); else mspace_free(m,mem);
3140
   if (m == gm) dlfree(mem); else mspace_free(m,mem);
3141
#else /* MSPACES */
3141
#else /* MSPACES */
3142
#define internal_malloc(m, b) dlmalloc(b)
3142
#define internal_malloc(m, b) dlmalloc(b)
3143
#define internal_free(m, mem) dlfree(mem)
3143
#define internal_free(m, mem) dlfree(mem)
3144
#endif /* MSPACES */
3144
#endif /* MSPACES */
3145
#endif /* ONLY_MSPACES */
3145
#endif /* ONLY_MSPACES */
3146
 
3146
 
3147
/* -----------------------  Direct-mmapping chunks ----------------------- */
3147
/* -----------------------  Direct-mmapping chunks ----------------------- */
3148
 
3148
 
3149
/*
3149
/*
3150
  Directly mmapped chunks are set up with an offset to the start of
3150
  Directly mmapped chunks are set up with an offset to the start of
3151
  the mmapped region stored in the prev_foot field of the chunk. This
3151
  the mmapped region stored in the prev_foot field of the chunk. This
3152
  allows reconstruction of the required argument to MUNMAP when freed,
3152
  allows reconstruction of the required argument to MUNMAP when freed,
3153
  and also allows adjustment of the returned chunk to meet alignment
3153
  and also allows adjustment of the returned chunk to meet alignment
3154
  requirements (especially in memalign).  There is also enough space
3154
  requirements (especially in memalign).  There is also enough space
3155
  allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain
3155
  allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain
3156
  the PINUSE bit so frees can be checked.
3156
  the PINUSE bit so frees can be checked.
3157
*/
3157
*/
3158
 
3158
 
3159
/* Malloc using mmap */
3159
/* Malloc using mmap */
3160
static void* mmap_alloc(mstate m, size_t nb) {
3160
static void* mmap_alloc(mstate m, size_t nb) {
3161
  size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
3161
  size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
3162
  if (mmsize > nb) {     /* Check for wrap around 0 */
3162
  if (mmsize > nb) {     /* Check for wrap around 0 */
3163
    char* mm = (char*)(DIRECT_MMAP(mmsize));
3163
    char* mm = (char*)(DIRECT_MMAP(mmsize));
3164
    if (mm != CMFAIL) {
3164
    if (mm != CMFAIL) {
3165
      size_t offset = align_offset(chunk2mem(mm));
3165
      size_t offset = align_offset(chunk2mem(mm));
3166
      size_t psize = mmsize - offset - MMAP_FOOT_PAD;
3166
      size_t psize = mmsize - offset - MMAP_FOOT_PAD;
3167
      mchunkptr p = (mchunkptr)(mm + offset);
3167
      mchunkptr p = (mchunkptr)(mm + offset);
3168
      p->prev_foot = offset | IS_MMAPPED_BIT;
3168
      p->prev_foot = offset | IS_MMAPPED_BIT;
3169
      (p)->head = (psize|CINUSE_BIT);
3169
      (p)->head = (psize|CINUSE_BIT);
3170
      mark_inuse_foot(m, p, psize);
3170
      mark_inuse_foot(m, p, psize);
3171
      chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
3171
      chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
3172
      chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
3172
      chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
3173
 
3173
 
3174
      if (mm < m->least_addr)
3174
      if (mm < m->least_addr)
3175
        m->least_addr = mm;
3175
        m->least_addr = mm;
3176
      if ((m->footprint += mmsize) > m->max_footprint)
3176
      if ((m->footprint += mmsize) > m->max_footprint)
3177
        m->max_footprint = m->footprint;
3177
        m->max_footprint = m->footprint;
3178
      assert(is_aligned(chunk2mem(p)));
3178
      assert(is_aligned(chunk2mem(p)));
3179
      check_mmapped_chunk(m, p);
3179
      check_mmapped_chunk(m, p);
3180
      return chunk2mem(p);
3180
      return chunk2mem(p);
3181
    }
3181
    }
3182
  }
3182
  }
3183
  return 0;
3183
  return 0;
3184
}
3184
}
3185
 
3185
 
3186
/* Realloc using mmap */
3186
/* Realloc using mmap */
3187
static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
3187
static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
3188
  size_t oldsize = chunksize(oldp);
3188
  size_t oldsize = chunksize(oldp);
3189
  if (is_small(nb)) /* Can't shrink mmap regions below small size */
3189
  if (is_small(nb)) /* Can't shrink mmap regions below small size */
3190
    return 0;
3190
    return 0;
3191
  /* Keep old chunk if big enough but not too big */
3191
  /* Keep old chunk if big enough but not too big */
3192
  if (oldsize >= nb + SIZE_T_SIZE &&
3192
  if (oldsize >= nb + SIZE_T_SIZE &&
3193
      (oldsize - nb) <= (mparams.granularity << 1))
3193
      (oldsize - nb) <= (mparams.granularity << 1))
3194
    return oldp;
3194
    return oldp;
3195
  else {
3195
  else {
3196
    size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
3196
    size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
3197
    size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
3197
    size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
3198
    size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
3198
    size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
3199
                                         CHUNK_ALIGN_MASK);
3199
                                         CHUNK_ALIGN_MASK);
3200
    char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
3200
    char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
3201
                                  oldmmsize, newmmsize, 1);
3201
                                  oldmmsize, newmmsize, 1);
3202
    if (cp != CMFAIL) {
3202
    if (cp != CMFAIL) {
3203
      mchunkptr newp = (mchunkptr)(cp + offset);
3203
      mchunkptr newp = (mchunkptr)(cp + offset);
3204
      size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
3204
      size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
3205
      newp->head = (psize|CINUSE_BIT);
3205
      newp->head = (psize|CINUSE_BIT);
3206
      mark_inuse_foot(m, newp, psize);
3206
      mark_inuse_foot(m, newp, psize);
3207
      chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
3207
      chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
3208
      chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
3208
      chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
3209
 
3209
 
3210
      if (cp < m->least_addr)
3210
      if (cp < m->least_addr)
3211
        m->least_addr = cp;
3211
        m->least_addr = cp;
3212
      if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
3212
      if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
3213
        m->max_footprint = m->footprint;
3213
        m->max_footprint = m->footprint;
3214
      check_mmapped_chunk(m, newp);
3214
      check_mmapped_chunk(m, newp);
3215
      return newp;
3215
      return newp;
3216
    }
3216
    }
3217
  }
3217
  }
3218
  return 0;
3218
  return 0;
3219
}
3219
}
3220
 
3220
 
3221
/* -------------------------- mspace management -------------------------- */
3221
/* -------------------------- mspace management -------------------------- */
3222
 
3222
 
3223
/* Initialize top chunk and its size */
3223
/* Initialize top chunk and its size */
3224
static void init_top(mstate m, mchunkptr p, size_t psize) {
3224
static void init_top(mstate m, mchunkptr p, size_t psize) {
3225
  /* Ensure alignment */
3225
  /* Ensure alignment */
3226
  size_t offset = align_offset(chunk2mem(p));
3226
  size_t offset = align_offset(chunk2mem(p));
3227
  p = (mchunkptr)((char*)p + offset);
3227
  p = (mchunkptr)((char*)p + offset);
3228
  psize -= offset;
3228
  psize -= offset;
3229
 
3229
 
3230
  m->top = p;
3230
  m->top = p;
3231
  m->topsize = psize;
3231
  m->topsize = psize;
3232
  p->head = psize | PINUSE_BIT;
3232
  p->head = psize | PINUSE_BIT;
3233
  /* set size of fake trailing chunk holding overhead space only once */
3233
  /* set size of fake trailing chunk holding overhead space only once */
3234
  chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
3234
  chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
3235
  m->trim_check = mparams.trim_threshold; /* reset on each update */
3235
  m->trim_check = mparams.trim_threshold; /* reset on each update */
3236
}
3236
}
3237
 
3237
 
3238
/* Initialize bins for a new mstate that is otherwise zeroed out */
3238
/* Initialize bins for a new mstate that is otherwise zeroed out */
3239
static void init_bins(mstate m) {
3239
static void init_bins(mstate m) {
3240
  /* Establish circular links for smallbins */
3240
  /* Establish circular links for smallbins */
3241
  bindex_t i;
3241
  bindex_t i;
3242
  for (i = 0; i < NSMALLBINS; ++i) {
3242
  for (i = 0; i < NSMALLBINS; ++i) {
3243
    sbinptr bin = smallbin_at(m,i);
3243
    sbinptr bin = smallbin_at(m,i);
3244
    bin->fd = bin->bk = bin;
3244
    bin->fd = bin->bk = bin;
3245
  }
3245
  }
3246
}
3246
}
3247
 
3247
 
3248
#if PROCEED_ON_ERROR
3248
#if PROCEED_ON_ERROR
3249
 
3249
 
3250
/* default corruption action */
3250
/* default corruption action */
3251
static void reset_on_error(mstate m) {
3251
static void reset_on_error(mstate m) {
3252
  int i;
3252
  int i;
3253
  ++malloc_corruption_error_count;
3253
  ++malloc_corruption_error_count;
3254
  /* Reinitialize fields to forget about all memory */
3254
  /* Reinitialize fields to forget about all memory */
3255
  m->smallbins = m->treebins = 0;
3255
  m->smallbins = m->treebins = 0;
3256
  m->dvsize = m->topsize = 0;
3256
  m->dvsize = m->topsize = 0;
3257
  m->seg.base = 0;
3257
  m->seg.base = 0;
3258
  m->seg.size = 0;
3258
  m->seg.size = 0;
3259
  m->seg.next = 0;
3259
  m->seg.next = 0;
3260
  m->top = m->dv = 0;
3260
  m->top = m->dv = 0;
3261
  for (i = 0; i < NTREEBINS; ++i)
3261
  for (i = 0; i < NTREEBINS; ++i)
3262
    *treebin_at(m, i) = 0;
3262
    *treebin_at(m, i) = 0;
3263
  init_bins(m);
3263
  init_bins(m);
3264
}
3264
}
3265
#endif /* PROCEED_ON_ERROR */
3265
#endif /* PROCEED_ON_ERROR */
3266
 
3266
 
3267
/* Allocate chunk and prepend remainder with chunk in successor base. */
3267
/* Allocate chunk and prepend remainder with chunk in successor base. */
3268
static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
3268
static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
3269
                           size_t nb) {
3269
                           size_t nb) {
3270
  mchunkptr p = align_as_chunk(newbase);
3270
  mchunkptr p = align_as_chunk(newbase);
3271
  mchunkptr oldfirst = align_as_chunk(oldbase);
3271
  mchunkptr oldfirst = align_as_chunk(oldbase);
3272
  size_t psize = (char*)oldfirst - (char*)p;
3272
  size_t psize = (char*)oldfirst - (char*)p;
3273
  mchunkptr q = chunk_plus_offset(p, nb);
3273
  mchunkptr q = chunk_plus_offset(p, nb);
3274
  size_t qsize = psize - nb;
3274
  size_t qsize = psize - nb;
3275
  set_size_and_pinuse_of_inuse_chunk(m, p, nb);
3275
  set_size_and_pinuse_of_inuse_chunk(m, p, nb);
3276
 
3276
 
3277
  assert((char*)oldfirst > (char*)q);
3277
  assert((char*)oldfirst > (char*)q);
3278
  assert(pinuse(oldfirst));
3278
  assert(pinuse(oldfirst));
3279
  assert(qsize >= MIN_CHUNK_SIZE);
3279
  assert(qsize >= MIN_CHUNK_SIZE);
3280
 
3280
 
3281
  /* consolidate remainder with first chunk of old base */
3281
  /* consolidate remainder with first chunk of old base */
3282
  if (oldfirst == m->top) {
3282
  if (oldfirst == m->top) {
3283
    size_t tsize = m->topsize += qsize;
3283
    size_t tsize = m->topsize += qsize;
3284
    m->top = q;
3284
    m->top = q;
3285
    q->head = tsize | PINUSE_BIT;
3285
    q->head = tsize | PINUSE_BIT;
3286
    check_top_chunk(m, q);
3286
    check_top_chunk(m, q);
3287
  }
3287
  }
3288
  else if (oldfirst == m->dv) {
3288
  else if (oldfirst == m->dv) {
3289
    size_t dsize = m->dvsize += qsize;
3289
    size_t dsize = m->dvsize += qsize;
3290
    m->dv = q;
3290
    m->dv = q;
3291
    set_size_and_pinuse_of_free_chunk(q, dsize);
3291
    set_size_and_pinuse_of_free_chunk(q, dsize);
3292
  }
3292
  }
3293
  else {
3293
  else {
3294
    if (!cinuse(oldfirst)) {
3294
    if (!cinuse(oldfirst)) {
3295
      size_t nsize = chunksize(oldfirst);
3295
      size_t nsize = chunksize(oldfirst);
3296
      unlink_chunk(m, oldfirst, nsize);
3296
      unlink_chunk(m, oldfirst, nsize);
3297
      oldfirst = chunk_plus_offset(oldfirst, nsize);
3297
      oldfirst = chunk_plus_offset(oldfirst, nsize);
3298
      qsize += nsize;
3298
      qsize += nsize;
3299
    }
3299
    }
3300
    set_free_with_pinuse(q, qsize, oldfirst);
3300
    set_free_with_pinuse(q, qsize, oldfirst);
3301
    insert_chunk(m, q, qsize);
3301
    insert_chunk(m, q, qsize);
3302
    check_free_chunk(m, q);
3302
    check_free_chunk(m, q);
3303
  }
3303
  }
3304
 
3304
 
3305
  check_malloced_chunk(m, chunk2mem(p), nb);
3305
  check_malloced_chunk(m, chunk2mem(p), nb);
3306
  return chunk2mem(p);
3306
  return chunk2mem(p);
3307
}
3307
}
3308
 
3308
 
3309
 
3309
 
3310
/* Add a segment to hold a new noncontiguous region */
3310
/* Add a segment to hold a new noncontiguous region */
3311
static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
3311
static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
3312
  /* Determine locations and sizes of segment, fenceposts, old top */
3312
  /* Determine locations and sizes of segment, fenceposts, old top */
3313
  char* old_top = (char*)m->top;
3313
  char* old_top = (char*)m->top;
3314
  msegmentptr oldsp = segment_holding(m, old_top);
3314
  msegmentptr oldsp = segment_holding(m, old_top);
3315
  char* old_end = oldsp->base + oldsp->size;
3315
  char* old_end = oldsp->base + oldsp->size;
3316
  size_t ssize = pad_request(sizeof(struct malloc_segment));
3316
  size_t ssize = pad_request(sizeof(struct malloc_segment));
3317
  char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
3317
  char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
3318
  size_t offset = align_offset(chunk2mem(rawsp));
3318
  size_t offset = align_offset(chunk2mem(rawsp));
3319
  char* asp = rawsp + offset;
3319
  char* asp = rawsp + offset;
3320
  char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
3320
  char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
3321
  mchunkptr sp = (mchunkptr)csp;
3321
  mchunkptr sp = (mchunkptr)csp;
3322
  msegmentptr ss = (msegmentptr)(chunk2mem(sp));
3322
  msegmentptr ss = (msegmentptr)(chunk2mem(sp));
3323
  mchunkptr tnext = chunk_plus_offset(sp, ssize);
3323
  mchunkptr tnext = chunk_plus_offset(sp, ssize);
3324
  mchunkptr p = tnext;
3324
  mchunkptr p = tnext;
3325
  int nfences = 0;
3325
  int nfences = 0;
3326
 
3326
 
3327
  /* reset top to new space */
3327
  /* reset top to new space */
3328
  init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
3328
  init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
3329
 
3329
 
3330
  /* Set up segment record */
3330
  /* Set up segment record */
3331
  assert(is_aligned(ss));
3331
  assert(is_aligned(ss));
3332
  set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
3332
  set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
3333
  *ss = m->seg; /* Push current record */
3333
  *ss = m->seg; /* Push current record */
3334
  m->seg.base = tbase;
3334
  m->seg.base = tbase;
3335
  m->seg.size = tsize;
3335
  m->seg.size = tsize;
3336
  m->seg.sflags = mmapped;
3336
  m->seg.sflags = mmapped;
3337
  m->seg.next = ss;
3337
  m->seg.next = ss;
3338
 
3338
 
3339
  /* Insert trailing fenceposts */
3339
  /* Insert trailing fenceposts */
3340
  for (;;) {
3340
  for (;;) {
3341
    mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
3341
    mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
3342
    p->head = FENCEPOST_HEAD;
3342
    p->head = FENCEPOST_HEAD;
3343
    ++nfences;
3343
    ++nfences;
3344
    if ((char*)(&(nextp->head)) < old_end)
3344
    if ((char*)(&(nextp->head)) < old_end)
3345
      p = nextp;
3345
      p = nextp;
3346
    else
3346
    else
3347
      break;
3347
      break;
3348
  }
3348
  }
3349
  assert(nfences >= 2);
3349
  assert(nfences >= 2);
3350
 
3350
 
3351
  /* Insert the rest of old top into a bin as an ordinary free chunk */
3351
  /* Insert the rest of old top into a bin as an ordinary free chunk */
3352
  if (csp != old_top) {
3352
  if (csp != old_top) {
3353
    mchunkptr q = (mchunkptr)old_top;
3353
    mchunkptr q = (mchunkptr)old_top;
3354
    size_t psize = csp - old_top;
3354
    size_t psize = csp - old_top;
3355
    mchunkptr tn = chunk_plus_offset(q, psize);
3355
    mchunkptr tn = chunk_plus_offset(q, psize);
3356
    set_free_with_pinuse(q, psize, tn);
3356
    set_free_with_pinuse(q, psize, tn);
3357
    insert_chunk(m, q, psize);
3357
    insert_chunk(m, q, psize);
3358
  }
3358
  }
3359
 
3359
 
3360
  check_top_chunk(m, m->top);
3360
  check_top_chunk(m, m->top);
3361
}
3361
}
3362
 
3362
 
3363
/* -------------------------- System allocation -------------------------- */
3363
/* -------------------------- System allocation -------------------------- */
3364
 
3364
 
3365
/* Get memory from system using MORECORE or MMAP */
3365
/* Get memory from system using MORECORE or MMAP */
3366
static void* sys_alloc(mstate m, size_t nb) {
3366
static void* sys_alloc(mstate m, size_t nb) {
3367
  char* tbase = CMFAIL;
3367
  char* tbase = CMFAIL;
3368
  size_t tsize = 0;
3368
  size_t tsize = 0;
3369
  flag_t mmap_flag = 0;
3369
  flag_t mmap_flag = 0;
3370
 
3370
 
3371
  init_mparams();
3371
  init_mparams();
3372
 
3372
 
3373
  /* Directly map large chunks */
3373
  /* Directly map large chunks */
3374
  if (use_mmap(m) && nb >= mparams.mmap_threshold) {
3374
  if (use_mmap(m) && nb >= mparams.mmap_threshold) {
3375
    void* mem = mmap_alloc(m, nb);
3375
    void* mem = mmap_alloc(m, nb);
3376
    if (mem != 0)
3376
    if (mem != 0)
3377
      return mem;
3377
      return mem;
3378
  }
3378
  }
3379
 
3379
 
3380
  /*
3380
  /*
3381
    Try getting memory in any of three ways (in most-preferred to
3381
    Try getting memory in any of three ways (in most-preferred to
3382
    least-preferred order):
3382
    least-preferred order):
3383
    1. A call to MORECORE that can normally contiguously extend memory.
3383
    1. A call to MORECORE that can normally contiguously extend memory.
3384
       (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
3384
       (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
3385
       or main space is mmapped or a previous contiguous call failed)
3385
       or main space is mmapped or a previous contiguous call failed)
3386
    2. A call to MMAP new space (disabled if not HAVE_MMAP).
3386
    2. A call to MMAP new space (disabled if not HAVE_MMAP).
3387
       Note that under the default settings, if MORECORE is unable to
3387
       Note that under the default settings, if MORECORE is unable to
3388
       fulfill a request, and HAVE_MMAP is true, then mmap is
3388
       fulfill a request, and HAVE_MMAP is true, then mmap is
3389
       used as a noncontiguous system allocator. This is a useful backup
3389
       used as a noncontiguous system allocator. This is a useful backup
3390
       strategy for systems with holes in address spaces -- in this case
3390
       strategy for systems with holes in address spaces -- in this case
3391
       sbrk cannot contiguously expand the heap, but mmap may be able to
3391
       sbrk cannot contiguously expand the heap, but mmap may be able to
3392
       find space.
3392
       find space.
3393
    3. A call to MORECORE that cannot usually contiguously extend memory.
3393
    3. A call to MORECORE that cannot usually contiguously extend memory.
3394
       (disabled if not HAVE_MORECORE)
3394
       (disabled if not HAVE_MORECORE)
3395
  */
3395
  */
3396
 
3396
 
3397
  if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
3397
  if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
3398
    char* br = CMFAIL;
3398
    char* br = CMFAIL;
3399
    msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
3399
    msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
3400
    size_t asize = 0;
3400
    size_t asize = 0;
3401
    ACQUIRE_MORECORE_LOCK();
3401
    ACQUIRE_MORECORE_LOCK();
3402
 
3402
 
3403
    if (ss == 0) {  /* First time through or recovery */
3403
    if (ss == 0) {  /* First time through or recovery */
3404
      char* base = (char*)CALL_MORECORE(0);
3404
      char* base = (char*)CALL_MORECORE(0);
3405
      if (base != CMFAIL) {
3405
      if (base != CMFAIL) {
3406
        asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
3406
        asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
3407
        /* Adjust to end on a page boundary */
3407
        /* Adjust to end on a page boundary */
3408
        if (!is_page_aligned(base))
3408
        if (!is_page_aligned(base))
3409
          asize += (page_align((size_t)base) - (size_t)base);
3409
          asize += (page_align((size_t)base) - (size_t)base);
3410
        /* Can't call MORECORE if size is negative when treated as signed */
3410
        /* Can't call MORECORE if size is negative when treated as signed */
3411
        if (asize < HALF_MAX_SIZE_T &&
3411
        if (asize < HALF_MAX_SIZE_T &&
3412
            (br = (char*)(CALL_MORECORE(asize))) == base) {
3412
            (br = (char*)(CALL_MORECORE(asize))) == base) {
3413
          tbase = base;
3413
          tbase = base;
3414
          tsize = asize;
3414
          tsize = asize;
3415
        }
3415
        }
3416
      }
3416
      }
3417
    }
3417
    }
3418
    else {
3418
    else {
3419
      /* Subtract out existing available top space from MORECORE request. */
3419
      /* Subtract out existing available top space from MORECORE request. */
3420
      asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE);
3420
      asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE);
3421
      /* Use mem here only if it did continuously extend old space */
3421
      /* Use mem here only if it did continuously extend old space */
3422
      if (asize < HALF_MAX_SIZE_T &&
3422
      if (asize < HALF_MAX_SIZE_T &&
3423
          (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
3423
          (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
3424
        tbase = br;
3424
        tbase = br;
3425
        tsize = asize;
3425
        tsize = asize;
3426
      }
3426
      }
3427
    }
3427
    }
3428
 
3428
 
3429
    if (tbase == CMFAIL) {    /* Cope with partial failure */
3429
    if (tbase == CMFAIL) {    /* Cope with partial failure */
3430
      if (br != CMFAIL) {    /* Try to use/extend the space we did get */
3430
      if (br != CMFAIL) {    /* Try to use/extend the space we did get */
3431
        if (asize < HALF_MAX_SIZE_T &&
3431
        if (asize < HALF_MAX_SIZE_T &&
3432
            asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
3432
            asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
3433
          size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize);
3433
          size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize);
3434
          if (esize < HALF_MAX_SIZE_T) {
3434
          if (esize < HALF_MAX_SIZE_T) {
3435
            char* end = (char*)CALL_MORECORE(esize);
3435
            char* end = (char*)CALL_MORECORE(esize);
3436
            if (end != CMFAIL)
3436
            if (end != CMFAIL)
3437
              asize += esize;
3437
              asize += esize;
3438
            else {            /* Can't use; try to release */
3438
            else {            /* Can't use; try to release */
3439
#if 0 /* warning: statement with no effect */
3439
#if 0 /* warning: statement with no effect */
3440
              CALL_MORECORE(-asize);
3440
              CALL_MORECORE(-asize);
3441
#endif
3441
#endif
3442
              br = CMFAIL;
3442
              br = CMFAIL;
3443
            }
3443
            }
3444
          }
3444
          }
3445
        }
3445
        }
3446
      }
3446
      }
3447
      if (br != CMFAIL) {    /* Use the space we did get */
3447
      if (br != CMFAIL) {    /* Use the space we did get */
3448
        tbase = br;
3448
        tbase = br;
3449
        tsize = asize;
3449
        tsize = asize;
3450
      }
3450
      }
3451
      else
3451
      else
3452
        disable_contiguous(m); /* Don't try contiguous path in the future */
3452
        disable_contiguous(m); /* Don't try contiguous path in the future */
3453
    }
3453
    }
3454
 
3454
 
3455
    RELEASE_MORECORE_LOCK();
3455
    RELEASE_MORECORE_LOCK();
3456
  }
3456
  }
3457
 
3457
 
3458
  if (HAVE_MMAP && tbase == CMFAIL) {  /* Try MMAP */
3458
  if (HAVE_MMAP && tbase == CMFAIL) {  /* Try MMAP */
3459
    size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
3459
    size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
3460
    size_t rsize = granularity_align(req);
3460
    size_t rsize = granularity_align(req);
3461
    if (rsize > nb) { /* Fail if wraps around zero */
3461
    if (rsize > nb) { /* Fail if wraps around zero */
3462
      char* mp = (char*)(CALL_MMAP(rsize));
3462
      char* mp = (char*)(CALL_MMAP(rsize));
3463
      if (mp != CMFAIL) {
3463
      if (mp != CMFAIL) {
3464
        tbase = mp;
3464
        tbase = mp;
3465
        tsize = rsize;
3465
        tsize = rsize;
3466
        mmap_flag = IS_MMAPPED_BIT;
3466
        mmap_flag = IS_MMAPPED_BIT;
3467
      }
3467
      }
3468
    }
3468
    }
3469
  }
3469
  }
3470
 
3470
 
3471
  if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
3471
  if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
3472
    size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
3472
    size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
3473
    if (asize < HALF_MAX_SIZE_T) {
3473
    if (asize < HALF_MAX_SIZE_T) {
3474
      char* br = CMFAIL;
3474
      char* br = CMFAIL;
3475
      char* end = CMFAIL;
3475
      char* end = CMFAIL;
3476
      ACQUIRE_MORECORE_LOCK();
3476
      ACQUIRE_MORECORE_LOCK();
3477
      br = (char*)(CALL_MORECORE(asize));
3477
      br = (char*)(CALL_MORECORE(asize));
3478
      end = (char*)(CALL_MORECORE(0));
3478
      end = (char*)(CALL_MORECORE(0));
3479
      RELEASE_MORECORE_LOCK();
3479
      RELEASE_MORECORE_LOCK();
3480
      if (br != CMFAIL && end != CMFAIL && br < end) {
3480
      if (br != CMFAIL && end != CMFAIL && br < end) {
3481
        size_t ssize = end - br;
3481
        size_t ssize = end - br;
3482
        if (ssize > nb + TOP_FOOT_SIZE) {
3482
        if (ssize > nb + TOP_FOOT_SIZE) {
3483
          tbase = br;
3483
          tbase = br;
3484
          tsize = ssize;
3484
          tsize = ssize;
3485
        }
3485
        }
3486
      }
3486
      }
3487
    }
3487
    }
3488
  }
3488
  }
3489
 
3489
 
3490
  if (tbase != CMFAIL) {
3490
  if (tbase != CMFAIL) {
3491
 
3491
 
3492
    if ((m->footprint += tsize) > m->max_footprint)
3492
    if ((m->footprint += tsize) > m->max_footprint)
3493
      m->max_footprint = m->footprint;
3493
      m->max_footprint = m->footprint;
3494
 
3494
 
3495
    if (!is_initialized(m)) { /* first-time initialization */
3495
    if (!is_initialized(m)) { /* first-time initialization */
3496
      m->seg.base = m->least_addr = tbase;
3496
      m->seg.base = m->least_addr = tbase;
3497
      m->seg.size = tsize;
3497
      m->seg.size = tsize;
3498
      m->seg.sflags = mmap_flag;
3498
      m->seg.sflags = mmap_flag;
3499
      m->magic = mparams.magic;
3499
      m->magic = mparams.magic;
3500
      init_bins(m);
3500
      init_bins(m);
3501
      if (is_global(m)) 
3501
      if (is_global(m)) 
3502
        init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
3502
        init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
3503
      else {
3503
      else {
3504
        /* Offset top by embedded malloc_state */
3504
        /* Offset top by embedded malloc_state */
3505
        mchunkptr mn = next_chunk(mem2chunk(m));
3505
        mchunkptr mn = next_chunk(mem2chunk(m));
3506
        init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
3506
        init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
3507
      }
3507
      }
3508
    }
3508
    }
3509
 
3509
 
3510
    else {
3510
    else {
3511
      /* Try to merge with an existing segment */
3511
      /* Try to merge with an existing segment */
3512
      msegmentptr sp = &m->seg;
3512
      msegmentptr sp = &m->seg;
3513
      while (sp != 0 && tbase != sp->base + sp->size)
3513
      while (sp != 0 && tbase != sp->base + sp->size)
3514
        sp = sp->next;
3514
        sp = sp->next;
3515
      if (sp != 0 &&
3515
      if (sp != 0 &&
3516
          !is_extern_segment(sp) &&
3516
          !is_extern_segment(sp) &&
3517
          (sp->sflags & IS_MMAPPED_BIT) == mmap_flag &&
3517
          (sp->sflags & IS_MMAPPED_BIT) == mmap_flag &&
3518
          segment_holds(sp, m->top)) { /* append */
3518
          segment_holds(sp, m->top)) { /* append */
3519
        sp->size += tsize;
3519
        sp->size += tsize;
3520
        init_top(m, m->top, m->topsize + tsize);
3520
        init_top(m, m->top, m->topsize + tsize);
3521
      }
3521
      }
3522
      else {
3522
      else {
3523
        if (tbase < m->least_addr)
3523
        if (tbase < m->least_addr)
3524
          m->least_addr = tbase;
3524
          m->least_addr = tbase;
3525
        sp = &m->seg;
3525
        sp = &m->seg;
3526
        while (sp != 0 && sp->base != tbase + tsize)
3526
        while (sp != 0 && sp->base != tbase + tsize)
3527
          sp = sp->next;
3527
          sp = sp->next;
3528
        if (sp != 0 &&
3528
        if (sp != 0 &&
3529
            !is_extern_segment(sp) &&
3529
            !is_extern_segment(sp) &&
3530
            (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) {
3530
            (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) {
3531
          char* oldbase = sp->base;
3531
          char* oldbase = sp->base;
3532
          sp->base = tbase;
3532
          sp->base = tbase;
3533
          sp->size += tsize;
3533
          sp->size += tsize;
3534
          return prepend_alloc(m, tbase, oldbase, nb);
3534
          return prepend_alloc(m, tbase, oldbase, nb);
3535
        }
3535
        }
3536
        else
3536
        else
3537
          add_segment(m, tbase, tsize, mmap_flag);
3537
          add_segment(m, tbase, tsize, mmap_flag);
3538
      }
3538
      }
3539
    }
3539
    }
3540
 
3540
 
3541
    if (nb < m->topsize) { /* Allocate from new or extended top space */
3541
    if (nb < m->topsize) { /* Allocate from new or extended top space */
3542
      size_t rsize = m->topsize -= nb;
3542
      size_t rsize = m->topsize -= nb;
3543
      mchunkptr p = m->top;
3543
      mchunkptr p = m->top;
3544
      mchunkptr r = m->top = chunk_plus_offset(p, nb);
3544
      mchunkptr r = m->top = chunk_plus_offset(p, nb);
3545
      r->head = rsize | PINUSE_BIT;
3545
      r->head = rsize | PINUSE_BIT;
3546
      set_size_and_pinuse_of_inuse_chunk(m, p, nb);
3546
      set_size_and_pinuse_of_inuse_chunk(m, p, nb);
3547
      check_top_chunk(m, m->top);
3547
      check_top_chunk(m, m->top);
3548
      check_malloced_chunk(m, chunk2mem(p), nb);
3548
      check_malloced_chunk(m, chunk2mem(p), nb);
3549
      return chunk2mem(p);
3549
      return chunk2mem(p);
3550
    }
3550
    }
3551
  }
3551
  }
3552
 
3552
 
3553
  MALLOC_FAILURE_ACTION;
3553
  MALLOC_FAILURE_ACTION;
3554
  return 0;
3554
  return 0;
3555
}
3555
}
3556
 
3556
 
3557
/* -----------------------  system deallocation -------------------------- */
3557
/* -----------------------  system deallocation -------------------------- */
3558
 
3558
 
3559
/* Unmap and unlink any mmapped segments that don't contain used chunks */
3559
/* Unmap and unlink any mmapped segments that don't contain used chunks */
3560
static size_t release_unused_segments(mstate m) {
3560
static size_t release_unused_segments(mstate m) {
3561
  size_t released = 0;
3561
  size_t released = 0;
3562
  msegmentptr pred = &m->seg;
3562
  msegmentptr pred = &m->seg;
3563
  msegmentptr sp = pred->next;
3563
  msegmentptr sp = pred->next;
3564
  while (sp != 0) {
3564
  while (sp != 0) {
3565
    char* base = sp->base;
3565
    char* base = sp->base;
3566
    size_t size = sp->size;
3566
    size_t size = sp->size;
3567
    msegmentptr next = sp->next;
3567
    msegmentptr next = sp->next;
3568
    if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
3568
    if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
3569
      mchunkptr p = align_as_chunk(base);
3569
      mchunkptr p = align_as_chunk(base);
3570
      size_t psize = chunksize(p);
3570
      size_t psize = chunksize(p);
3571
      /* Can unmap if first chunk holds entire segment and not pinned */
3571
      /* Can unmap if first chunk holds entire segment and not pinned */
3572
      if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
3572
      if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
3573
        tchunkptr tp = (tchunkptr)p;
3573
        tchunkptr tp = (tchunkptr)p;
3574
        assert(segment_holds(sp, (char*)sp));
3574
        assert(segment_holds(sp, (char*)sp));
3575
        if (p == m->dv) {
3575
        if (p == m->dv) {
3576
          m->dv = 0;
3576
          m->dv = 0;
3577
          m->dvsize = 0;
3577
          m->dvsize = 0;
3578
        }
3578
        }
3579
        else {
3579
        else {
3580
          unlink_large_chunk(m, tp);
3580
          unlink_large_chunk(m, tp);
3581
        }
3581
        }
3582
        if (CALL_MUNMAP(base, size) == 0) {
3582
        if (CALL_MUNMAP(base, size) == 0) {
3583
          released += size;
3583
          released += size;
3584
          m->footprint -= size;
3584
          m->footprint -= size;
3585
          /* unlink obsoleted record */
3585
          /* unlink obsoleted record */
3586
          sp = pred;
3586
          sp = pred;
3587
          sp->next = next;
3587
          sp->next = next;
3588
        }
3588
        }
3589
        else { /* back out if cannot unmap */
3589
        else { /* back out if cannot unmap */
3590
          insert_large_chunk(m, tp, psize);
3590
          insert_large_chunk(m, tp, psize);
3591
        }
3591
        }
3592
      }
3592
      }
3593
    }
3593
    }
3594
    pred = sp;
3594
    pred = sp;
3595
    sp = next;
3595
    sp = next;
3596
  }
3596
  }
3597
  return released;
3597
  return released;
3598
}
3598
}
3599
 
3599
 
3600
static int sys_trim(mstate m, size_t pad) {
3600
static int sys_trim(mstate m, size_t pad) {
3601
  size_t released = 0;
3601
  size_t released = 0;
3602
  if (pad < MAX_REQUEST && is_initialized(m)) {
3602
  if (pad < MAX_REQUEST && is_initialized(m)) {
3603
    pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
3603
    pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
3604
 
3604
 
3605
    if (m->topsize > pad) {
3605
    if (m->topsize > pad) {
3606
      /* Shrink top space in granularity-size units, keeping at least one */
3606
      /* Shrink top space in granularity-size units, keeping at least one */
3607
      size_t unit = mparams.granularity;
3607
      size_t unit = mparams.granularity;
3608
      size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
3608
      size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
3609
                      SIZE_T_ONE) * unit;
3609
                      SIZE_T_ONE) * unit;
3610
      msegmentptr sp = segment_holding(m, (char*)m->top);
3610
      msegmentptr sp = segment_holding(m, (char*)m->top);
3611
 
3611
 
3612
      if (!is_extern_segment(sp)) {
3612
      if (!is_extern_segment(sp)) {
3613
        if (is_mmapped_segment(sp)) {
3613
        if (is_mmapped_segment(sp)) {
3614
          if (HAVE_MMAP &&
3614
          if (HAVE_MMAP &&
3615
              sp->size >= extra &&
3615
              sp->size >= extra &&
3616
              !has_segment_link(m, sp)) { /* can't shrink if pinned */
3616
              !has_segment_link(m, sp)) { /* can't shrink if pinned */
3617
            size_t newsize = sp->size - extra;
3617
            size_t newsize = sp->size - extra;
3618
            /* Prefer mremap, fall back to munmap */
3618
            /* Prefer mremap, fall back to munmap */
3619
            if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
3619
            if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
3620
                (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
3620
                (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
3621
              released = extra;
3621
              released = extra;
3622
            }
3622
            }
3623
          }
3623
          }
3624
        }
3624
        }
3625
        else if (HAVE_MORECORE) {
3625
        else if (HAVE_MORECORE) {
3626
          if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
3626
          if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
3627
            extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
3627
            extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
3628
          ACQUIRE_MORECORE_LOCK();
3628
          ACQUIRE_MORECORE_LOCK();
3629
          {
3629
          {
3630
            /* Make sure end of memory is where we last set it. */
3630
            /* Make sure end of memory is where we last set it. */
3631
            char* old_br = (char*)(CALL_MORECORE(0));
3631
            char* old_br = (char*)(CALL_MORECORE(0));
3632
            if (old_br == sp->base + sp->size) {
3632
            if (old_br == sp->base + sp->size) {
3633
              char* rel_br = (char*)(CALL_MORECORE(-extra));
3633
              char* rel_br = (char*)(CALL_MORECORE(-extra));
3634
              char* new_br = (char*)(CALL_MORECORE(0));
3634
              char* new_br = (char*)(CALL_MORECORE(0));
3635
              if (rel_br != CMFAIL && new_br < old_br)
3635
              if (rel_br != CMFAIL && new_br < old_br)
3636
                released = old_br - new_br;
3636
                released = old_br - new_br;
3637
            }
3637
            }
3638
          }
3638
          }
3639
          RELEASE_MORECORE_LOCK();
3639
          RELEASE_MORECORE_LOCK();
3640
        }
3640
        }
3641
      }
3641
      }
3642
 
3642
 
3643
      if (released != 0) {
3643
      if (released != 0) {
3644
        sp->size -= released;
3644
        sp->size -= released;
3645
        m->footprint -= released;
3645
        m->footprint -= released;
3646
        init_top(m, m->top, m->topsize - released);
3646
        init_top(m, m->top, m->topsize - released);
3647
        check_top_chunk(m, m->top);
3647
        check_top_chunk(m, m->top);
3648
      }
3648
      }
3649
    }
3649
    }
3650
 
3650
 
3651
    /* Unmap any unused mmapped segments */
3651
    /* Unmap any unused mmapped segments */
3652
    if (HAVE_MMAP) 
3652
    if (HAVE_MMAP) 
3653
      released += release_unused_segments(m);
3653
      released += release_unused_segments(m);
3654
 
3654
 
3655
    /* On failure, disable autotrim to avoid repeated failed future calls */
3655
    /* On failure, disable autotrim to avoid repeated failed future calls */
3656
    if (released == 0)
3656
    if (released == 0)
3657
      m->trim_check = MAX_SIZE_T;
3657
      m->trim_check = MAX_SIZE_T;
3658
  }
3658
  }
3659
 
3659
 
3660
  return (released != 0)? 1 : 0;
3660
  return (released != 0)? 1 : 0;
3661
}
3661
}
3662
 
3662
 
3663
/* ---------------------------- malloc support --------------------------- */
3663
/* ---------------------------- malloc support --------------------------- */
3664
 
3664
 
3665
/* allocate a large request from the best fitting chunk in a treebin */
3665
/* allocate a large request from the best fitting chunk in a treebin */
3666
static void* tmalloc_large(mstate m, size_t nb) {
3666
static void* tmalloc_large(mstate m, size_t nb) {
3667
  tchunkptr v = 0;
3667
  tchunkptr v = 0;
3668
  size_t rsize = -nb; /* Unsigned negation */
3668
  size_t rsize = -nb; /* Unsigned negation */
3669
  tchunkptr t;
3669
  tchunkptr t;
3670
  bindex_t idx;
3670
  bindex_t idx;
3671
  compute_tree_index(nb, idx);
3671
  compute_tree_index(nb, idx);
3672
 
3672
 
3673
  if ((t = *treebin_at(m, idx)) != 0) {
3673
  if ((t = *treebin_at(m, idx)) != 0) {
3674
    /* Traverse tree for this bin looking for node with size == nb */
3674
    /* Traverse tree for this bin looking for node with size == nb */
3675
    size_t sizebits = nb << leftshift_for_tree_index(idx);
3675
    size_t sizebits = nb << leftshift_for_tree_index(idx);
3676
    tchunkptr rst = 0;  /* The deepest untaken right subtree */
3676
    tchunkptr rst = 0;  /* The deepest untaken right subtree */
3677
    for (;;) {
3677
    for (;;) {
3678
      tchunkptr rt;
3678
      tchunkptr rt;
3679
      size_t trem = chunksize(t) - nb;
3679
      size_t trem = chunksize(t) - nb;
3680
      if (trem < rsize) {
3680
      if (trem < rsize) {
3681
        v = t;
3681
        v = t;
3682
        if ((rsize = trem) == 0)
3682
        if ((rsize = trem) == 0)
3683
          break;
3683
          break;
3684
      }
3684
      }
3685
      rt = t->child[1];
3685
      rt = t->child[1];
3686
      t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
3686
      t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
3687
      if (rt != 0 && rt != t)
3687
      if (rt != 0 && rt != t)
3688
        rst = rt;
3688
        rst = rt;
3689
      if (t == 0) {
3689
      if (t == 0) {
3690
        t = rst; /* set t to least subtree holding sizes > nb */
3690
        t = rst; /* set t to least subtree holding sizes > nb */
3691
        break;
3691
        break;
3692
      }
3692
      }
3693
      sizebits <<= 1;
3693
      sizebits <<= 1;
3694
    }
3694
    }
3695
  }
3695
  }
3696
 
3696
 
3697
  if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
3697
  if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
3698
    binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
3698
    binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
3699
    if (leftbits != 0) {
3699
    if (leftbits != 0) {
3700
      bindex_t i;
3700
      bindex_t i;
3701
      binmap_t leastbit = least_bit(leftbits);
3701
      binmap_t leastbit = least_bit(leftbits);
3702
      compute_bit2idx(leastbit, i);
3702
      compute_bit2idx(leastbit, i);
3703
      t = *treebin_at(m, i);
3703
      t = *treebin_at(m, i);
3704
    }
3704
    }
3705
  }
3705
  }
3706
 
3706
 
3707
  while (t != 0) { /* find smallest of tree or subtree */
3707
  while (t != 0) { /* find smallest of tree or subtree */
3708
    size_t trem = chunksize(t) - nb;
3708
    size_t trem = chunksize(t) - nb;
3709
    if (trem < rsize) {
3709
    if (trem < rsize) {
3710
      rsize = trem;
3710
      rsize = trem;
3711
      v = t;
3711
      v = t;
3712
    }
3712
    }
3713
    t = leftmost_child(t);
3713
    t = leftmost_child(t);
3714
  }
3714
  }
3715
 
3715
 
3716
  /*  If dv is a better fit, return 0 so malloc will use it */
3716
  /*  If dv is a better fit, return 0 so malloc will use it */
3717
  if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
3717
  if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
3718
    if (RTCHECK(ok_address(m, v))) { /* split */
3718
    if (RTCHECK(ok_address(m, v))) { /* split */
3719
      mchunkptr r = chunk_plus_offset(v, nb);
3719
      mchunkptr r = chunk_plus_offset(v, nb);
3720
      assert(chunksize(v) == rsize + nb);
3720
      assert(chunksize(v) == rsize + nb);
3721
      if (RTCHECK(ok_next(v, r))) {
3721
      if (RTCHECK(ok_next(v, r))) {
3722
        unlink_large_chunk(m, v);
3722
        unlink_large_chunk(m, v);
3723
        if (rsize < MIN_CHUNK_SIZE)
3723
        if (rsize < MIN_CHUNK_SIZE)
3724
          set_inuse_and_pinuse(m, v, (rsize + nb));
3724
          set_inuse_and_pinuse(m, v, (rsize + nb));
3725
        else {
3725
        else {
3726
          set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3726
          set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3727
          set_size_and_pinuse_of_free_chunk(r, rsize);
3727
          set_size_and_pinuse_of_free_chunk(r, rsize);
3728
          insert_chunk(m, r, rsize);
3728
          insert_chunk(m, r, rsize);
3729
        }
3729
        }
3730
        return chunk2mem(v);
3730
        return chunk2mem(v);
3731
      }
3731
      }
3732
    }
3732
    }
3733
    CORRUPTION_ERROR_ACTION(m);
3733
    CORRUPTION_ERROR_ACTION(m);
3734
  }
3734
  }
3735
  return 0;
3735
  return 0;
3736
}
3736
}
3737
 
3737
 
3738
/* allocate a small request from the best fitting chunk in a treebin */
3738
/* allocate a small request from the best fitting chunk in a treebin */
3739
static void* tmalloc_small(mstate m, size_t nb) {
3739
static void* tmalloc_small(mstate m, size_t nb) {
3740
  tchunkptr t, v;
3740
  tchunkptr t, v;
3741
  size_t rsize;
3741
  size_t rsize;
3742
  bindex_t i;
3742
  bindex_t i;
3743
  binmap_t leastbit = least_bit(m->treemap);
3743
  binmap_t leastbit = least_bit(m->treemap);
3744
  compute_bit2idx(leastbit, i);
3744
  compute_bit2idx(leastbit, i);
3745
 
3745
 
3746
  v = t = *treebin_at(m, i);
3746
  v = t = *treebin_at(m, i);
3747
  rsize = chunksize(t) - nb;
3747
  rsize = chunksize(t) - nb;
3748
 
3748
 
3749
  while ((t = leftmost_child(t)) != 0) {
3749
  while ((t = leftmost_child(t)) != 0) {
3750
    size_t trem = chunksize(t) - nb;
3750
    size_t trem = chunksize(t) - nb;
3751
    if (trem < rsize) {
3751
    if (trem < rsize) {
3752
      rsize = trem;
3752
      rsize = trem;
3753
      v = t;
3753
      v = t;
3754
    }
3754
    }
3755
  }
3755
  }
3756
 
3756
 
3757
  if (RTCHECK(ok_address(m, v))) {
3757
  if (RTCHECK(ok_address(m, v))) {
3758
    mchunkptr r = chunk_plus_offset(v, nb);
3758
    mchunkptr r = chunk_plus_offset(v, nb);
3759
    assert(chunksize(v) == rsize + nb);
3759
    assert(chunksize(v) == rsize + nb);
3760
    if (RTCHECK(ok_next(v, r))) {
3760
    if (RTCHECK(ok_next(v, r))) {
3761
      unlink_large_chunk(m, v);
3761
      unlink_large_chunk(m, v);
3762
      if (rsize < MIN_CHUNK_SIZE)
3762
      if (rsize < MIN_CHUNK_SIZE)
3763
        set_inuse_and_pinuse(m, v, (rsize + nb));
3763
        set_inuse_and_pinuse(m, v, (rsize + nb));
3764
      else {
3764
      else {
3765
        set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3765
        set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3766
        set_size_and_pinuse_of_free_chunk(r, rsize);
3766
        set_size_and_pinuse_of_free_chunk(r, rsize);
3767
        replace_dv(m, r, rsize);
3767
        replace_dv(m, r, rsize);
3768
      }
3768
      }
3769
      return chunk2mem(v);
3769
      return chunk2mem(v);
3770
    }
3770
    }
3771
  }
3771
  }
3772
 
3772
 
3773
  CORRUPTION_ERROR_ACTION(m);
3773
  CORRUPTION_ERROR_ACTION(m);
3774
  return 0;
3774
  return 0;
3775
}
3775
}
3776
 
3776
 
3777
/* --------------------------- realloc support --------------------------- */
3777
/* --------------------------- realloc support --------------------------- */
3778
 
3778
 
3779
static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
3779
static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
3780
  if (bytes >= MAX_REQUEST) {
3780
  if (bytes >= MAX_REQUEST) {
3781
    MALLOC_FAILURE_ACTION;
3781
    MALLOC_FAILURE_ACTION;
3782
    return 0;
3782
    return 0;
3783
  }
3783
  }
3784
  if (!PREACTION(m)) {
3784
  if (!PREACTION(m)) {
3785
    mchunkptr oldp = mem2chunk(oldmem);
3785
    mchunkptr oldp = mem2chunk(oldmem);
3786
    size_t oldsize = chunksize(oldp);
3786
    size_t oldsize = chunksize(oldp);
3787
    mchunkptr next = chunk_plus_offset(oldp, oldsize);
3787
    mchunkptr next = chunk_plus_offset(oldp, oldsize);
3788
    mchunkptr newp = 0;
3788
    mchunkptr newp = 0;
3789
    void* extra = 0;
3789
    void* extra = 0;
3790
 
3790
 
3791
    /* Try to either shrink or extend into top. Else malloc-copy-free */
3791
    /* Try to either shrink or extend into top. Else malloc-copy-free */
3792
 
3792
 
3793
    if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
3793
    if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
3794
                ok_next(oldp, next) && ok_pinuse(next))) {
3794
                ok_next(oldp, next) && ok_pinuse(next))) {
3795
      size_t nb = request2size(bytes);
3795
      size_t nb = request2size(bytes);
3796
      if (is_mmapped(oldp))
3796
      if (is_mmapped(oldp))
3797
        newp = mmap_resize(m, oldp, nb);
3797
        newp = mmap_resize(m, oldp, nb);
3798
      else if (oldsize >= nb) { /* already big enough */
3798
      else if (oldsize >= nb) { /* already big enough */
3799
        size_t rsize = oldsize - nb;
3799
        size_t rsize = oldsize - nb;
3800
        newp = oldp;
3800
        newp = oldp;
3801
        if (rsize >= MIN_CHUNK_SIZE) {
3801
        if (rsize >= MIN_CHUNK_SIZE) {
3802
          mchunkptr remainder = chunk_plus_offset(newp, nb);
3802
          mchunkptr remainder = chunk_plus_offset(newp, nb);
3803
          set_inuse(m, newp, nb);
3803
          set_inuse(m, newp, nb);
3804
          set_inuse(m, remainder, rsize);
3804
          set_inuse(m, remainder, rsize);
3805
          extra = chunk2mem(remainder);
3805
          extra = chunk2mem(remainder);
3806
        }
3806
        }
3807
      }
3807
      }
3808
      else if (next == m->top && oldsize + m->topsize > nb) {
3808
      else if (next == m->top && oldsize + m->topsize > nb) {
3809
        /* Expand into top */
3809
        /* Expand into top */
3810
        size_t newsize = oldsize + m->topsize;
3810
        size_t newsize = oldsize + m->topsize;
3811
        size_t newtopsize = newsize - nb;
3811
        size_t newtopsize = newsize - nb;
3812
        mchunkptr newtop = chunk_plus_offset(oldp, nb);
3812
        mchunkptr newtop = chunk_plus_offset(oldp, nb);
3813
        set_inuse(m, oldp, nb);
3813
        set_inuse(m, oldp, nb);
3814
        newtop->head = newtopsize |PINUSE_BIT;
3814
        newtop->head = newtopsize |PINUSE_BIT;
3815
        m->top = newtop;
3815
        m->top = newtop;
3816
        m->topsize = newtopsize;
3816
        m->topsize = newtopsize;
3817
        newp = oldp;
3817
        newp = oldp;
3818
      }
3818
      }
3819
    }
3819
    }
3820
    else {
3820
    else {
3821
      USAGE_ERROR_ACTION(m, oldmem);
3821
      USAGE_ERROR_ACTION(m, oldmem);
3822
      POSTACTION(m);
3822
      POSTACTION(m);
3823
      return 0;
3823
      return 0;
3824
    }
3824
    }
3825
 
3825
 
3826
    POSTACTION(m);
3826
    POSTACTION(m);
3827
 
3827
 
3828
    if (newp != 0) {
3828
    if (newp != 0) {
3829
      if (extra != 0) {
3829
      if (extra != 0) {
3830
        internal_free(m, extra);
3830
        internal_free(m, extra);
3831
      }
3831
      }
3832
      check_inuse_chunk(m, newp);
3832
      check_inuse_chunk(m, newp);
3833
      return chunk2mem(newp);
3833
      return chunk2mem(newp);
3834
    }
3834
    }
3835
    else {
3835
    else {
3836
      void* newmem = internal_malloc(m, bytes);
3836
      void* newmem = internal_malloc(m, bytes);
3837
      if (newmem != 0) {
3837
      if (newmem != 0) {
3838
        size_t oc = oldsize - overhead_for(oldp);
3838
        size_t oc = oldsize - overhead_for(oldp);
3839
        memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
3839
        memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
3840
        internal_free(m, oldmem);
3840
        internal_free(m, oldmem);
3841
      }
3841
      }
3842
      return newmem;
3842
      return newmem;
3843
    }
3843
    }
3844
  }
3844
  }
3845
  return 0;
3845
  return 0;
3846
}
3846
}
3847
 
3847
 
3848
/* --------------------------- memalign support -------------------------- */
3848
/* --------------------------- memalign support -------------------------- */
3849
 
3849
 
3850
#if 0
3850
#if 0
3851
static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
3851
static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
3852
  if (alignment <= MALLOC_ALIGNMENT)    /* Can just use malloc */
3852
  if (alignment <= MALLOC_ALIGNMENT)    /* Can just use malloc */
3853
    return internal_malloc(m, bytes);
3853
    return internal_malloc(m, bytes);
3854
  if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
3854
  if (alignment <  MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
3855
    alignment = MIN_CHUNK_SIZE;
3855
    alignment = MIN_CHUNK_SIZE;
3856
  if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
3856
  if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
3857
    size_t a = MALLOC_ALIGNMENT << 1;
3857
    size_t a = MALLOC_ALIGNMENT << 1;
3858
    while (a < alignment) a <<= 1;
3858
    while (a < alignment) a <<= 1;
3859
    alignment = a;
3859
    alignment = a;
3860
  }
3860
  }
3861
  
3861
  
3862
  if (bytes >= MAX_REQUEST - alignment) {
3862
  if (bytes >= MAX_REQUEST - alignment) {
3863
    if (m != 0)  { /* Test isn't needed but avoids compiler warning */
3863
    if (m != 0)  { /* Test isn't needed but avoids compiler warning */
3864
      MALLOC_FAILURE_ACTION;
3864
      MALLOC_FAILURE_ACTION;
3865
    }
3865
    }
3866
  }
3866
  }
3867
  else {
3867
  else {
3868
    size_t nb = request2size(bytes);
3868
    size_t nb = request2size(bytes);
3869
    size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
3869
    size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
3870
    char* mem = (char*)internal_malloc(m, req);
3870
    char* mem = (char*)internal_malloc(m, req);
3871
    if (mem != 0) {
3871
    if (mem != 0) {
3872
      void* leader = 0;
3872
      void* leader = 0;
3873
      void* trailer = 0;
3873
      void* trailer = 0;
3874
      mchunkptr p = mem2chunk(mem);
3874
      mchunkptr p = mem2chunk(mem);
3875
 
3875
 
3876
      if (PREACTION(m)) return 0;
3876
      if (PREACTION(m)) return 0;
3877
      if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
3877
      if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
3878
        /*
3878
        /*
3879
          Find an aligned spot inside chunk.  Since we need to give
3879
          Find an aligned spot inside chunk.  Since we need to give
3880
          back leading space in a chunk of at least MIN_CHUNK_SIZE, if
3880
          back leading space in a chunk of at least MIN_CHUNK_SIZE, if
3881
          the first calculation places us at a spot with less than
3881
          the first calculation places us at a spot with less than
3882
          MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
3882
          MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
3883
          We've allocated enough total room so that this is always
3883
          We've allocated enough total room so that this is always
3884
          possible.
3884
          possible.
3885
        */
3885
        */
3886
        char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
3886
        char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
3887
                                                       alignment -
3887
                                                       alignment -
3888
                                                       SIZE_T_ONE)) &
3888
                                                       SIZE_T_ONE)) &
3889
                                             -alignment));
3889
                                             -alignment));
3890
        char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
3890
        char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
3891
          br : br+alignment;
3891
          br : br+alignment;
3892
        mchunkptr newp = (mchunkptr)pos;
3892
        mchunkptr newp = (mchunkptr)pos;
3893
        size_t leadsize = pos - (char*)(p);
3893
        size_t leadsize = pos - (char*)(p);
3894
        size_t newsize = chunksize(p) - leadsize;
3894
        size_t newsize = chunksize(p) - leadsize;
3895
 
3895
 
3896
        if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
3896
        if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
3897
          newp->prev_foot = p->prev_foot + leadsize;
3897
          newp->prev_foot = p->prev_foot + leadsize;
3898
          newp->head = (newsize|CINUSE_BIT);
3898
          newp->head = (newsize|CINUSE_BIT);
3899
        }
3899
        }
3900
        else { /* Otherwise, give back leader, use the rest */
3900
        else { /* Otherwise, give back leader, use the rest */
3901
          set_inuse(m, newp, newsize);
3901
          set_inuse(m, newp, newsize);
3902
          set_inuse(m, p, leadsize);
3902
          set_inuse(m, p, leadsize);
3903
          leader = chunk2mem(p);
3903
          leader = chunk2mem(p);
3904
        }
3904
        }
3905
        p = newp;
3905
        p = newp;
3906
      }
3906
      }
3907
 
3907
 
3908
      /* Give back spare room at the end */
3908
      /* Give back spare room at the end */
3909
      if (!is_mmapped(p)) {
3909
      if (!is_mmapped(p)) {
3910
        size_t size = chunksize(p);
3910
        size_t size = chunksize(p);
3911
        if (size > nb + MIN_CHUNK_SIZE) {
3911
        if (size > nb + MIN_CHUNK_SIZE) {
3912
          size_t remainder_size = size - nb;
3912
          size_t remainder_size = size - nb;
3913
          mchunkptr remainder = chunk_plus_offset(p, nb);
3913
          mchunkptr remainder = chunk_plus_offset(p, nb);
3914
          set_inuse(m, p, nb);
3914
          set_inuse(m, p, nb);
3915
          set_inuse(m, remainder, remainder_size);
3915
          set_inuse(m, remainder, remainder_size);
3916
          trailer = chunk2mem(remainder);
3916
          trailer = chunk2mem(remainder);
3917
        }
3917
        }
3918
      }
3918
      }
3919
 
3919
 
3920
      assert (chunksize(p) >= nb);
3920
      assert (chunksize(p) >= nb);
3921
      assert((((size_t)(chunk2mem(p))) % alignment) == 0);
3921
      assert((((size_t)(chunk2mem(p))) % alignment) == 0);
3922
      check_inuse_chunk(m, p);
3922
      check_inuse_chunk(m, p);
3923
      POSTACTION(m);
3923
      POSTACTION(m);
3924
      if (leader != 0) {
3924
      if (leader != 0) {
3925
        internal_free(m, leader);
3925
        internal_free(m, leader);
3926
      }
3926
      }
3927
      if (trailer != 0) {
3927
      if (trailer != 0) {
3928
        internal_free(m, trailer);
3928
        internal_free(m, trailer);
3929
      }
3929
      }
3930
      return chunk2mem(p);
3930
      return chunk2mem(p);
3931
    }
3931
    }
3932
  }
3932
  }
3933
  return 0;
3933
  return 0;
3934
}
3934
}
3935
 
3935
 
3936
/* ------------------------ comalloc/coalloc support --------------------- */
3936
/* ------------------------ comalloc/coalloc support --------------------- */
3937
 
3937
 
3938
static void** ialloc(mstate m,
3938
static void** ialloc(mstate m,
3939
                     size_t n_elements,
3939
                     size_t n_elements,
3940
                     size_t* sizes,
3940
                     size_t* sizes,
3941
                     int opts,
3941
                     int opts,
3942
                     void* chunks[]) {
3942
                     void* chunks[]) {
3943
  /*
3943
  /*
3944
    This provides common support for independent_X routines, handling
3944
    This provides common support for independent_X routines, handling
3945
    all of the combinations that can result.
3945
    all of the combinations that can result.
3946
 
3946
 
3947
    The opts arg has:
3947
    The opts arg has:
3948
    bit 0 set if all elements are same size (using sizes[0])
3948
    bit 0 set if all elements are same size (using sizes[0])
3949
    bit 1 set if elements should be zeroed
3949
    bit 1 set if elements should be zeroed
3950
  */
3950
  */
3951
 
3951
 
3952
  size_t    element_size;   /* chunksize of each element, if all same */
3952
  size_t    element_size;   /* chunksize of each element, if all same */
3953
  size_t    contents_size;  /* total size of elements */
3953
  size_t    contents_size;  /* total size of elements */
3954
  size_t    array_size;     /* request size of pointer array */
3954
  size_t    array_size;     /* request size of pointer array */
3955
  void*     mem;            /* malloced aggregate space */
3955
  void*     mem;            /* malloced aggregate space */
3956
  mchunkptr p;              /* corresponding chunk */
3956
  mchunkptr p;              /* corresponding chunk */
3957
  size_t    remainder_size; /* remaining bytes while splitting */
3957
  size_t    remainder_size; /* remaining bytes while splitting */
3958
  void**    marray;         /* either "chunks" or malloced ptr array */
3958
  void**    marray;         /* either "chunks" or malloced ptr array */
3959
  mchunkptr array_chunk;    /* chunk for malloced ptr array */
3959
  mchunkptr array_chunk;    /* chunk for malloced ptr array */
3960
  flag_t    was_enabled;    /* to disable mmap */
3960
  flag_t    was_enabled;    /* to disable mmap */
3961
  size_t    size;
3961
  size_t    size;
3962
  size_t    i;
3962
  size_t    i;
3963
 
3963
 
3964
  /* compute array length, if needed */
3964
  /* compute array length, if needed */
3965
  if (chunks != 0) {
3965
  if (chunks != 0) {
3966
    if (n_elements == 0)
3966
    if (n_elements == 0)
3967
      return chunks; /* nothing to do */
3967
      return chunks; /* nothing to do */
3968
    marray = chunks;
3968
    marray = chunks;
3969
    array_size = 0;
3969
    array_size = 0;
3970
  }
3970
  }
3971
  else {
3971
  else {
3972
    /* if empty req, must still return chunk representing empty array */
3972
    /* if empty req, must still return chunk representing empty array */
3973
    if (n_elements == 0)
3973
    if (n_elements == 0)
3974
      return (void**)internal_malloc(m, 0);
3974
      return (void**)internal_malloc(m, 0);
3975
    marray = 0;
3975
    marray = 0;
3976
    array_size = request2size(n_elements * (sizeof(void*)));
3976
    array_size = request2size(n_elements * (sizeof(void*)));
3977
  }
3977
  }
3978
 
3978
 
3979
  /* compute total element size */
3979
  /* compute total element size */
3980
  if (opts & 0x1) { /* all-same-size */
3980
  if (opts & 0x1) { /* all-same-size */
3981
    element_size = request2size(*sizes);
3981
    element_size = request2size(*sizes);
3982
    contents_size = n_elements * element_size;
3982
    contents_size = n_elements * element_size;
3983
  }
3983
  }
3984
  else { /* add up all the sizes */
3984
  else { /* add up all the sizes */
3985
    element_size = 0;
3985
    element_size = 0;
3986
    contents_size = 0;
3986
    contents_size = 0;
3987
    for (i = 0; i != n_elements; ++i)
3987
    for (i = 0; i != n_elements; ++i)
3988
      contents_size += request2size(sizes[i]);
3988
      contents_size += request2size(sizes[i]);
3989
  }
3989
  }
3990
 
3990
 
3991
  size = contents_size + array_size;
3991
  size = contents_size + array_size;
3992
 
3992
 
3993
  /*
3993
  /*
3994
     Allocate the aggregate chunk.  First disable direct-mmapping so
3994
     Allocate the aggregate chunk.  First disable direct-mmapping so
3995
     malloc won't use it, since we would not be able to later
3995
     malloc won't use it, since we would not be able to later
3996
     free/realloc space internal to a segregated mmap region.
3996
     free/realloc space internal to a segregated mmap region.
3997
  */
3997
  */
3998
  was_enabled = use_mmap(m);
3998
  was_enabled = use_mmap(m);
3999
  disable_mmap(m);
3999
  disable_mmap(m);
4000
  mem = internal_malloc(m, size - CHUNK_OVERHEAD);
4000
  mem = internal_malloc(m, size - CHUNK_OVERHEAD);
4001
  if (was_enabled)
4001
  if (was_enabled)
4002
    enable_mmap(m);
4002
    enable_mmap(m);
4003
  if (mem == 0)
4003
  if (mem == 0)
4004
    return 0;
4004
    return 0;
4005
 
4005
 
4006
  if (PREACTION(m)) return 0;
4006
  if (PREACTION(m)) return 0;
4007
  p = mem2chunk(mem);
4007
  p = mem2chunk(mem);
4008
  remainder_size = chunksize(p);
4008
  remainder_size = chunksize(p);
4009
 
4009
 
4010
  assert(!is_mmapped(p));
4010
  assert(!is_mmapped(p));
4011
 
4011
 
4012
  if (opts & 0x2) {       /* optionally clear the elements */
4012
  if (opts & 0x2) {       /* optionally clear the elements */
4013
    memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
4013
    memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
4014
  }
4014
  }
4015
 
4015
 
4016
  /* If not provided, allocate the pointer array as final part of chunk */
4016
  /* If not provided, allocate the pointer array as final part of chunk */
4017
  if (marray == 0) {
4017
  if (marray == 0) {
4018
    size_t  array_chunk_size;
4018
    size_t  array_chunk_size;
4019
    array_chunk = chunk_plus_offset(p, contents_size);
4019
    array_chunk = chunk_plus_offset(p, contents_size);
4020
    array_chunk_size = remainder_size - contents_size;
4020
    array_chunk_size = remainder_size - contents_size;
4021
    marray = (void**) (chunk2mem(array_chunk));
4021
    marray = (void**) (chunk2mem(array_chunk));
4022
    set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
4022
    set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
4023
    remainder_size = contents_size;
4023
    remainder_size = contents_size;
4024
  }
4024
  }
4025
 
4025
 
4026
  /* split out elements */
4026
  /* split out elements */
4027
  for (i = 0; ; ++i) {
4027
  for (i = 0; ; ++i) {
4028
    marray[i] = chunk2mem(p);
4028
    marray[i] = chunk2mem(p);
4029
    if (i != n_elements-1) {
4029
    if (i != n_elements-1) {
4030
      if (element_size != 0)
4030
      if (element_size != 0)
4031
        size = element_size;
4031
        size = element_size;
4032
      else
4032
      else
4033
        size = request2size(sizes[i]);
4033
        size = request2size(sizes[i]);
4034
      remainder_size -= size;
4034
      remainder_size -= size;
4035
      set_size_and_pinuse_of_inuse_chunk(m, p, size);
4035
      set_size_and_pinuse_of_inuse_chunk(m, p, size);
4036
      p = chunk_plus_offset(p, size);
4036
      p = chunk_plus_offset(p, size);
4037
    }
4037
    }
4038
    else { /* the final element absorbs any overallocation slop */
4038
    else { /* the final element absorbs any overallocation slop */
4039
      set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
4039
      set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
4040
      break;
4040
      break;
4041
    }
4041
    }
4042
  }
4042
  }
4043
 
4043
 
4044
#if DEBUG
4044
#if DEBUG
4045
  if (marray != chunks) {
4045
  if (marray != chunks) {
4046
    /* final element must have exactly exhausted chunk */
4046
    /* final element must have exactly exhausted chunk */
4047
    if (element_size != 0) {
4047
    if (element_size != 0) {
4048
      assert(remainder_size == element_size);
4048
      assert(remainder_size == element_size);
4049
    }
4049
    }
4050
    else {
4050
    else {
4051
      assert(remainder_size == request2size(sizes[i]));
4051
      assert(remainder_size == request2size(sizes[i]));
4052
    }
4052
    }
4053
    check_inuse_chunk(m, mem2chunk(marray));
4053
    check_inuse_chunk(m, mem2chunk(marray));
4054
  }
4054
  }
4055
  for (i = 0; i != n_elements; ++i)
4055
  for (i = 0; i != n_elements; ++i)
4056
    check_inuse_chunk(m, mem2chunk(marray[i]));
4056
    check_inuse_chunk(m, mem2chunk(marray[i]));
4057
 
4057
 
4058
#endif /* DEBUG */
4058
#endif /* DEBUG */
4059
 
4059
 
4060
  POSTACTION(m);
4060
  POSTACTION(m);
4061
  return marray;
4061
  return marray;
4062
}
4062
}
4063
#endif
4063
#endif
4064
 
4064
 
4065
/* -------------------------- public routines ---------------------------- */
4065
/* -------------------------- public routines ---------------------------- */
4066
 
4066
 
4067
#if !ONLY_MSPACES
4067
#if !ONLY_MSPACES
4068
 
4068
 
4069
void* dlmalloc(size_t bytes) {
4069
void* dlmalloc(size_t bytes) {
4070
  /*
4070
  /*
4071
     Basic algorithm:
4071
     Basic algorithm:
4072
     If a small request (< 256 bytes minus per-chunk overhead):
4072
     If a small request (< 256 bytes minus per-chunk overhead):
4073
       1. If one exists, use a remainderless chunk in associated smallbin.
4073
       1. If one exists, use a remainderless chunk in associated smallbin.
4074
          (Remainderless means that there are too few excess bytes to
4074
          (Remainderless means that there are too few excess bytes to
4075
          represent as a chunk.)
4075
          represent as a chunk.)
4076
       2. If it is big enough, use the dv chunk, which is normally the
4076
       2. If it is big enough, use the dv chunk, which is normally the
4077
          chunk adjacent to the one used for the most recent small request.
4077
          chunk adjacent to the one used for the most recent small request.
4078
       3. If one exists, split the smallest available chunk in a bin,
4078
       3. If one exists, split the smallest available chunk in a bin,
4079
          saving remainder in dv.
4079
          saving remainder in dv.
4080
       4. If it is big enough, use the top chunk.
4080
       4. If it is big enough, use the top chunk.
4081
       5. If available, get memory from system and use it
4081
       5. If available, get memory from system and use it
4082
     Otherwise, for a large request:
4082
     Otherwise, for a large request:
4083
       1. Find the smallest available binned chunk that fits, and use it
4083
       1. Find the smallest available binned chunk that fits, and use it
4084
          if it is better fitting than dv chunk, splitting if necessary.
4084
          if it is better fitting than dv chunk, splitting if necessary.
4085
       2. If better fitting than any binned chunk, use the dv chunk.
4085
       2. If better fitting than any binned chunk, use the dv chunk.
4086
       3. If it is big enough, use the top chunk.
4086
       3. If it is big enough, use the top chunk.
4087
       4. If request size >= mmap threshold, try to directly mmap this chunk.
4087
       4. If request size >= mmap threshold, try to directly mmap this chunk.
4088
       5. If available, get memory from system and use it
4088
       5. If available, get memory from system and use it
4089
 
4089
 
4090
     The ugly goto's here ensure that postaction occurs along all paths.
4090
     The ugly goto's here ensure that postaction occurs along all paths.
4091
  */
4091
  */
4092
 
4092
 
4093
  if (!PREACTION(gm)) {
4093
  if (!PREACTION(gm)) {
4094
    void* mem;
4094
    void* mem;
4095
    size_t nb;
4095
    size_t nb;
4096
    if (bytes <= MAX_SMALL_REQUEST) {
4096
    if (bytes <= MAX_SMALL_REQUEST) {
4097
      bindex_t idx;
4097
      bindex_t idx;
4098
      binmap_t smallbits;
4098
      binmap_t smallbits;
4099
      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
4099
      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
4100
      idx = small_index(nb);
4100
      idx = small_index(nb);
4101
      smallbits = gm->smallmap >> idx;
4101
      smallbits = gm->smallmap >> idx;
4102
 
4102
 
4103
      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
4103
      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
4104
        mchunkptr b, p;
4104
        mchunkptr b, p;
4105
        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
4105
        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
4106
        b = smallbin_at(gm, idx);
4106
        b = smallbin_at(gm, idx);
4107
        p = b->fd;
4107
        p = b->fd;
4108
        assert(chunksize(p) == small_index2size(idx));
4108
        assert(chunksize(p) == small_index2size(idx));
4109
        unlink_first_small_chunk(gm, b, p, idx);
4109
        unlink_first_small_chunk(gm, b, p, idx);
4110
        set_inuse_and_pinuse(gm, p, small_index2size(idx));
4110
        set_inuse_and_pinuse(gm, p, small_index2size(idx));
4111
        mem = chunk2mem(p);
4111
        mem = chunk2mem(p);
4112
        check_malloced_chunk(gm, mem, nb);
4112
        check_malloced_chunk(gm, mem, nb);
4113
        goto postaction;
4113
        goto postaction;
4114
      }
4114
      }
4115
 
4115
 
4116
      else if (nb > gm->dvsize) {
4116
      else if (nb > gm->dvsize) {
4117
        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
4117
        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
4118
          mchunkptr b, p, r;
4118
          mchunkptr b, p, r;
4119
          size_t rsize;
4119
          size_t rsize;
4120
          bindex_t i;
4120
          bindex_t i;
4121
          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
4121
          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
4122
          binmap_t leastbit = least_bit(leftbits);
4122
          binmap_t leastbit = least_bit(leftbits);
4123
          compute_bit2idx(leastbit, i);
4123
          compute_bit2idx(leastbit, i);
4124
          b = smallbin_at(gm, i);
4124
          b = smallbin_at(gm, i);
4125
          p = b->fd;
4125
          p = b->fd;
4126
          assert(chunksize(p) == small_index2size(i));
4126
          assert(chunksize(p) == small_index2size(i));
4127
          unlink_first_small_chunk(gm, b, p, i);
4127
          unlink_first_small_chunk(gm, b, p, i);
4128
          rsize = small_index2size(i) - nb;
4128
          rsize = small_index2size(i) - nb;
4129
          /* Fit here cannot be remainderless if 4byte sizes */
4129
          /* Fit here cannot be remainderless if 4byte sizes */
4130
          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
4130
          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
4131
            set_inuse_and_pinuse(gm, p, small_index2size(i));
4131
            set_inuse_and_pinuse(gm, p, small_index2size(i));
4132
          else {
4132
          else {
4133
            set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4133
            set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4134
            r = chunk_plus_offset(p, nb);
4134
            r = chunk_plus_offset(p, nb);
4135
            set_size_and_pinuse_of_free_chunk(r, rsize);
4135
            set_size_and_pinuse_of_free_chunk(r, rsize);
4136
            replace_dv(gm, r, rsize);
4136
            replace_dv(gm, r, rsize);
4137
          }
4137
          }
4138
          mem = chunk2mem(p);
4138
          mem = chunk2mem(p);
4139
          check_malloced_chunk(gm, mem, nb);
4139
          check_malloced_chunk(gm, mem, nb);
4140
          goto postaction;
4140
          goto postaction;
4141
        }
4141
        }
4142
 
4142
 
4143
        else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
4143
        else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
4144
          check_malloced_chunk(gm, mem, nb);
4144
          check_malloced_chunk(gm, mem, nb);
4145
          goto postaction;
4145
          goto postaction;
4146
        }
4146
        }
4147
      }
4147
      }
4148
    }
4148
    }
4149
    else if (bytes >= MAX_REQUEST)
4149
    else if (bytes >= MAX_REQUEST)
4150
      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
4150
      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
4151
    else {
4151
    else {
4152
      nb = pad_request(bytes);
4152
      nb = pad_request(bytes);
4153
      if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
4153
      if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
4154
        check_malloced_chunk(gm, mem, nb);
4154
        check_malloced_chunk(gm, mem, nb);
4155
        goto postaction;
4155
        goto postaction;
4156
      }
4156
      }
4157
    }
4157
    }
4158
 
4158
 
4159
    if (nb <= gm->dvsize) {
4159
    if (nb <= gm->dvsize) {
4160
      size_t rsize = gm->dvsize - nb;
4160
      size_t rsize = gm->dvsize - nb;
4161
      mchunkptr p = gm->dv;
4161
      mchunkptr p = gm->dv;
4162
      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
4162
      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
4163
        mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
4163
        mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
4164
        gm->dvsize = rsize;
4164
        gm->dvsize = rsize;
4165
        set_size_and_pinuse_of_free_chunk(r, rsize);
4165
        set_size_and_pinuse_of_free_chunk(r, rsize);
4166
        set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4166
        set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4167
      }
4167
      }
4168
      else { /* exhaust dv */
4168
      else { /* exhaust dv */
4169
        size_t dvs = gm->dvsize;
4169
        size_t dvs = gm->dvsize;
4170
        gm->dvsize = 0;
4170
        gm->dvsize = 0;
4171
        gm->dv = 0;
4171
        gm->dv = 0;
4172
        set_inuse_and_pinuse(gm, p, dvs);
4172
        set_inuse_and_pinuse(gm, p, dvs);
4173
      }
4173
      }
4174
      mem = chunk2mem(p);
4174
      mem = chunk2mem(p);
4175
      check_malloced_chunk(gm, mem, nb);
4175
      check_malloced_chunk(gm, mem, nb);
4176
      goto postaction;
4176
      goto postaction;
4177
    }
4177
    }
4178
 
4178
 
4179
    else if (nb < gm->topsize) { /* Split top */
4179
    else if (nb < gm->topsize) { /* Split top */
4180
      size_t rsize = gm->topsize -= nb;
4180
      size_t rsize = gm->topsize -= nb;
4181
      mchunkptr p = gm->top;
4181
      mchunkptr p = gm->top;
4182
      mchunkptr r = gm->top = chunk_plus_offset(p, nb);
4182
      mchunkptr r = gm->top = chunk_plus_offset(p, nb);
4183
      r->head = rsize | PINUSE_BIT;
4183
      r->head = rsize | PINUSE_BIT;
4184
      set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4184
      set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4185
      mem = chunk2mem(p);
4185
      mem = chunk2mem(p);
4186
      check_top_chunk(gm, gm->top);
4186
      check_top_chunk(gm, gm->top);
4187
      check_malloced_chunk(gm, mem, nb);
4187
      check_malloced_chunk(gm, mem, nb);
4188
      goto postaction;
4188
      goto postaction;
4189
    }
4189
    }
4190
 
4190
 
4191
    mem = sys_alloc(gm, nb);
4191
    mem = sys_alloc(gm, nb);
4192
 
4192
 
4193
  postaction:
4193
  postaction:
4194
    POSTACTION(gm);
4194
    POSTACTION(gm);
4195
    return mem;
4195
    return mem;
4196
  }
4196
  }
4197
 
4197
 
4198
  return 0;
4198
  return 0;
4199
}
4199
}
4200
 
4200
 
4201
void dlfree(void* mem) {
4201
void dlfree(void* mem) {
4202
  /*
4202
  /*
4203
     Consolidate freed chunks with preceeding or succeeding bordering
4203
     Consolidate freed chunks with preceeding or succeeding bordering
4204
     free chunks, if they exist, and then place in a bin.  Intermixed
4204
     free chunks, if they exist, and then place in a bin.  Intermixed
4205
     with special cases for top, dv, mmapped chunks, and usage errors.
4205
     with special cases for top, dv, mmapped chunks, and usage errors.
4206
  */
4206
  */
4207
 
4207
 
4208
  if (mem != 0) {
4208
  if (mem != 0) {
4209
    mchunkptr p  = mem2chunk(mem);
4209
    mchunkptr p  = mem2chunk(mem);
4210
#if FOOTERS
4210
#if FOOTERS
4211
    mstate fm = get_mstate_for(p);
4211
    mstate fm = get_mstate_for(p);
4212
    if (!ok_magic(fm)) {
4212
    if (!ok_magic(fm)) {
4213
      USAGE_ERROR_ACTION(fm, p);
4213
      USAGE_ERROR_ACTION(fm, p);
4214
      return;
4214
      return;
4215
    }
4215
    }
4216
#else /* FOOTERS */
4216
#else /* FOOTERS */
4217
#define fm gm
4217
#define fm gm
4218
#endif /* FOOTERS */
4218
#endif /* FOOTERS */
4219
    if (!PREACTION(fm)) {
4219
    if (!PREACTION(fm)) {
4220
      check_inuse_chunk(fm, p);
4220
      check_inuse_chunk(fm, p);
4221
      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
4221
      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
4222
        size_t psize = chunksize(p);
4222
        size_t psize = chunksize(p);
4223
        mchunkptr next = chunk_plus_offset(p, psize);
4223
        mchunkptr next = chunk_plus_offset(p, psize);
4224
        if (!pinuse(p)) {
4224
        if (!pinuse(p)) {
4225
          size_t prevsize = p->prev_foot;
4225
          size_t prevsize = p->prev_foot;
4226
          if ((prevsize & IS_MMAPPED_BIT) != 0) {
4226
          if ((prevsize & IS_MMAPPED_BIT) != 0) {
4227
            prevsize &= ~IS_MMAPPED_BIT;
4227
            prevsize &= ~IS_MMAPPED_BIT;
4228
            psize += prevsize + MMAP_FOOT_PAD;
4228
            psize += prevsize + MMAP_FOOT_PAD;
4229
            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
4229
            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
4230
              fm->footprint -= psize;
4230
              fm->footprint -= psize;
4231
            goto postaction;
4231
            goto postaction;
4232
          }
4232
          }
4233
          else {
4233
          else {
4234
            mchunkptr prev = chunk_minus_offset(p, prevsize);
4234
            mchunkptr prev = chunk_minus_offset(p, prevsize);
4235
            psize += prevsize;
4235
            psize += prevsize;
4236
            p = prev;
4236
            p = prev;
4237
            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
4237
            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
4238
              if (p != fm->dv) {
4238
              if (p != fm->dv) {
4239
                unlink_chunk(fm, p, prevsize);
4239
                unlink_chunk(fm, p, prevsize);
4240
              }
4240
              }
4241
              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
4241
              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
4242
                fm->dvsize = psize;
4242
                fm->dvsize = psize;
4243
                set_free_with_pinuse(p, psize, next);
4243
                set_free_with_pinuse(p, psize, next);
4244
                goto postaction;
4244
                goto postaction;
4245
              }
4245
              }
4246
            }
4246
            }
4247
            else
4247
            else
4248
              goto erroraction;
4248
              goto erroraction;
4249
          }
4249
          }
4250
        }
4250
        }
4251
 
4251
 
4252
        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
4252
        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
4253
          if (!cinuse(next)) {  /* consolidate forward */
4253
          if (!cinuse(next)) {  /* consolidate forward */
4254
            if (next == fm->top) {
4254
            if (next == fm->top) {
4255
              size_t tsize = fm->topsize += psize;
4255
              size_t tsize = fm->topsize += psize;
4256
              fm->top = p;
4256
              fm->top = p;
4257
              p->head = tsize | PINUSE_BIT;
4257
              p->head = tsize | PINUSE_BIT;
4258
              if (p == fm->dv) {
4258
              if (p == fm->dv) {
4259
                fm->dv = 0;
4259
                fm->dv = 0;
4260
                fm->dvsize = 0;
4260
                fm->dvsize = 0;
4261
              }
4261
              }
4262
              if (should_trim(fm, tsize))
4262
              if (should_trim(fm, tsize))
4263
                sys_trim(fm, 0);
4263
                sys_trim(fm, 0);
4264
              goto postaction;
4264
              goto postaction;
4265
            }
4265
            }
4266
            else if (next == fm->dv) {
4266
            else if (next == fm->dv) {
4267
              size_t dsize = fm->dvsize += psize;
4267
              size_t dsize = fm->dvsize += psize;
4268
              fm->dv = p;
4268
              fm->dv = p;
4269
              set_size_and_pinuse_of_free_chunk(p, dsize);
4269
              set_size_and_pinuse_of_free_chunk(p, dsize);
4270
              goto postaction;
4270
              goto postaction;
4271
            }
4271
            }
4272
            else {
4272
            else {
4273
              size_t nsize = chunksize(next);
4273
              size_t nsize = chunksize(next);
4274
              psize += nsize;
4274
              psize += nsize;
4275
              unlink_chunk(fm, next, nsize);
4275
              unlink_chunk(fm, next, nsize);
4276
              set_size_and_pinuse_of_free_chunk(p, psize);
4276
              set_size_and_pinuse_of_free_chunk(p, psize);
4277
              if (p == fm->dv) {
4277
              if (p == fm->dv) {
4278
                fm->dvsize = psize;
4278
                fm->dvsize = psize;
4279
                goto postaction;
4279
                goto postaction;
4280
              }
4280
              }
4281
            }
4281
            }
4282
          }
4282
          }
4283
          else
4283
          else
4284
            set_free_with_pinuse(p, psize, next);
4284
            set_free_with_pinuse(p, psize, next);
4285
          insert_chunk(fm, p, psize);
4285
          insert_chunk(fm, p, psize);
4286
          check_free_chunk(fm, p);
4286
          check_free_chunk(fm, p);
4287
          goto postaction;
4287
          goto postaction;
4288
        }
4288
        }
4289
      }
4289
      }
4290
    erroraction:
4290
    erroraction:
4291
      USAGE_ERROR_ACTION(fm, p);
4291
      USAGE_ERROR_ACTION(fm, p);
4292
    postaction:
4292
    postaction:
4293
      POSTACTION(fm);
4293
      POSTACTION(fm);
4294
    }
4294
    }
4295
  }
4295
  }
4296
#if !FOOTERS
4296
#if !FOOTERS
4297
#undef fm
4297
#undef fm
4298
#endif /* FOOTERS */
4298
#endif /* FOOTERS */
4299
}
4299
}
4300
 
4300
 
4301
void* dlcalloc(size_t n_elements, size_t elem_size) {
4301
void* dlcalloc(size_t n_elements, size_t elem_size) {
4302
  void* mem;
4302
  void* mem;
4303
  size_t req = 0;
4303
  size_t req = 0;
4304
  if (n_elements != 0) {
4304
  if (n_elements != 0) {
4305
    req = n_elements * elem_size;
4305
    req = n_elements * elem_size;
4306
    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
4306
    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
4307
        (req / n_elements != elem_size))
4307
        (req / n_elements != elem_size))
4308
      req = MAX_SIZE_T; /* force downstream failure on overflow */
4308
      req = MAX_SIZE_T; /* force downstream failure on overflow */
4309
  }
4309
  }
4310
  mem = dlmalloc(req);
4310
  mem = dlmalloc(req);
4311
  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
4311
  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
4312
    memset(mem, 0, req);
4312
    memset(mem, 0, req);
4313
  return mem;
4313
  return mem;
4314
}
4314
}
4315
 
4315
 
4316
void* dlrealloc(void* oldmem, size_t bytes) {
4316
void* dlrealloc(void* oldmem, size_t bytes) {
4317
  if (oldmem == 0)
4317
  if (oldmem == 0)
4318
    return dlmalloc(bytes);
4318
    return dlmalloc(bytes);
4319
#ifdef REALLOC_ZERO_BYTES_FREES
4319
#ifdef REALLOC_ZERO_BYTES_FREES
4320
  if (bytes == 0) {
4320
  if (bytes == 0) {
4321
    dlfree(oldmem);
4321
    dlfree(oldmem);
4322
    return 0;
4322
    return 0;
4323
  }
4323
  }
4324
#endif /* REALLOC_ZERO_BYTES_FREES */
4324
#endif /* REALLOC_ZERO_BYTES_FREES */
4325
  else {
4325
  else {
4326
#if ! FOOTERS
4326
#if ! FOOTERS
4327
    mstate m = gm;
4327
    mstate m = gm;
4328
#else /* FOOTERS */
4328
#else /* FOOTERS */
4329
    mstate m = get_mstate_for(mem2chunk(oldmem));
4329
    mstate m = get_mstate_for(mem2chunk(oldmem));
4330
    if (!ok_magic(m)) {
4330
    if (!ok_magic(m)) {
4331
      USAGE_ERROR_ACTION(m, oldmem);
4331
      USAGE_ERROR_ACTION(m, oldmem);
4332
      return 0;
4332
      return 0;
4333
    }
4333
    }
4334
#endif /* FOOTERS */
4334
#endif /* FOOTERS */
4335
    return internal_realloc(m, oldmem, bytes);
4335
    return internal_realloc(m, oldmem, bytes);
4336
  }
4336
  }
4337
}
4337
}
4338
 
4338
 
4339
#if 0
4339
#if 0
4340
void* dlmemalign(size_t alignment, size_t bytes) {
4340
void* dlmemalign(size_t alignment, size_t bytes) {
4341
  return internal_memalign(gm, alignment, bytes);
4341
  return internal_memalign(gm, alignment, bytes);
4342
}
4342
}
4343
 
4343
 
4344
void** dlindependent_calloc(size_t n_elements, size_t elem_size,
4344
void** dlindependent_calloc(size_t n_elements, size_t elem_size,
4345
                                 void* chunks[]) {
4345
                                 void* chunks[]) {
4346
  size_t sz = elem_size; /* serves as 1-element array */
4346
  size_t sz = elem_size; /* serves as 1-element array */
4347
  return ialloc(gm, n_elements, &sz, 3, chunks);
4347
  return ialloc(gm, n_elements, &sz, 3, chunks);
4348
}
4348
}
4349
 
4349
 
4350
void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
4350
void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
4351
                                   void* chunks[]) {
4351
                                   void* chunks[]) {
4352
  return ialloc(gm, n_elements, sizes, 0, chunks);
4352
  return ialloc(gm, n_elements, sizes, 0, chunks);
4353
}
4353
}
4354
 
4354
 
4355
void* dlvalloc(size_t bytes) {
4355
void* dlvalloc(size_t bytes) {
4356
  size_t pagesz;
4356
  size_t pagesz;
4357
  init_mparams();
4357
  init_mparams();
4358
  pagesz = mparams.page_size;
4358
  pagesz = mparams.page_size;
4359
  return dlmemalign(pagesz, bytes);
4359
  return dlmemalign(pagesz, bytes);
4360
}
4360
}
4361
 
4361
 
4362
void* dlpvalloc(size_t bytes) {
4362
void* dlpvalloc(size_t bytes) {
4363
  size_t pagesz;
4363
  size_t pagesz;
4364
  init_mparams();
4364
  init_mparams();
4365
  pagesz = mparams.page_size;
4365
  pagesz = mparams.page_size;
4366
  return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
4366
  return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
4367
}
4367
}
4368
 
4368
 
4369
int dlmalloc_trim(size_t pad) {
4369
int dlmalloc_trim(size_t pad) {
4370
  int result = 0;
4370
  int result = 0;
4371
  if (!PREACTION(gm)) {
4371
  if (!PREACTION(gm)) {
4372
    result = sys_trim(gm, pad);
4372
    result = sys_trim(gm, pad);
4373
    POSTACTION(gm);
4373
    POSTACTION(gm);
4374
  }
4374
  }
4375
  return result;
4375
  return result;
4376
}
4376
}
4377
 
4377
 
4378
size_t dlmalloc_footprint(void) {
4378
size_t dlmalloc_footprint(void) {
4379
  return gm->footprint;
4379
  return gm->footprint;
4380
}
4380
}
4381
 
4381
 
4382
size_t dlmalloc_max_footprint(void) {
4382
size_t dlmalloc_max_footprint(void) {
4383
  return gm->max_footprint;
4383
  return gm->max_footprint;
4384
}
4384
}
4385
#endif
4385
#endif
4386
 
4386
 
4387
#if !NO_MALLINFO
4387
#if !NO_MALLINFO
4388
struct mallinfo dlmallinfo(void) {
4388
struct mallinfo dlmallinfo(void) {
4389
  return internal_mallinfo(gm);
4389
  return internal_mallinfo(gm);
4390
}
4390
}
4391
#endif /* NO_MALLINFO */
4391
#endif /* NO_MALLINFO */
4392
 
4392
 
4393
#if 0
4393
#if 0
4394
void dlmalloc_stats() {
4394
void dlmalloc_stats() {
4395
  internal_malloc_stats(gm);
4395
  internal_malloc_stats(gm);
4396
}
4396
}
4397
 
4397
 
4398
size_t dlmalloc_usable_size(void* mem) {
4398
size_t dlmalloc_usable_size(void* mem) {
4399
  if (mem != 0) {
4399
  if (mem != 0) {
4400
    mchunkptr p = mem2chunk(mem);
4400
    mchunkptr p = mem2chunk(mem);
4401
    if (cinuse(p))
4401
    if (cinuse(p))
4402
      return chunksize(p) - overhead_for(p);
4402
      return chunksize(p) - overhead_for(p);
4403
  }
4403
  }
4404
  return 0;
4404
  return 0;
4405
}
4405
}
4406
 
4406
 
4407
int dlmallopt(int param_number, int value) {
4407
int dlmallopt(int param_number, int value) {
4408
  return change_mparam(param_number, value);
4408
  return change_mparam(param_number, value);
4409
}
4409
}
4410
#endif
4410
#endif
4411
 
4411
 
4412
#endif /* !ONLY_MSPACES */
4412
#endif /* !ONLY_MSPACES */
4413
 
4413
 
4414
/* ----------------------------- user mspaces ---------------------------- */
4414
/* ----------------------------- user mspaces ---------------------------- */
4415
 
4415
 
4416
#if MSPACES
4416
#if MSPACES
4417
 
4417
 
4418
static mstate init_user_mstate(char* tbase, size_t tsize) {
4418
static mstate init_user_mstate(char* tbase, size_t tsize) {
4419
  size_t msize = pad_request(sizeof(struct malloc_state));
4419
  size_t msize = pad_request(sizeof(struct malloc_state));
4420
  mchunkptr mn;
4420
  mchunkptr mn;
4421
  mchunkptr msp = align_as_chunk(tbase);
4421
  mchunkptr msp = align_as_chunk(tbase);
4422
  mstate m = (mstate)(chunk2mem(msp));
4422
  mstate m = (mstate)(chunk2mem(msp));
4423
  memset(m, 0, msize);
4423
  memset(m, 0, msize);
4424
  INITIAL_LOCK(&m->mutex);
4424
  INITIAL_LOCK(&m->mutex);
4425
  msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
4425
  msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
4426
  m->seg.base = m->least_addr = tbase;
4426
  m->seg.base = m->least_addr = tbase;
4427
  m->seg.size = m->footprint = m->max_footprint = tsize;
4427
  m->seg.size = m->footprint = m->max_footprint = tsize;
4428
  m->magic = mparams.magic;
4428
  m->magic = mparams.magic;
4429
  m->mflags = mparams.default_mflags;
4429
  m->mflags = mparams.default_mflags;
4430
  disable_contiguous(m);
4430
  disable_contiguous(m);
4431
  init_bins(m);
4431
  init_bins(m);
4432
  mn = next_chunk(mem2chunk(m));
4432
  mn = next_chunk(mem2chunk(m));
4433
  init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
4433
  init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
4434
  check_top_chunk(m, m->top);
4434
  check_top_chunk(m, m->top);
4435
  return m;
4435
  return m;
4436
}
4436
}
4437
 
4437
 
4438
mspace create_mspace(size_t capacity, int locked) {
4438
mspace create_mspace(size_t capacity, int locked) {
4439
  mstate m = 0;
4439
  mstate m = 0;
4440
  size_t msize = pad_request(sizeof(struct malloc_state));
4440
  size_t msize = pad_request(sizeof(struct malloc_state));
4441
  init_mparams(); /* Ensure pagesize etc initialized */
4441
  init_mparams(); /* Ensure pagesize etc initialized */
4442
 
4442
 
4443
  if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4443
  if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4444
    size_t rs = ((capacity == 0)? mparams.granularity :
4444
    size_t rs = ((capacity == 0)? mparams.granularity :
4445
                 (capacity + TOP_FOOT_SIZE + msize));
4445
                 (capacity + TOP_FOOT_SIZE + msize));
4446
    size_t tsize = granularity_align(rs);
4446
    size_t tsize = granularity_align(rs);
4447
    char* tbase = (char*)(CALL_MMAP(tsize));
4447
    char* tbase = (char*)(CALL_MMAP(tsize));
4448
    if (tbase != CMFAIL) {
4448
    if (tbase != CMFAIL) {
4449
      m = init_user_mstate(tbase, tsize);
4449
      m = init_user_mstate(tbase, tsize);
4450
      m->seg.sflags = IS_MMAPPED_BIT;
4450
      m->seg.sflags = IS_MMAPPED_BIT;
4451
      set_lock(m, locked);
4451
      set_lock(m, locked);
4452
    }
4452
    }
4453
  }
4453
  }
4454
  return (mspace)m;
4454
  return (mspace)m;
4455
}
4455
}
4456
 
4456
 
4457
mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
4457
mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
4458
  mstate m = 0;
4458
  mstate m = 0;
4459
  size_t msize = pad_request(sizeof(struct malloc_state));
4459
  size_t msize = pad_request(sizeof(struct malloc_state));
4460
  init_mparams(); /* Ensure pagesize etc initialized */
4460
  init_mparams(); /* Ensure pagesize etc initialized */
4461
 
4461
 
4462
  if (capacity > msize + TOP_FOOT_SIZE &&
4462
  if (capacity > msize + TOP_FOOT_SIZE &&
4463
      capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4463
      capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4464
    m = init_user_mstate((char*)base, capacity);
4464
    m = init_user_mstate((char*)base, capacity);
4465
    m->seg.sflags = EXTERN_BIT;
4465
    m->seg.sflags = EXTERN_BIT;
4466
    set_lock(m, locked);
4466
    set_lock(m, locked);
4467
  }
4467
  }
4468
  return (mspace)m;
4468
  return (mspace)m;
4469
}
4469
}
4470
 
4470
 
4471
size_t destroy_mspace(mspace msp) {
4471
size_t destroy_mspace(mspace msp) {
4472
  size_t freed = 0;
4472
  size_t freed = 0;
4473
  mstate ms = (mstate)msp;
4473
  mstate ms = (mstate)msp;
4474
  if (ok_magic(ms)) {
4474
  if (ok_magic(ms)) {
4475
    msegmentptr sp = &ms->seg;
4475
    msegmentptr sp = &ms->seg;
4476
    while (sp != 0) {
4476
    while (sp != 0) {
4477
      char* base = sp->base;
4477
      char* base = sp->base;
4478
      size_t size = sp->size;
4478
      size_t size = sp->size;
4479
      flag_t flag = sp->sflags;
4479
      flag_t flag = sp->sflags;
4480
      sp = sp->next;
4480
      sp = sp->next;
4481
      if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
4481
      if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
4482
          CALL_MUNMAP(base, size) == 0)
4482
          CALL_MUNMAP(base, size) == 0)
4483
        freed += size;
4483
        freed += size;
4484
    }
4484
    }
4485
  }
4485
  }
4486
  else {
4486
  else {
4487
    USAGE_ERROR_ACTION(ms,ms);
4487
    USAGE_ERROR_ACTION(ms,ms);
4488
  }
4488
  }
4489
  return freed;
4489
  return freed;
4490
}
4490
}
4491
 
4491
 
4492
/*
4492
/*
4493
  mspace versions of routines are near-clones of the global
4493
  mspace versions of routines are near-clones of the global
4494
  versions. This is not so nice but better than the alternatives.
4494
  versions. This is not so nice but better than the alternatives.
4495
*/
4495
*/
4496
 
4496
 
4497
 
4497
 
4498
void* mspace_malloc(mspace msp, size_t bytes) {
4498
void* mspace_malloc(mspace msp, size_t bytes) {
4499
  mstate ms = (mstate)msp;
4499
  mstate ms = (mstate)msp;
4500
  if (!ok_magic(ms)) {
4500
  if (!ok_magic(ms)) {
4501
    USAGE_ERROR_ACTION(ms,ms);
4501
    USAGE_ERROR_ACTION(ms,ms);
4502
    return 0;
4502
    return 0;
4503
  }
4503
  }
4504
  if (!PREACTION(ms)) {
4504
  if (!PREACTION(ms)) {
4505
    void* mem;
4505
    void* mem;
4506
    size_t nb;
4506
    size_t nb;
4507
    if (bytes <= MAX_SMALL_REQUEST) {
4507
    if (bytes <= MAX_SMALL_REQUEST) {
4508
      bindex_t idx;
4508
      bindex_t idx;
4509
      binmap_t smallbits;
4509
      binmap_t smallbits;
4510
      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
4510
      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
4511
      idx = small_index(nb);
4511
      idx = small_index(nb);
4512
      smallbits = ms->smallmap >> idx;
4512
      smallbits = ms->smallmap >> idx;
4513
 
4513
 
4514
      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
4514
      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
4515
        mchunkptr b, p;
4515
        mchunkptr b, p;
4516
        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
4516
        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
4517
        b = smallbin_at(ms, idx);
4517
        b = smallbin_at(ms, idx);
4518
        p = b->fd;
4518
        p = b->fd;
4519
        assert(chunksize(p) == small_index2size(idx));
4519
        assert(chunksize(p) == small_index2size(idx));
4520
        unlink_first_small_chunk(ms, b, p, idx);
4520
        unlink_first_small_chunk(ms, b, p, idx);
4521
        set_inuse_and_pinuse(ms, p, small_index2size(idx));
4521
        set_inuse_and_pinuse(ms, p, small_index2size(idx));
4522
        mem = chunk2mem(p);
4522
        mem = chunk2mem(p);
4523
        check_malloced_chunk(ms, mem, nb);
4523
        check_malloced_chunk(ms, mem, nb);
4524
        goto postaction;
4524
        goto postaction;
4525
      }
4525
      }
4526
 
4526
 
4527
      else if (nb > ms->dvsize) {
4527
      else if (nb > ms->dvsize) {
4528
        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
4528
        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
4529
          mchunkptr b, p, r;
4529
          mchunkptr b, p, r;
4530
          size_t rsize;
4530
          size_t rsize;
4531
          bindex_t i;
4531
          bindex_t i;
4532
          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
4532
          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
4533
          binmap_t leastbit = least_bit(leftbits);
4533
          binmap_t leastbit = least_bit(leftbits);
4534
          compute_bit2idx(leastbit, i);
4534
          compute_bit2idx(leastbit, i);
4535
          b = smallbin_at(ms, i);
4535
          b = smallbin_at(ms, i);
4536
          p = b->fd;
4536
          p = b->fd;
4537
          assert(chunksize(p) == small_index2size(i));
4537
          assert(chunksize(p) == small_index2size(i));
4538
          unlink_first_small_chunk(ms, b, p, i);
4538
          unlink_first_small_chunk(ms, b, p, i);
4539
          rsize = small_index2size(i) - nb;
4539
          rsize = small_index2size(i) - nb;
4540
          /* Fit here cannot be remainderless if 4byte sizes */
4540
          /* Fit here cannot be remainderless if 4byte sizes */
4541
          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
4541
          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
4542
            set_inuse_and_pinuse(ms, p, small_index2size(i));
4542
            set_inuse_and_pinuse(ms, p, small_index2size(i));
4543
          else {
4543
          else {
4544
            set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4544
            set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4545
            r = chunk_plus_offset(p, nb);
4545
            r = chunk_plus_offset(p, nb);
4546
            set_size_and_pinuse_of_free_chunk(r, rsize);
4546
            set_size_and_pinuse_of_free_chunk(r, rsize);
4547
            replace_dv(ms, r, rsize);
4547
            replace_dv(ms, r, rsize);
4548
          }
4548
          }
4549
          mem = chunk2mem(p);
4549
          mem = chunk2mem(p);
4550
          check_malloced_chunk(ms, mem, nb);
4550
          check_malloced_chunk(ms, mem, nb);
4551
          goto postaction;
4551
          goto postaction;
4552
        }
4552
        }
4553
 
4553
 
4554
        else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
4554
        else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
4555
          check_malloced_chunk(ms, mem, nb);
4555
          check_malloced_chunk(ms, mem, nb);
4556
          goto postaction;
4556
          goto postaction;
4557
        }
4557
        }
4558
      }
4558
      }
4559
    }
4559
    }
4560
    else if (bytes >= MAX_REQUEST)
4560
    else if (bytes >= MAX_REQUEST)
4561
      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
4561
      nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
4562
    else {
4562
    else {
4563
      nb = pad_request(bytes);
4563
      nb = pad_request(bytes);
4564
      if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
4564
      if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
4565
        check_malloced_chunk(ms, mem, nb);
4565
        check_malloced_chunk(ms, mem, nb);
4566
        goto postaction;
4566
        goto postaction;
4567
      }
4567
      }
4568
    }
4568
    }
4569
 
4569
 
4570
    if (nb <= ms->dvsize) {
4570
    if (nb <= ms->dvsize) {
4571
      size_t rsize = ms->dvsize - nb;
4571
      size_t rsize = ms->dvsize - nb;
4572
      mchunkptr p = ms->dv;
4572
      mchunkptr p = ms->dv;
4573
      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
4573
      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
4574
        mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
4574
        mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
4575
        ms->dvsize = rsize;
4575
        ms->dvsize = rsize;
4576
        set_size_and_pinuse_of_free_chunk(r, rsize);
4576
        set_size_and_pinuse_of_free_chunk(r, rsize);
4577
        set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4577
        set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4578
      }
4578
      }
4579
      else { /* exhaust dv */
4579
      else { /* exhaust dv */
4580
        size_t dvs = ms->dvsize;
4580
        size_t dvs = ms->dvsize;
4581
        ms->dvsize = 0;
4581
        ms->dvsize = 0;
4582
        ms->dv = 0;
4582
        ms->dv = 0;
4583
        set_inuse_and_pinuse(ms, p, dvs);
4583
        set_inuse_and_pinuse(ms, p, dvs);
4584
      }
4584
      }
4585
      mem = chunk2mem(p);
4585
      mem = chunk2mem(p);
4586
      check_malloced_chunk(ms, mem, nb);
4586
      check_malloced_chunk(ms, mem, nb);
4587
      goto postaction;
4587
      goto postaction;
4588
    }
4588
    }
4589
 
4589
 
4590
    else if (nb < ms->topsize) { /* Split top */
4590
    else if (nb < ms->topsize) { /* Split top */
4591
      size_t rsize = ms->topsize -= nb;
4591
      size_t rsize = ms->topsize -= nb;
4592
      mchunkptr p = ms->top;
4592
      mchunkptr p = ms->top;
4593
      mchunkptr r = ms->top = chunk_plus_offset(p, nb);
4593
      mchunkptr r = ms->top = chunk_plus_offset(p, nb);
4594
      r->head = rsize | PINUSE_BIT;
4594
      r->head = rsize | PINUSE_BIT;
4595
      set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4595
      set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4596
      mem = chunk2mem(p);
4596
      mem = chunk2mem(p);
4597
      check_top_chunk(ms, ms->top);
4597
      check_top_chunk(ms, ms->top);
4598
      check_malloced_chunk(ms, mem, nb);
4598
      check_malloced_chunk(ms, mem, nb);
4599
      goto postaction;
4599
      goto postaction;
4600
    }
4600
    }
4601
 
4601
 
4602
    mem = sys_alloc(ms, nb);
4602
    mem = sys_alloc(ms, nb);
4603
 
4603
 
4604
  postaction:
4604
  postaction:
4605
    POSTACTION(ms);
4605
    POSTACTION(ms);
4606
    return mem;
4606
    return mem;
4607
  }
4607
  }
4608
 
4608
 
4609
  return 0;
4609
  return 0;
4610
}
4610
}
4611
 
4611
 
4612
void mspace_free(mspace msp, void* mem) {
4612
void mspace_free(mspace msp, void* mem) {
4613
  if (mem != 0) {
4613
  if (mem != 0) {
4614
    mchunkptr p  = mem2chunk(mem);
4614
    mchunkptr p  = mem2chunk(mem);
4615
#if FOOTERS
4615
#if FOOTERS
4616
    mstate fm = get_mstate_for(p);
4616
    mstate fm = get_mstate_for(p);
4617
#else /* FOOTERS */
4617
#else /* FOOTERS */
4618
    mstate fm = (mstate)msp;
4618
    mstate fm = (mstate)msp;
4619
#endif /* FOOTERS */
4619
#endif /* FOOTERS */
4620
    if (!ok_magic(fm)) {
4620
    if (!ok_magic(fm)) {
4621
      USAGE_ERROR_ACTION(fm, p);
4621
      USAGE_ERROR_ACTION(fm, p);
4622
      return;
4622
      return;
4623
    }
4623
    }
4624
    if (!PREACTION(fm)) {
4624
    if (!PREACTION(fm)) {
4625
      check_inuse_chunk(fm, p);
4625
      check_inuse_chunk(fm, p);
4626
      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
4626
      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
4627
        size_t psize = chunksize(p);
4627
        size_t psize = chunksize(p);
4628
        mchunkptr next = chunk_plus_offset(p, psize);
4628
        mchunkptr next = chunk_plus_offset(p, psize);
4629
        if (!pinuse(p)) {
4629
        if (!pinuse(p)) {
4630
          size_t prevsize = p->prev_foot;
4630
          size_t prevsize = p->prev_foot;
4631
          if ((prevsize & IS_MMAPPED_BIT) != 0) {
4631
          if ((prevsize & IS_MMAPPED_BIT) != 0) {
4632
            prevsize &= ~IS_MMAPPED_BIT;
4632
            prevsize &= ~IS_MMAPPED_BIT;
4633
            psize += prevsize + MMAP_FOOT_PAD;
4633
            psize += prevsize + MMAP_FOOT_PAD;
4634
            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
4634
            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
4635
              fm->footprint -= psize;
4635
              fm->footprint -= psize;
4636
            goto postaction;
4636
            goto postaction;
4637
          }
4637
          }
4638
          else {
4638
          else {
4639
            mchunkptr prev = chunk_minus_offset(p, prevsize);
4639
            mchunkptr prev = chunk_minus_offset(p, prevsize);
4640
            psize += prevsize;
4640
            psize += prevsize;
4641
            p = prev;
4641
            p = prev;
4642
            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
4642
            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
4643
              if (p != fm->dv) {
4643
              if (p != fm->dv) {
4644
                unlink_chunk(fm, p, prevsize);
4644
                unlink_chunk(fm, p, prevsize);
4645
              }
4645
              }
4646
              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
4646
              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
4647
                fm->dvsize = psize;
4647
                fm->dvsize = psize;
4648
                set_free_with_pinuse(p, psize, next);
4648
                set_free_with_pinuse(p, psize, next);
4649
                goto postaction;
4649
                goto postaction;
4650
              }
4650
              }
4651
            }
4651
            }
4652
            else
4652
            else
4653
              goto erroraction;
4653
              goto erroraction;
4654
          }
4654
          }
4655
        }
4655
        }
4656
 
4656
 
4657
        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
4657
        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
4658
          if (!cinuse(next)) {  /* consolidate forward */
4658
          if (!cinuse(next)) {  /* consolidate forward */
4659
            if (next == fm->top) {
4659
            if (next == fm->top) {
4660
              size_t tsize = fm->topsize += psize;
4660
              size_t tsize = fm->topsize += psize;
4661
              fm->top = p;
4661
              fm->top = p;
4662
              p->head = tsize | PINUSE_BIT;
4662
              p->head = tsize | PINUSE_BIT;
4663
              if (p == fm->dv) {
4663
              if (p == fm->dv) {
4664
                fm->dv = 0;
4664
                fm->dv = 0;
4665
                fm->dvsize = 0;
4665
                fm->dvsize = 0;
4666
              }
4666
              }
4667
              if (should_trim(fm, tsize))
4667
              if (should_trim(fm, tsize))
4668
                sys_trim(fm, 0);
4668
                sys_trim(fm, 0);
4669
              goto postaction;
4669
              goto postaction;
4670
            }
4670
            }
4671
            else if (next == fm->dv) {
4671
            else if (next == fm->dv) {
4672
              size_t dsize = fm->dvsize += psize;
4672
              size_t dsize = fm->dvsize += psize;
4673
              fm->dv = p;
4673
              fm->dv = p;
4674
              set_size_and_pinuse_of_free_chunk(p, dsize);
4674
              set_size_and_pinuse_of_free_chunk(p, dsize);
4675
              goto postaction;
4675
              goto postaction;
4676
            }
4676
            }
4677
            else {
4677
            else {
4678
              size_t nsize = chunksize(next);
4678
              size_t nsize = chunksize(next);
4679
              psize += nsize;
4679
              psize += nsize;
4680
              unlink_chunk(fm, next, nsize);
4680
              unlink_chunk(fm, next, nsize);
4681
              set_size_and_pinuse_of_free_chunk(p, psize);
4681
              set_size_and_pinuse_of_free_chunk(p, psize);
4682
              if (p == fm->dv) {
4682
              if (p == fm->dv) {
4683
                fm->dvsize = psize;
4683
                fm->dvsize = psize;
4684
                goto postaction;
4684
                goto postaction;
4685
              }
4685
              }
4686
            }
4686
            }
4687
          }
4687
          }
4688
          else
4688
          else
4689
            set_free_with_pinuse(p, psize, next);
4689
            set_free_with_pinuse(p, psize, next);
4690
          insert_chunk(fm, p, psize);
4690
          insert_chunk(fm, p, psize);
4691
          check_free_chunk(fm, p);
4691
          check_free_chunk(fm, p);
4692
          goto postaction;
4692
          goto postaction;
4693
        }
4693
        }
4694
      }
4694
      }
4695
    erroraction:
4695
    erroraction:
4696
      USAGE_ERROR_ACTION(fm, p);
4696
      USAGE_ERROR_ACTION(fm, p);
4697
    postaction:
4697
    postaction:
4698
      POSTACTION(fm);
4698
      POSTACTION(fm);
4699
    }
4699
    }
4700
  }
4700
  }
4701
}
4701
}
4702
 
4702
 
4703
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
4703
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
4704
  void* mem;
4704
  void* mem;
4705
  size_t req = 0;
4705
  size_t req = 0;
4706
  mstate ms = (mstate)msp;
4706
  mstate ms = (mstate)msp;
4707
  if (!ok_magic(ms)) {
4707
  if (!ok_magic(ms)) {
4708
    USAGE_ERROR_ACTION(ms,ms);
4708
    USAGE_ERROR_ACTION(ms,ms);
4709
    return 0;
4709
    return 0;
4710
  }
4710
  }
4711
  if (n_elements != 0) {
4711
  if (n_elements != 0) {
4712
    req = n_elements * elem_size;
4712
    req = n_elements * elem_size;
4713
    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
4713
    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
4714
        (req / n_elements != elem_size))
4714
        (req / n_elements != elem_size))
4715
      req = MAX_SIZE_T; /* force downstream failure on overflow */
4715
      req = MAX_SIZE_T; /* force downstream failure on overflow */
4716
  }
4716
  }
4717
  mem = internal_malloc(ms, req);
4717
  mem = internal_malloc(ms, req);
4718
  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
4718
  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
4719
    memset(mem, 0, req);
4719
    memset(mem, 0, req);
4720
  return mem;
4720
  return mem;
4721
}
4721
}
4722
 
4722
 
4723
void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
4723
void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
4724
  if (oldmem == 0)
4724
  if (oldmem == 0)
4725
    return mspace_malloc(msp, bytes);
4725
    return mspace_malloc(msp, bytes);
4726
#ifdef REALLOC_ZERO_BYTES_FREES
4726
#ifdef REALLOC_ZERO_BYTES_FREES
4727
  if (bytes == 0) {
4727
  if (bytes == 0) {
4728
    mspace_free(msp, oldmem);
4728
    mspace_free(msp, oldmem);
4729
    return 0;
4729
    return 0;
4730
  }
4730
  }
4731
#endif /* REALLOC_ZERO_BYTES_FREES */
4731
#endif /* REALLOC_ZERO_BYTES_FREES */
4732
  else {
4732
  else {
4733
#if FOOTERS
4733
#if FOOTERS
4734
    mchunkptr p  = mem2chunk(oldmem);
4734
    mchunkptr p  = mem2chunk(oldmem);
4735
    mstate ms = get_mstate_for(p);
4735
    mstate ms = get_mstate_for(p);
4736
#else /* FOOTERS */
4736
#else /* FOOTERS */
4737
    mstate ms = (mstate)msp;
4737
    mstate ms = (mstate)msp;
4738
#endif /* FOOTERS */
4738
#endif /* FOOTERS */
4739
    if (!ok_magic(ms)) {
4739
    if (!ok_magic(ms)) {
4740
      USAGE_ERROR_ACTION(ms,ms);
4740
      USAGE_ERROR_ACTION(ms,ms);
4741
      return 0;
4741
      return 0;
4742
    }
4742
    }
4743
    return internal_realloc(ms, oldmem, bytes);
4743
    return internal_realloc(ms, oldmem, bytes);
4744
  }
4744
  }
4745
}
4745
}
4746
 
4746
 
4747
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
4747
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
4748
  mstate ms = (mstate)msp;
4748
  mstate ms = (mstate)msp;
4749
  if (!ok_magic(ms)) {
4749
  if (!ok_magic(ms)) {
4750
    USAGE_ERROR_ACTION(ms,ms);
4750
    USAGE_ERROR_ACTION(ms,ms);
4751
    return 0;
4751
    return 0;
4752
  }
4752
  }
4753
  return internal_memalign(ms, alignment, bytes);
4753
  return internal_memalign(ms, alignment, bytes);
4754
}
4754
}
4755
 
4755
 
4756
void** mspace_independent_calloc(mspace msp, size_t n_elements,
4756
void** mspace_independent_calloc(mspace msp, size_t n_elements,
4757
                                 size_t elem_size, void* chunks[]) {
4757
                                 size_t elem_size, void* chunks[]) {
4758
  size_t sz = elem_size; /* serves as 1-element array */
4758
  size_t sz = elem_size; /* serves as 1-element array */
4759
  mstate ms = (mstate)msp;
4759
  mstate ms = (mstate)msp;
4760
  if (!ok_magic(ms)) {
4760
  if (!ok_magic(ms)) {
4761
    USAGE_ERROR_ACTION(ms,ms);
4761
    USAGE_ERROR_ACTION(ms,ms);
4762
    return 0;
4762
    return 0;
4763
  }
4763
  }
4764
  return ialloc(ms, n_elements, &sz, 3, chunks);
4764
  return ialloc(ms, n_elements, &sz, 3, chunks);
4765
}
4765
}
4766
 
4766
 
4767
void** mspace_independent_comalloc(mspace msp, size_t n_elements,
4767
void** mspace_independent_comalloc(mspace msp, size_t n_elements,
4768
                                   size_t sizes[], void* chunks[]) {
4768
                                   size_t sizes[], void* chunks[]) {
4769
  mstate ms = (mstate)msp;
4769
  mstate ms = (mstate)msp;
4770
  if (!ok_magic(ms)) {
4770
  if (!ok_magic(ms)) {
4771
    USAGE_ERROR_ACTION(ms,ms);
4771
    USAGE_ERROR_ACTION(ms,ms);
4772
    return 0;
4772
    return 0;
4773
  }
4773
  }
4774
  return ialloc(ms, n_elements, sizes, 0, chunks);
4774
  return ialloc(ms, n_elements, sizes, 0, chunks);
4775
}
4775
}
4776
 
4776
 
4777
int mspace_trim(mspace msp, size_t pad) {
4777
int mspace_trim(mspace msp, size_t pad) {
4778
  int result = 0;
4778
  int result = 0;
4779
  mstate ms = (mstate)msp;
4779
  mstate ms = (mstate)msp;
4780
  if (ok_magic(ms)) {
4780
  if (ok_magic(ms)) {
4781
    if (!PREACTION(ms)) {
4781
    if (!PREACTION(ms)) {
4782
      result = sys_trim(ms, pad);
4782
      result = sys_trim(ms, pad);
4783
      POSTACTION(ms);
4783
      POSTACTION(ms);
4784
    }
4784
    }
4785
  }
4785
  }
4786
  else {
4786
  else {
4787
    USAGE_ERROR_ACTION(ms,ms);
4787
    USAGE_ERROR_ACTION(ms,ms);
4788
  }
4788
  }
4789
  return result;
4789
  return result;
4790
}
4790
}
4791
 
4791
 
4792
void mspace_malloc_stats(mspace msp) {
4792
void mspace_malloc_stats(mspace msp) {
4793
  mstate ms = (mstate)msp;
4793
  mstate ms = (mstate)msp;
4794
  if (ok_magic(ms)) {
4794
  if (ok_magic(ms)) {
4795
    internal_malloc_stats(ms);
4795
    internal_malloc_stats(ms);
4796
  }
4796
  }
4797
  else {
4797
  else {
4798
    USAGE_ERROR_ACTION(ms,ms);
4798
    USAGE_ERROR_ACTION(ms,ms);
4799
  }
4799
  }
4800
}
4800
}
4801
 
4801
 
4802
size_t mspace_footprint(mspace msp) {
4802
size_t mspace_footprint(mspace msp) {
4803
  size_t result;
4803
  size_t result;
4804
  mstate ms = (mstate)msp;
4804
  mstate ms = (mstate)msp;
4805
  if (ok_magic(ms)) {
4805
  if (ok_magic(ms)) {
4806
    result = ms->footprint;
4806
    result = ms->footprint;
4807
  }
4807
  }
4808
  USAGE_ERROR_ACTION(ms,ms);
4808
  USAGE_ERROR_ACTION(ms,ms);
4809
  return result;
4809
  return result;
4810
}
4810
}
4811
 
4811
 
4812
 
4812
 
4813
size_t mspace_max_footprint(mspace msp) {
4813
size_t mspace_max_footprint(mspace msp) {
4814
  size_t result;
4814
  size_t result;
4815
  mstate ms = (mstate)msp;
4815
  mstate ms = (mstate)msp;
4816
  if (ok_magic(ms)) {
4816
  if (ok_magic(ms)) {
4817
    result = ms->max_footprint;
4817
    result = ms->max_footprint;
4818
  }
4818
  }
4819
  USAGE_ERROR_ACTION(ms,ms);
4819
  USAGE_ERROR_ACTION(ms,ms);
4820
  return result;
4820
  return result;
4821
}
4821
}
4822
 
4822
 
4823
 
4823
 
4824
#if !NO_MALLINFO
4824
#if !NO_MALLINFO
4825
struct mallinfo mspace_mallinfo(mspace msp) {
4825
struct mallinfo mspace_mallinfo(mspace msp) {
4826
  mstate ms = (mstate)msp;
4826
  mstate ms = (mstate)msp;
4827
  if (!ok_magic(ms)) {
4827
  if (!ok_magic(ms)) {
4828
    USAGE_ERROR_ACTION(ms,ms);
4828
    USAGE_ERROR_ACTION(ms,ms);
4829
  }
4829
  }
4830
  return internal_mallinfo(ms);
4830
  return internal_mallinfo(ms);
4831
}
4831
}
4832
#endif /* NO_MALLINFO */
4832
#endif /* NO_MALLINFO */
4833
 
4833
 
4834
int mspace_mallopt(int param_number, int value) {
4834
int mspace_mallopt(int param_number, int value) {
4835
  return change_mparam(param_number, value);
4835
  return change_mparam(param_number, value);
4836
}
4836
}
4837
 
4837
 
4838
#endif /* MSPACES */
4838
#endif /* MSPACES */
4839
 
4839
 
4840
/* -------------------- Alternative MORECORE functions ------------------- */
4840
/* -------------------- Alternative MORECORE functions ------------------- */
4841
 
4841
 
4842
/*
4842
/*
4843
  Guidelines for creating a custom version of MORECORE:
4843
  Guidelines for creating a custom version of MORECORE:
4844
 
4844
 
4845
  * For best performance, MORECORE should allocate in multiples of pagesize.
4845
  * For best performance, MORECORE should allocate in multiples of pagesize.
4846
  * MORECORE may allocate more memory than requested. (Or even less,
4846
  * MORECORE may allocate more memory than requested. (Or even less,
4847
      but this will usually result in a malloc failure.)
4847
      but this will usually result in a malloc failure.)
4848
  * MORECORE must not allocate memory when given argument zero, but
4848
  * MORECORE must not allocate memory when given argument zero, but
4849
      instead return one past the end address of memory from previous
4849
      instead return one past the end address of memory from previous
4850
      nonzero call.
4850
      nonzero call.
4851
  * For best performance, consecutive calls to MORECORE with positive
4851
  * For best performance, consecutive calls to MORECORE with positive
4852
      arguments should return increasing addresses, indicating that
4852
      arguments should return increasing addresses, indicating that
4853
      space has been contiguously extended.
4853
      space has been contiguously extended.
4854
  * Even though consecutive calls to MORECORE need not return contiguous
4854
  * Even though consecutive calls to MORECORE need not return contiguous
4855
      addresses, it must be OK for malloc'ed chunks to span multiple
4855
      addresses, it must be OK for malloc'ed chunks to span multiple
4856
      regions in those cases where they do happen to be contiguous.
4856
      regions in those cases where they do happen to be contiguous.
4857
  * MORECORE need not handle negative arguments -- it may instead
4857
  * MORECORE need not handle negative arguments -- it may instead
4858
      just return MFAIL when given negative arguments.
4858
      just return MFAIL when given negative arguments.
4859
      Negative arguments are always multiples of pagesize. MORECORE
4859
      Negative arguments are always multiples of pagesize. MORECORE
4860
      must not misinterpret negative args as large positive unsigned
4860
      must not misinterpret negative args as large positive unsigned
4861
      args. You can suppress all such calls from even occurring by defining
4861
      args. You can suppress all such calls from even occurring by defining
4862
      MORECORE_CANNOT_TRIM,
4862
      MORECORE_CANNOT_TRIM,
4863
 
4863
 
4864
  As an example alternative MORECORE, here is a custom allocator
4864
  As an example alternative MORECORE, here is a custom allocator
4865
  kindly contributed for pre-OSX macOS.  It uses virtually but not
4865
  kindly contributed for pre-OSX macOS.  It uses virtually but not
4866
  necessarily physically contiguous non-paged memory (locked in,
4866
  necessarily physically contiguous non-paged memory (locked in,
4867
  present and won't get swapped out).  You can use it by uncommenting
4867
  present and won't get swapped out).  You can use it by uncommenting
4868
  this section, adding some #includes, and setting up the appropriate
4868
  this section, adding some #includes, and setting up the appropriate
4869
  defines above:
4869
  defines above:
4870
 
4870
 
4871
      #define MORECORE osMoreCore
4871
      #define MORECORE osMoreCore
4872
 
4872
 
4873
  There is also a shutdown routine that should somehow be called for
4873
  There is also a shutdown routine that should somehow be called for
4874
  cleanup upon program exit.
4874
  cleanup upon program exit.
4875
 
4875
 
4876
  #define MAX_POOL_ENTRIES 100
4876
  #define MAX_POOL_ENTRIES 100
4877
  #define MINIMUM_MORECORE_SIZE  (64 * 1024U)
4877
  #define MINIMUM_MORECORE_SIZE  (64 * 1024U)
4878
  static int next_os_pool;
4878
  static int next_os_pool;
4879
  void *our_os_pools[MAX_POOL_ENTRIES];
4879
  void *our_os_pools[MAX_POOL_ENTRIES];
4880
 
4880
 
4881
  void *osMoreCore(int size)
4881
  void *osMoreCore(int size)
4882
  {
4882
  {
4883
    void *ptr = 0;
4883
    void *ptr = 0;
4884
    static void *sbrk_top = 0;
4884
    static void *sbrk_top = 0;
4885
 
4885
 
4886
    if (size > 0)
4886
    if (size > 0)
4887
    {
4887
    {
4888
      if (size < MINIMUM_MORECORE_SIZE)
4888
      if (size < MINIMUM_MORECORE_SIZE)
4889
         size = MINIMUM_MORECORE_SIZE;
4889
         size = MINIMUM_MORECORE_SIZE;
4890
      if (CurrentExecutionLevel() == kTaskLevel)
4890
      if (CurrentExecutionLevel() == kTaskLevel)
4891
         ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
4891
         ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
4892
      if (ptr == 0)
4892
      if (ptr == 0)
4893
      {
4893
      {
4894
        return (void *) MFAIL;
4894
        return (void *) MFAIL;
4895
      }
4895
      }
4896
      // save ptrs so they can be freed during cleanup
4896
      // save ptrs so they can be freed during cleanup
4897
      our_os_pools[next_os_pool] = ptr;
4897
      our_os_pools[next_os_pool] = ptr;
4898
      next_os_pool++;
4898
      next_os_pool++;
4899
      ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
4899
      ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
4900
      sbrk_top = (char *) ptr + size;
4900
      sbrk_top = (char *) ptr + size;
4901
      return ptr;
4901
      return ptr;
4902
    }
4902
    }
4903
    else if (size < 0)
4903
    else if (size < 0)
4904
    {
4904
    {
4905
      // we don't currently support shrink behavior
4905
      // we don't currently support shrink behavior
4906
      return (void *) MFAIL;
4906
      return (void *) MFAIL;
4907
    }
4907
    }
4908
    else
4908
    else
4909
    {
4909
    {
4910
      return sbrk_top;
4910
      return sbrk_top;
4911
    }
4911
    }
4912
  }
4912
  }
4913
 
4913
 
4914
  // cleanup any allocated memory pools
4914
  // cleanup any allocated memory pools
4915
  // called as last thing before shutting down driver
4915
  // called as last thing before shutting down driver
4916
 
4916
 
4917
  void osCleanupMem(void)
4917
  void osCleanupMem(void)
4918
  {
4918
  {
4919
    void **ptr;
4919
    void **ptr;
4920
 
4920
 
4921
    for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
4921
    for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
4922
      if (*ptr)
4922
      if (*ptr)
4923
      {
4923
      {
4924
         PoolDeallocate(*ptr);
4924
         PoolDeallocate(*ptr);
4925
         *ptr = 0;
4925
         *ptr = 0;
4926
      }
4926
      }
4927
  }
4927
  }
4928
 
4928
 
4929
*/
4929
*/
4930
 
4930
 
4931
 
4931
 
4932
/* -----------------------------------------------------------------------
4932
/* -----------------------------------------------------------------------
4933
History:
4933
History:
4934
    V2.8.3 Thu Sep 22 11:16:32 2005  Doug Lea  (dl at gee)
4934
    V2.8.3 Thu Sep 22 11:16:32 2005  Doug Lea  (dl at gee)
4935
      * Add max_footprint functions
4935
      * Add max_footprint functions
4936
      * Ensure all appropriate literals are size_t
4936
      * Ensure all appropriate literals are size_t
4937
      * Fix conditional compilation problem for some #define settings
4937
      * Fix conditional compilation problem for some #define settings
4938
      * Avoid concatenating segments with the one provided
4938
      * Avoid concatenating segments with the one provided
4939
        in create_mspace_with_base
4939
        in create_mspace_with_base
4940
      * Rename some variables to avoid compiler shadowing warnings
4940
      * Rename some variables to avoid compiler shadowing warnings
4941
      * Use explicit lock initialization.
4941
      * Use explicit lock initialization.
4942
      * Better handling of sbrk interference.
4942
      * Better handling of sbrk interference.
4943
      * Simplify and fix segment insertion, trimming and mspace_destroy
4943
      * Simplify and fix segment insertion, trimming and mspace_destroy
4944
      * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
4944
      * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
4945
      * Thanks especially to Dennis Flanagan for help on these.
4945
      * Thanks especially to Dennis Flanagan for help on these.
4946
 
4946
 
4947
    V2.8.2 Sun Jun 12 16:01:10 2005  Doug Lea  (dl at gee)
4947
    V2.8.2 Sun Jun 12 16:01:10 2005  Doug Lea  (dl at gee)
4948
      * Fix memalign brace error.
4948
      * Fix memalign brace error.
4949
 
4949
 
4950
    V2.8.1 Wed Jun  8 16:11:46 2005  Doug Lea  (dl at gee)
4950
    V2.8.1 Wed Jun  8 16:11:46 2005  Doug Lea  (dl at gee)
4951
      * Fix improper #endif nesting in C++
4951
      * Fix improper #endif nesting in C++
4952
      * Add explicit casts needed for C++
4952
      * Add explicit casts needed for C++
4953
 
4953
 
4954
    V2.8.0 Mon May 30 14:09:02 2005  Doug Lea  (dl at gee)
4954
    V2.8.0 Mon May 30 14:09:02 2005  Doug Lea  (dl at gee)
4955
      * Use trees for large bins
4955
      * Use trees for large bins
4956
      * Support mspaces
4956
      * Support mspaces
4957
      * Use segments to unify sbrk-based and mmap-based system allocation,
4957
      * Use segments to unify sbrk-based and mmap-based system allocation,
4958
        removing need for emulation on most platforms without sbrk.
4958
        removing need for emulation on most platforms without sbrk.
4959
      * Default safety checks
4959
      * Default safety checks
4960
      * Optional footer checks. Thanks to William Robertson for the idea.
4960
      * Optional footer checks. Thanks to William Robertson for the idea.
4961
      * Internal code refactoring
4961
      * Internal code refactoring
4962
      * Incorporate suggestions and platform-specific changes.
4962
      * Incorporate suggestions and platform-specific changes.
4963
        Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
4963
        Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
4964
        Aaron Bachmann,  Emery Berger, and others.
4964
        Aaron Bachmann,  Emery Berger, and others.
4965
      * Speed up non-fastbin processing enough to remove fastbins.
4965
      * Speed up non-fastbin processing enough to remove fastbins.
4966
      * Remove useless cfree() to avoid conflicts with other apps.
4966
      * Remove useless cfree() to avoid conflicts with other apps.
4967
      * Remove internal memcpy, memset. Compilers handle builtins better.
4967
      * Remove internal memcpy, memset. Compilers handle builtins better.
4968
      * Remove some options that no one ever used and rename others.
4968
      * Remove some options that no one ever used and rename others.
4969
 
4969
 
4970
    V2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
4970
    V2.7.2 Sat Aug 17 09:07:30 2002  Doug Lea  (dl at gee)
4971
      * Fix malloc_state bitmap array misdeclaration
4971
      * Fix malloc_state bitmap array misdeclaration
4972
 
4972
 
4973
    V2.7.1 Thu Jul 25 10:58:03 2002  Doug Lea  (dl at gee)
4973
    V2.7.1 Thu Jul 25 10:58:03 2002  Doug Lea  (dl at gee)
4974
      * Allow tuning of FIRST_SORTED_BIN_SIZE
4974
      * Allow tuning of FIRST_SORTED_BIN_SIZE
4975
      * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
4975
      * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
4976
      * Better detection and support for non-contiguousness of MORECORE.
4976
      * Better detection and support for non-contiguousness of MORECORE.
4977
        Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
4977
        Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
4978
      * Bypass most of malloc if no frees. Thanks To Emery Berger.
4978
      * Bypass most of malloc if no frees. Thanks To Emery Berger.
4979
      * Fix freeing of old top non-contiguous chunk im sysmalloc.
4979
      * Fix freeing of old top non-contiguous chunk im sysmalloc.
4980
      * Raised default trim and map thresholds to 256K.
4980
      * Raised default trim and map thresholds to 256K.
4981
      * Fix mmap-related #defines. Thanks to Lubos Lunak.
4981
      * Fix mmap-related #defines. Thanks to Lubos Lunak.
4982
      * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
4982
      * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
4983
      * Branch-free bin calculation
4983
      * Branch-free bin calculation
4984
      * Default trim and mmap thresholds now 256K.
4984
      * Default trim and mmap thresholds now 256K.
4985
 
4985
 
4986
    V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
4986
    V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
4987
      * Introduce independent_comalloc and independent_calloc.
4987
      * Introduce independent_comalloc and independent_calloc.
4988
        Thanks to Michael Pachos for motivation and help.
4988
        Thanks to Michael Pachos for motivation and help.
4989
      * Make optional .h file available
4989
      * Make optional .h file available
4990
      * Allow > 2GB requests on 32bit systems.
4990
      * Allow > 2GB requests on 32bit systems.
4991
      * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
4991
      * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
4992
        Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
4992
        Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
4993
        and Anonymous.
4993
        and Anonymous.
4994
      * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
4994
      * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
4995
        helping test this.)
4995
        helping test this.)
4996
      * memalign: check alignment arg
4996
      * memalign: check alignment arg
4997
      * realloc: don't try to shift chunks backwards, since this
4997
      * realloc: don't try to shift chunks backwards, since this
4998
        leads to  more fragmentation in some programs and doesn't
4998
        leads to  more fragmentation in some programs and doesn't
4999
        seem to help in any others.
4999
        seem to help in any others.
5000
      * Collect all cases in malloc requiring system memory into sysmalloc
5000
      * Collect all cases in malloc requiring system memory into sysmalloc
5001
      * Use mmap as backup to sbrk
5001
      * Use mmap as backup to sbrk
5002
      * Place all internal state in malloc_state
5002
      * Place all internal state in malloc_state
5003
      * Introduce fastbins (although similar to 2.5.1)
5003
      * Introduce fastbins (although similar to 2.5.1)
5004
      * Many minor tunings and cosmetic improvements
5004
      * Many minor tunings and cosmetic improvements
5005
      * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
5005
      * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
5006
      * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
5006
      * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
5007
        Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
5007
        Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
5008
      * Include errno.h to support default failure action.
5008
      * Include errno.h to support default failure action.
5009
 
5009
 
5010
    V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
5010
    V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
5011
      * return null for negative arguments
5011
      * return null for negative arguments
5012
      * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
5012
      * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
5013
         * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
5013
         * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
5014
          (e.g. WIN32 platforms)
5014
          (e.g. WIN32 platforms)
5015
         * Cleanup header file inclusion for WIN32 platforms
5015
         * Cleanup header file inclusion for WIN32 platforms
5016
         * Cleanup code to avoid Microsoft Visual C++ compiler complaints
5016
         * Cleanup code to avoid Microsoft Visual C++ compiler complaints
5017
         * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
5017
         * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
5018
           memory allocation routines
5018
           memory allocation routines
5019
         * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
5019
         * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
5020
         * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
5020
         * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
5021
           usage of 'assert' in non-WIN32 code
5021
           usage of 'assert' in non-WIN32 code
5022
         * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
5022
         * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
5023
           avoid infinite loop
5023
           avoid infinite loop
5024
      * Always call 'fREe()' rather than 'free()'
5024
      * Always call 'fREe()' rather than 'free()'
5025
 
5025
 
5026
    V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
5026
    V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
5027
      * Fixed ordering problem with boundary-stamping
5027
      * Fixed ordering problem with boundary-stamping
5028
 
5028
 
5029
    V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
5029
    V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
5030
      * Added pvalloc, as recommended by H.J. Liu
5030
      * Added pvalloc, as recommended by H.J. Liu
5031
      * Added 64bit pointer support mainly from Wolfram Gloger
5031
      * Added 64bit pointer support mainly from Wolfram Gloger
5032
      * Added anonymously donated WIN32 sbrk emulation
5032
      * Added anonymously donated WIN32 sbrk emulation
5033
      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
5033
      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
5034
      * malloc_extend_top: fix mask error that caused wastage after
5034
      * malloc_extend_top: fix mask error that caused wastage after
5035
        foreign sbrks
5035
        foreign sbrks
5036
      * Add linux mremap support code from HJ Liu
5036
      * Add linux mremap support code from HJ Liu
5037
 
5037
 
5038
    V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
5038
    V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
5039
      * Integrated most documentation with the code.
5039
      * Integrated most documentation with the code.
5040
      * Add support for mmap, with help from
5040
      * Add support for mmap, with help from
5041
        Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5041
        Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5042
      * Use last_remainder in more cases.
5042
      * Use last_remainder in more cases.
5043
      * Pack bins using idea from  colin@nyx10.cs.du.edu
5043
      * Pack bins using idea from  colin@nyx10.cs.du.edu
5044
      * Use ordered bins instead of best-fit threshhold
5044
      * Use ordered bins instead of best-fit threshhold
5045
      * Eliminate block-local decls to simplify tracing and debugging.
5045
      * Eliminate block-local decls to simplify tracing and debugging.
5046
      * Support another case of realloc via move into top
5046
      * Support another case of realloc via move into top
5047
      * Fix error occuring when initial sbrk_base not word-aligned.
5047
      * Fix error occuring when initial sbrk_base not word-aligned.
5048
      * Rely on page size for units instead of SBRK_UNIT to
5048
      * Rely on page size for units instead of SBRK_UNIT to
5049
        avoid surprises about sbrk alignment conventions.
5049
        avoid surprises about sbrk alignment conventions.
5050
      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
5050
      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
5051
        (raymond@es.ele.tue.nl) for the suggestion.
5051
        (raymond@es.ele.tue.nl) for the suggestion.
5052
      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
5052
      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
5053
      * More precautions for cases where other routines call sbrk,
5053
      * More precautions for cases where other routines call sbrk,
5054
        courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5054
        courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5055
      * Added macros etc., allowing use in linux libc from
5055
      * Added macros etc., allowing use in linux libc from
5056
        H.J. Lu (hjl@gnu.ai.mit.edu)
5056
        H.J. Lu (hjl@gnu.ai.mit.edu)
5057
      * Inverted this history list
5057
      * Inverted this history list
5058
 
5058
 
5059
    V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
5059
    V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
5060
      * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
5060
      * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
5061
      * Removed all preallocation code since under current scheme
5061
      * Removed all preallocation code since under current scheme
5062
        the work required to undo bad preallocations exceeds
5062
        the work required to undo bad preallocations exceeds
5063
        the work saved in good cases for most test programs.
5063
        the work saved in good cases for most test programs.
5064
      * No longer use return list or unconsolidated bins since
5064
      * No longer use return list or unconsolidated bins since
5065
        no scheme using them consistently outperforms those that don't
5065
        no scheme using them consistently outperforms those that don't
5066
        given above changes.
5066
        given above changes.
5067
      * Use best fit for very large chunks to prevent some worst-cases.
5067
      * Use best fit for very large chunks to prevent some worst-cases.
5068
      * Added some support for debugging
5068
      * Added some support for debugging
5069
 
5069
 
5070
    V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
5070
    V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
5071
      * Removed footers when chunks are in use. Thanks to
5071
      * Removed footers when chunks are in use. Thanks to
5072
        Paul Wilson (wilson@cs.texas.edu) for the suggestion.
5072
        Paul Wilson (wilson@cs.texas.edu) for the suggestion.
5073
 
5073
 
5074
    V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
5074
    V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
5075
      * Added malloc_trim, with help from Wolfram Gloger
5075
      * Added malloc_trim, with help from Wolfram Gloger
5076
        (wmglo@Dent.MED.Uni-Muenchen.DE).
5076
        (wmglo@Dent.MED.Uni-Muenchen.DE).
5077
 
5077
 
5078
    V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
5078
    V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
5079
 
5079
 
5080
    V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
5080
    V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
5081
      * realloc: try to expand in both directions
5081
      * realloc: try to expand in both directions
5082
      * malloc: swap order of clean-bin strategy;
5082
      * malloc: swap order of clean-bin strategy;
5083
      * realloc: only conditionally expand backwards
5083
      * realloc: only conditionally expand backwards
5084
      * Try not to scavenge used bins
5084
      * Try not to scavenge used bins
5085
      * Use bin counts as a guide to preallocation
5085
      * Use bin counts as a guide to preallocation
5086
      * Occasionally bin return list chunks in first scan
5086
      * Occasionally bin return list chunks in first scan
5087
      * Add a few optimizations from colin@nyx10.cs.du.edu
5087
      * Add a few optimizations from colin@nyx10.cs.du.edu
5088
 
5088
 
5089
    V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
5089
    V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
5090
      * faster bin computation & slightly different binning
5090
      * faster bin computation & slightly different binning
5091
      * merged all consolidations to one part of malloc proper
5091
      * merged all consolidations to one part of malloc proper
5092
         (eliminating old malloc_find_space & malloc_clean_bin)
5092
         (eliminating old malloc_find_space & malloc_clean_bin)
5093
      * Scan 2 returns chunks (not just 1)
5093
      * Scan 2 returns chunks (not just 1)
5094
      * Propagate failure in realloc if malloc returns 0
5094
      * Propagate failure in realloc if malloc returns 0
5095
      * Add stuff to allow compilation on non-ANSI compilers
5095
      * Add stuff to allow compilation on non-ANSI compilers
5096
          from kpv@research.att.com
5096
          from kpv@research.att.com
5097
 
5097
 
5098
    V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
5098
    V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
5099
      * removed potential for odd address access in prev_chunk
5099
      * removed potential for odd address access in prev_chunk
5100
      * removed dependency on getpagesize.h
5100
      * removed dependency on getpagesize.h
5101
      * misc cosmetics and a bit more internal documentation
5101
      * misc cosmetics and a bit more internal documentation
5102
      * anticosmetics: mangled names in macros to evade debugger strangeness
5102
      * anticosmetics: mangled names in macros to evade debugger strangeness
5103
      * tested on sparc, hp-700, dec-mips, rs6000
5103
      * tested on sparc, hp-700, dec-mips, rs6000
5104
          with gcc & native cc (hp, dec only) allowing
5104
          with gcc & native cc (hp, dec only) allowing
5105
          Detlefs & Zorn comparison study (in SIGPLAN Notices.)
5105
          Detlefs & Zorn comparison study (in SIGPLAN Notices.)
5106
 
5106
 
5107
    Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
5107
    Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
5108
      * Based loosely on libg++-1.2X malloc. (It retains some of the overall
5108
      * Based loosely on libg++-1.2X malloc. (It retains some of the overall
5109
         structure of old version,  but most details differ.)
5109
         structure of old version,  but most details differ.)
5110
 
5110
 
5111
*/
5111
*/