The R Project SVN R

Rev

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

Rev 40788 Rev 40801
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 unsigned int 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
/* support for mallopt */
2531
/* support for mallopt */
2531
static int change_mparam(int param_number, int value) {
2532
static int change_mparam(int param_number, int value) {
2532
  size_t val = (size_t)value;
2533
  size_t val = (size_t)value;
2533
  init_mparams();
2534
  init_mparams();
2534
  switch(param_number) {
2535
  switch(param_number) {
2535
  case M_TRIM_THRESHOLD:
2536
  case M_TRIM_THRESHOLD:
2536
    mparams.trim_threshold = val;
2537
    mparams.trim_threshold = val;
2537
    return 1;
2538
    return 1;
2538
  case M_GRANULARITY:
2539
  case M_GRANULARITY:
2539
    if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
2540
    if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
2540
      mparams.granularity = val;
2541
      mparams.granularity = val;
2541
      return 1;
2542
      return 1;
2542
    }
2543
    }
2543
    else
2544
    else
2544
      return 0;
2545
      return 0;
2545
  case M_MMAP_THRESHOLD:
2546
  case M_MMAP_THRESHOLD:
2546
    mparams.mmap_threshold = val;
2547
    mparams.mmap_threshold = val;
2547
    return 1;
2548
    return 1;
2548
  default:
2549
  default:
2549
    return 0;
2550
    return 0;
2550
  }
2551
  }
2551
}
2552
}
-
 
2553
#endif
2552
 
2554
 
2553
#if DEBUG
2555
#if DEBUG
2554
/* ------------------------- Debugging Support --------------------------- */
2556
/* ------------------------- Debugging Support --------------------------- */
2555
 
2557
 
2556
/* Check properties of any chunk, whether free, inuse, mmapped etc  */
2558
/* Check properties of any chunk, whether free, inuse, mmapped etc  */
2557
static void do_check_any_chunk(mstate m, mchunkptr p) {
2559
static void do_check_any_chunk(mstate m, mchunkptr p) {
2558
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2560
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2559
  assert(ok_address(m, p));
2561
  assert(ok_address(m, p));
2560
}
2562
}
2561
 
2563
 
2562
/* Check properties of top chunk */
2564
/* Check properties of top chunk */
2563
static void do_check_top_chunk(mstate m, mchunkptr p) {
2565
static void do_check_top_chunk(mstate m, mchunkptr p) {
2564
  msegmentptr sp = segment_holding(m, (char*)p);
2566
  msegmentptr sp = segment_holding(m, (char*)p);
2565
  size_t  sz = chunksize(p);
2567
  size_t  sz = chunksize(p);
2566
  assert(sp != 0);
2568
  assert(sp != 0);
2567
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2569
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2568
  assert(ok_address(m, p));
2570
  assert(ok_address(m, p));
2569
  assert(sz == m->topsize);
2571
  assert(sz == m->topsize);
2570
  assert(sz > 0);
2572
  assert(sz > 0);
2571
  assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
2573
  assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
2572
  assert(pinuse(p));
2574
  assert(pinuse(p));
2573
  assert(!next_pinuse(p));
2575
  assert(!next_pinuse(p));
2574
}
2576
}
2575
 
2577
 
2576
/* Check properties of (inuse) mmapped chunks */
2578
/* Check properties of (inuse) mmapped chunks */
2577
static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
2579
static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
2578
  size_t  sz = chunksize(p);
2580
  size_t  sz = chunksize(p);
2579
  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);
2580
  assert(is_mmapped(p));
2582
  assert(is_mmapped(p));
2581
  assert(use_mmap(m));
2583
  assert(use_mmap(m));
2582
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2584
  assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
2583
  assert(ok_address(m, p));
2585
  assert(ok_address(m, p));
2584
  assert(!is_small(sz));
2586
  assert(!is_small(sz));
2585
  assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
2587
  assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
2586
  assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
2588
  assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
2587
  assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
2589
  assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
2588
}
2590
}
2589
 
2591
 
2590
/* Check properties of inuse chunks */
2592
/* Check properties of inuse chunks */
2591
static void do_check_inuse_chunk(mstate m, mchunkptr p) {
2593
static void do_check_inuse_chunk(mstate m, mchunkptr p) {
2592
  do_check_any_chunk(m, p);
2594
  do_check_any_chunk(m, p);
2593
  assert(cinuse(p));
2595
  assert(cinuse(p));
2594
  assert(next_pinuse(p));
2596
  assert(next_pinuse(p));
2595
  /* If not pinuse and not mmapped, previous chunk has OK offset */
2597
  /* If not pinuse and not mmapped, previous chunk has OK offset */
2596
  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);
2597
  if (is_mmapped(p))
2599
  if (is_mmapped(p))
2598
    do_check_mmapped_chunk(m, p);
2600
    do_check_mmapped_chunk(m, p);
2599
}
2601
}
2600
 
2602
 
2601
/* Check properties of free chunks */
2603
/* Check properties of free chunks */
2602
static void do_check_free_chunk(mstate m, mchunkptr p) {
2604
static void do_check_free_chunk(mstate m, mchunkptr p) {
2603
  size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
2605
  size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
2604
  mchunkptr next = chunk_plus_offset(p, sz);
2606
  mchunkptr next = chunk_plus_offset(p, sz);
2605
  do_check_any_chunk(m, p);
2607
  do_check_any_chunk(m, p);
2606
  assert(!cinuse(p));
2608
  assert(!cinuse(p));
2607
  assert(!next_pinuse(p));
2609
  assert(!next_pinuse(p));
2608
  assert (!is_mmapped(p));
2610
  assert (!is_mmapped(p));
2609
  if (p != m->dv && p != m->top) {
2611
  if (p != m->dv && p != m->top) {
2610
    if (sz >= MIN_CHUNK_SIZE) {
2612
    if (sz >= MIN_CHUNK_SIZE) {
2611
      assert((sz & CHUNK_ALIGN_MASK) == 0);
2613
      assert((sz & CHUNK_ALIGN_MASK) == 0);
2612
      assert(is_aligned(chunk2mem(p)));
2614
      assert(is_aligned(chunk2mem(p)));
2613
      assert(next->prev_foot == sz);
2615
      assert(next->prev_foot == sz);
2614
      assert(pinuse(p));
2616
      assert(pinuse(p));
2615
      assert (next == m->top || cinuse(next));
2617
      assert (next == m->top || cinuse(next));
2616
      assert(p->fd->bk == p);
2618
      assert(p->fd->bk == p);
2617
      assert(p->bk->fd == p);
2619
      assert(p->bk->fd == p);
2618
    }
2620
    }
2619
    else  /* markers are always of size SIZE_T_SIZE */
2621
    else  /* markers are always of size SIZE_T_SIZE */
2620
      assert(sz == SIZE_T_SIZE);
2622
      assert(sz == SIZE_T_SIZE);
2621
  }
2623
  }
2622
}
2624
}
2623
 
2625
 
2624
/* Check properties of malloced chunks at the point they are malloced */
2626
/* Check properties of malloced chunks at the point they are malloced */
2625
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) {
2626
  if (mem != 0) {
2628
  if (mem != 0) {
2627
    mchunkptr p = mem2chunk(mem);
2629
    mchunkptr p = mem2chunk(mem);
2628
    size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
2630
    size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
2629
    do_check_inuse_chunk(m, p);
2631
    do_check_inuse_chunk(m, p);
2630
    assert((sz & CHUNK_ALIGN_MASK) == 0);
2632
    assert((sz & CHUNK_ALIGN_MASK) == 0);
2631
    assert(sz >= MIN_CHUNK_SIZE);
2633
    assert(sz >= MIN_CHUNK_SIZE);
2632
    assert(sz >= s);
2634
    assert(sz >= s);
2633
    /* 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 */
2634
    assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
2636
    assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
2635
  }
2637
  }
2636
}
2638
}
2637
 
2639
 
2638
/* Check a tree and its subtrees.  */
2640
/* Check a tree and its subtrees.  */
2639
static void do_check_tree(mstate m, tchunkptr t) {
2641
static void do_check_tree(mstate m, tchunkptr t) {
2640
  tchunkptr head = 0;
2642
  tchunkptr head = 0;
2641
  tchunkptr u = t;
2643
  tchunkptr u = t;
2642
  bindex_t tindex = t->index;
2644
  bindex_t tindex = t->index;
2643
  size_t tsize = chunksize(t);
2645
  size_t tsize = chunksize(t);
2644
  bindex_t idx;
2646
  bindex_t idx;
2645
  compute_tree_index(tsize, idx);
2647
  compute_tree_index(tsize, idx);
2646
  assert(tindex == idx);
2648
  assert(tindex == idx);
2647
  assert(tsize >= MIN_LARGE_SIZE);
2649
  assert(tsize >= MIN_LARGE_SIZE);
2648
  assert(tsize >= minsize_for_tree_index(idx));
2650
  assert(tsize >= minsize_for_tree_index(idx));
2649
  assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
2651
  assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
2650
 
2652
 
2651
  do { /* traverse through chain of same-sized nodes */
2653
  do { /* traverse through chain of same-sized nodes */
2652
    do_check_any_chunk(m, ((mchunkptr)u));
2654
    do_check_any_chunk(m, ((mchunkptr)u));
2653
    assert(u->index == tindex);
2655
    assert(u->index == tindex);
2654
    assert(chunksize(u) == tsize);
2656
    assert(chunksize(u) == tsize);
2655
    assert(!cinuse(u));
2657
    assert(!cinuse(u));
2656
    assert(!next_pinuse(u));
2658
    assert(!next_pinuse(u));
2657
    assert(u->fd->bk == u);
2659
    assert(u->fd->bk == u);
2658
    assert(u->bk->fd == u);
2660
    assert(u->bk->fd == u);
2659
    if (u->parent == 0) {
2661
    if (u->parent == 0) {
2660
      assert(u->child[0] == 0);
2662
      assert(u->child[0] == 0);
2661
      assert(u->child[1] == 0);
2663
      assert(u->child[1] == 0);
2662
    }
2664
    }
2663
    else {
2665
    else {
2664
      assert(head == 0); /* only one node on chain has parent */
2666
      assert(head == 0); /* only one node on chain has parent */
2665
      head = u;
2667
      head = u;
2666
      assert(u->parent != u);
2668
      assert(u->parent != u);
2667
      assert (u->parent->child[0] == u ||
2669
      assert (u->parent->child[0] == u ||
2668
              u->parent->child[1] == u ||
2670
              u->parent->child[1] == u ||
2669
              *((tbinptr*)(u->parent)) == u);
2671
              *((tbinptr*)(u->parent)) == u);
2670
      if (u->child[0] != 0) {
2672
      if (u->child[0] != 0) {
2671
        assert(u->child[0]->parent == u);
2673
        assert(u->child[0]->parent == u);
2672
        assert(u->child[0] != u);
2674
        assert(u->child[0] != u);
2673
        do_check_tree(m, u->child[0]);
2675
        do_check_tree(m, u->child[0]);
2674
      }
2676
      }
2675
      if (u->child[1] != 0) {
2677
      if (u->child[1] != 0) {
2676
        assert(u->child[1]->parent == u);
2678
        assert(u->child[1]->parent == u);
2677
        assert(u->child[1] != u);
2679
        assert(u->child[1] != u);
2678
        do_check_tree(m, u->child[1]);
2680
        do_check_tree(m, u->child[1]);
2679
      }
2681
      }
2680
      if (u->child[0] != 0 && u->child[1] != 0) {
2682
      if (u->child[0] != 0 && u->child[1] != 0) {
2681
        assert(chunksize(u->child[0]) < chunksize(u->child[1]));
2683
        assert(chunksize(u->child[0]) < chunksize(u->child[1]));
2682
      }
2684
      }
2683
    }
2685
    }
2684
    u = u->fd;
2686
    u = u->fd;
2685
  } while (u != t);
2687
  } while (u != t);
2686
  assert(head != 0);
2688
  assert(head != 0);
2687
}
2689
}
2688
 
2690
 
2689
/*  Check all the chunks in a treebin.  */
2691
/*  Check all the chunks in a treebin.  */
2690
static void do_check_treebin(mstate m, bindex_t i) {
2692
static void do_check_treebin(mstate m, bindex_t i) {
2691
  tbinptr* tb = treebin_at(m, i);
2693
  tbinptr* tb = treebin_at(m, i);
2692
  tchunkptr t = *tb;
2694
  tchunkptr t = *tb;
2693
  int empty = (m->treemap & (1U << i)) == 0;
2695
  int empty = (m->treemap & (1U << i)) == 0;
2694
  if (t == 0)
2696
  if (t == 0)
2695
    assert(empty);
2697
    assert(empty);
2696
  if (!empty)
2698
  if (!empty)
2697
    do_check_tree(m, t);
2699
    do_check_tree(m, t);
2698
}
2700
}
2699
 
2701
 
2700
/*  Check all the chunks in a smallbin.  */
2702
/*  Check all the chunks in a smallbin.  */
2701
static void do_check_smallbin(mstate m, bindex_t i) {
2703
static void do_check_smallbin(mstate m, bindex_t i) {
2702
  sbinptr b = smallbin_at(m, i);
2704
  sbinptr b = smallbin_at(m, i);
2703
  mchunkptr p = b->bk;
2705
  mchunkptr p = b->bk;
2704
  unsigned int empty = (m->smallmap & (1U << i)) == 0;
2706
  unsigned int empty = (m->smallmap & (1U << i)) == 0;
2705
  if (p == b)
2707
  if (p == b)
2706
    assert(empty);
2708
    assert(empty);
2707
  if (!empty) {
2709
  if (!empty) {
2708
    for (; p != b; p = p->bk) {
2710
    for (; p != b; p = p->bk) {
2709
      size_t size = chunksize(p);
2711
      size_t size = chunksize(p);
2710
      mchunkptr q;
2712
      mchunkptr q;
2711
      /* each chunk claims to be free */
2713
      /* each chunk claims to be free */
2712
      do_check_free_chunk(m, p);
2714
      do_check_free_chunk(m, p);
2713
      /* chunk belongs in bin */
2715
      /* chunk belongs in bin */
2714
      assert(small_index(size) == i);
2716
      assert(small_index(size) == i);
2715
      assert(p->bk == b || chunksize(p->bk) == chunksize(p));
2717
      assert(p->bk == b || chunksize(p->bk) == chunksize(p));
2716
      /* chunk is followed by an inuse chunk */
2718
      /* chunk is followed by an inuse chunk */
2717
      q = next_chunk(p);
2719
      q = next_chunk(p);
2718
      if (q->head != FENCEPOST_HEAD)
2720
      if (q->head != FENCEPOST_HEAD)
2719
        do_check_inuse_chunk(m, q);
2721
        do_check_inuse_chunk(m, q);
2720
    }
2722
    }
2721
  }
2723
  }
2722
}
2724
}
2723
 
2725
 
2724
/* Find x in a bin. Used in other check functions. */
2726
/* Find x in a bin. Used in other check functions. */
2725
static int bin_find(mstate m, mchunkptr x) {
2727
static int bin_find(mstate m, mchunkptr x) {
2726
  size_t size = chunksize(x);
2728
  size_t size = chunksize(x);
2727
  if (is_small(size)) {
2729
  if (is_small(size)) {
2728
    bindex_t sidx = small_index(size);
2730
    bindex_t sidx = small_index(size);
2729
    sbinptr b = smallbin_at(m, sidx);
2731
    sbinptr b = smallbin_at(m, sidx);
2730
    if (smallmap_is_marked(m, sidx)) {
2732
    if (smallmap_is_marked(m, sidx)) {
2731
      mchunkptr p = b;
2733
      mchunkptr p = b;
2732
      do {
2734
      do {
2733
        if (p == x)
2735
        if (p == x)
2734
          return 1;
2736
          return 1;
2735
      } while ((p = p->fd) != b);
2737
      } while ((p = p->fd) != b);
2736
    }
2738
    }
2737
  }
2739
  }
2738
  else {
2740
  else {
2739
    bindex_t tidx;
2741
    bindex_t tidx;
2740
    compute_tree_index(size, tidx);
2742
    compute_tree_index(size, tidx);
2741
    if (treemap_is_marked(m, tidx)) {
2743
    if (treemap_is_marked(m, tidx)) {
2742
      tchunkptr t = *treebin_at(m, tidx);
2744
      tchunkptr t = *treebin_at(m, tidx);
2743
      size_t sizebits = size << leftshift_for_tree_index(tidx);
2745
      size_t sizebits = size << leftshift_for_tree_index(tidx);
2744
      while (t != 0 && chunksize(t) != size) {
2746
      while (t != 0 && chunksize(t) != size) {
2745
        t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
2747
        t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
2746
        sizebits <<= 1;
2748
        sizebits <<= 1;
2747
      }
2749
      }
2748
      if (t != 0) {
2750
      if (t != 0) {
2749
        tchunkptr u = t;
2751
        tchunkptr u = t;
2750
        do {
2752
        do {
2751
          if (u == (tchunkptr)x)
2753
          if (u == (tchunkptr)x)
2752
            return 1;
2754
            return 1;
2753
        } while ((u = u->fd) != t);
2755
        } while ((u = u->fd) != t);
2754
      }
2756
      }
2755
    }
2757
    }
2756
  }
2758
  }
2757
  return 0;
2759
  return 0;
2758
}
2760
}
2759
 
2761
 
2760
/* Traverse each chunk and check it; return total */
2762
/* Traverse each chunk and check it; return total */
2761
static size_t traverse_and_check(mstate m) {
2763
static size_t traverse_and_check(mstate m) {
2762
  size_t sum = 0;
2764
  size_t sum = 0;
2763
  if (is_initialized(m)) {
2765
  if (is_initialized(m)) {
2764
    msegmentptr s = &m->seg;
2766
    msegmentptr s = &m->seg;
2765
    sum += m->topsize + TOP_FOOT_SIZE;
2767
    sum += m->topsize + TOP_FOOT_SIZE;
2766
    while (s != 0) {
2768
    while (s != 0) {
2767
      mchunkptr q = align_as_chunk(s->base);
2769
      mchunkptr q = align_as_chunk(s->base);
2768
      mchunkptr lastq = 0;
2770
      mchunkptr lastq = 0;
2769
      assert(pinuse(q));
2771
      assert(pinuse(q));
2770
      while (segment_holds(s, q) &&
2772
      while (segment_holds(s, q) &&
2771
             q != m->top && q->head != FENCEPOST_HEAD) {
2773
             q != m->top && q->head != FENCEPOST_HEAD) {
2772
        sum += chunksize(q);
2774
        sum += chunksize(q);
2773
        if (cinuse(q)) {
2775
        if (cinuse(q)) {
2774
          assert(!bin_find(m, q));
2776
          assert(!bin_find(m, q));
2775
          do_check_inuse_chunk(m, q);
2777
          do_check_inuse_chunk(m, q);
2776
        }
2778
        }
2777
        else {
2779
        else {
2778
          assert(q == m->dv || bin_find(m, q));
2780
          assert(q == m->dv || bin_find(m, q));
2779
          assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */
2781
          assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */
2780
          do_check_free_chunk(m, q);
2782
          do_check_free_chunk(m, q);
2781
        }
2783
        }
2782
        lastq = q;
2784
        lastq = q;
2783
        q = next_chunk(q);
2785
        q = next_chunk(q);
2784
      }
2786
      }
2785
      s = s->next;
2787
      s = s->next;
2786
    }
2788
    }
2787
  }
2789
  }
2788
  return sum;
2790
  return sum;
2789
}
2791
}
2790
 
2792
 
2791
/* Check all properties of malloc_state. */
2793
/* Check all properties of malloc_state. */
2792
static void do_check_malloc_state(mstate m) {
2794
static void do_check_malloc_state(mstate m) {
2793
  bindex_t i;
2795
  bindex_t i;
2794
  size_t total;
2796
  size_t total;
2795
  /* check bins */
2797
  /* check bins */
2796
  for (i = 0; i < NSMALLBINS; ++i)
2798
  for (i = 0; i < NSMALLBINS; ++i)
2797
    do_check_smallbin(m, i);
2799
    do_check_smallbin(m, i);
2798
  for (i = 0; i < NTREEBINS; ++i)
2800
  for (i = 0; i < NTREEBINS; ++i)
2799
    do_check_treebin(m, i);
2801
    do_check_treebin(m, i);
2800
 
2802
 
2801
  if (m->dvsize != 0) { /* check dv chunk */
2803
  if (m->dvsize != 0) { /* check dv chunk */
2802
    do_check_any_chunk(m, m->dv);
2804
    do_check_any_chunk(m, m->dv);
2803
    assert(m->dvsize == chunksize(m->dv));
2805
    assert(m->dvsize == chunksize(m->dv));
2804
    assert(m->dvsize >= MIN_CHUNK_SIZE);
2806
    assert(m->dvsize >= MIN_CHUNK_SIZE);
2805
    assert(bin_find(m, m->dv) == 0);
2807
    assert(bin_find(m, m->dv) == 0);
2806
  }
2808
  }
2807
 
2809
 
2808
  if (m->top != 0) {   /* check top chunk */
2810
  if (m->top != 0) {   /* check top chunk */
2809
    do_check_top_chunk(m, m->top);
2811
    do_check_top_chunk(m, m->top);
2810
    assert(m->topsize == chunksize(m->top));
2812
    assert(m->topsize == chunksize(m->top));
2811
    assert(m->topsize > 0);
2813
    assert(m->topsize > 0);
2812
    assert(bin_find(m, m->top) == 0);
2814
    assert(bin_find(m, m->top) == 0);
2813
  }
2815
  }
2814
 
2816
 
2815
  total = traverse_and_check(m);
2817
  total = traverse_and_check(m);
2816
  assert(total <= m->footprint);
2818
  assert(total <= m->footprint);
2817
  assert(m->footprint <= m->max_footprint);
2819
  assert(m->footprint <= m->max_footprint);
2818
}
2820
}
2819
#endif /* DEBUG */
2821
#endif /* DEBUG */
2820
 
2822
 
2821
/* ----------------------------- statistics ------------------------------ */
2823
/* ----------------------------- statistics ------------------------------ */
2822
 
2824
 
2823
#if !NO_MALLINFO
2825
#if !NO_MALLINFO
2824
static struct mallinfo internal_mallinfo(mstate m) {
2826
static struct mallinfo internal_mallinfo(mstate m) {
2825
  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 };
2826
  if (!PREACTION(m)) {
2828
  if (!PREACTION(m)) {
2827
    check_malloc_state(m);
2829
    check_malloc_state(m);
2828
    if (is_initialized(m)) {
2830
    if (is_initialized(m)) {
2829
      size_t nfree = SIZE_T_ONE; /* top always free */
2831
      size_t nfree = SIZE_T_ONE; /* top always free */
2830
      size_t mfree = m->topsize + TOP_FOOT_SIZE;
2832
      size_t mfree = m->topsize + TOP_FOOT_SIZE;
2831
      size_t sum = mfree;
2833
      size_t sum = mfree;
2832
      msegmentptr s = &m->seg;
2834
      msegmentptr s = &m->seg;
2833
      while (s != 0) {
2835
      while (s != 0) {
2834
        mchunkptr q = align_as_chunk(s->base);
2836
        mchunkptr q = align_as_chunk(s->base);
2835
        while (segment_holds(s, q) &&
2837
        while (segment_holds(s, q) &&
2836
               q != m->top && q->head != FENCEPOST_HEAD) {
2838
               q != m->top && q->head != FENCEPOST_HEAD) {
2837
          size_t sz = chunksize(q);
2839
          size_t sz = chunksize(q);
2838
          sum += sz;
2840
          sum += sz;
2839
          if (!cinuse(q)) {
2841
          if (!cinuse(q)) {
2840
            mfree += sz;
2842
            mfree += sz;
2841
            ++nfree;
2843
            ++nfree;
2842
          }
2844
          }
2843
          q = next_chunk(q);
2845
          q = next_chunk(q);
2844
        }
2846
        }
2845
        s = s->next;
2847
        s = s->next;
2846
      }
2848
      }
2847
 
2849
 
2848
      nm.arena    = sum;
2850
      nm.arena    = sum;
2849
      nm.ordblks  = nfree;
2851
      nm.ordblks  = nfree;
2850
      nm.hblkhd   = m->footprint - sum;
2852
      nm.hblkhd   = m->footprint - sum;
2851
      nm.usmblks  = m->max_footprint;
2853
      nm.usmblks  = m->max_footprint;
2852
      nm.uordblks = m->footprint - mfree;
2854
      nm.uordblks = m->footprint - mfree;
2853
      nm.fordblks = mfree;
2855
      nm.fordblks = mfree;
2854
      nm.keepcost = m->topsize;
2856
      nm.keepcost = m->topsize;
2855
    }
2857
    }
2856
 
2858
 
2857
    POSTACTION(m);
2859
    POSTACTION(m);
2858
  }
2860
  }
2859
  return nm;
2861
  return nm;
2860
}
2862
}
2861
#endif /* !NO_MALLINFO */
2863
#endif /* !NO_MALLINFO */
2862
 
2864
 
-
 
2865
#if 0
2863
static void internal_malloc_stats(mstate m) {
2866
static void internal_malloc_stats(mstate m) {
2864
  if (!PREACTION(m)) {
2867
  if (!PREACTION(m)) {
2865
    size_t maxfp = 0;
2868
    size_t maxfp = 0;
2866
    size_t fp = 0;
2869
    size_t fp = 0;
2867
    size_t used = 0;
2870
    size_t used = 0;
2868
    check_malloc_state(m);
2871
    check_malloc_state(m);
2869
    if (is_initialized(m)) {
2872
    if (is_initialized(m)) {
2870
      msegmentptr s = &m->seg;
2873
      msegmentptr s = &m->seg;
2871
      maxfp = m->max_footprint;
2874
      maxfp = m->max_footprint;
2872
      fp = m->footprint;
2875
      fp = m->footprint;
2873
      used = fp - (m->topsize + TOP_FOOT_SIZE);
2876
      used = fp - (m->topsize + TOP_FOOT_SIZE);
2874
 
2877
 
2875
      while (s != 0) {
2878
      while (s != 0) {
2876
        mchunkptr q = align_as_chunk(s->base);
2879
        mchunkptr q = align_as_chunk(s->base);
2877
        while (segment_holds(s, q) &&
2880
        while (segment_holds(s, q) &&
2878
               q != m->top && q->head != FENCEPOST_HEAD) {
2881
               q != m->top && q->head != FENCEPOST_HEAD) {
2879
          if (!cinuse(q))
2882
          if (!cinuse(q))
2880
            used -= chunksize(q);
2883
            used -= chunksize(q);
2881
          q = next_chunk(q);
2884
          q = next_chunk(q);
2882
        }
2885
        }
2883
        s = s->next;
2886
        s = s->next;
2884
      }
2887
      }
2885
    }
2888
    }
2886
 
2889
 
2887
    fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
2890
    fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
2888
    fprintf(stderr, "system bytes     = %10lu\n", (unsigned long)(fp));
2891
    fprintf(stderr, "system bytes     = %10lu\n", (unsigned long)(fp));
2889
    fprintf(stderr, "in use bytes     = %10lu\n", (unsigned long)(used));
2892
    fprintf(stderr, "in use bytes     = %10lu\n", (unsigned long)(used));
2890
 
2893
 
2891
    POSTACTION(m);
2894
    POSTACTION(m);
2892
  }
2895
  }
2893
}
2896
}
-
 
2897
#endif
2894
 
2898
 
2895
/* ----------------------- Operations on smallbins ----------------------- */
2899
/* ----------------------- Operations on smallbins ----------------------- */
2896
 
2900
 
2897
/*
2901
/*
2898
  Various forms of linking and unlinking are defined as macros.  Even
2902
  Various forms of linking and unlinking are defined as macros.  Even
2899
  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
2900
  paths.  This is ugly but reduces reliance on inlining support of
2904
  paths.  This is ugly but reduces reliance on inlining support of
2901
  compilers.
2905
  compilers.
2902
*/
2906
*/
2903
 
2907
 
2904
/* Link a free chunk into a smallbin  */
2908
/* Link a free chunk into a smallbin  */
2905
#define insert_small_chunk(M, P, S) {\
2909
#define insert_small_chunk(M, P, S) {\
2906
  bindex_t I  = small_index(S);\
2910
  bindex_t I  = small_index(S);\
2907
  mchunkptr B = smallbin_at(M, I);\
2911
  mchunkptr B = smallbin_at(M, I);\
2908
  mchunkptr F = B;\
2912
  mchunkptr F = B;\
2909
  assert(S >= MIN_CHUNK_SIZE);\
2913
  assert(S >= MIN_CHUNK_SIZE);\
2910
  if (!smallmap_is_marked(M, I))\
2914
  if (!smallmap_is_marked(M, I))\
2911
    mark_smallmap(M, I);\
2915
    mark_smallmap(M, I);\
2912
  else if (RTCHECK(ok_address(M, B->fd)))\
2916
  else if (RTCHECK(ok_address(M, B->fd)))\
2913
    F = B->fd;\
2917
    F = B->fd;\
2914
  else {\
2918
  else {\
2915
    CORRUPTION_ERROR_ACTION(M);\
2919
    CORRUPTION_ERROR_ACTION(M);\
2916
  }\
2920
  }\
2917
  B->fd = P;\
2921
  B->fd = P;\
2918
  F->bk = P;\
2922
  F->bk = P;\
2919
  P->fd = F;\
2923
  P->fd = F;\
2920
  P->bk = B;\
2924
  P->bk = B;\
2921
}
2925
}
2922
 
2926
 
2923
/* Unlink a chunk from a smallbin  */
2927
/* Unlink a chunk from a smallbin  */
2924
#define unlink_small_chunk(M, P, S) {\
2928
#define unlink_small_chunk(M, P, S) {\
2925
  mchunkptr F = P->fd;\
2929
  mchunkptr F = P->fd;\
2926
  mchunkptr B = P->bk;\
2930
  mchunkptr B = P->bk;\
2927
  bindex_t I = small_index(S);\
2931
  bindex_t I = small_index(S);\
2928
  assert(P != B);\
2932
  assert(P != B);\
2929
  assert(P != F);\
2933
  assert(P != F);\
2930
  assert(chunksize(P) == small_index2size(I));\
2934
  assert(chunksize(P) == small_index2size(I));\
2931
  if (F == B)\
2935
  if (F == B)\
2932
    clear_smallmap(M, I);\
2936
    clear_smallmap(M, I);\
2933
  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)) &&\
2934
                   (B == smallbin_at(M,I) || ok_address(M, B)))) {\
2938
                   (B == smallbin_at(M,I) || ok_address(M, B)))) {\
2935
    F->bk = B;\
2939
    F->bk = B;\
2936
    B->fd = F;\
2940
    B->fd = F;\
2937
  }\
2941
  }\
2938
  else {\
2942
  else {\
2939
    CORRUPTION_ERROR_ACTION(M);\
2943
    CORRUPTION_ERROR_ACTION(M);\
2940
  }\
2944
  }\
2941
}
2945
}
2942
 
2946
 
2943
/* Unlink the first chunk from a smallbin */
2947
/* Unlink the first chunk from a smallbin */
2944
#define unlink_first_small_chunk(M, B, P, I) {\
2948
#define unlink_first_small_chunk(M, B, P, I) {\
2945
  mchunkptr F = P->fd;\
2949
  mchunkptr F = P->fd;\
2946
  assert(P != B);\
2950
  assert(P != B);\
2947
  assert(P != F);\
2951
  assert(P != F);\
2948
  assert(chunksize(P) == small_index2size(I));\
2952
  assert(chunksize(P) == small_index2size(I));\
2949
  if (B == F)\
2953
  if (B == F)\
2950
    clear_smallmap(M, I);\
2954
    clear_smallmap(M, I);\
2951
  else if (RTCHECK(ok_address(M, F))) {\
2955
  else if (RTCHECK(ok_address(M, F))) {\
2952
    B->fd = F;\
2956
    B->fd = F;\
2953
    F->bk = B;\
2957
    F->bk = B;\
2954
  }\
2958
  }\
2955
  else {\
2959
  else {\
2956
    CORRUPTION_ERROR_ACTION(M);\
2960
    CORRUPTION_ERROR_ACTION(M);\
2957
  }\
2961
  }\
2958
}
2962
}
2959
 
2963
 
2960
/* Replace dv node, binning the old one */
2964
/* Replace dv node, binning the old one */
2961
/* Used only when dvsize known to be small */
2965
/* Used only when dvsize known to be small */
2962
#define replace_dv(M, P, S) {\
2966
#define replace_dv(M, P, S) {\
2963
  size_t DVS = M->dvsize;\
2967
  size_t DVS = M->dvsize;\
2964
  if (DVS != 0) {\
2968
  if (DVS != 0) {\
2965
    mchunkptr DV = M->dv;\
2969
    mchunkptr DV = M->dv;\
2966
    assert(is_small(DVS));\
2970
    assert(is_small(DVS));\
2967
    insert_small_chunk(M, DV, DVS);\
2971
    insert_small_chunk(M, DV, DVS);\
2968
  }\
2972
  }\
2969
  M->dvsize = S;\
2973
  M->dvsize = S;\
2970
  M->dv = P;\
2974
  M->dv = P;\
2971
}
2975
}
2972
 
2976
 
2973
/* ------------------------- Operations on trees ------------------------- */
2977
/* ------------------------- Operations on trees ------------------------- */
2974
 
2978
 
2975
/* Insert chunk into tree */
2979
/* Insert chunk into tree */
2976
#define insert_large_chunk(M, X, S) {\
2980
#define insert_large_chunk(M, X, S) {\
2977
  tbinptr* H;\
2981
  tbinptr* H;\
2978
  bindex_t I;\
2982
  bindex_t I;\
2979
  compute_tree_index(S, I);\
2983
  compute_tree_index(S, I);\
2980
  H = treebin_at(M, I);\
2984
  H = treebin_at(M, I);\
2981
  X->index = I;\
2985
  X->index = I;\
2982
  X->child[0] = X->child[1] = 0;\
2986
  X->child[0] = X->child[1] = 0;\
2983
  if (!treemap_is_marked(M, I)) {\
2987
  if (!treemap_is_marked(M, I)) {\
2984
    mark_treemap(M, I);\
2988
    mark_treemap(M, I);\
2985
    *H = X;\
2989
    *H = X;\
2986
    X->parent = (tchunkptr)H;\
2990
    X->parent = (tchunkptr)H;\
2987
    X->fd = X->bk = X;\
2991
    X->fd = X->bk = X;\
2988
  }\
2992
  }\
2989
  else {\
2993
  else {\
2990
    tchunkptr T = *H;\
2994
    tchunkptr T = *H;\
2991
    size_t K = S << leftshift_for_tree_index(I);\
2995
    size_t K = S << leftshift_for_tree_index(I);\
2992
    for (;;) {\
2996
    for (;;) {\
2993
      if (chunksize(T) != S) {\
2997
      if (chunksize(T) != S) {\
2994
        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]);\
2995
        K <<= 1;\
2999
        K <<= 1;\
2996
        if (*C != 0)\
3000
        if (*C != 0)\
2997
          T = *C;\
3001
          T = *C;\
2998
        else if (RTCHECK(ok_address(M, C))) {\
3002
        else if (RTCHECK(ok_address(M, C))) {\
2999
          *C = X;\
3003
          *C = X;\
3000
          X->parent = T;\
3004
          X->parent = T;\
3001
          X->fd = X->bk = X;\
3005
          X->fd = X->bk = X;\
3002
          break;\
3006
          break;\
3003
        }\
3007
        }\
3004
        else {\
3008
        else {\
3005
          CORRUPTION_ERROR_ACTION(M);\
3009
          CORRUPTION_ERROR_ACTION(M);\
3006
          break;\
3010
          break;\
3007
        }\
3011
        }\
3008
      }\
3012
      }\
3009
      else {\
3013
      else {\
3010
        tchunkptr F = T->fd;\
3014
        tchunkptr F = T->fd;\
3011
        if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
3015
        if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
3012
          T->fd = F->bk = X;\
3016
          T->fd = F->bk = X;\
3013
          X->fd = F;\
3017
          X->fd = F;\
3014
          X->bk = T;\
3018
          X->bk = T;\
3015
          X->parent = 0;\
3019
          X->parent = 0;\
3016
          break;\
3020
          break;\
3017
        }\
3021
        }\
3018
        else {\
3022
        else {\
3019
          CORRUPTION_ERROR_ACTION(M);\
3023
          CORRUPTION_ERROR_ACTION(M);\
3020
          break;\
3024
          break;\
3021
        }\
3025
        }\
3022
      }\
3026
      }\
3023
    }\
3027
    }\
3024
  }\
3028
  }\
3025
}
3029
}
3026
 
3030
 
3027
/*
3031
/*
3028
  Unlink steps:
3032
  Unlink steps:
3029
 
3033
 
3030
  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
3031
     and choose its bk node as its replacement.
3035
     and choose its bk node as its replacement.
3032
  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
3033
     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
3034
     right), to make sure that lefts and rights of descendents
3038
     right), to make sure that lefts and rights of descendents
3035
     correspond properly to bit masks.  We use the rightmost descendent
3039
     correspond properly to bit masks.  We use the rightmost descendent
3036
     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
3037
     tends to counteract removal of leftmosts elsewhere, and so keeps
3041
     tends to counteract removal of leftmosts elsewhere, and so keeps
3038
     paths shorter than minimally guaranteed.  This doesn't loop much
3042
     paths shorter than minimally guaranteed.  This doesn't loop much
3039
     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.
3040
  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
3041
     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).
3042
*/
3046
*/
3043
 
3047
 
3044
#define unlink_large_chunk(M, X) {\
3048
#define unlink_large_chunk(M, X) {\
3045
  tchunkptr XP = X->parent;\
3049
  tchunkptr XP = X->parent;\
3046
  tchunkptr R;\
3050
  tchunkptr R;\
3047
  if (X->bk != X) {\
3051
  if (X->bk != X) {\
3048
    tchunkptr F = X->fd;\
3052
    tchunkptr F = X->fd;\
3049
    R = X->bk;\
3053
    R = X->bk;\
3050
    if (RTCHECK(ok_address(M, F))) {\
3054
    if (RTCHECK(ok_address(M, F))) {\
3051
      F->bk = R;\
3055
      F->bk = R;\
3052
      R->fd = F;\
3056
      R->fd = F;\
3053
    }\
3057
    }\
3054
    else {\
3058
    else {\
3055
      CORRUPTION_ERROR_ACTION(M);\
3059
      CORRUPTION_ERROR_ACTION(M);\
3056
    }\
3060
    }\
3057
  }\
3061
  }\
3058
  else {\
3062
  else {\
3059
    tchunkptr* RP;\
3063
    tchunkptr* RP;\
3060
    if (((R = *(RP = &(X->child[1]))) != 0) ||\
3064
    if (((R = *(RP = &(X->child[1]))) != 0) ||\
3061
        ((R = *(RP = &(X->child[0]))) != 0)) {\
3065
        ((R = *(RP = &(X->child[0]))) != 0)) {\
3062
      tchunkptr* CP;\
3066
      tchunkptr* CP;\
3063
      while ((*(CP = &(R->child[1])) != 0) ||\
3067
      while ((*(CP = &(R->child[1])) != 0) ||\
3064
             (*(CP = &(R->child[0])) != 0)) {\
3068
             (*(CP = &(R->child[0])) != 0)) {\
3065
        R = *(RP = CP);\
3069
        R = *(RP = CP);\
3066
      }\
3070
      }\
3067
      if (RTCHECK(ok_address(M, RP)))\
3071
      if (RTCHECK(ok_address(M, RP)))\
3068
        *RP = 0;\
3072
        *RP = 0;\
3069
      else {\
3073
      else {\
3070
        CORRUPTION_ERROR_ACTION(M);\
3074
        CORRUPTION_ERROR_ACTION(M);\
3071
      }\
3075
      }\
3072
    }\
3076
    }\
3073
  }\
3077
  }\
3074
  if (XP != 0) {\
3078
  if (XP != 0) {\
3075
    tbinptr* H = treebin_at(M, X->index);\
3079
    tbinptr* H = treebin_at(M, X->index);\
3076
    if (X == *H) {\
3080
    if (X == *H) {\
3077
      if ((*H = R) == 0) \
3081
      if ((*H = R) == 0) \
3078
        clear_treemap(M, X->index);\
3082
        clear_treemap(M, X->index);\
3079
    }\
3083
    }\
3080
    else if (RTCHECK(ok_address(M, XP))) {\
3084
    else if (RTCHECK(ok_address(M, XP))) {\
3081
      if (XP->child[0] == X) \
3085
      if (XP->child[0] == X) \
3082
        XP->child[0] = R;\
3086
        XP->child[0] = R;\
3083
      else \
3087
      else \
3084
        XP->child[1] = R;\
3088
        XP->child[1] = R;\
3085
    }\
3089
    }\
3086
    else\
3090
    else\
3087
      CORRUPTION_ERROR_ACTION(M);\
3091
      CORRUPTION_ERROR_ACTION(M);\
3088
    if (R != 0) {\
3092
    if (R != 0) {\
3089
      if (RTCHECK(ok_address(M, R))) {\
3093
      if (RTCHECK(ok_address(M, R))) {\
3090
        tchunkptr C0, C1;\
3094
        tchunkptr C0, C1;\
3091
        R->parent = XP;\
3095
        R->parent = XP;\
3092
        if ((C0 = X->child[0]) != 0) {\
3096
        if ((C0 = X->child[0]) != 0) {\
3093
          if (RTCHECK(ok_address(M, C0))) {\
3097
          if (RTCHECK(ok_address(M, C0))) {\
3094
            R->child[0] = C0;\
3098
            R->child[0] = C0;\
3095
            C0->parent = R;\
3099
            C0->parent = R;\
3096
          }\
3100
          }\
3097
          else\
3101
          else\
3098
            CORRUPTION_ERROR_ACTION(M);\
3102
            CORRUPTION_ERROR_ACTION(M);\
3099
        }\
3103
        }\
3100
        if ((C1 = X->child[1]) != 0) {\
3104
        if ((C1 = X->child[1]) != 0) {\
3101
          if (RTCHECK(ok_address(M, C1))) {\
3105
          if (RTCHECK(ok_address(M, C1))) {\
3102
            R->child[1] = C1;\
3106
            R->child[1] = C1;\
3103
            C1->parent = R;\
3107
            C1->parent = R;\
3104
          }\
3108
          }\
3105
          else\
3109
          else\
3106
            CORRUPTION_ERROR_ACTION(M);\
3110
            CORRUPTION_ERROR_ACTION(M);\
3107
        }\
3111
        }\
3108
      }\
3112
      }\
3109
      else\
3113
      else\
3110
        CORRUPTION_ERROR_ACTION(M);\
3114
        CORRUPTION_ERROR_ACTION(M);\
3111
    }\
3115
    }\
3112
  }\
3116
  }\
3113
}
3117
}
3114
 
3118
 
3115
/* Relays to large vs small bin operations */
3119
/* Relays to large vs small bin operations */
3116
 
3120
 
3117
#define insert_chunk(M, P, S)\
3121
#define insert_chunk(M, P, S)\
3118
  if (is_small(S)) insert_small_chunk(M, P, S)\
3122
  if (is_small(S)) insert_small_chunk(M, P, S)\
3119
  else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
3123
  else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
3120
 
3124
 
3121
#define unlink_chunk(M, P, S)\
3125
#define unlink_chunk(M, P, S)\
3122
  if (is_small(S)) unlink_small_chunk(M, P, S)\
3126
  if (is_small(S)) unlink_small_chunk(M, P, S)\
3123
  else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
3127
  else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
3124
 
3128
 
3125
 
3129
 
3126
/* Relays to internal calls to malloc/free from realloc, memalign etc */
3130
/* Relays to internal calls to malloc/free from realloc, memalign etc */
3127
 
3131
 
3128
#if ONLY_MSPACES
3132
#if ONLY_MSPACES
3129
#define internal_malloc(m, b) mspace_malloc(m, b)
3133
#define internal_malloc(m, b) mspace_malloc(m, b)
3130
#define internal_free(m, mem) mspace_free(m,mem);
3134
#define internal_free(m, mem) mspace_free(m,mem);
3131
#else /* ONLY_MSPACES */
3135
#else /* ONLY_MSPACES */
3132
#if MSPACES
3136
#if MSPACES
3133
#define internal_malloc(m, b)\
3137
#define internal_malloc(m, b)\
3134
   (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
3138
   (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
3135
#define internal_free(m, mem)\
3139
#define internal_free(m, mem)\
3136
   if (m == gm) dlfree(mem); else mspace_free(m,mem);
3140
   if (m == gm) dlfree(mem); else mspace_free(m,mem);
3137
#else /* MSPACES */
3141
#else /* MSPACES */
3138
#define internal_malloc(m, b) dlmalloc(b)
3142
#define internal_malloc(m, b) dlmalloc(b)
3139
#define internal_free(m, mem) dlfree(mem)
3143
#define internal_free(m, mem) dlfree(mem)
3140
#endif /* MSPACES */
3144
#endif /* MSPACES */
3141
#endif /* ONLY_MSPACES */
3145
#endif /* ONLY_MSPACES */
3142
 
3146
 
3143
/* -----------------------  Direct-mmapping chunks ----------------------- */
3147
/* -----------------------  Direct-mmapping chunks ----------------------- */
3144
 
3148
 
3145
/*
3149
/*
3146
  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
3147
  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
3148
  allows reconstruction of the required argument to MUNMAP when freed,
3152
  allows reconstruction of the required argument to MUNMAP when freed,
3149
  and also allows adjustment of the returned chunk to meet alignment
3153
  and also allows adjustment of the returned chunk to meet alignment
3150
  requirements (especially in memalign).  There is also enough space
3154
  requirements (especially in memalign).  There is also enough space
3151
  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
3152
  the PINUSE bit so frees can be checked.
3156
  the PINUSE bit so frees can be checked.
3153
*/
3157
*/
3154
 
3158
 
3155
/* Malloc using mmap */
3159
/* Malloc using mmap */
3156
static void* mmap_alloc(mstate m, size_t nb) {
3160
static void* mmap_alloc(mstate m, size_t nb) {
3157
  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);
3158
  if (mmsize > nb) {     /* Check for wrap around 0 */
3162
  if (mmsize > nb) {     /* Check for wrap around 0 */
3159
    char* mm = (char*)(DIRECT_MMAP(mmsize));
3163
    char* mm = (char*)(DIRECT_MMAP(mmsize));
3160
    if (mm != CMFAIL) {
3164
    if (mm != CMFAIL) {
3161
      size_t offset = align_offset(chunk2mem(mm));
3165
      size_t offset = align_offset(chunk2mem(mm));
3162
      size_t psize = mmsize - offset - MMAP_FOOT_PAD;
3166
      size_t psize = mmsize - offset - MMAP_FOOT_PAD;
3163
      mchunkptr p = (mchunkptr)(mm + offset);
3167
      mchunkptr p = (mchunkptr)(mm + offset);
3164
      p->prev_foot = offset | IS_MMAPPED_BIT;
3168
      p->prev_foot = offset | IS_MMAPPED_BIT;
3165
      (p)->head = (psize|CINUSE_BIT);
3169
      (p)->head = (psize|CINUSE_BIT);
3166
      mark_inuse_foot(m, p, psize);
3170
      mark_inuse_foot(m, p, psize);
3167
      chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
3171
      chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
3168
      chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
3172
      chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
3169
 
3173
 
3170
      if (mm < m->least_addr)
3174
      if (mm < m->least_addr)
3171
        m->least_addr = mm;
3175
        m->least_addr = mm;
3172
      if ((m->footprint += mmsize) > m->max_footprint)
3176
      if ((m->footprint += mmsize) > m->max_footprint)
3173
        m->max_footprint = m->footprint;
3177
        m->max_footprint = m->footprint;
3174
      assert(is_aligned(chunk2mem(p)));
3178
      assert(is_aligned(chunk2mem(p)));
3175
      check_mmapped_chunk(m, p);
3179
      check_mmapped_chunk(m, p);
3176
      return chunk2mem(p);
3180
      return chunk2mem(p);
3177
    }
3181
    }
3178
  }
3182
  }
3179
  return 0;
3183
  return 0;
3180
}
3184
}
3181
 
3185
 
3182
/* Realloc using mmap */
3186
/* Realloc using mmap */
3183
static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
3187
static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
3184
  size_t oldsize = chunksize(oldp);
3188
  size_t oldsize = chunksize(oldp);
3185
  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 */
3186
    return 0;
3190
    return 0;
3187
  /* Keep old chunk if big enough but not too big */
3191
  /* Keep old chunk if big enough but not too big */
3188
  if (oldsize >= nb + SIZE_T_SIZE &&
3192
  if (oldsize >= nb + SIZE_T_SIZE &&
3189
      (oldsize - nb) <= (mparams.granularity << 1))
3193
      (oldsize - nb) <= (mparams.granularity << 1))
3190
    return oldp;
3194
    return oldp;
3191
  else {
3195
  else {
3192
    size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
3196
    size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
3193
    size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
3197
    size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
3194
    size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
3198
    size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
3195
                                         CHUNK_ALIGN_MASK);
3199
                                         CHUNK_ALIGN_MASK);
3196
    char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
3200
    char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
3197
                                  oldmmsize, newmmsize, 1);
3201
                                  oldmmsize, newmmsize, 1);
3198
    if (cp != CMFAIL) {
3202
    if (cp != CMFAIL) {
3199
      mchunkptr newp = (mchunkptr)(cp + offset);
3203
      mchunkptr newp = (mchunkptr)(cp + offset);
3200
      size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
3204
      size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
3201
      newp->head = (psize|CINUSE_BIT);
3205
      newp->head = (psize|CINUSE_BIT);
3202
      mark_inuse_foot(m, newp, psize);
3206
      mark_inuse_foot(m, newp, psize);
3203
      chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
3207
      chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
3204
      chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
3208
      chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
3205
 
3209
 
3206
      if (cp < m->least_addr)
3210
      if (cp < m->least_addr)
3207
        m->least_addr = cp;
3211
        m->least_addr = cp;
3208
      if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
3212
      if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
3209
        m->max_footprint = m->footprint;
3213
        m->max_footprint = m->footprint;
3210
      check_mmapped_chunk(m, newp);
3214
      check_mmapped_chunk(m, newp);
3211
      return newp;
3215
      return newp;
3212
    }
3216
    }
3213
  }
3217
  }
3214
  return 0;
3218
  return 0;
3215
}
3219
}
3216
 
3220
 
3217
/* -------------------------- mspace management -------------------------- */
3221
/* -------------------------- mspace management -------------------------- */
3218
 
3222
 
3219
/* Initialize top chunk and its size */
3223
/* Initialize top chunk and its size */
3220
static void init_top(mstate m, mchunkptr p, size_t psize) {
3224
static void init_top(mstate m, mchunkptr p, size_t psize) {
3221
  /* Ensure alignment */
3225
  /* Ensure alignment */
3222
  size_t offset = align_offset(chunk2mem(p));
3226
  size_t offset = align_offset(chunk2mem(p));
3223
  p = (mchunkptr)((char*)p + offset);
3227
  p = (mchunkptr)((char*)p + offset);
3224
  psize -= offset;
3228
  psize -= offset;
3225
 
3229
 
3226
  m->top = p;
3230
  m->top = p;
3227
  m->topsize = psize;
3231
  m->topsize = psize;
3228
  p->head = psize | PINUSE_BIT;
3232
  p->head = psize | PINUSE_BIT;
3229
  /* set size of fake trailing chunk holding overhead space only once */
3233
  /* set size of fake trailing chunk holding overhead space only once */
3230
  chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
3234
  chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
3231
  m->trim_check = mparams.trim_threshold; /* reset on each update */
3235
  m->trim_check = mparams.trim_threshold; /* reset on each update */
3232
}
3236
}
3233
 
3237
 
3234
/* Initialize bins for a new mstate that is otherwise zeroed out */
3238
/* Initialize bins for a new mstate that is otherwise zeroed out */
3235
static void init_bins(mstate m) {
3239
static void init_bins(mstate m) {
3236
  /* Establish circular links for smallbins */
3240
  /* Establish circular links for smallbins */
3237
  bindex_t i;
3241
  bindex_t i;
3238
  for (i = 0; i < NSMALLBINS; ++i) {
3242
  for (i = 0; i < NSMALLBINS; ++i) {
3239
    sbinptr bin = smallbin_at(m,i);
3243
    sbinptr bin = smallbin_at(m,i);
3240
    bin->fd = bin->bk = bin;
3244
    bin->fd = bin->bk = bin;
3241
  }
3245
  }
3242
}
3246
}
3243
 
3247
 
3244
#if PROCEED_ON_ERROR
3248
#if PROCEED_ON_ERROR
3245
 
3249
 
3246
/* default corruption action */
3250
/* default corruption action */
3247
static void reset_on_error(mstate m) {
3251
static void reset_on_error(mstate m) {
3248
  int i;
3252
  int i;
3249
  ++malloc_corruption_error_count;
3253
  ++malloc_corruption_error_count;
3250
  /* Reinitialize fields to forget about all memory */
3254
  /* Reinitialize fields to forget about all memory */
3251
  m->smallbins = m->treebins = 0;
3255
  m->smallbins = m->treebins = 0;
3252
  m->dvsize = m->topsize = 0;
3256
  m->dvsize = m->topsize = 0;
3253
  m->seg.base = 0;
3257
  m->seg.base = 0;
3254
  m->seg.size = 0;
3258
  m->seg.size = 0;
3255
  m->seg.next = 0;
3259
  m->seg.next = 0;
3256
  m->top = m->dv = 0;
3260
  m->top = m->dv = 0;
3257
  for (i = 0; i < NTREEBINS; ++i)
3261
  for (i = 0; i < NTREEBINS; ++i)
3258
    *treebin_at(m, i) = 0;
3262
    *treebin_at(m, i) = 0;
3259
  init_bins(m);
3263
  init_bins(m);
3260
}
3264
}
3261
#endif /* PROCEED_ON_ERROR */
3265
#endif /* PROCEED_ON_ERROR */
3262
 
3266
 
3263
/* Allocate chunk and prepend remainder with chunk in successor base. */
3267
/* Allocate chunk and prepend remainder with chunk in successor base. */
3264
static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
3268
static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
3265
                           size_t nb) {
3269
                           size_t nb) {
3266
  mchunkptr p = align_as_chunk(newbase);
3270
  mchunkptr p = align_as_chunk(newbase);
3267
  mchunkptr oldfirst = align_as_chunk(oldbase);
3271
  mchunkptr oldfirst = align_as_chunk(oldbase);
3268
  size_t psize = (char*)oldfirst - (char*)p;
3272
  size_t psize = (char*)oldfirst - (char*)p;
3269
  mchunkptr q = chunk_plus_offset(p, nb);
3273
  mchunkptr q = chunk_plus_offset(p, nb);
3270
  size_t qsize = psize - nb;
3274
  size_t qsize = psize - nb;
3271
  set_size_and_pinuse_of_inuse_chunk(m, p, nb);
3275
  set_size_and_pinuse_of_inuse_chunk(m, p, nb);
3272
 
3276
 
3273
  assert((char*)oldfirst > (char*)q);
3277
  assert((char*)oldfirst > (char*)q);
3274
  assert(pinuse(oldfirst));
3278
  assert(pinuse(oldfirst));
3275
  assert(qsize >= MIN_CHUNK_SIZE);
3279
  assert(qsize >= MIN_CHUNK_SIZE);
3276
 
3280
 
3277
  /* consolidate remainder with first chunk of old base */
3281
  /* consolidate remainder with first chunk of old base */
3278
  if (oldfirst == m->top) {
3282
  if (oldfirst == m->top) {
3279
    size_t tsize = m->topsize += qsize;
3283
    size_t tsize = m->topsize += qsize;
3280
    m->top = q;
3284
    m->top = q;
3281
    q->head = tsize | PINUSE_BIT;
3285
    q->head = tsize | PINUSE_BIT;
3282
    check_top_chunk(m, q);
3286
    check_top_chunk(m, q);
3283
  }
3287
  }
3284
  else if (oldfirst == m->dv) {
3288
  else if (oldfirst == m->dv) {
3285
    size_t dsize = m->dvsize += qsize;
3289
    size_t dsize = m->dvsize += qsize;
3286
    m->dv = q;
3290
    m->dv = q;
3287
    set_size_and_pinuse_of_free_chunk(q, dsize);
3291
    set_size_and_pinuse_of_free_chunk(q, dsize);
3288
  }
3292
  }
3289
  else {
3293
  else {
3290
    if (!cinuse(oldfirst)) {
3294
    if (!cinuse(oldfirst)) {
3291
      size_t nsize = chunksize(oldfirst);
3295
      size_t nsize = chunksize(oldfirst);
3292
      unlink_chunk(m, oldfirst, nsize);
3296
      unlink_chunk(m, oldfirst, nsize);
3293
      oldfirst = chunk_plus_offset(oldfirst, nsize);
3297
      oldfirst = chunk_plus_offset(oldfirst, nsize);
3294
      qsize += nsize;
3298
      qsize += nsize;
3295
    }
3299
    }
3296
    set_free_with_pinuse(q, qsize, oldfirst);
3300
    set_free_with_pinuse(q, qsize, oldfirst);
3297
    insert_chunk(m, q, qsize);
3301
    insert_chunk(m, q, qsize);
3298
    check_free_chunk(m, q);
3302
    check_free_chunk(m, q);
3299
  }
3303
  }
3300
 
3304
 
3301
  check_malloced_chunk(m, chunk2mem(p), nb);
3305
  check_malloced_chunk(m, chunk2mem(p), nb);
3302
  return chunk2mem(p);
3306
  return chunk2mem(p);
3303
}
3307
}
3304
 
3308
 
3305
 
3309
 
3306
/* Add a segment to hold a new noncontiguous region */
3310
/* Add a segment to hold a new noncontiguous region */
3307
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) {
3308
  /* Determine locations and sizes of segment, fenceposts, old top */
3312
  /* Determine locations and sizes of segment, fenceposts, old top */
3309
  char* old_top = (char*)m->top;
3313
  char* old_top = (char*)m->top;
3310
  msegmentptr oldsp = segment_holding(m, old_top);
3314
  msegmentptr oldsp = segment_holding(m, old_top);
3311
  char* old_end = oldsp->base + oldsp->size;
3315
  char* old_end = oldsp->base + oldsp->size;
3312
  size_t ssize = pad_request(sizeof(struct malloc_segment));
3316
  size_t ssize = pad_request(sizeof(struct malloc_segment));
3313
  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);
3314
  size_t offset = align_offset(chunk2mem(rawsp));
3318
  size_t offset = align_offset(chunk2mem(rawsp));
3315
  char* asp = rawsp + offset;
3319
  char* asp = rawsp + offset;
3316
  char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
3320
  char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
3317
  mchunkptr sp = (mchunkptr)csp;
3321
  mchunkptr sp = (mchunkptr)csp;
3318
  msegmentptr ss = (msegmentptr)(chunk2mem(sp));
3322
  msegmentptr ss = (msegmentptr)(chunk2mem(sp));
3319
  mchunkptr tnext = chunk_plus_offset(sp, ssize);
3323
  mchunkptr tnext = chunk_plus_offset(sp, ssize);
3320
  mchunkptr p = tnext;
3324
  mchunkptr p = tnext;
3321
  int nfences = 0;
3325
  int nfences = 0;
3322
 
3326
 
3323
  /* reset top to new space */
3327
  /* reset top to new space */
3324
  init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
3328
  init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
3325
 
3329
 
3326
  /* Set up segment record */
3330
  /* Set up segment record */
3327
  assert(is_aligned(ss));
3331
  assert(is_aligned(ss));
3328
  set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
3332
  set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
3329
  *ss = m->seg; /* Push current record */
3333
  *ss = m->seg; /* Push current record */
3330
  m->seg.base = tbase;
3334
  m->seg.base = tbase;
3331
  m->seg.size = tsize;
3335
  m->seg.size = tsize;
3332
  m->seg.sflags = mmapped;
3336
  m->seg.sflags = mmapped;
3333
  m->seg.next = ss;
3337
  m->seg.next = ss;
3334
 
3338
 
3335
  /* Insert trailing fenceposts */
3339
  /* Insert trailing fenceposts */
3336
  for (;;) {
3340
  for (;;) {
3337
    mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
3341
    mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
3338
    p->head = FENCEPOST_HEAD;
3342
    p->head = FENCEPOST_HEAD;
3339
    ++nfences;
3343
    ++nfences;
3340
    if ((char*)(&(nextp->head)) < old_end)
3344
    if ((char*)(&(nextp->head)) < old_end)
3341
      p = nextp;
3345
      p = nextp;
3342
    else
3346
    else
3343
      break;
3347
      break;
3344
  }
3348
  }
3345
  assert(nfences >= 2);
3349
  assert(nfences >= 2);
3346
 
3350
 
3347
  /* 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 */
3348
  if (csp != old_top) {
3352
  if (csp != old_top) {
3349
    mchunkptr q = (mchunkptr)old_top;
3353
    mchunkptr q = (mchunkptr)old_top;
3350
    size_t psize = csp - old_top;
3354
    size_t psize = csp - old_top;
3351
    mchunkptr tn = chunk_plus_offset(q, psize);
3355
    mchunkptr tn = chunk_plus_offset(q, psize);
3352
    set_free_with_pinuse(q, psize, tn);
3356
    set_free_with_pinuse(q, psize, tn);
3353
    insert_chunk(m, q, psize);
3357
    insert_chunk(m, q, psize);
3354
  }
3358
  }
3355
 
3359
 
3356
  check_top_chunk(m, m->top);
3360
  check_top_chunk(m, m->top);
3357
}
3361
}
3358
 
3362
 
3359
/* -------------------------- System allocation -------------------------- */
3363
/* -------------------------- System allocation -------------------------- */
3360
 
3364
 
3361
/* Get memory from system using MORECORE or MMAP */
3365
/* Get memory from system using MORECORE or MMAP */
3362
static void* sys_alloc(mstate m, size_t nb) {
3366
static void* sys_alloc(mstate m, size_t nb) {
3363
  char* tbase = CMFAIL;
3367
  char* tbase = CMFAIL;
3364
  size_t tsize = 0;
3368
  size_t tsize = 0;
3365
  flag_t mmap_flag = 0;
3369
  flag_t mmap_flag = 0;
3366
 
3370
 
3367
  init_mparams();
3371
  init_mparams();
3368
 
3372
 
3369
  /* Directly map large chunks */
3373
  /* Directly map large chunks */
3370
  if (use_mmap(m) && nb >= mparams.mmap_threshold) {
3374
  if (use_mmap(m) && nb >= mparams.mmap_threshold) {
3371
    void* mem = mmap_alloc(m, nb);
3375
    void* mem = mmap_alloc(m, nb);
3372
    if (mem != 0)
3376
    if (mem != 0)
3373
      return mem;
3377
      return mem;
3374
  }
3378
  }
3375
 
3379
 
3376
  /*
3380
  /*
3377
    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
3378
    least-preferred order):
3382
    least-preferred order):
3379
    1. A call to MORECORE that can normally contiguously extend memory.
3383
    1. A call to MORECORE that can normally contiguously extend memory.
3380
       (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
3384
       (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
3381
       or main space is mmapped or a previous contiguous call failed)
3385
       or main space is mmapped or a previous contiguous call failed)
3382
    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).
3383
       Note that under the default settings, if MORECORE is unable to
3387
       Note that under the default settings, if MORECORE is unable to
3384
       fulfill a request, and HAVE_MMAP is true, then mmap is
3388
       fulfill a request, and HAVE_MMAP is true, then mmap is
3385
       used as a noncontiguous system allocator. This is a useful backup
3389
       used as a noncontiguous system allocator. This is a useful backup
3386
       strategy for systems with holes in address spaces -- in this case
3390
       strategy for systems with holes in address spaces -- in this case
3387
       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
3388
       find space.
3392
       find space.
3389
    3. A call to MORECORE that cannot usually contiguously extend memory.
3393
    3. A call to MORECORE that cannot usually contiguously extend memory.
3390
       (disabled if not HAVE_MORECORE)
3394
       (disabled if not HAVE_MORECORE)
3391
  */
3395
  */
3392
 
3396
 
3393
  if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
3397
  if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
3394
    char* br = CMFAIL;
3398
    char* br = CMFAIL;
3395
    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);
3396
    size_t asize = 0;
3400
    size_t asize = 0;
3397
    ACQUIRE_MORECORE_LOCK();
3401
    ACQUIRE_MORECORE_LOCK();
3398
 
3402
 
3399
    if (ss == 0) {  /* First time through or recovery */
3403
    if (ss == 0) {  /* First time through or recovery */
3400
      char* base = (char*)CALL_MORECORE(0);
3404
      char* base = (char*)CALL_MORECORE(0);
3401
      if (base != CMFAIL) {
3405
      if (base != CMFAIL) {
3402
        asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
3406
        asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
3403
        /* Adjust to end on a page boundary */
3407
        /* Adjust to end on a page boundary */
3404
        if (!is_page_aligned(base))
3408
        if (!is_page_aligned(base))
3405
          asize += (page_align((size_t)base) - (size_t)base);
3409
          asize += (page_align((size_t)base) - (size_t)base);
3406
        /* 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 */
3407
        if (asize < HALF_MAX_SIZE_T &&
3411
        if (asize < HALF_MAX_SIZE_T &&
3408
            (br = (char*)(CALL_MORECORE(asize))) == base) {
3412
            (br = (char*)(CALL_MORECORE(asize))) == base) {
3409
          tbase = base;
3413
          tbase = base;
3410
          tsize = asize;
3414
          tsize = asize;
3411
        }
3415
        }
3412
      }
3416
      }
3413
    }
3417
    }
3414
    else {
3418
    else {
3415
      /* Subtract out existing available top space from MORECORE request. */
3419
      /* Subtract out existing available top space from MORECORE request. */
3416
      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);
3417
      /* Use mem here only if it did continuously extend old space */
3421
      /* Use mem here only if it did continuously extend old space */
3418
      if (asize < HALF_MAX_SIZE_T &&
3422
      if (asize < HALF_MAX_SIZE_T &&
3419
          (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
3423
          (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
3420
        tbase = br;
3424
        tbase = br;
3421
        tsize = asize;
3425
        tsize = asize;
3422
      }
3426
      }
3423
    }
3427
    }
3424
 
3428
 
3425
    if (tbase == CMFAIL) {    /* Cope with partial failure */
3429
    if (tbase == CMFAIL) {    /* Cope with partial failure */
3426
      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 */
3427
        if (asize < HALF_MAX_SIZE_T &&
3431
        if (asize < HALF_MAX_SIZE_T &&
3428
            asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
3432
            asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
3429
          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);
3430
          if (esize < HALF_MAX_SIZE_T) {
3434
          if (esize < HALF_MAX_SIZE_T) {
3431
            char* end = (char*)CALL_MORECORE(esize);
3435
            char* end = (char*)CALL_MORECORE(esize);
3432
            if (end != CMFAIL)
3436
            if (end != CMFAIL)
3433
              asize += esize;
3437
              asize += esize;
3434
            else {            /* Can't use; try to release */
3438
            else {            /* Can't use; try to release */
3435
#if 0 /* warning: statement with no effect */
3439
#if 0 /* warning: statement with no effect */
3436
              CALL_MORECORE(-asize);
3440
              CALL_MORECORE(-asize);
3437
#endif
3441
#endif
3438
              br = CMFAIL;
3442
              br = CMFAIL;
3439
            }
3443
            }
3440
          }
3444
          }
3441
        }
3445
        }
3442
      }
3446
      }
3443
      if (br != CMFAIL) {    /* Use the space we did get */
3447
      if (br != CMFAIL) {    /* Use the space we did get */
3444
        tbase = br;
3448
        tbase = br;
3445
        tsize = asize;
3449
        tsize = asize;
3446
      }
3450
      }
3447
      else
3451
      else
3448
        disable_contiguous(m); /* Don't try contiguous path in the future */
3452
        disable_contiguous(m); /* Don't try contiguous path in the future */
3449
    }
3453
    }
3450
 
3454
 
3451
    RELEASE_MORECORE_LOCK();
3455
    RELEASE_MORECORE_LOCK();
3452
  }
3456
  }
3453
 
3457
 
3454
  if (HAVE_MMAP && tbase == CMFAIL) {  /* Try MMAP */
3458
  if (HAVE_MMAP && tbase == CMFAIL) {  /* Try MMAP */
3455
    size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
3459
    size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
3456
    size_t rsize = granularity_align(req);
3460
    size_t rsize = granularity_align(req);
3457
    if (rsize > nb) { /* Fail if wraps around zero */
3461
    if (rsize > nb) { /* Fail if wraps around zero */
3458
      char* mp = (char*)(CALL_MMAP(rsize));
3462
      char* mp = (char*)(CALL_MMAP(rsize));
3459
      if (mp != CMFAIL) {
3463
      if (mp != CMFAIL) {
3460
        tbase = mp;
3464
        tbase = mp;
3461
        tsize = rsize;
3465
        tsize = rsize;
3462
        mmap_flag = IS_MMAPPED_BIT;
3466
        mmap_flag = IS_MMAPPED_BIT;
3463
      }
3467
      }
3464
    }
3468
    }
3465
  }
3469
  }
3466
 
3470
 
3467
  if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
3471
  if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
3468
    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);
3469
    if (asize < HALF_MAX_SIZE_T) {
3473
    if (asize < HALF_MAX_SIZE_T) {
3470
      char* br = CMFAIL;
3474
      char* br = CMFAIL;
3471
      char* end = CMFAIL;
3475
      char* end = CMFAIL;
3472
      ACQUIRE_MORECORE_LOCK();
3476
      ACQUIRE_MORECORE_LOCK();
3473
      br = (char*)(CALL_MORECORE(asize));
3477
      br = (char*)(CALL_MORECORE(asize));
3474
      end = (char*)(CALL_MORECORE(0));
3478
      end = (char*)(CALL_MORECORE(0));
3475
      RELEASE_MORECORE_LOCK();
3479
      RELEASE_MORECORE_LOCK();
3476
      if (br != CMFAIL && end != CMFAIL && br < end) {
3480
      if (br != CMFAIL && end != CMFAIL && br < end) {
3477
        size_t ssize = end - br;
3481
        size_t ssize = end - br;
3478
        if (ssize > nb + TOP_FOOT_SIZE) {
3482
        if (ssize > nb + TOP_FOOT_SIZE) {
3479
          tbase = br;
3483
          tbase = br;
3480
          tsize = ssize;
3484
          tsize = ssize;
3481
        }
3485
        }
3482
      }
3486
      }
3483
    }
3487
    }
3484
  }
3488
  }
3485
 
3489
 
3486
  if (tbase != CMFAIL) {
3490
  if (tbase != CMFAIL) {
3487
 
3491
 
3488
    if ((m->footprint += tsize) > m->max_footprint)
3492
    if ((m->footprint += tsize) > m->max_footprint)
3489
      m->max_footprint = m->footprint;
3493
      m->max_footprint = m->footprint;
3490
 
3494
 
3491
    if (!is_initialized(m)) { /* first-time initialization */
3495
    if (!is_initialized(m)) { /* first-time initialization */
3492
      m->seg.base = m->least_addr = tbase;
3496
      m->seg.base = m->least_addr = tbase;
3493
      m->seg.size = tsize;
3497
      m->seg.size = tsize;
3494
      m->seg.sflags = mmap_flag;
3498
      m->seg.sflags = mmap_flag;
3495
      m->magic = mparams.magic;
3499
      m->magic = mparams.magic;
3496
      init_bins(m);
3500
      init_bins(m);
3497
      if (is_global(m)) 
3501
      if (is_global(m)) 
3498
        init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
3502
        init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
3499
      else {
3503
      else {
3500
        /* Offset top by embedded malloc_state */
3504
        /* Offset top by embedded malloc_state */
3501
        mchunkptr mn = next_chunk(mem2chunk(m));
3505
        mchunkptr mn = next_chunk(mem2chunk(m));
3502
        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);
3503
      }
3507
      }
3504
    }
3508
    }
3505
 
3509
 
3506
    else {
3510
    else {
3507
      /* Try to merge with an existing segment */
3511
      /* Try to merge with an existing segment */
3508
      msegmentptr sp = &m->seg;
3512
      msegmentptr sp = &m->seg;
3509
      while (sp != 0 && tbase != sp->base + sp->size)
3513
      while (sp != 0 && tbase != sp->base + sp->size)
3510
        sp = sp->next;
3514
        sp = sp->next;
3511
      if (sp != 0 &&
3515
      if (sp != 0 &&
3512
          !is_extern_segment(sp) &&
3516
          !is_extern_segment(sp) &&
3513
          (sp->sflags & IS_MMAPPED_BIT) == mmap_flag &&
3517
          (sp->sflags & IS_MMAPPED_BIT) == mmap_flag &&
3514
          segment_holds(sp, m->top)) { /* append */
3518
          segment_holds(sp, m->top)) { /* append */
3515
        sp->size += tsize;
3519
        sp->size += tsize;
3516
        init_top(m, m->top, m->topsize + tsize);
3520
        init_top(m, m->top, m->topsize + tsize);
3517
      }
3521
      }
3518
      else {
3522
      else {
3519
        if (tbase < m->least_addr)
3523
        if (tbase < m->least_addr)
3520
          m->least_addr = tbase;
3524
          m->least_addr = tbase;
3521
        sp = &m->seg;
3525
        sp = &m->seg;
3522
        while (sp != 0 && sp->base != tbase + tsize)
3526
        while (sp != 0 && sp->base != tbase + tsize)
3523
          sp = sp->next;
3527
          sp = sp->next;
3524
        if (sp != 0 &&
3528
        if (sp != 0 &&
3525
            !is_extern_segment(sp) &&
3529
            !is_extern_segment(sp) &&
3526
            (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) {
3530
            (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) {
3527
          char* oldbase = sp->base;
3531
          char* oldbase = sp->base;
3528
          sp->base = tbase;
3532
          sp->base = tbase;
3529
          sp->size += tsize;
3533
          sp->size += tsize;
3530
          return prepend_alloc(m, tbase, oldbase, nb);
3534
          return prepend_alloc(m, tbase, oldbase, nb);
3531
        }
3535
        }
3532
        else
3536
        else
3533
          add_segment(m, tbase, tsize, mmap_flag);
3537
          add_segment(m, tbase, tsize, mmap_flag);
3534
      }
3538
      }
3535
    }
3539
    }
3536
 
3540
 
3537
    if (nb < m->topsize) { /* Allocate from new or extended top space */
3541
    if (nb < m->topsize) { /* Allocate from new or extended top space */
3538
      size_t rsize = m->topsize -= nb;
3542
      size_t rsize = m->topsize -= nb;
3539
      mchunkptr p = m->top;
3543
      mchunkptr p = m->top;
3540
      mchunkptr r = m->top = chunk_plus_offset(p, nb);
3544
      mchunkptr r = m->top = chunk_plus_offset(p, nb);
3541
      r->head = rsize | PINUSE_BIT;
3545
      r->head = rsize | PINUSE_BIT;
3542
      set_size_and_pinuse_of_inuse_chunk(m, p, nb);
3546
      set_size_and_pinuse_of_inuse_chunk(m, p, nb);
3543
      check_top_chunk(m, m->top);
3547
      check_top_chunk(m, m->top);
3544
      check_malloced_chunk(m, chunk2mem(p), nb);
3548
      check_malloced_chunk(m, chunk2mem(p), nb);
3545
      return chunk2mem(p);
3549
      return chunk2mem(p);
3546
    }
3550
    }
3547
  }
3551
  }
3548
 
3552
 
3549
  MALLOC_FAILURE_ACTION;
3553
  MALLOC_FAILURE_ACTION;
3550
  return 0;
3554
  return 0;
3551
}
3555
}
3552
 
3556
 
3553
/* -----------------------  system deallocation -------------------------- */
3557
/* -----------------------  system deallocation -------------------------- */
3554
 
3558
 
3555
/* 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 */
3556
static size_t release_unused_segments(mstate m) {
3560
static size_t release_unused_segments(mstate m) {
3557
  size_t released = 0;
3561
  size_t released = 0;
3558
  msegmentptr pred = &m->seg;
3562
  msegmentptr pred = &m->seg;
3559
  msegmentptr sp = pred->next;
3563
  msegmentptr sp = pred->next;
3560
  while (sp != 0) {
3564
  while (sp != 0) {
3561
    char* base = sp->base;
3565
    char* base = sp->base;
3562
    size_t size = sp->size;
3566
    size_t size = sp->size;
3563
    msegmentptr next = sp->next;
3567
    msegmentptr next = sp->next;
3564
    if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
3568
    if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
3565
      mchunkptr p = align_as_chunk(base);
3569
      mchunkptr p = align_as_chunk(base);
3566
      size_t psize = chunksize(p);
3570
      size_t psize = chunksize(p);
3567
      /* Can unmap if first chunk holds entire segment and not pinned */
3571
      /* Can unmap if first chunk holds entire segment and not pinned */
3568
      if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
3572
      if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
3569
        tchunkptr tp = (tchunkptr)p;
3573
        tchunkptr tp = (tchunkptr)p;
3570
        assert(segment_holds(sp, (char*)sp));
3574
        assert(segment_holds(sp, (char*)sp));
3571
        if (p == m->dv) {
3575
        if (p == m->dv) {
3572
          m->dv = 0;
3576
          m->dv = 0;
3573
          m->dvsize = 0;
3577
          m->dvsize = 0;
3574
        }
3578
        }
3575
        else {
3579
        else {
3576
          unlink_large_chunk(m, tp);
3580
          unlink_large_chunk(m, tp);
3577
        }
3581
        }
3578
        if (CALL_MUNMAP(base, size) == 0) {
3582
        if (CALL_MUNMAP(base, size) == 0) {
3579
          released += size;
3583
          released += size;
3580
          m->footprint -= size;
3584
          m->footprint -= size;
3581
          /* unlink obsoleted record */
3585
          /* unlink obsoleted record */
3582
          sp = pred;
3586
          sp = pred;
3583
          sp->next = next;
3587
          sp->next = next;
3584
        }
3588
        }
3585
        else { /* back out if cannot unmap */
3589
        else { /* back out if cannot unmap */
3586
          insert_large_chunk(m, tp, psize);
3590
          insert_large_chunk(m, tp, psize);
3587
        }
3591
        }
3588
      }
3592
      }
3589
    }
3593
    }
3590
    pred = sp;
3594
    pred = sp;
3591
    sp = next;
3595
    sp = next;
3592
  }
3596
  }
3593
  return released;
3597
  return released;
3594
}
3598
}
3595
 
3599
 
3596
static int sys_trim(mstate m, size_t pad) {
3600
static int sys_trim(mstate m, size_t pad) {
3597
  size_t released = 0;
3601
  size_t released = 0;
3598
  if (pad < MAX_REQUEST && is_initialized(m)) {
3602
  if (pad < MAX_REQUEST && is_initialized(m)) {
3599
    pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
3603
    pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
3600
 
3604
 
3601
    if (m->topsize > pad) {
3605
    if (m->topsize > pad) {
3602
      /* Shrink top space in granularity-size units, keeping at least one */
3606
      /* Shrink top space in granularity-size units, keeping at least one */
3603
      size_t unit = mparams.granularity;
3607
      size_t unit = mparams.granularity;
3604
      size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
3608
      size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
3605
                      SIZE_T_ONE) * unit;
3609
                      SIZE_T_ONE) * unit;
3606
      msegmentptr sp = segment_holding(m, (char*)m->top);
3610
      msegmentptr sp = segment_holding(m, (char*)m->top);
3607
 
3611
 
3608
      if (!is_extern_segment(sp)) {
3612
      if (!is_extern_segment(sp)) {
3609
        if (is_mmapped_segment(sp)) {
3613
        if (is_mmapped_segment(sp)) {
3610
          if (HAVE_MMAP &&
3614
          if (HAVE_MMAP &&
3611
              sp->size >= extra &&
3615
              sp->size >= extra &&
3612
              !has_segment_link(m, sp)) { /* can't shrink if pinned */
3616
              !has_segment_link(m, sp)) { /* can't shrink if pinned */
3613
            size_t newsize = sp->size - extra;
3617
            size_t newsize = sp->size - extra;
3614
            /* Prefer mremap, fall back to munmap */
3618
            /* Prefer mremap, fall back to munmap */
3615
            if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
3619
            if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
3616
                (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
3620
                (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
3617
              released = extra;
3621
              released = extra;
3618
            }
3622
            }
3619
          }
3623
          }
3620
        }
3624
        }
3621
        else if (HAVE_MORECORE) {
3625
        else if (HAVE_MORECORE) {
3622
          if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
3626
          if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
3623
            extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
3627
            extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
3624
          ACQUIRE_MORECORE_LOCK();
3628
          ACQUIRE_MORECORE_LOCK();
3625
          {
3629
          {
3626
            /* Make sure end of memory is where we last set it. */
3630
            /* Make sure end of memory is where we last set it. */
3627
            char* old_br = (char*)(CALL_MORECORE(0));
3631
            char* old_br = (char*)(CALL_MORECORE(0));
3628
            if (old_br == sp->base + sp->size) {
3632
            if (old_br == sp->base + sp->size) {
3629
              char* rel_br = (char*)(CALL_MORECORE(-extra));
3633
              char* rel_br = (char*)(CALL_MORECORE(-extra));
3630
              char* new_br = (char*)(CALL_MORECORE(0));
3634
              char* new_br = (char*)(CALL_MORECORE(0));
3631
              if (rel_br != CMFAIL && new_br < old_br)
3635
              if (rel_br != CMFAIL && new_br < old_br)
3632
                released = old_br - new_br;
3636
                released = old_br - new_br;
3633
            }
3637
            }
3634
          }
3638
          }
3635
          RELEASE_MORECORE_LOCK();
3639
          RELEASE_MORECORE_LOCK();
3636
        }
3640
        }
3637
      }
3641
      }
3638
 
3642
 
3639
      if (released != 0) {
3643
      if (released != 0) {
3640
        sp->size -= released;
3644
        sp->size -= released;
3641
        m->footprint -= released;
3645
        m->footprint -= released;
3642
        init_top(m, m->top, m->topsize - released);
3646
        init_top(m, m->top, m->topsize - released);
3643
        check_top_chunk(m, m->top);
3647
        check_top_chunk(m, m->top);
3644
      }
3648
      }
3645
    }
3649
    }
3646
 
3650
 
3647
    /* Unmap any unused mmapped segments */
3651
    /* Unmap any unused mmapped segments */
3648
    if (HAVE_MMAP) 
3652
    if (HAVE_MMAP) 
3649
      released += release_unused_segments(m);
3653
      released += release_unused_segments(m);
3650
 
3654
 
3651
    /* On failure, disable autotrim to avoid repeated failed future calls */
3655
    /* On failure, disable autotrim to avoid repeated failed future calls */
3652
    if (released == 0)
3656
    if (released == 0)
3653
      m->trim_check = MAX_SIZE_T;
3657
      m->trim_check = MAX_SIZE_T;
3654
  }
3658
  }
3655
 
3659
 
3656
  return (released != 0)? 1 : 0;
3660
  return (released != 0)? 1 : 0;
3657
}
3661
}
3658
 
3662
 
3659
/* ---------------------------- malloc support --------------------------- */
3663
/* ---------------------------- malloc support --------------------------- */
3660
 
3664
 
3661
/* 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 */
3662
static void* tmalloc_large(mstate m, size_t nb) {
3666
static void* tmalloc_large(mstate m, size_t nb) {
3663
  tchunkptr v = 0;
3667
  tchunkptr v = 0;
3664
  size_t rsize = -nb; /* Unsigned negation */
3668
  size_t rsize = -nb; /* Unsigned negation */
3665
  tchunkptr t;
3669
  tchunkptr t;
3666
  bindex_t idx;
3670
  bindex_t idx;
3667
  compute_tree_index(nb, idx);
3671
  compute_tree_index(nb, idx);
3668
 
3672
 
3669
  if ((t = *treebin_at(m, idx)) != 0) {
3673
  if ((t = *treebin_at(m, idx)) != 0) {
3670
    /* Traverse tree for this bin looking for node with size == nb */
3674
    /* Traverse tree for this bin looking for node with size == nb */
3671
    size_t sizebits = nb << leftshift_for_tree_index(idx);
3675
    size_t sizebits = nb << leftshift_for_tree_index(idx);
3672
    tchunkptr rst = 0;  /* The deepest untaken right subtree */
3676
    tchunkptr rst = 0;  /* The deepest untaken right subtree */
3673
    for (;;) {
3677
    for (;;) {
3674
      tchunkptr rt;
3678
      tchunkptr rt;
3675
      size_t trem = chunksize(t) - nb;
3679
      size_t trem = chunksize(t) - nb;
3676
      if (trem < rsize) {
3680
      if (trem < rsize) {
3677
        v = t;
3681
        v = t;
3678
        if ((rsize = trem) == 0)
3682
        if ((rsize = trem) == 0)
3679
          break;
3683
          break;
3680
      }
3684
      }
3681
      rt = t->child[1];
3685
      rt = t->child[1];
3682
      t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
3686
      t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
3683
      if (rt != 0 && rt != t)
3687
      if (rt != 0 && rt != t)
3684
        rst = rt;
3688
        rst = rt;
3685
      if (t == 0) {
3689
      if (t == 0) {
3686
        t = rst; /* set t to least subtree holding sizes > nb */
3690
        t = rst; /* set t to least subtree holding sizes > nb */
3687
        break;
3691
        break;
3688
      }
3692
      }
3689
      sizebits <<= 1;
3693
      sizebits <<= 1;
3690
    }
3694
    }
3691
  }
3695
  }
3692
 
3696
 
3693
  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 */
3694
    binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
3698
    binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
3695
    if (leftbits != 0) {
3699
    if (leftbits != 0) {
3696
      bindex_t i;
3700
      bindex_t i;
3697
      binmap_t leastbit = least_bit(leftbits);
3701
      binmap_t leastbit = least_bit(leftbits);
3698
      compute_bit2idx(leastbit, i);
3702
      compute_bit2idx(leastbit, i);
3699
      t = *treebin_at(m, i);
3703
      t = *treebin_at(m, i);
3700
    }
3704
    }
3701
  }
3705
  }
3702
 
3706
 
3703
  while (t != 0) { /* find smallest of tree or subtree */
3707
  while (t != 0) { /* find smallest of tree or subtree */
3704
    size_t trem = chunksize(t) - nb;
3708
    size_t trem = chunksize(t) - nb;
3705
    if (trem < rsize) {
3709
    if (trem < rsize) {
3706
      rsize = trem;
3710
      rsize = trem;
3707
      v = t;
3711
      v = t;
3708
    }
3712
    }
3709
    t = leftmost_child(t);
3713
    t = leftmost_child(t);
3710
  }
3714
  }
3711
 
3715
 
3712
  /*  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 */
3713
  if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
3717
  if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
3714
    if (RTCHECK(ok_address(m, v))) { /* split */
3718
    if (RTCHECK(ok_address(m, v))) { /* split */
3715
      mchunkptr r = chunk_plus_offset(v, nb);
3719
      mchunkptr r = chunk_plus_offset(v, nb);
3716
      assert(chunksize(v) == rsize + nb);
3720
      assert(chunksize(v) == rsize + nb);
3717
      if (RTCHECK(ok_next(v, r))) {
3721
      if (RTCHECK(ok_next(v, r))) {
3718
        unlink_large_chunk(m, v);
3722
        unlink_large_chunk(m, v);
3719
        if (rsize < MIN_CHUNK_SIZE)
3723
        if (rsize < MIN_CHUNK_SIZE)
3720
          set_inuse_and_pinuse(m, v, (rsize + nb));
3724
          set_inuse_and_pinuse(m, v, (rsize + nb));
3721
        else {
3725
        else {
3722
          set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3726
          set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3723
          set_size_and_pinuse_of_free_chunk(r, rsize);
3727
          set_size_and_pinuse_of_free_chunk(r, rsize);
3724
          insert_chunk(m, r, rsize);
3728
          insert_chunk(m, r, rsize);
3725
        }
3729
        }
3726
        return chunk2mem(v);
3730
        return chunk2mem(v);
3727
      }
3731
      }
3728
    }
3732
    }
3729
    CORRUPTION_ERROR_ACTION(m);
3733
    CORRUPTION_ERROR_ACTION(m);
3730
  }
3734
  }
3731
  return 0;
3735
  return 0;
3732
}
3736
}
3733
 
3737
 
3734
/* 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 */
3735
static void* tmalloc_small(mstate m, size_t nb) {
3739
static void* tmalloc_small(mstate m, size_t nb) {
3736
  tchunkptr t, v;
3740
  tchunkptr t, v;
3737
  size_t rsize;
3741
  size_t rsize;
3738
  bindex_t i;
3742
  bindex_t i;
3739
  binmap_t leastbit = least_bit(m->treemap);
3743
  binmap_t leastbit = least_bit(m->treemap);
3740
  compute_bit2idx(leastbit, i);
3744
  compute_bit2idx(leastbit, i);
3741
 
3745
 
3742
  v = t = *treebin_at(m, i);
3746
  v = t = *treebin_at(m, i);
3743
  rsize = chunksize(t) - nb;
3747
  rsize = chunksize(t) - nb;
3744
 
3748
 
3745
  while ((t = leftmost_child(t)) != 0) {
3749
  while ((t = leftmost_child(t)) != 0) {
3746
    size_t trem = chunksize(t) - nb;
3750
    size_t trem = chunksize(t) - nb;
3747
    if (trem < rsize) {
3751
    if (trem < rsize) {
3748
      rsize = trem;
3752
      rsize = trem;
3749
      v = t;
3753
      v = t;
3750
    }
3754
    }
3751
  }
3755
  }
3752
 
3756
 
3753
  if (RTCHECK(ok_address(m, v))) {
3757
  if (RTCHECK(ok_address(m, v))) {
3754
    mchunkptr r = chunk_plus_offset(v, nb);
3758
    mchunkptr r = chunk_plus_offset(v, nb);
3755
    assert(chunksize(v) == rsize + nb);
3759
    assert(chunksize(v) == rsize + nb);
3756
    if (RTCHECK(ok_next(v, r))) {
3760
    if (RTCHECK(ok_next(v, r))) {
3757
      unlink_large_chunk(m, v);
3761
      unlink_large_chunk(m, v);
3758
      if (rsize < MIN_CHUNK_SIZE)
3762
      if (rsize < MIN_CHUNK_SIZE)
3759
        set_inuse_and_pinuse(m, v, (rsize + nb));
3763
        set_inuse_and_pinuse(m, v, (rsize + nb));
3760
      else {
3764
      else {
3761
        set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3765
        set_size_and_pinuse_of_inuse_chunk(m, v, nb);
3762
        set_size_and_pinuse_of_free_chunk(r, rsize);
3766
        set_size_and_pinuse_of_free_chunk(r, rsize);
3763
        replace_dv(m, r, rsize);
3767
        replace_dv(m, r, rsize);
3764
      }
3768
      }
3765
      return chunk2mem(v);
3769
      return chunk2mem(v);
3766
    }
3770
    }
3767
  }
3771
  }
3768
 
3772
 
3769
  CORRUPTION_ERROR_ACTION(m);
3773
  CORRUPTION_ERROR_ACTION(m);
3770
  return 0;
3774
  return 0;
3771
}
3775
}
3772
 
3776
 
3773
/* --------------------------- realloc support --------------------------- */
3777
/* --------------------------- realloc support --------------------------- */
3774
 
3778
 
3775
static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
3779
static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
3776
  if (bytes >= MAX_REQUEST) {
3780
  if (bytes >= MAX_REQUEST) {
3777
    MALLOC_FAILURE_ACTION;
3781
    MALLOC_FAILURE_ACTION;
3778
    return 0;
3782
    return 0;
3779
  }
3783
  }
3780
  if (!PREACTION(m)) {
3784
  if (!PREACTION(m)) {
3781
    mchunkptr oldp = mem2chunk(oldmem);
3785
    mchunkptr oldp = mem2chunk(oldmem);
3782
    size_t oldsize = chunksize(oldp);
3786
    size_t oldsize = chunksize(oldp);
3783
    mchunkptr next = chunk_plus_offset(oldp, oldsize);
3787
    mchunkptr next = chunk_plus_offset(oldp, oldsize);
3784
    mchunkptr newp = 0;
3788
    mchunkptr newp = 0;
3785
    void* extra = 0;
3789
    void* extra = 0;
3786
 
3790
 
3787
    /* 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 */
3788
 
3792
 
3789
    if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
3793
    if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
3790
                ok_next(oldp, next) && ok_pinuse(next))) {
3794
                ok_next(oldp, next) && ok_pinuse(next))) {
3791
      size_t nb = request2size(bytes);
3795
      size_t nb = request2size(bytes);
3792
      if (is_mmapped(oldp))
3796
      if (is_mmapped(oldp))
3793
        newp = mmap_resize(m, oldp, nb);
3797
        newp = mmap_resize(m, oldp, nb);
3794
      else if (oldsize >= nb) { /* already big enough */
3798
      else if (oldsize >= nb) { /* already big enough */
3795
        size_t rsize = oldsize - nb;
3799
        size_t rsize = oldsize - nb;
3796
        newp = oldp;
3800
        newp = oldp;
3797
        if (rsize >= MIN_CHUNK_SIZE) {
3801
        if (rsize >= MIN_CHUNK_SIZE) {
3798
          mchunkptr remainder = chunk_plus_offset(newp, nb);
3802
          mchunkptr remainder = chunk_plus_offset(newp, nb);
3799
          set_inuse(m, newp, nb);
3803
          set_inuse(m, newp, nb);
3800
          set_inuse(m, remainder, rsize);
3804
          set_inuse(m, remainder, rsize);
3801
          extra = chunk2mem(remainder);
3805
          extra = chunk2mem(remainder);
3802
        }
3806
        }
3803
      }
3807
      }
3804
      else if (next == m->top && oldsize + m->topsize > nb) {
3808
      else if (next == m->top && oldsize + m->topsize > nb) {
3805
        /* Expand into top */
3809
        /* Expand into top */
3806
        size_t newsize = oldsize + m->topsize;
3810
        size_t newsize = oldsize + m->topsize;
3807
        size_t newtopsize = newsize - nb;
3811
        size_t newtopsize = newsize - nb;
3808
        mchunkptr newtop = chunk_plus_offset(oldp, nb);
3812
        mchunkptr newtop = chunk_plus_offset(oldp, nb);
3809
        set_inuse(m, oldp, nb);
3813
        set_inuse(m, oldp, nb);
3810
        newtop->head = newtopsize |PINUSE_BIT;
3814
        newtop->head = newtopsize |PINUSE_BIT;
3811
        m->top = newtop;
3815
        m->top = newtop;
3812
        m->topsize = newtopsize;
3816
        m->topsize = newtopsize;
3813
        newp = oldp;
3817
        newp = oldp;
3814
      }
3818
      }
3815
    }
3819
    }
3816
    else {
3820
    else {
3817
      USAGE_ERROR_ACTION(m, oldmem);
3821
      USAGE_ERROR_ACTION(m, oldmem);
3818
      POSTACTION(m);
3822
      POSTACTION(m);
3819
      return 0;
3823
      return 0;
3820
    }
3824
    }
3821
 
3825
 
3822
    POSTACTION(m);
3826
    POSTACTION(m);
3823
 
3827
 
3824
    if (newp != 0) {
3828
    if (newp != 0) {
3825
      if (extra != 0) {
3829
      if (extra != 0) {
3826
        internal_free(m, extra);
3830
        internal_free(m, extra);
3827
      }
3831
      }
3828
      check_inuse_chunk(m, newp);
3832
      check_inuse_chunk(m, newp);
3829
      return chunk2mem(newp);
3833
      return chunk2mem(newp);
3830
    }
3834
    }
3831
    else {
3835
    else {
3832
      void* newmem = internal_malloc(m, bytes);
3836
      void* newmem = internal_malloc(m, bytes);
3833
      if (newmem != 0) {
3837
      if (newmem != 0) {
3834
        size_t oc = oldsize - overhead_for(oldp);
3838
        size_t oc = oldsize - overhead_for(oldp);
3835
        memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
3839
        memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
3836
        internal_free(m, oldmem);
3840
        internal_free(m, oldmem);
3837
      }
3841
      }
3838
      return newmem;
3842
      return newmem;
3839
    }
3843
    }
3840
  }
3844
  }
3841
  return 0;
3845
  return 0;
3842
}
3846
}
3843
 
3847
 
3844
/* --------------------------- memalign support -------------------------- */
3848
/* --------------------------- memalign support -------------------------- */
3845
 
3849
 
-
 
3850
#if 0
3846
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) {
3847
  if (alignment <= MALLOC_ALIGNMENT)    /* Can just use malloc */
3852
  if (alignment <= MALLOC_ALIGNMENT)    /* Can just use malloc */
3848
    return internal_malloc(m, bytes);
3853
    return internal_malloc(m, bytes);
3849
  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 */
3850
    alignment = MIN_CHUNK_SIZE;
3855
    alignment = MIN_CHUNK_SIZE;
3851
  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 */
3852
    size_t a = MALLOC_ALIGNMENT << 1;
3857
    size_t a = MALLOC_ALIGNMENT << 1;
3853
    while (a < alignment) a <<= 1;
3858
    while (a < alignment) a <<= 1;
3854
    alignment = a;
3859
    alignment = a;
3855
  }
3860
  }
3856
  
3861
  
3857
  if (bytes >= MAX_REQUEST - alignment) {
3862
  if (bytes >= MAX_REQUEST - alignment) {
3858
    if (m != 0)  { /* Test isn't needed but avoids compiler warning */
3863
    if (m != 0)  { /* Test isn't needed but avoids compiler warning */
3859
      MALLOC_FAILURE_ACTION;
3864
      MALLOC_FAILURE_ACTION;
3860
    }
3865
    }
3861
  }
3866
  }
3862
  else {
3867
  else {
3863
    size_t nb = request2size(bytes);
3868
    size_t nb = request2size(bytes);
3864
    size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
3869
    size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
3865
    char* mem = (char*)internal_malloc(m, req);
3870
    char* mem = (char*)internal_malloc(m, req);
3866
    if (mem != 0) {
3871
    if (mem != 0) {
3867
      void* leader = 0;
3872
      void* leader = 0;
3868
      void* trailer = 0;
3873
      void* trailer = 0;
3869
      mchunkptr p = mem2chunk(mem);
3874
      mchunkptr p = mem2chunk(mem);
3870
 
3875
 
3871
      if (PREACTION(m)) return 0;
3876
      if (PREACTION(m)) return 0;
3872
      if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
3877
      if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
3873
        /*
3878
        /*
3874
          Find an aligned spot inside chunk.  Since we need to give
3879
          Find an aligned spot inside chunk.  Since we need to give
3875
          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
3876
          the first calculation places us at a spot with less than
3881
          the first calculation places us at a spot with less than
3877
          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.
3878
          We've allocated enough total room so that this is always
3883
          We've allocated enough total room so that this is always
3879
          possible.
3884
          possible.
3880
        */
3885
        */
3881
        char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
3886
        char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
3882
                                                       alignment -
3887
                                                       alignment -
3883
                                                       SIZE_T_ONE)) &
3888
                                                       SIZE_T_ONE)) &
3884
                                             -alignment));
3889
                                             -alignment));
3885
        char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
3890
        char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
3886
          br : br+alignment;
3891
          br : br+alignment;
3887
        mchunkptr newp = (mchunkptr)pos;
3892
        mchunkptr newp = (mchunkptr)pos;
3888
        size_t leadsize = pos - (char*)(p);
3893
        size_t leadsize = pos - (char*)(p);
3889
        size_t newsize = chunksize(p) - leadsize;
3894
        size_t newsize = chunksize(p) - leadsize;
3890
 
3895
 
3891
        if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
3896
        if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
3892
          newp->prev_foot = p->prev_foot + leadsize;
3897
          newp->prev_foot = p->prev_foot + leadsize;
3893
          newp->head = (newsize|CINUSE_BIT);
3898
          newp->head = (newsize|CINUSE_BIT);
3894
        }
3899
        }
3895
        else { /* Otherwise, give back leader, use the rest */
3900
        else { /* Otherwise, give back leader, use the rest */
3896
          set_inuse(m, newp, newsize);
3901
          set_inuse(m, newp, newsize);
3897
          set_inuse(m, p, leadsize);
3902
          set_inuse(m, p, leadsize);
3898
          leader = chunk2mem(p);
3903
          leader = chunk2mem(p);
3899
        }
3904
        }
3900
        p = newp;
3905
        p = newp;
3901
      }
3906
      }
3902
 
3907
 
3903
      /* Give back spare room at the end */
3908
      /* Give back spare room at the end */
3904
      if (!is_mmapped(p)) {
3909
      if (!is_mmapped(p)) {
3905
        size_t size = chunksize(p);
3910
        size_t size = chunksize(p);
3906
        if (size > nb + MIN_CHUNK_SIZE) {
3911
        if (size > nb + MIN_CHUNK_SIZE) {
3907
          size_t remainder_size = size - nb;
3912
          size_t remainder_size = size - nb;
3908
          mchunkptr remainder = chunk_plus_offset(p, nb);
3913
          mchunkptr remainder = chunk_plus_offset(p, nb);
3909
          set_inuse(m, p, nb);
3914
          set_inuse(m, p, nb);
3910
          set_inuse(m, remainder, remainder_size);
3915
          set_inuse(m, remainder, remainder_size);
3911
          trailer = chunk2mem(remainder);
3916
          trailer = chunk2mem(remainder);
3912
        }
3917
        }
3913
      }
3918
      }
3914
 
3919
 
3915
      assert (chunksize(p) >= nb);
3920
      assert (chunksize(p) >= nb);
3916
      assert((((size_t)(chunk2mem(p))) % alignment) == 0);
3921
      assert((((size_t)(chunk2mem(p))) % alignment) == 0);
3917
      check_inuse_chunk(m, p);
3922
      check_inuse_chunk(m, p);
3918
      POSTACTION(m);
3923
      POSTACTION(m);
3919
      if (leader != 0) {
3924
      if (leader != 0) {
3920
        internal_free(m, leader);
3925
        internal_free(m, leader);
3921
      }
3926
      }
3922
      if (trailer != 0) {
3927
      if (trailer != 0) {
3923
        internal_free(m, trailer);
3928
        internal_free(m, trailer);
3924
      }
3929
      }
3925
      return chunk2mem(p);
3930
      return chunk2mem(p);
3926
    }
3931
    }
3927
  }
3932
  }
3928
  return 0;
3933
  return 0;
3929
}
3934
}
3930
 
3935
 
3931
/* ------------------------ comalloc/coalloc support --------------------- */
3936
/* ------------------------ comalloc/coalloc support --------------------- */
3932
 
3937
 
3933
static void** ialloc(mstate m,
3938
static void** ialloc(mstate m,
3934
                     size_t n_elements,
3939
                     size_t n_elements,
3935
                     size_t* sizes,
3940
                     size_t* sizes,
3936
                     int opts,
3941
                     int opts,
3937
                     void* chunks[]) {
3942
                     void* chunks[]) {
3938
  /*
3943
  /*
3939
    This provides common support for independent_X routines, handling
3944
    This provides common support for independent_X routines, handling
3940
    all of the combinations that can result.
3945
    all of the combinations that can result.
3941
 
3946
 
3942
    The opts arg has:
3947
    The opts arg has:
3943
    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])
3944
    bit 1 set if elements should be zeroed
3949
    bit 1 set if elements should be zeroed
3945
  */
3950
  */
3946
 
3951
 
3947
  size_t    element_size;   /* chunksize of each element, if all same */
3952
  size_t    element_size;   /* chunksize of each element, if all same */
3948
  size_t    contents_size;  /* total size of elements */
3953
  size_t    contents_size;  /* total size of elements */
3949
  size_t    array_size;     /* request size of pointer array */
3954
  size_t    array_size;     /* request size of pointer array */
3950
  void*     mem;            /* malloced aggregate space */
3955
  void*     mem;            /* malloced aggregate space */
3951
  mchunkptr p;              /* corresponding chunk */
3956
  mchunkptr p;              /* corresponding chunk */
3952
  size_t    remainder_size; /* remaining bytes while splitting */
3957
  size_t    remainder_size; /* remaining bytes while splitting */
3953
  void**    marray;         /* either "chunks" or malloced ptr array */
3958
  void**    marray;         /* either "chunks" or malloced ptr array */
3954
  mchunkptr array_chunk;    /* chunk for malloced ptr array */
3959
  mchunkptr array_chunk;    /* chunk for malloced ptr array */
3955
  flag_t    was_enabled;    /* to disable mmap */
3960
  flag_t    was_enabled;    /* to disable mmap */
3956
  size_t    size;
3961
  size_t    size;
3957
  size_t    i;
3962
  size_t    i;
3958
 
3963
 
3959
  /* compute array length, if needed */
3964
  /* compute array length, if needed */
3960
  if (chunks != 0) {
3965
  if (chunks != 0) {
3961
    if (n_elements == 0)
3966
    if (n_elements == 0)
3962
      return chunks; /* nothing to do */
3967
      return chunks; /* nothing to do */
3963
    marray = chunks;
3968
    marray = chunks;
3964
    array_size = 0;
3969
    array_size = 0;
3965
  }
3970
  }
3966
  else {
3971
  else {
3967
    /* if empty req, must still return chunk representing empty array */
3972
    /* if empty req, must still return chunk representing empty array */
3968
    if (n_elements == 0)
3973
    if (n_elements == 0)
3969
      return (void**)internal_malloc(m, 0);
3974
      return (void**)internal_malloc(m, 0);
3970
    marray = 0;
3975
    marray = 0;
3971
    array_size = request2size(n_elements * (sizeof(void*)));
3976
    array_size = request2size(n_elements * (sizeof(void*)));
3972
  }
3977
  }
3973
 
3978
 
3974
  /* compute total element size */
3979
  /* compute total element size */
3975
  if (opts & 0x1) { /* all-same-size */
3980
  if (opts & 0x1) { /* all-same-size */
3976
    element_size = request2size(*sizes);
3981
    element_size = request2size(*sizes);
3977
    contents_size = n_elements * element_size;
3982
    contents_size = n_elements * element_size;
3978
  }
3983
  }
3979
  else { /* add up all the sizes */
3984
  else { /* add up all the sizes */
3980
    element_size = 0;
3985
    element_size = 0;
3981
    contents_size = 0;
3986
    contents_size = 0;
3982
    for (i = 0; i != n_elements; ++i)
3987
    for (i = 0; i != n_elements; ++i)
3983
      contents_size += request2size(sizes[i]);
3988
      contents_size += request2size(sizes[i]);
3984
  }
3989
  }
3985
 
3990
 
3986
  size = contents_size + array_size;
3991
  size = contents_size + array_size;
3987
 
3992
 
3988
  /*
3993
  /*
3989
     Allocate the aggregate chunk.  First disable direct-mmapping so
3994
     Allocate the aggregate chunk.  First disable direct-mmapping so
3990
     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
3991
     free/realloc space internal to a segregated mmap region.
3996
     free/realloc space internal to a segregated mmap region.
3992
  */
3997
  */
3993
  was_enabled = use_mmap(m);
3998
  was_enabled = use_mmap(m);
3994
  disable_mmap(m);
3999
  disable_mmap(m);
3995
  mem = internal_malloc(m, size - CHUNK_OVERHEAD);
4000
  mem = internal_malloc(m, size - CHUNK_OVERHEAD);
3996
  if (was_enabled)
4001
  if (was_enabled)
3997
    enable_mmap(m);
4002
    enable_mmap(m);
3998
  if (mem == 0)
4003
  if (mem == 0)
3999
    return 0;
4004
    return 0;
4000
 
4005
 
4001
  if (PREACTION(m)) return 0;
4006
  if (PREACTION(m)) return 0;
4002
  p = mem2chunk(mem);
4007
  p = mem2chunk(mem);
4003
  remainder_size = chunksize(p);
4008
  remainder_size = chunksize(p);
4004
 
4009
 
4005
  assert(!is_mmapped(p));
4010
  assert(!is_mmapped(p));
4006
 
4011
 
4007
  if (opts & 0x2) {       /* optionally clear the elements */
4012
  if (opts & 0x2) {       /* optionally clear the elements */
4008
    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);
4009
  }
4014
  }
4010
 
4015
 
4011
  /* 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 */
4012
  if (marray == 0) {
4017
  if (marray == 0) {
4013
    size_t  array_chunk_size;
4018
    size_t  array_chunk_size;
4014
    array_chunk = chunk_plus_offset(p, contents_size);
4019
    array_chunk = chunk_plus_offset(p, contents_size);
4015
    array_chunk_size = remainder_size - contents_size;
4020
    array_chunk_size = remainder_size - contents_size;
4016
    marray = (void**) (chunk2mem(array_chunk));
4021
    marray = (void**) (chunk2mem(array_chunk));
4017
    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);
4018
    remainder_size = contents_size;
4023
    remainder_size = contents_size;
4019
  }
4024
  }
4020
 
4025
 
4021
  /* split out elements */
4026
  /* split out elements */
4022
  for (i = 0; ; ++i) {
4027
  for (i = 0; ; ++i) {
4023
    marray[i] = chunk2mem(p);
4028
    marray[i] = chunk2mem(p);
4024
    if (i != n_elements-1) {
4029
    if (i != n_elements-1) {
4025
      if (element_size != 0)
4030
      if (element_size != 0)
4026
        size = element_size;
4031
        size = element_size;
4027
      else
4032
      else
4028
        size = request2size(sizes[i]);
4033
        size = request2size(sizes[i]);
4029
      remainder_size -= size;
4034
      remainder_size -= size;
4030
      set_size_and_pinuse_of_inuse_chunk(m, p, size);
4035
      set_size_and_pinuse_of_inuse_chunk(m, p, size);
4031
      p = chunk_plus_offset(p, size);
4036
      p = chunk_plus_offset(p, size);
4032
    }
4037
    }
4033
    else { /* the final element absorbs any overallocation slop */
4038
    else { /* the final element absorbs any overallocation slop */
4034
      set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
4039
      set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
4035
      break;
4040
      break;
4036
    }
4041
    }
4037
  }
4042
  }
4038
 
4043
 
4039
#if DEBUG
4044
#if DEBUG
4040
  if (marray != chunks) {
4045
  if (marray != chunks) {
4041
    /* final element must have exactly exhausted chunk */
4046
    /* final element must have exactly exhausted chunk */
4042
    if (element_size != 0) {
4047
    if (element_size != 0) {
4043
      assert(remainder_size == element_size);
4048
      assert(remainder_size == element_size);
4044
    }
4049
    }
4045
    else {
4050
    else {
4046
      assert(remainder_size == request2size(sizes[i]));
4051
      assert(remainder_size == request2size(sizes[i]));
4047
    }
4052
    }
4048
    check_inuse_chunk(m, mem2chunk(marray));
4053
    check_inuse_chunk(m, mem2chunk(marray));
4049
  }
4054
  }
4050
  for (i = 0; i != n_elements; ++i)
4055
  for (i = 0; i != n_elements; ++i)
4051
    check_inuse_chunk(m, mem2chunk(marray[i]));
4056
    check_inuse_chunk(m, mem2chunk(marray[i]));
4052
 
4057
 
4053
#endif /* DEBUG */
4058
#endif /* DEBUG */
4054
 
4059
 
4055
  POSTACTION(m);
4060
  POSTACTION(m);
4056
  return marray;
4061
  return marray;
4057
}
4062
}
4058
 
4063
#endif
4059
 
4064
 
4060
/* -------------------------- public routines ---------------------------- */
4065
/* -------------------------- public routines ---------------------------- */
4061
 
4066
 
4062
#if !ONLY_MSPACES
4067
#if !ONLY_MSPACES
4063
 
4068
 
4064
void* dlmalloc(size_t bytes) {
4069
void* dlmalloc(size_t bytes) {
4065
  /*
4070
  /*
4066
     Basic algorithm:
4071
     Basic algorithm:
4067
     If a small request (< 256 bytes minus per-chunk overhead):
4072
     If a small request (< 256 bytes minus per-chunk overhead):
4068
       1. If one exists, use a remainderless chunk in associated smallbin.
4073
       1. If one exists, use a remainderless chunk in associated smallbin.
4069
          (Remainderless means that there are too few excess bytes to
4074
          (Remainderless means that there are too few excess bytes to
4070
          represent as a chunk.)
4075
          represent as a chunk.)
4071
       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
4072
          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.
4073
       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,
4074
          saving remainder in dv.
4079
          saving remainder in dv.
4075
       4. If it is big enough, use the top chunk.
4080
       4. If it is big enough, use the top chunk.
4076
       5. If available, get memory from system and use it
4081
       5. If available, get memory from system and use it
4077
     Otherwise, for a large request:
4082
     Otherwise, for a large request:
4078
       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
4079
          if it is better fitting than dv chunk, splitting if necessary.
4084
          if it is better fitting than dv chunk, splitting if necessary.
4080
       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.
4081
       3. If it is big enough, use the top chunk.
4086
       3. If it is big enough, use the top chunk.
4082
       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.
4083
       5. If available, get memory from system and use it
4088
       5. If available, get memory from system and use it
4084
 
4089
 
4085
     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.
4086
  */
4091
  */
4087
 
4092
 
4088
  if (!PREACTION(gm)) {
4093
  if (!PREACTION(gm)) {
4089
    void* mem;
4094
    void* mem;
4090
    size_t nb;
4095
    size_t nb;
4091
    if (bytes <= MAX_SMALL_REQUEST) {
4096
    if (bytes <= MAX_SMALL_REQUEST) {
4092
      bindex_t idx;
4097
      bindex_t idx;
4093
      binmap_t smallbits;
4098
      binmap_t smallbits;
4094
      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
4099
      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
4095
      idx = small_index(nb);
4100
      idx = small_index(nb);
4096
      smallbits = gm->smallmap >> idx;
4101
      smallbits = gm->smallmap >> idx;
4097
 
4102
 
4098
      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
4103
      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
4099
        mchunkptr b, p;
4104
        mchunkptr b, p;
4100
        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
4105
        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
4101
        b = smallbin_at(gm, idx);
4106
        b = smallbin_at(gm, idx);
4102
        p = b->fd;
4107
        p = b->fd;
4103
        assert(chunksize(p) == small_index2size(idx));
4108
        assert(chunksize(p) == small_index2size(idx));
4104
        unlink_first_small_chunk(gm, b, p, idx);
4109
        unlink_first_small_chunk(gm, b, p, idx);
4105
        set_inuse_and_pinuse(gm, p, small_index2size(idx));
4110
        set_inuse_and_pinuse(gm, p, small_index2size(idx));
4106
        mem = chunk2mem(p);
4111
        mem = chunk2mem(p);
4107
        check_malloced_chunk(gm, mem, nb);
4112
        check_malloced_chunk(gm, mem, nb);
4108
        goto postaction;
4113
        goto postaction;
4109
      }
4114
      }
4110
 
4115
 
4111
      else if (nb > gm->dvsize) {
4116
      else if (nb > gm->dvsize) {
4112
        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
4117
        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
4113
          mchunkptr b, p, r;
4118
          mchunkptr b, p, r;
4114
          size_t rsize;
4119
          size_t rsize;
4115
          bindex_t i;
4120
          bindex_t i;
4116
          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
4121
          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
4117
          binmap_t leastbit = least_bit(leftbits);
4122
          binmap_t leastbit = least_bit(leftbits);
4118
          compute_bit2idx(leastbit, i);
4123
          compute_bit2idx(leastbit, i);
4119
          b = smallbin_at(gm, i);
4124
          b = smallbin_at(gm, i);
4120
          p = b->fd;
4125
          p = b->fd;
4121
          assert(chunksize(p) == small_index2size(i));
4126
          assert(chunksize(p) == small_index2size(i));
4122
          unlink_first_small_chunk(gm, b, p, i);
4127
          unlink_first_small_chunk(gm, b, p, i);
4123
          rsize = small_index2size(i) - nb;
4128
          rsize = small_index2size(i) - nb;
4124
          /* Fit here cannot be remainderless if 4byte sizes */
4129
          /* Fit here cannot be remainderless if 4byte sizes */
4125
          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
4130
          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
4126
            set_inuse_and_pinuse(gm, p, small_index2size(i));
4131
            set_inuse_and_pinuse(gm, p, small_index2size(i));
4127
          else {
4132
          else {
4128
            set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4133
            set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4129
            r = chunk_plus_offset(p, nb);
4134
            r = chunk_plus_offset(p, nb);
4130
            set_size_and_pinuse_of_free_chunk(r, rsize);
4135
            set_size_and_pinuse_of_free_chunk(r, rsize);
4131
            replace_dv(gm, r, rsize);
4136
            replace_dv(gm, r, rsize);
4132
          }
4137
          }
4133
          mem = chunk2mem(p);
4138
          mem = chunk2mem(p);
4134
          check_malloced_chunk(gm, mem, nb);
4139
          check_malloced_chunk(gm, mem, nb);
4135
          goto postaction;
4140
          goto postaction;
4136
        }
4141
        }
4137
 
4142
 
4138
        else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
4143
        else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
4139
          check_malloced_chunk(gm, mem, nb);
4144
          check_malloced_chunk(gm, mem, nb);
4140
          goto postaction;
4145
          goto postaction;
4141
        }
4146
        }
4142
      }
4147
      }
4143
    }
4148
    }
4144
    else if (bytes >= MAX_REQUEST)
4149
    else if (bytes >= MAX_REQUEST)
4145
      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) */
4146
    else {
4151
    else {
4147
      nb = pad_request(bytes);
4152
      nb = pad_request(bytes);
4148
      if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
4153
      if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
4149
        check_malloced_chunk(gm, mem, nb);
4154
        check_malloced_chunk(gm, mem, nb);
4150
        goto postaction;
4155
        goto postaction;
4151
      }
4156
      }
4152
    }
4157
    }
4153
 
4158
 
4154
    if (nb <= gm->dvsize) {
4159
    if (nb <= gm->dvsize) {
4155
      size_t rsize = gm->dvsize - nb;
4160
      size_t rsize = gm->dvsize - nb;
4156
      mchunkptr p = gm->dv;
4161
      mchunkptr p = gm->dv;
4157
      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
4162
      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
4158
        mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
4163
        mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
4159
        gm->dvsize = rsize;
4164
        gm->dvsize = rsize;
4160
        set_size_and_pinuse_of_free_chunk(r, rsize);
4165
        set_size_and_pinuse_of_free_chunk(r, rsize);
4161
        set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4166
        set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4162
      }
4167
      }
4163
      else { /* exhaust dv */
4168
      else { /* exhaust dv */
4164
        size_t dvs = gm->dvsize;
4169
        size_t dvs = gm->dvsize;
4165
        gm->dvsize = 0;
4170
        gm->dvsize = 0;
4166
        gm->dv = 0;
4171
        gm->dv = 0;
4167
        set_inuse_and_pinuse(gm, p, dvs);
4172
        set_inuse_and_pinuse(gm, p, dvs);
4168
      }
4173
      }
4169
      mem = chunk2mem(p);
4174
      mem = chunk2mem(p);
4170
      check_malloced_chunk(gm, mem, nb);
4175
      check_malloced_chunk(gm, mem, nb);
4171
      goto postaction;
4176
      goto postaction;
4172
    }
4177
    }
4173
 
4178
 
4174
    else if (nb < gm->topsize) { /* Split top */
4179
    else if (nb < gm->topsize) { /* Split top */
4175
      size_t rsize = gm->topsize -= nb;
4180
      size_t rsize = gm->topsize -= nb;
4176
      mchunkptr p = gm->top;
4181
      mchunkptr p = gm->top;
4177
      mchunkptr r = gm->top = chunk_plus_offset(p, nb);
4182
      mchunkptr r = gm->top = chunk_plus_offset(p, nb);
4178
      r->head = rsize | PINUSE_BIT;
4183
      r->head = rsize | PINUSE_BIT;
4179
      set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4184
      set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
4180
      mem = chunk2mem(p);
4185
      mem = chunk2mem(p);
4181
      check_top_chunk(gm, gm->top);
4186
      check_top_chunk(gm, gm->top);
4182
      check_malloced_chunk(gm, mem, nb);
4187
      check_malloced_chunk(gm, mem, nb);
4183
      goto postaction;
4188
      goto postaction;
4184
    }
4189
    }
4185
 
4190
 
4186
    mem = sys_alloc(gm, nb);
4191
    mem = sys_alloc(gm, nb);
4187
 
4192
 
4188
  postaction:
4193
  postaction:
4189
    POSTACTION(gm);
4194
    POSTACTION(gm);
4190
    return mem;
4195
    return mem;
4191
  }
4196
  }
4192
 
4197
 
4193
  return 0;
4198
  return 0;
4194
}
4199
}
4195
 
4200
 
4196
void dlfree(void* mem) {
4201
void dlfree(void* mem) {
4197
  /*
4202
  /*
4198
     Consolidate freed chunks with preceeding or succeeding bordering
4203
     Consolidate freed chunks with preceeding or succeeding bordering
4199
     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
4200
     with special cases for top, dv, mmapped chunks, and usage errors.
4205
     with special cases for top, dv, mmapped chunks, and usage errors.
4201
  */
4206
  */
4202
 
4207
 
4203
  if (mem != 0) {
4208
  if (mem != 0) {
4204
    mchunkptr p  = mem2chunk(mem);
4209
    mchunkptr p  = mem2chunk(mem);
4205
#if FOOTERS
4210
#if FOOTERS
4206
    mstate fm = get_mstate_for(p);
4211
    mstate fm = get_mstate_for(p);
4207
    if (!ok_magic(fm)) {
4212
    if (!ok_magic(fm)) {
4208
      USAGE_ERROR_ACTION(fm, p);
4213
      USAGE_ERROR_ACTION(fm, p);
4209
      return;
4214
      return;
4210
    }
4215
    }
4211
#else /* FOOTERS */
4216
#else /* FOOTERS */
4212
#define fm gm
4217
#define fm gm
4213
#endif /* FOOTERS */
4218
#endif /* FOOTERS */
4214
    if (!PREACTION(fm)) {
4219
    if (!PREACTION(fm)) {
4215
      check_inuse_chunk(fm, p);
4220
      check_inuse_chunk(fm, p);
4216
      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
4221
      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
4217
        size_t psize = chunksize(p);
4222
        size_t psize = chunksize(p);
4218
        mchunkptr next = chunk_plus_offset(p, psize);
4223
        mchunkptr next = chunk_plus_offset(p, psize);
4219
        if (!pinuse(p)) {
4224
        if (!pinuse(p)) {
4220
          size_t prevsize = p->prev_foot;
4225
          size_t prevsize = p->prev_foot;
4221
          if ((prevsize & IS_MMAPPED_BIT) != 0) {
4226
          if ((prevsize & IS_MMAPPED_BIT) != 0) {
4222
            prevsize &= ~IS_MMAPPED_BIT;
4227
            prevsize &= ~IS_MMAPPED_BIT;
4223
            psize += prevsize + MMAP_FOOT_PAD;
4228
            psize += prevsize + MMAP_FOOT_PAD;
4224
            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
4229
            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
4225
              fm->footprint -= psize;
4230
              fm->footprint -= psize;
4226
            goto postaction;
4231
            goto postaction;
4227
          }
4232
          }
4228
          else {
4233
          else {
4229
            mchunkptr prev = chunk_minus_offset(p, prevsize);
4234
            mchunkptr prev = chunk_minus_offset(p, prevsize);
4230
            psize += prevsize;
4235
            psize += prevsize;
4231
            p = prev;
4236
            p = prev;
4232
            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
4237
            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
4233
              if (p != fm->dv) {
4238
              if (p != fm->dv) {
4234
                unlink_chunk(fm, p, prevsize);
4239
                unlink_chunk(fm, p, prevsize);
4235
              }
4240
              }
4236
              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
4241
              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
4237
                fm->dvsize = psize;
4242
                fm->dvsize = psize;
4238
                set_free_with_pinuse(p, psize, next);
4243
                set_free_with_pinuse(p, psize, next);
4239
                goto postaction;
4244
                goto postaction;
4240
              }
4245
              }
4241
            }
4246
            }
4242
            else
4247
            else
4243
              goto erroraction;
4248
              goto erroraction;
4244
          }
4249
          }
4245
        }
4250
        }
4246
 
4251
 
4247
        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
4252
        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
4248
          if (!cinuse(next)) {  /* consolidate forward */
4253
          if (!cinuse(next)) {  /* consolidate forward */
4249
            if (next == fm->top) {
4254
            if (next == fm->top) {
4250
              size_t tsize = fm->topsize += psize;
4255
              size_t tsize = fm->topsize += psize;
4251
              fm->top = p;
4256
              fm->top = p;
4252
              p->head = tsize | PINUSE_BIT;
4257
              p->head = tsize | PINUSE_BIT;
4253
              if (p == fm->dv) {
4258
              if (p == fm->dv) {
4254
                fm->dv = 0;
4259
                fm->dv = 0;
4255
                fm->dvsize = 0;
4260
                fm->dvsize = 0;
4256
              }
4261
              }
4257
              if (should_trim(fm, tsize))
4262
              if (should_trim(fm, tsize))
4258
                sys_trim(fm, 0);
4263
                sys_trim(fm, 0);
4259
              goto postaction;
4264
              goto postaction;
4260
            }
4265
            }
4261
            else if (next == fm->dv) {
4266
            else if (next == fm->dv) {
4262
              size_t dsize = fm->dvsize += psize;
4267
              size_t dsize = fm->dvsize += psize;
4263
              fm->dv = p;
4268
              fm->dv = p;
4264
              set_size_and_pinuse_of_free_chunk(p, dsize);
4269
              set_size_and_pinuse_of_free_chunk(p, dsize);
4265
              goto postaction;
4270
              goto postaction;
4266
            }
4271
            }
4267
            else {
4272
            else {
4268
              size_t nsize = chunksize(next);
4273
              size_t nsize = chunksize(next);
4269
              psize += nsize;
4274
              psize += nsize;
4270
              unlink_chunk(fm, next, nsize);
4275
              unlink_chunk(fm, next, nsize);
4271
              set_size_and_pinuse_of_free_chunk(p, psize);
4276
              set_size_and_pinuse_of_free_chunk(p, psize);
4272
              if (p == fm->dv) {
4277
              if (p == fm->dv) {
4273
                fm->dvsize = psize;
4278
                fm->dvsize = psize;
4274
                goto postaction;
4279
                goto postaction;
4275
              }
4280
              }
4276
            }
4281
            }
4277
          }
4282
          }
4278
          else
4283
          else
4279
            set_free_with_pinuse(p, psize, next);
4284
            set_free_with_pinuse(p, psize, next);
4280
          insert_chunk(fm, p, psize);
4285
          insert_chunk(fm, p, psize);
4281
          check_free_chunk(fm, p);
4286
          check_free_chunk(fm, p);
4282
          goto postaction;
4287
          goto postaction;
4283
        }
4288
        }
4284
      }
4289
      }
4285
    erroraction:
4290
    erroraction:
4286
      USAGE_ERROR_ACTION(fm, p);
4291
      USAGE_ERROR_ACTION(fm, p);
4287
    postaction:
4292
    postaction:
4288
      POSTACTION(fm);
4293
      POSTACTION(fm);
4289
    }
4294
    }
4290
  }
4295
  }
4291
#if !FOOTERS
4296
#if !FOOTERS
4292
#undef fm
4297
#undef fm
4293
#endif /* FOOTERS */
4298
#endif /* FOOTERS */
4294
}
4299
}
4295
 
4300
 
4296
void* dlcalloc(size_t n_elements, size_t elem_size) {
4301
void* dlcalloc(size_t n_elements, size_t elem_size) {
4297
  void* mem;
4302
  void* mem;
4298
  size_t req = 0;
4303
  size_t req = 0;
4299
  if (n_elements != 0) {
4304
  if (n_elements != 0) {
4300
    req = n_elements * elem_size;
4305
    req = n_elements * elem_size;
4301
    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
4306
    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
4302
        (req / n_elements != elem_size))
4307
        (req / n_elements != elem_size))
4303
      req = MAX_SIZE_T; /* force downstream failure on overflow */
4308
      req = MAX_SIZE_T; /* force downstream failure on overflow */
4304
  }
4309
  }
4305
  mem = dlmalloc(req);
4310
  mem = dlmalloc(req);
4306
  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
4311
  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
4307
    memset(mem, 0, req);
4312
    memset(mem, 0, req);
4308
  return mem;
4313
  return mem;
4309
}
4314
}
4310
 
4315
 
4311
void* dlrealloc(void* oldmem, size_t bytes) {
4316
void* dlrealloc(void* oldmem, size_t bytes) {
4312
  if (oldmem == 0)
4317
  if (oldmem == 0)
4313
    return dlmalloc(bytes);
4318
    return dlmalloc(bytes);
4314
#ifdef REALLOC_ZERO_BYTES_FREES
4319
#ifdef REALLOC_ZERO_BYTES_FREES
4315
  if (bytes == 0) {
4320
  if (bytes == 0) {
4316
    dlfree(oldmem);
4321
    dlfree(oldmem);
4317
    return 0;
4322
    return 0;
4318
  }
4323
  }
4319
#endif /* REALLOC_ZERO_BYTES_FREES */
4324
#endif /* REALLOC_ZERO_BYTES_FREES */
4320
  else {
4325
  else {
4321
#if ! FOOTERS
4326
#if ! FOOTERS
4322
    mstate m = gm;
4327
    mstate m = gm;
4323
#else /* FOOTERS */
4328
#else /* FOOTERS */
4324
    mstate m = get_mstate_for(mem2chunk(oldmem));
4329
    mstate m = get_mstate_for(mem2chunk(oldmem));
4325
    if (!ok_magic(m)) {
4330
    if (!ok_magic(m)) {
4326
      USAGE_ERROR_ACTION(m, oldmem);
4331
      USAGE_ERROR_ACTION(m, oldmem);
4327
      return 0;
4332
      return 0;
4328
    }
4333
    }
4329
#endif /* FOOTERS */
4334
#endif /* FOOTERS */
4330
    return internal_realloc(m, oldmem, bytes);
4335
    return internal_realloc(m, oldmem, bytes);
4331
  }
4336
  }
4332
}
4337
}
4333
 
4338
 
-
 
4339
#if 0
4334
void* dlmemalign(size_t alignment, size_t bytes) {
4340
void* dlmemalign(size_t alignment, size_t bytes) {
4335
  return internal_memalign(gm, alignment, bytes);
4341
  return internal_memalign(gm, alignment, bytes);
4336
}
4342
}
4337
 
4343
 
4338
void** dlindependent_calloc(size_t n_elements, size_t elem_size,
4344
void** dlindependent_calloc(size_t n_elements, size_t elem_size,
4339
                                 void* chunks[]) {
4345
                                 void* chunks[]) {
4340
  size_t sz = elem_size; /* serves as 1-element array */
4346
  size_t sz = elem_size; /* serves as 1-element array */
4341
  return ialloc(gm, n_elements, &sz, 3, chunks);
4347
  return ialloc(gm, n_elements, &sz, 3, chunks);
4342
}
4348
}
4343
 
4349
 
4344
void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
4350
void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
4345
                                   void* chunks[]) {
4351
                                   void* chunks[]) {
4346
  return ialloc(gm, n_elements, sizes, 0, chunks);
4352
  return ialloc(gm, n_elements, sizes, 0, chunks);
4347
}
4353
}
4348
 
4354
 
4349
void* dlvalloc(size_t bytes) {
4355
void* dlvalloc(size_t bytes) {
4350
  size_t pagesz;
4356
  size_t pagesz;
4351
  init_mparams();
4357
  init_mparams();
4352
  pagesz = mparams.page_size;
4358
  pagesz = mparams.page_size;
4353
  return dlmemalign(pagesz, bytes);
4359
  return dlmemalign(pagesz, bytes);
4354
}
4360
}
4355
 
4361
 
4356
void* dlpvalloc(size_t bytes) {
4362
void* dlpvalloc(size_t bytes) {
4357
  size_t pagesz;
4363
  size_t pagesz;
4358
  init_mparams();
4364
  init_mparams();
4359
  pagesz = mparams.page_size;
4365
  pagesz = mparams.page_size;
4360
  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));
4361
}
4367
}
4362
 
4368
 
4363
int dlmalloc_trim(size_t pad) {
4369
int dlmalloc_trim(size_t pad) {
4364
  int result = 0;
4370
  int result = 0;
4365
  if (!PREACTION(gm)) {
4371
  if (!PREACTION(gm)) {
4366
    result = sys_trim(gm, pad);
4372
    result = sys_trim(gm, pad);
4367
    POSTACTION(gm);
4373
    POSTACTION(gm);
4368
  }
4374
  }
4369
  return result;
4375
  return result;
4370
}
4376
}
4371
 
4377
 
4372
size_t dlmalloc_footprint(void) {
4378
size_t dlmalloc_footprint(void) {
4373
  return gm->footprint;
4379
  return gm->footprint;
4374
}
4380
}
4375
 
4381
 
4376
size_t dlmalloc_max_footprint(void) {
4382
size_t dlmalloc_max_footprint(void) {
4377
  return gm->max_footprint;
4383
  return gm->max_footprint;
4378
}
4384
}
-
 
4385
#endif
4379
 
4386
 
4380
#if !NO_MALLINFO
4387
#if !NO_MALLINFO
4381
struct mallinfo dlmallinfo(void) {
4388
struct mallinfo dlmallinfo(void) {
4382
  return internal_mallinfo(gm);
4389
  return internal_mallinfo(gm);
4383
}
4390
}
4384
#endif /* NO_MALLINFO */
4391
#endif /* NO_MALLINFO */
4385
 
4392
 
-
 
4393
#if 0
4386
void dlmalloc_stats() {
4394
void dlmalloc_stats() {
4387
  internal_malloc_stats(gm);
4395
  internal_malloc_stats(gm);
4388
}
4396
}
4389
 
4397
 
4390
size_t dlmalloc_usable_size(void* mem) {
4398
size_t dlmalloc_usable_size(void* mem) {
4391
  if (mem != 0) {
4399
  if (mem != 0) {
4392
    mchunkptr p = mem2chunk(mem);
4400
    mchunkptr p = mem2chunk(mem);
4393
    if (cinuse(p))
4401
    if (cinuse(p))
4394
      return chunksize(p) - overhead_for(p);
4402
      return chunksize(p) - overhead_for(p);
4395
  }
4403
  }
4396
  return 0;
4404
  return 0;
4397
}
4405
}
4398
 
4406
 
4399
int dlmallopt(int param_number, int value) {
4407
int dlmallopt(int param_number, int value) {
4400
  return change_mparam(param_number, value);
4408
  return change_mparam(param_number, value);
4401
}
4409
}
-
 
4410
#endif
4402
 
4411
 
4403
#endif /* !ONLY_MSPACES */
4412
#endif /* !ONLY_MSPACES */
4404
 
4413
 
4405
/* ----------------------------- user mspaces ---------------------------- */
4414
/* ----------------------------- user mspaces ---------------------------- */
4406
 
4415
 
4407
#if MSPACES
4416
#if MSPACES
4408
 
4417
 
4409
static mstate init_user_mstate(char* tbase, size_t tsize) {
4418
static mstate init_user_mstate(char* tbase, size_t tsize) {
4410
  size_t msize = pad_request(sizeof(struct malloc_state));
4419
  size_t msize = pad_request(sizeof(struct malloc_state));
4411
  mchunkptr mn;
4420
  mchunkptr mn;
4412
  mchunkptr msp = align_as_chunk(tbase);
4421
  mchunkptr msp = align_as_chunk(tbase);
4413
  mstate m = (mstate)(chunk2mem(msp));
4422
  mstate m = (mstate)(chunk2mem(msp));
4414
  memset(m, 0, msize);
4423
  memset(m, 0, msize);
4415
  INITIAL_LOCK(&m->mutex);
4424
  INITIAL_LOCK(&m->mutex);
4416
  msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
4425
  msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
4417
  m->seg.base = m->least_addr = tbase;
4426
  m->seg.base = m->least_addr = tbase;
4418
  m->seg.size = m->footprint = m->max_footprint = tsize;
4427
  m->seg.size = m->footprint = m->max_footprint = tsize;
4419
  m->magic = mparams.magic;
4428
  m->magic = mparams.magic;
4420
  m->mflags = mparams.default_mflags;
4429
  m->mflags = mparams.default_mflags;
4421
  disable_contiguous(m);
4430
  disable_contiguous(m);
4422
  init_bins(m);
4431
  init_bins(m);
4423
  mn = next_chunk(mem2chunk(m));
4432
  mn = next_chunk(mem2chunk(m));
4424
  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);
4425
  check_top_chunk(m, m->top);
4434
  check_top_chunk(m, m->top);
4426
  return m;
4435
  return m;
4427
}
4436
}
4428
 
4437
 
4429
mspace create_mspace(size_t capacity, int locked) {
4438
mspace create_mspace(size_t capacity, int locked) {
4430
  mstate m = 0;
4439
  mstate m = 0;
4431
  size_t msize = pad_request(sizeof(struct malloc_state));
4440
  size_t msize = pad_request(sizeof(struct malloc_state));
4432
  init_mparams(); /* Ensure pagesize etc initialized */
4441
  init_mparams(); /* Ensure pagesize etc initialized */
4433
 
4442
 
4434
  if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4443
  if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4435
    size_t rs = ((capacity == 0)? mparams.granularity :
4444
    size_t rs = ((capacity == 0)? mparams.granularity :
4436
                 (capacity + TOP_FOOT_SIZE + msize));
4445
                 (capacity + TOP_FOOT_SIZE + msize));
4437
    size_t tsize = granularity_align(rs);
4446
    size_t tsize = granularity_align(rs);
4438
    char* tbase = (char*)(CALL_MMAP(tsize));
4447
    char* tbase = (char*)(CALL_MMAP(tsize));
4439
    if (tbase != CMFAIL) {
4448
    if (tbase != CMFAIL) {
4440
      m = init_user_mstate(tbase, tsize);
4449
      m = init_user_mstate(tbase, tsize);
4441
      m->seg.sflags = IS_MMAPPED_BIT;
4450
      m->seg.sflags = IS_MMAPPED_BIT;
4442
      set_lock(m, locked);
4451
      set_lock(m, locked);
4443
    }
4452
    }
4444
  }
4453
  }
4445
  return (mspace)m;
4454
  return (mspace)m;
4446
}
4455
}
4447
 
4456
 
4448
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) {
4449
  mstate m = 0;
4458
  mstate m = 0;
4450
  size_t msize = pad_request(sizeof(struct malloc_state));
4459
  size_t msize = pad_request(sizeof(struct malloc_state));
4451
  init_mparams(); /* Ensure pagesize etc initialized */
4460
  init_mparams(); /* Ensure pagesize etc initialized */
4452
 
4461
 
4453
  if (capacity > msize + TOP_FOOT_SIZE &&
4462
  if (capacity > msize + TOP_FOOT_SIZE &&
4454
      capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4463
      capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
4455
    m = init_user_mstate((char*)base, capacity);
4464
    m = init_user_mstate((char*)base, capacity);
4456
    m->seg.sflags = EXTERN_BIT;
4465
    m->seg.sflags = EXTERN_BIT;
4457
    set_lock(m, locked);
4466
    set_lock(m, locked);
4458
  }
4467
  }
4459
  return (mspace)m;
4468
  return (mspace)m;
4460
}
4469
}
4461
 
4470
 
4462
size_t destroy_mspace(mspace msp) {
4471
size_t destroy_mspace(mspace msp) {
4463
  size_t freed = 0;
4472
  size_t freed = 0;
4464
  mstate ms = (mstate)msp;
4473
  mstate ms = (mstate)msp;
4465
  if (ok_magic(ms)) {
4474
  if (ok_magic(ms)) {
4466
    msegmentptr sp = &ms->seg;
4475
    msegmentptr sp = &ms->seg;
4467
    while (sp != 0) {
4476
    while (sp != 0) {
4468
      char* base = sp->base;
4477
      char* base = sp->base;
4469
      size_t size = sp->size;
4478
      size_t size = sp->size;
4470
      flag_t flag = sp->sflags;
4479
      flag_t flag = sp->sflags;
4471
      sp = sp->next;
4480
      sp = sp->next;
4472
      if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
4481
      if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
4473
          CALL_MUNMAP(base, size) == 0)
4482
          CALL_MUNMAP(base, size) == 0)
4474
        freed += size;
4483
        freed += size;
4475
    }
4484
    }
4476
  }
4485
  }
4477
  else {
4486
  else {
4478
    USAGE_ERROR_ACTION(ms,ms);
4487
    USAGE_ERROR_ACTION(ms,ms);
4479
  }
4488
  }
4480
  return freed;
4489
  return freed;
4481
}
4490
}
4482
 
4491
 
4483
/*
4492
/*
4484
  mspace versions of routines are near-clones of the global
4493
  mspace versions of routines are near-clones of the global
4485
  versions. This is not so nice but better than the alternatives.
4494
  versions. This is not so nice but better than the alternatives.
4486
*/
4495
*/
4487
 
4496
 
4488
 
4497
 
4489
void* mspace_malloc(mspace msp, size_t bytes) {
4498
void* mspace_malloc(mspace msp, size_t bytes) {
4490
  mstate ms = (mstate)msp;
4499
  mstate ms = (mstate)msp;
4491
  if (!ok_magic(ms)) {
4500
  if (!ok_magic(ms)) {
4492
    USAGE_ERROR_ACTION(ms,ms);
4501
    USAGE_ERROR_ACTION(ms,ms);
4493
    return 0;
4502
    return 0;
4494
  }
4503
  }
4495
  if (!PREACTION(ms)) {
4504
  if (!PREACTION(ms)) {
4496
    void* mem;
4505
    void* mem;
4497
    size_t nb;
4506
    size_t nb;
4498
    if (bytes <= MAX_SMALL_REQUEST) {
4507
    if (bytes <= MAX_SMALL_REQUEST) {
4499
      bindex_t idx;
4508
      bindex_t idx;
4500
      binmap_t smallbits;
4509
      binmap_t smallbits;
4501
      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
4510
      nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
4502
      idx = small_index(nb);
4511
      idx = small_index(nb);
4503
      smallbits = ms->smallmap >> idx;
4512
      smallbits = ms->smallmap >> idx;
4504
 
4513
 
4505
      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
4514
      if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
4506
        mchunkptr b, p;
4515
        mchunkptr b, p;
4507
        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
4516
        idx += ~smallbits & 1;       /* Uses next bin if idx empty */
4508
        b = smallbin_at(ms, idx);
4517
        b = smallbin_at(ms, idx);
4509
        p = b->fd;
4518
        p = b->fd;
4510
        assert(chunksize(p) == small_index2size(idx));
4519
        assert(chunksize(p) == small_index2size(idx));
4511
        unlink_first_small_chunk(ms, b, p, idx);
4520
        unlink_first_small_chunk(ms, b, p, idx);
4512
        set_inuse_and_pinuse(ms, p, small_index2size(idx));
4521
        set_inuse_and_pinuse(ms, p, small_index2size(idx));
4513
        mem = chunk2mem(p);
4522
        mem = chunk2mem(p);
4514
        check_malloced_chunk(ms, mem, nb);
4523
        check_malloced_chunk(ms, mem, nb);
4515
        goto postaction;
4524
        goto postaction;
4516
      }
4525
      }
4517
 
4526
 
4518
      else if (nb > ms->dvsize) {
4527
      else if (nb > ms->dvsize) {
4519
        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
4528
        if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
4520
          mchunkptr b, p, r;
4529
          mchunkptr b, p, r;
4521
          size_t rsize;
4530
          size_t rsize;
4522
          bindex_t i;
4531
          bindex_t i;
4523
          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
4532
          binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
4524
          binmap_t leastbit = least_bit(leftbits);
4533
          binmap_t leastbit = least_bit(leftbits);
4525
          compute_bit2idx(leastbit, i);
4534
          compute_bit2idx(leastbit, i);
4526
          b = smallbin_at(ms, i);
4535
          b = smallbin_at(ms, i);
4527
          p = b->fd;
4536
          p = b->fd;
4528
          assert(chunksize(p) == small_index2size(i));
4537
          assert(chunksize(p) == small_index2size(i));
4529
          unlink_first_small_chunk(ms, b, p, i);
4538
          unlink_first_small_chunk(ms, b, p, i);
4530
          rsize = small_index2size(i) - nb;
4539
          rsize = small_index2size(i) - nb;
4531
          /* Fit here cannot be remainderless if 4byte sizes */
4540
          /* Fit here cannot be remainderless if 4byte sizes */
4532
          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
4541
          if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
4533
            set_inuse_and_pinuse(ms, p, small_index2size(i));
4542
            set_inuse_and_pinuse(ms, p, small_index2size(i));
4534
          else {
4543
          else {
4535
            set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4544
            set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4536
            r = chunk_plus_offset(p, nb);
4545
            r = chunk_plus_offset(p, nb);
4537
            set_size_and_pinuse_of_free_chunk(r, rsize);
4546
            set_size_and_pinuse_of_free_chunk(r, rsize);
4538
            replace_dv(ms, r, rsize);
4547
            replace_dv(ms, r, rsize);
4539
          }
4548
          }
4540
          mem = chunk2mem(p);
4549
          mem = chunk2mem(p);
4541
          check_malloced_chunk(ms, mem, nb);
4550
          check_malloced_chunk(ms, mem, nb);
4542
          goto postaction;
4551
          goto postaction;
4543
        }
4552
        }
4544
 
4553
 
4545
        else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
4554
        else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
4546
          check_malloced_chunk(ms, mem, nb);
4555
          check_malloced_chunk(ms, mem, nb);
4547
          goto postaction;
4556
          goto postaction;
4548
        }
4557
        }
4549
      }
4558
      }
4550
    }
4559
    }
4551
    else if (bytes >= MAX_REQUEST)
4560
    else if (bytes >= MAX_REQUEST)
4552
      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) */
4553
    else {
4562
    else {
4554
      nb = pad_request(bytes);
4563
      nb = pad_request(bytes);
4555
      if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
4564
      if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
4556
        check_malloced_chunk(ms, mem, nb);
4565
        check_malloced_chunk(ms, mem, nb);
4557
        goto postaction;
4566
        goto postaction;
4558
      }
4567
      }
4559
    }
4568
    }
4560
 
4569
 
4561
    if (nb <= ms->dvsize) {
4570
    if (nb <= ms->dvsize) {
4562
      size_t rsize = ms->dvsize - nb;
4571
      size_t rsize = ms->dvsize - nb;
4563
      mchunkptr p = ms->dv;
4572
      mchunkptr p = ms->dv;
4564
      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
4573
      if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
4565
        mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
4574
        mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
4566
        ms->dvsize = rsize;
4575
        ms->dvsize = rsize;
4567
        set_size_and_pinuse_of_free_chunk(r, rsize);
4576
        set_size_and_pinuse_of_free_chunk(r, rsize);
4568
        set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4577
        set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4569
      }
4578
      }
4570
      else { /* exhaust dv */
4579
      else { /* exhaust dv */
4571
        size_t dvs = ms->dvsize;
4580
        size_t dvs = ms->dvsize;
4572
        ms->dvsize = 0;
4581
        ms->dvsize = 0;
4573
        ms->dv = 0;
4582
        ms->dv = 0;
4574
        set_inuse_and_pinuse(ms, p, dvs);
4583
        set_inuse_and_pinuse(ms, p, dvs);
4575
      }
4584
      }
4576
      mem = chunk2mem(p);
4585
      mem = chunk2mem(p);
4577
      check_malloced_chunk(ms, mem, nb);
4586
      check_malloced_chunk(ms, mem, nb);
4578
      goto postaction;
4587
      goto postaction;
4579
    }
4588
    }
4580
 
4589
 
4581
    else if (nb < ms->topsize) { /* Split top */
4590
    else if (nb < ms->topsize) { /* Split top */
4582
      size_t rsize = ms->topsize -= nb;
4591
      size_t rsize = ms->topsize -= nb;
4583
      mchunkptr p = ms->top;
4592
      mchunkptr p = ms->top;
4584
      mchunkptr r = ms->top = chunk_plus_offset(p, nb);
4593
      mchunkptr r = ms->top = chunk_plus_offset(p, nb);
4585
      r->head = rsize | PINUSE_BIT;
4594
      r->head = rsize | PINUSE_BIT;
4586
      set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4595
      set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
4587
      mem = chunk2mem(p);
4596
      mem = chunk2mem(p);
4588
      check_top_chunk(ms, ms->top);
4597
      check_top_chunk(ms, ms->top);
4589
      check_malloced_chunk(ms, mem, nb);
4598
      check_malloced_chunk(ms, mem, nb);
4590
      goto postaction;
4599
      goto postaction;
4591
    }
4600
    }
4592
 
4601
 
4593
    mem = sys_alloc(ms, nb);
4602
    mem = sys_alloc(ms, nb);
4594
 
4603
 
4595
  postaction:
4604
  postaction:
4596
    POSTACTION(ms);
4605
    POSTACTION(ms);
4597
    return mem;
4606
    return mem;
4598
  }
4607
  }
4599
 
4608
 
4600
  return 0;
4609
  return 0;
4601
}
4610
}
4602
 
4611
 
4603
void mspace_free(mspace msp, void* mem) {
4612
void mspace_free(mspace msp, void* mem) {
4604
  if (mem != 0) {
4613
  if (mem != 0) {
4605
    mchunkptr p  = mem2chunk(mem);
4614
    mchunkptr p  = mem2chunk(mem);
4606
#if FOOTERS
4615
#if FOOTERS
4607
    mstate fm = get_mstate_for(p);
4616
    mstate fm = get_mstate_for(p);
4608
#else /* FOOTERS */
4617
#else /* FOOTERS */
4609
    mstate fm = (mstate)msp;
4618
    mstate fm = (mstate)msp;
4610
#endif /* FOOTERS */
4619
#endif /* FOOTERS */
4611
    if (!ok_magic(fm)) {
4620
    if (!ok_magic(fm)) {
4612
      USAGE_ERROR_ACTION(fm, p);
4621
      USAGE_ERROR_ACTION(fm, p);
4613
      return;
4622
      return;
4614
    }
4623
    }
4615
    if (!PREACTION(fm)) {
4624
    if (!PREACTION(fm)) {
4616
      check_inuse_chunk(fm, p);
4625
      check_inuse_chunk(fm, p);
4617
      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
4626
      if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
4618
        size_t psize = chunksize(p);
4627
        size_t psize = chunksize(p);
4619
        mchunkptr next = chunk_plus_offset(p, psize);
4628
        mchunkptr next = chunk_plus_offset(p, psize);
4620
        if (!pinuse(p)) {
4629
        if (!pinuse(p)) {
4621
          size_t prevsize = p->prev_foot;
4630
          size_t prevsize = p->prev_foot;
4622
          if ((prevsize & IS_MMAPPED_BIT) != 0) {
4631
          if ((prevsize & IS_MMAPPED_BIT) != 0) {
4623
            prevsize &= ~IS_MMAPPED_BIT;
4632
            prevsize &= ~IS_MMAPPED_BIT;
4624
            psize += prevsize + MMAP_FOOT_PAD;
4633
            psize += prevsize + MMAP_FOOT_PAD;
4625
            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
4634
            if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
4626
              fm->footprint -= psize;
4635
              fm->footprint -= psize;
4627
            goto postaction;
4636
            goto postaction;
4628
          }
4637
          }
4629
          else {
4638
          else {
4630
            mchunkptr prev = chunk_minus_offset(p, prevsize);
4639
            mchunkptr prev = chunk_minus_offset(p, prevsize);
4631
            psize += prevsize;
4640
            psize += prevsize;
4632
            p = prev;
4641
            p = prev;
4633
            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
4642
            if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
4634
              if (p != fm->dv) {
4643
              if (p != fm->dv) {
4635
                unlink_chunk(fm, p, prevsize);
4644
                unlink_chunk(fm, p, prevsize);
4636
              }
4645
              }
4637
              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
4646
              else if ((next->head & INUSE_BITS) == INUSE_BITS) {
4638
                fm->dvsize = psize;
4647
                fm->dvsize = psize;
4639
                set_free_with_pinuse(p, psize, next);
4648
                set_free_with_pinuse(p, psize, next);
4640
                goto postaction;
4649
                goto postaction;
4641
              }
4650
              }
4642
            }
4651
            }
4643
            else
4652
            else
4644
              goto erroraction;
4653
              goto erroraction;
4645
          }
4654
          }
4646
        }
4655
        }
4647
 
4656
 
4648
        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
4657
        if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
4649
          if (!cinuse(next)) {  /* consolidate forward */
4658
          if (!cinuse(next)) {  /* consolidate forward */
4650
            if (next == fm->top) {
4659
            if (next == fm->top) {
4651
              size_t tsize = fm->topsize += psize;
4660
              size_t tsize = fm->topsize += psize;
4652
              fm->top = p;
4661
              fm->top = p;
4653
              p->head = tsize | PINUSE_BIT;
4662
              p->head = tsize | PINUSE_BIT;
4654
              if (p == fm->dv) {
4663
              if (p == fm->dv) {
4655
                fm->dv = 0;
4664
                fm->dv = 0;
4656
                fm->dvsize = 0;
4665
                fm->dvsize = 0;
4657
              }
4666
              }
4658
              if (should_trim(fm, tsize))
4667
              if (should_trim(fm, tsize))
4659
                sys_trim(fm, 0);
4668
                sys_trim(fm, 0);
4660
              goto postaction;
4669
              goto postaction;
4661
            }
4670
            }
4662
            else if (next == fm->dv) {
4671
            else if (next == fm->dv) {
4663
              size_t dsize = fm->dvsize += psize;
4672
              size_t dsize = fm->dvsize += psize;
4664
              fm->dv = p;
4673
              fm->dv = p;
4665
              set_size_and_pinuse_of_free_chunk(p, dsize);
4674
              set_size_and_pinuse_of_free_chunk(p, dsize);
4666
              goto postaction;
4675
              goto postaction;
4667
            }
4676
            }
4668
            else {
4677
            else {
4669
              size_t nsize = chunksize(next);
4678
              size_t nsize = chunksize(next);
4670
              psize += nsize;
4679
              psize += nsize;
4671
              unlink_chunk(fm, next, nsize);
4680
              unlink_chunk(fm, next, nsize);
4672
              set_size_and_pinuse_of_free_chunk(p, psize);
4681
              set_size_and_pinuse_of_free_chunk(p, psize);
4673
              if (p == fm->dv) {
4682
              if (p == fm->dv) {
4674
                fm->dvsize = psize;
4683
                fm->dvsize = psize;
4675
                goto postaction;
4684
                goto postaction;
4676
              }
4685
              }
4677
            }
4686
            }
4678
          }
4687
          }
4679
          else
4688
          else
4680
            set_free_with_pinuse(p, psize, next);
4689
            set_free_with_pinuse(p, psize, next);
4681
          insert_chunk(fm, p, psize);
4690
          insert_chunk(fm, p, psize);
4682
          check_free_chunk(fm, p);
4691
          check_free_chunk(fm, p);
4683
          goto postaction;
4692
          goto postaction;
4684
        }
4693
        }
4685
      }
4694
      }
4686
    erroraction:
4695
    erroraction:
4687
      USAGE_ERROR_ACTION(fm, p);
4696
      USAGE_ERROR_ACTION(fm, p);
4688
    postaction:
4697
    postaction:
4689
      POSTACTION(fm);
4698
      POSTACTION(fm);
4690
    }
4699
    }
4691
  }
4700
  }
4692
}
4701
}
4693
 
4702
 
4694
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) {
4695
  void* mem;
4704
  void* mem;
4696
  size_t req = 0;
4705
  size_t req = 0;
4697
  mstate ms = (mstate)msp;
4706
  mstate ms = (mstate)msp;
4698
  if (!ok_magic(ms)) {
4707
  if (!ok_magic(ms)) {
4699
    USAGE_ERROR_ACTION(ms,ms);
4708
    USAGE_ERROR_ACTION(ms,ms);
4700
    return 0;
4709
    return 0;
4701
  }
4710
  }
4702
  if (n_elements != 0) {
4711
  if (n_elements != 0) {
4703
    req = n_elements * elem_size;
4712
    req = n_elements * elem_size;
4704
    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
4713
    if (((n_elements | elem_size) & ~(size_t)0xffff) &&
4705
        (req / n_elements != elem_size))
4714
        (req / n_elements != elem_size))
4706
      req = MAX_SIZE_T; /* force downstream failure on overflow */
4715
      req = MAX_SIZE_T; /* force downstream failure on overflow */
4707
  }
4716
  }
4708
  mem = internal_malloc(ms, req);
4717
  mem = internal_malloc(ms, req);
4709
  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
4718
  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
4710
    memset(mem, 0, req);
4719
    memset(mem, 0, req);
4711
  return mem;
4720
  return mem;
4712
}
4721
}
4713
 
4722
 
4714
void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
4723
void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
4715
  if (oldmem == 0)
4724
  if (oldmem == 0)
4716
    return mspace_malloc(msp, bytes);
4725
    return mspace_malloc(msp, bytes);
4717
#ifdef REALLOC_ZERO_BYTES_FREES
4726
#ifdef REALLOC_ZERO_BYTES_FREES
4718
  if (bytes == 0) {
4727
  if (bytes == 0) {
4719
    mspace_free(msp, oldmem);
4728
    mspace_free(msp, oldmem);
4720
    return 0;
4729
    return 0;
4721
  }
4730
  }
4722
#endif /* REALLOC_ZERO_BYTES_FREES */
4731
#endif /* REALLOC_ZERO_BYTES_FREES */
4723
  else {
4732
  else {
4724
#if FOOTERS
4733
#if FOOTERS
4725
    mchunkptr p  = mem2chunk(oldmem);
4734
    mchunkptr p  = mem2chunk(oldmem);
4726
    mstate ms = get_mstate_for(p);
4735
    mstate ms = get_mstate_for(p);
4727
#else /* FOOTERS */
4736
#else /* FOOTERS */
4728
    mstate ms = (mstate)msp;
4737
    mstate ms = (mstate)msp;
4729
#endif /* FOOTERS */
4738
#endif /* FOOTERS */
4730
    if (!ok_magic(ms)) {
4739
    if (!ok_magic(ms)) {
4731
      USAGE_ERROR_ACTION(ms,ms);
4740
      USAGE_ERROR_ACTION(ms,ms);
4732
      return 0;
4741
      return 0;
4733
    }
4742
    }
4734
    return internal_realloc(ms, oldmem, bytes);
4743
    return internal_realloc(ms, oldmem, bytes);
4735
  }
4744
  }
4736
}
4745
}
4737
 
4746
 
4738
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
4747
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
4739
  mstate ms = (mstate)msp;
4748
  mstate ms = (mstate)msp;
4740
  if (!ok_magic(ms)) {
4749
  if (!ok_magic(ms)) {
4741
    USAGE_ERROR_ACTION(ms,ms);
4750
    USAGE_ERROR_ACTION(ms,ms);
4742
    return 0;
4751
    return 0;
4743
  }
4752
  }
4744
  return internal_memalign(ms, alignment, bytes);
4753
  return internal_memalign(ms, alignment, bytes);
4745
}
4754
}
4746
 
4755
 
4747
void** mspace_independent_calloc(mspace msp, size_t n_elements,
4756
void** mspace_independent_calloc(mspace msp, size_t n_elements,
4748
                                 size_t elem_size, void* chunks[]) {
4757
                                 size_t elem_size, void* chunks[]) {
4749
  size_t sz = elem_size; /* serves as 1-element array */
4758
  size_t sz = elem_size; /* serves as 1-element array */
4750
  mstate ms = (mstate)msp;
4759
  mstate ms = (mstate)msp;
4751
  if (!ok_magic(ms)) {
4760
  if (!ok_magic(ms)) {
4752
    USAGE_ERROR_ACTION(ms,ms);
4761
    USAGE_ERROR_ACTION(ms,ms);
4753
    return 0;
4762
    return 0;
4754
  }
4763
  }
4755
  return ialloc(ms, n_elements, &sz, 3, chunks);
4764
  return ialloc(ms, n_elements, &sz, 3, chunks);
4756
}
4765
}
4757
 
4766
 
4758
void** mspace_independent_comalloc(mspace msp, size_t n_elements,
4767
void** mspace_independent_comalloc(mspace msp, size_t n_elements,
4759
                                   size_t sizes[], void* chunks[]) {
4768
                                   size_t sizes[], void* chunks[]) {
4760
  mstate ms = (mstate)msp;
4769
  mstate ms = (mstate)msp;
4761
  if (!ok_magic(ms)) {
4770
  if (!ok_magic(ms)) {
4762
    USAGE_ERROR_ACTION(ms,ms);
4771
    USAGE_ERROR_ACTION(ms,ms);
4763
    return 0;
4772
    return 0;
4764
  }
4773
  }
4765
  return ialloc(ms, n_elements, sizes, 0, chunks);
4774
  return ialloc(ms, n_elements, sizes, 0, chunks);
4766
}
4775
}
4767
 
4776
 
4768
int mspace_trim(mspace msp, size_t pad) {
4777
int mspace_trim(mspace msp, size_t pad) {
4769
  int result = 0;
4778
  int result = 0;
4770
  mstate ms = (mstate)msp;
4779
  mstate ms = (mstate)msp;
4771
  if (ok_magic(ms)) {
4780
  if (ok_magic(ms)) {
4772
    if (!PREACTION(ms)) {
4781
    if (!PREACTION(ms)) {
4773
      result = sys_trim(ms, pad);
4782
      result = sys_trim(ms, pad);
4774
      POSTACTION(ms);
4783
      POSTACTION(ms);
4775
    }
4784
    }
4776
  }
4785
  }
4777
  else {
4786
  else {
4778
    USAGE_ERROR_ACTION(ms,ms);
4787
    USAGE_ERROR_ACTION(ms,ms);
4779
  }
4788
  }
4780
  return result;
4789
  return result;
4781
}
4790
}
4782
 
4791
 
4783
void mspace_malloc_stats(mspace msp) {
4792
void mspace_malloc_stats(mspace msp) {
4784
  mstate ms = (mstate)msp;
4793
  mstate ms = (mstate)msp;
4785
  if (ok_magic(ms)) {
4794
  if (ok_magic(ms)) {
4786
    internal_malloc_stats(ms);
4795
    internal_malloc_stats(ms);
4787
  }
4796
  }
4788
  else {
4797
  else {
4789
    USAGE_ERROR_ACTION(ms,ms);
4798
    USAGE_ERROR_ACTION(ms,ms);
4790
  }
4799
  }
4791
}
4800
}
4792
 
4801
 
4793
size_t mspace_footprint(mspace msp) {
4802
size_t mspace_footprint(mspace msp) {
4794
  size_t result;
4803
  size_t result;
4795
  mstate ms = (mstate)msp;
4804
  mstate ms = (mstate)msp;
4796
  if (ok_magic(ms)) {
4805
  if (ok_magic(ms)) {
4797
    result = ms->footprint;
4806
    result = ms->footprint;
4798
  }
4807
  }
4799
  USAGE_ERROR_ACTION(ms,ms);
4808
  USAGE_ERROR_ACTION(ms,ms);
4800
  return result;
4809
  return result;
4801
}
4810
}
4802
 
4811
 
4803
 
4812
 
4804
size_t mspace_max_footprint(mspace msp) {
4813
size_t mspace_max_footprint(mspace msp) {
4805
  size_t result;
4814
  size_t result;
4806
  mstate ms = (mstate)msp;
4815
  mstate ms = (mstate)msp;
4807
  if (ok_magic(ms)) {
4816
  if (ok_magic(ms)) {
4808
    result = ms->max_footprint;
4817
    result = ms->max_footprint;
4809
  }
4818
  }
4810
  USAGE_ERROR_ACTION(ms,ms);
4819
  USAGE_ERROR_ACTION(ms,ms);
4811
  return result;
4820
  return result;
4812
}
4821
}
4813
 
4822
 
4814
 
4823
 
4815
#if !NO_MALLINFO
4824
#if !NO_MALLINFO
4816
struct mallinfo mspace_mallinfo(mspace msp) {
4825
struct mallinfo mspace_mallinfo(mspace msp) {
4817
  mstate ms = (mstate)msp;
4826
  mstate ms = (mstate)msp;
4818
  if (!ok_magic(ms)) {
4827
  if (!ok_magic(ms)) {
4819
    USAGE_ERROR_ACTION(ms,ms);
4828
    USAGE_ERROR_ACTION(ms,ms);
4820
  }
4829
  }
4821
  return internal_mallinfo(ms);
4830
  return internal_mallinfo(ms);
4822
}
4831
}
4823
#endif /* NO_MALLINFO */
4832
#endif /* NO_MALLINFO */
4824
 
4833
 
4825
int mspace_mallopt(int param_number, int value) {
4834
int mspace_mallopt(int param_number, int value) {
4826
  return change_mparam(param_number, value);
4835
  return change_mparam(param_number, value);
4827
}
4836
}
4828
 
4837
 
4829
#endif /* MSPACES */
4838
#endif /* MSPACES */
4830
 
4839
 
4831
/* -------------------- Alternative MORECORE functions ------------------- */
4840
/* -------------------- Alternative MORECORE functions ------------------- */
4832
 
4841
 
4833
/*
4842
/*
4834
  Guidelines for creating a custom version of MORECORE:
4843
  Guidelines for creating a custom version of MORECORE:
4835
 
4844
 
4836
  * For best performance, MORECORE should allocate in multiples of pagesize.
4845
  * For best performance, MORECORE should allocate in multiples of pagesize.
4837
  * MORECORE may allocate more memory than requested. (Or even less,
4846
  * MORECORE may allocate more memory than requested. (Or even less,
4838
      but this will usually result in a malloc failure.)
4847
      but this will usually result in a malloc failure.)
4839
  * MORECORE must not allocate memory when given argument zero, but
4848
  * MORECORE must not allocate memory when given argument zero, but
4840
      instead return one past the end address of memory from previous
4849
      instead return one past the end address of memory from previous
4841
      nonzero call.
4850
      nonzero call.
4842
  * For best performance, consecutive calls to MORECORE with positive
4851
  * For best performance, consecutive calls to MORECORE with positive
4843
      arguments should return increasing addresses, indicating that
4852
      arguments should return increasing addresses, indicating that
4844
      space has been contiguously extended.
4853
      space has been contiguously extended.
4845
  * Even though consecutive calls to MORECORE need not return contiguous
4854
  * Even though consecutive calls to MORECORE need not return contiguous
4846
      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
4847
      regions in those cases where they do happen to be contiguous.
4856
      regions in those cases where they do happen to be contiguous.
4848
  * MORECORE need not handle negative arguments -- it may instead
4857
  * MORECORE need not handle negative arguments -- it may instead
4849
      just return MFAIL when given negative arguments.
4858
      just return MFAIL when given negative arguments.
4850
      Negative arguments are always multiples of pagesize. MORECORE
4859
      Negative arguments are always multiples of pagesize. MORECORE
4851
      must not misinterpret negative args as large positive unsigned
4860
      must not misinterpret negative args as large positive unsigned
4852
      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
4853
      MORECORE_CANNOT_TRIM,
4862
      MORECORE_CANNOT_TRIM,
4854
 
4863
 
4855
  As an example alternative MORECORE, here is a custom allocator
4864
  As an example alternative MORECORE, here is a custom allocator
4856
  kindly contributed for pre-OSX macOS.  It uses virtually but not
4865
  kindly contributed for pre-OSX macOS.  It uses virtually but not
4857
  necessarily physically contiguous non-paged memory (locked in,
4866
  necessarily physically contiguous non-paged memory (locked in,
4858
  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
4859
  this section, adding some #includes, and setting up the appropriate
4868
  this section, adding some #includes, and setting up the appropriate
4860
  defines above:
4869
  defines above:
4861
 
4870
 
4862
      #define MORECORE osMoreCore
4871
      #define MORECORE osMoreCore
4863
 
4872
 
4864
  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
4865
  cleanup upon program exit.
4874
  cleanup upon program exit.
4866
 
4875
 
4867
  #define MAX_POOL_ENTRIES 100
4876
  #define MAX_POOL_ENTRIES 100
4868
  #define MINIMUM_MORECORE_SIZE  (64 * 1024U)
4877
  #define MINIMUM_MORECORE_SIZE  (64 * 1024U)
4869
  static int next_os_pool;
4878
  static int next_os_pool;
4870
  void *our_os_pools[MAX_POOL_ENTRIES];
4879
  void *our_os_pools[MAX_POOL_ENTRIES];
4871
 
4880
 
4872
  void *osMoreCore(int size)
4881
  void *osMoreCore(int size)
4873
  {
4882
  {
4874
    void *ptr = 0;
4883
    void *ptr = 0;
4875
    static void *sbrk_top = 0;
4884
    static void *sbrk_top = 0;
4876
 
4885
 
4877
    if (size > 0)
4886
    if (size > 0)
4878
    {
4887
    {
4879
      if (size < MINIMUM_MORECORE_SIZE)
4888
      if (size < MINIMUM_MORECORE_SIZE)
4880
         size = MINIMUM_MORECORE_SIZE;
4889
         size = MINIMUM_MORECORE_SIZE;
4881
      if (CurrentExecutionLevel() == kTaskLevel)
4890
      if (CurrentExecutionLevel() == kTaskLevel)
4882
         ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
4891
         ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
4883
      if (ptr == 0)
4892
      if (ptr == 0)
4884
      {
4893
      {
4885
        return (void *) MFAIL;
4894
        return (void *) MFAIL;
4886
      }
4895
      }
4887
      // save ptrs so they can be freed during cleanup
4896
      // save ptrs so they can be freed during cleanup
4888
      our_os_pools[next_os_pool] = ptr;
4897
      our_os_pools[next_os_pool] = ptr;
4889
      next_os_pool++;
4898
      next_os_pool++;
4890
      ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
4899
      ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
4891
      sbrk_top = (char *) ptr + size;
4900
      sbrk_top = (char *) ptr + size;
4892
      return ptr;
4901
      return ptr;
4893
    }
4902
    }
4894
    else if (size < 0)
4903
    else if (size < 0)
4895
    {
4904
    {
4896
      // we don't currently support shrink behavior
4905
      // we don't currently support shrink behavior
4897
      return (void *) MFAIL;
4906
      return (void *) MFAIL;
4898
    }
4907
    }
4899
    else
4908
    else
4900
    {
4909
    {
4901
      return sbrk_top;
4910
      return sbrk_top;
4902
    }
4911
    }
4903
  }
4912
  }
4904
 
4913
 
4905
  // cleanup any allocated memory pools
4914
  // cleanup any allocated memory pools
4906
  // called as last thing before shutting down driver
4915
  // called as last thing before shutting down driver
4907
 
4916
 
4908
  void osCleanupMem(void)
4917
  void osCleanupMem(void)
4909
  {
4918
  {
4910
    void **ptr;
4919
    void **ptr;
4911
 
4920
 
4912
    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++)
4913
      if (*ptr)
4922
      if (*ptr)
4914
      {
4923
      {
4915
         PoolDeallocate(*ptr);
4924
         PoolDeallocate(*ptr);
4916
         *ptr = 0;
4925
         *ptr = 0;
4917
      }
4926
      }
4918
  }
4927
  }
4919
 
4928
 
4920
*/
4929
*/
4921
 
4930
 
4922
 
4931
 
4923
/* -----------------------------------------------------------------------
4932
/* -----------------------------------------------------------------------
4924
History:
4933
History:
4925
    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)
4926
      * Add max_footprint functions
4935
      * Add max_footprint functions
4927
      * Ensure all appropriate literals are size_t
4936
      * Ensure all appropriate literals are size_t
4928
      * Fix conditional compilation problem for some #define settings
4937
      * Fix conditional compilation problem for some #define settings
4929
      * Avoid concatenating segments with the one provided
4938
      * Avoid concatenating segments with the one provided
4930
        in create_mspace_with_base
4939
        in create_mspace_with_base
4931
      * Rename some variables to avoid compiler shadowing warnings
4940
      * Rename some variables to avoid compiler shadowing warnings
4932
      * Use explicit lock initialization.
4941
      * Use explicit lock initialization.
4933
      * Better handling of sbrk interference.
4942
      * Better handling of sbrk interference.
4934
      * Simplify and fix segment insertion, trimming and mspace_destroy
4943
      * Simplify and fix segment insertion, trimming and mspace_destroy
4935
      * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
4944
      * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
4936
      * Thanks especially to Dennis Flanagan for help on these.
4945
      * Thanks especially to Dennis Flanagan for help on these.
4937
 
4946
 
4938
    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)
4939
      * Fix memalign brace error.
4948
      * Fix memalign brace error.
4940
 
4949
 
4941
    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)
4942
      * Fix improper #endif nesting in C++
4951
      * Fix improper #endif nesting in C++
4943
      * Add explicit casts needed for C++
4952
      * Add explicit casts needed for C++
4944
 
4953
 
4945
    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)
4946
      * Use trees for large bins
4955
      * Use trees for large bins
4947
      * Support mspaces
4956
      * Support mspaces
4948
      * Use segments to unify sbrk-based and mmap-based system allocation,
4957
      * Use segments to unify sbrk-based and mmap-based system allocation,
4949
        removing need for emulation on most platforms without sbrk.
4958
        removing need for emulation on most platforms without sbrk.
4950
      * Default safety checks
4959
      * Default safety checks
4951
      * Optional footer checks. Thanks to William Robertson for the idea.
4960
      * Optional footer checks. Thanks to William Robertson for the idea.
4952
      * Internal code refactoring
4961
      * Internal code refactoring
4953
      * Incorporate suggestions and platform-specific changes.
4962
      * Incorporate suggestions and platform-specific changes.
4954
        Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
4963
        Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
4955
        Aaron Bachmann,  Emery Berger, and others.
4964
        Aaron Bachmann,  Emery Berger, and others.
4956
      * Speed up non-fastbin processing enough to remove fastbins.
4965
      * Speed up non-fastbin processing enough to remove fastbins.
4957
      * Remove useless cfree() to avoid conflicts with other apps.
4966
      * Remove useless cfree() to avoid conflicts with other apps.
4958
      * Remove internal memcpy, memset. Compilers handle builtins better.
4967
      * Remove internal memcpy, memset. Compilers handle builtins better.
4959
      * Remove some options that no one ever used and rename others.
4968
      * Remove some options that no one ever used and rename others.
4960
 
4969
 
4961
    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)
4962
      * Fix malloc_state bitmap array misdeclaration
4971
      * Fix malloc_state bitmap array misdeclaration
4963
 
4972
 
4964
    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)
4965
      * Allow tuning of FIRST_SORTED_BIN_SIZE
4974
      * Allow tuning of FIRST_SORTED_BIN_SIZE
4966
      * 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.
4967
      * Better detection and support for non-contiguousness of MORECORE.
4976
      * Better detection and support for non-contiguousness of MORECORE.
4968
        Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
4977
        Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
4969
      * Bypass most of malloc if no frees. Thanks To Emery Berger.
4978
      * Bypass most of malloc if no frees. Thanks To Emery Berger.
4970
      * Fix freeing of old top non-contiguous chunk im sysmalloc.
4979
      * Fix freeing of old top non-contiguous chunk im sysmalloc.
4971
      * Raised default trim and map thresholds to 256K.
4980
      * Raised default trim and map thresholds to 256K.
4972
      * Fix mmap-related #defines. Thanks to Lubos Lunak.
4981
      * Fix mmap-related #defines. Thanks to Lubos Lunak.
4973
      * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
4982
      * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
4974
      * Branch-free bin calculation
4983
      * Branch-free bin calculation
4975
      * Default trim and mmap thresholds now 256K.
4984
      * Default trim and mmap thresholds now 256K.
4976
 
4985
 
4977
    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)
4978
      * Introduce independent_comalloc and independent_calloc.
4987
      * Introduce independent_comalloc and independent_calloc.
4979
        Thanks to Michael Pachos for motivation and help.
4988
        Thanks to Michael Pachos for motivation and help.
4980
      * Make optional .h file available
4989
      * Make optional .h file available
4981
      * Allow > 2GB requests on 32bit systems.
4990
      * Allow > 2GB requests on 32bit systems.
4982
      * 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>.
4983
        Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
4992
        Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
4984
        and Anonymous.
4993
        and Anonymous.
4985
      * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
4994
      * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
4986
        helping test this.)
4995
        helping test this.)
4987
      * memalign: check alignment arg
4996
      * memalign: check alignment arg
4988
      * realloc: don't try to shift chunks backwards, since this
4997
      * realloc: don't try to shift chunks backwards, since this
4989
        leads to  more fragmentation in some programs and doesn't
4998
        leads to  more fragmentation in some programs and doesn't
4990
        seem to help in any others.
4999
        seem to help in any others.
4991
      * Collect all cases in malloc requiring system memory into sysmalloc
5000
      * Collect all cases in malloc requiring system memory into sysmalloc
4992
      * Use mmap as backup to sbrk
5001
      * Use mmap as backup to sbrk
4993
      * Place all internal state in malloc_state
5002
      * Place all internal state in malloc_state
4994
      * Introduce fastbins (although similar to 2.5.1)
5003
      * Introduce fastbins (although similar to 2.5.1)
4995
      * Many minor tunings and cosmetic improvements
5004
      * Many minor tunings and cosmetic improvements
4996
      * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
5005
      * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
4997
      * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
5006
      * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
4998
        Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
5007
        Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
4999
      * Include errno.h to support default failure action.
5008
      * Include errno.h to support default failure action.
5000
 
5009
 
5001
    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)
5002
      * return null for negative arguments
5011
      * return null for negative arguments
5003
      * 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>
5004
         * 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'
5005
          (e.g. WIN32 platforms)
5014
          (e.g. WIN32 platforms)
5006
         * Cleanup header file inclusion for WIN32 platforms
5015
         * Cleanup header file inclusion for WIN32 platforms
5007
         * Cleanup code to avoid Microsoft Visual C++ compiler complaints
5016
         * Cleanup code to avoid Microsoft Visual C++ compiler complaints
5008
         * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
5017
         * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
5009
           memory allocation routines
5018
           memory allocation routines
5010
         * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
5019
         * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
5011
         * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
5020
         * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
5012
           usage of 'assert' in non-WIN32 code
5021
           usage of 'assert' in non-WIN32 code
5013
         * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
5022
         * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
5014
           avoid infinite loop
5023
           avoid infinite loop
5015
      * Always call 'fREe()' rather than 'free()'
5024
      * Always call 'fREe()' rather than 'free()'
5016
 
5025
 
5017
    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)
5018
      * Fixed ordering problem with boundary-stamping
5027
      * Fixed ordering problem with boundary-stamping
5019
 
5028
 
5020
    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)
5021
      * Added pvalloc, as recommended by H.J. Liu
5030
      * Added pvalloc, as recommended by H.J. Liu
5022
      * Added 64bit pointer support mainly from Wolfram Gloger
5031
      * Added 64bit pointer support mainly from Wolfram Gloger
5023
      * Added anonymously donated WIN32 sbrk emulation
5032
      * Added anonymously donated WIN32 sbrk emulation
5024
      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
5033
      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
5025
      * malloc_extend_top: fix mask error that caused wastage after
5034
      * malloc_extend_top: fix mask error that caused wastage after
5026
        foreign sbrks
5035
        foreign sbrks
5027
      * Add linux mremap support code from HJ Liu
5036
      * Add linux mremap support code from HJ Liu
5028
 
5037
 
5029
    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)
5030
      * Integrated most documentation with the code.
5039
      * Integrated most documentation with the code.
5031
      * Add support for mmap, with help from
5040
      * Add support for mmap, with help from
5032
        Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5041
        Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5033
      * Use last_remainder in more cases.
5042
      * Use last_remainder in more cases.
5034
      * Pack bins using idea from  colin@nyx10.cs.du.edu
5043
      * Pack bins using idea from  colin@nyx10.cs.du.edu
5035
      * Use ordered bins instead of best-fit threshhold
5044
      * Use ordered bins instead of best-fit threshhold
5036
      * Eliminate block-local decls to simplify tracing and debugging.
5045
      * Eliminate block-local decls to simplify tracing and debugging.
5037
      * Support another case of realloc via move into top
5046
      * Support another case of realloc via move into top
5038
      * Fix error occuring when initial sbrk_base not word-aligned.
5047
      * Fix error occuring when initial sbrk_base not word-aligned.
5039
      * Rely on page size for units instead of SBRK_UNIT to
5048
      * Rely on page size for units instead of SBRK_UNIT to
5040
        avoid surprises about sbrk alignment conventions.
5049
        avoid surprises about sbrk alignment conventions.
5041
      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
5050
      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
5042
        (raymond@es.ele.tue.nl) for the suggestion.
5051
        (raymond@es.ele.tue.nl) for the suggestion.
5043
      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
5052
      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
5044
      * More precautions for cases where other routines call sbrk,
5053
      * More precautions for cases where other routines call sbrk,
5045
        courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5054
        courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
5046
      * Added macros etc., allowing use in linux libc from
5055
      * Added macros etc., allowing use in linux libc from
5047
        H.J. Lu (hjl@gnu.ai.mit.edu)
5056
        H.J. Lu (hjl@gnu.ai.mit.edu)
5048
      * Inverted this history list
5057
      * Inverted this history list
5049
 
5058
 
5050
    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)
5051
      * 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.
5052
      * Removed all preallocation code since under current scheme
5061
      * Removed all preallocation code since under current scheme
5053
        the work required to undo bad preallocations exceeds
5062
        the work required to undo bad preallocations exceeds
5054
        the work saved in good cases for most test programs.
5063
        the work saved in good cases for most test programs.
5055
      * No longer use return list or unconsolidated bins since
5064
      * No longer use return list or unconsolidated bins since
5056
        no scheme using them consistently outperforms those that don't
5065
        no scheme using them consistently outperforms those that don't
5057
        given above changes.
5066
        given above changes.
5058
      * 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.
5059
      * Added some support for debugging
5068
      * Added some support for debugging
5060
 
5069
 
5061
    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)
5062
      * Removed footers when chunks are in use. Thanks to
5071
      * Removed footers when chunks are in use. Thanks to
5063
        Paul Wilson (wilson@cs.texas.edu) for the suggestion.
5072
        Paul Wilson (wilson@cs.texas.edu) for the suggestion.
5064
 
5073
 
5065
    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)
5066
      * Added malloc_trim, with help from Wolfram Gloger
5075
      * Added malloc_trim, with help from Wolfram Gloger
5067
        (wmglo@Dent.MED.Uni-Muenchen.DE).
5076
        (wmglo@Dent.MED.Uni-Muenchen.DE).
5068
 
5077
 
5069
    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)
5070
 
5079
 
5071
    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)
5072
      * realloc: try to expand in both directions
5081
      * realloc: try to expand in both directions
5073
      * malloc: swap order of clean-bin strategy;
5082
      * malloc: swap order of clean-bin strategy;
5074
      * realloc: only conditionally expand backwards
5083
      * realloc: only conditionally expand backwards
5075
      * Try not to scavenge used bins
5084
      * Try not to scavenge used bins
5076
      * Use bin counts as a guide to preallocation
5085
      * Use bin counts as a guide to preallocation
5077
      * Occasionally bin return list chunks in first scan
5086
      * Occasionally bin return list chunks in first scan
5078
      * Add a few optimizations from colin@nyx10.cs.du.edu
5087
      * Add a few optimizations from colin@nyx10.cs.du.edu
5079
 
5088
 
5080
    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)
5081
      * faster bin computation & slightly different binning
5090
      * faster bin computation & slightly different binning
5082
      * merged all consolidations to one part of malloc proper
5091
      * merged all consolidations to one part of malloc proper
5083
         (eliminating old malloc_find_space & malloc_clean_bin)
5092
         (eliminating old malloc_find_space & malloc_clean_bin)
5084
      * Scan 2 returns chunks (not just 1)
5093
      * Scan 2 returns chunks (not just 1)
5085
      * Propagate failure in realloc if malloc returns 0
5094
      * Propagate failure in realloc if malloc returns 0
5086
      * Add stuff to allow compilation on non-ANSI compilers
5095
      * Add stuff to allow compilation on non-ANSI compilers
5087
          from kpv@research.att.com
5096
          from kpv@research.att.com
5088
 
5097
 
5089
    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)
5090
      * removed potential for odd address access in prev_chunk
5099
      * removed potential for odd address access in prev_chunk
5091
      * removed dependency on getpagesize.h
5100
      * removed dependency on getpagesize.h
5092
      * misc cosmetics and a bit more internal documentation
5101
      * misc cosmetics and a bit more internal documentation
5093
      * anticosmetics: mangled names in macros to evade debugger strangeness
5102
      * anticosmetics: mangled names in macros to evade debugger strangeness
5094
      * tested on sparc, hp-700, dec-mips, rs6000
5103
      * tested on sparc, hp-700, dec-mips, rs6000
5095
          with gcc & native cc (hp, dec only) allowing
5104
          with gcc & native cc (hp, dec only) allowing
5096
          Detlefs & Zorn comparison study (in SIGPLAN Notices.)
5105
          Detlefs & Zorn comparison study (in SIGPLAN Notices.)
5097
 
5106
 
5098
    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)
5099
      * 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
5100
         structure of old version,  but most details differ.)
5109
         structure of old version,  but most details differ.)
5101
 
5110
 
5102
*/
5111
*/