00001
00002
00003 #ifndef DISABLE_POOL_ALLOC
00004
00005 #define USE_DL_PREFIX
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 #ifndef WIN32
00448 #ifdef _WIN32
00449 #define WIN32 1
00450 #endif
00451 #endif
00452 #ifdef WIN32
00453 #define WIN32_LEAN_AND_MEAN
00454 #include <windows.h>
00455 #define HAVE_MMAP 1
00456 #define HAVE_MORECORE 0
00457 #define LACKS_UNISTD_H
00458 #define LACKS_SYS_PARAM_H
00459 #define LACKS_SYS_MMAN_H
00460 #define LACKS_STRING_H
00461 #define LACKS_STRINGS_H
00462 #define LACKS_SYS_TYPES_H
00463 #define LACKS_ERRNO_H
00464 #define MALLOC_FAILURE_ACTION
00465 #define MMAP_CLEARS 0
00466 #endif
00467
00468 #if defined(DARWIN) || defined(_DARWIN)
00469
00470 #ifndef HAVE_MORECORE
00471 #define HAVE_MORECORE 0
00472 #define HAVE_MMAP 1
00473 #endif
00474 #endif
00475
00476 #ifndef LACKS_SYS_TYPES_H
00477 #include <sys/types.h>
00478 #endif
00479
00480
00481 #define MAX_SIZE_T (~(size_t)0)
00482
00483 #ifndef ONLY_MSPACES
00484 #define ONLY_MSPACES 0
00485 #endif
00486 #ifndef MSPACES
00487 #if ONLY_MSPACES
00488 #define MSPACES 1
00489 #else
00490 #define MSPACES 0
00491 #endif
00492 #endif
00493 #ifndef MALLOC_ALIGNMENT
00494 #define MALLOC_ALIGNMENT ((size_t)8U)
00495 #endif
00496 #ifndef FOOTERS
00497 #define FOOTERS 0
00498 #endif
00499 #ifndef ABORT
00500 #define ABORT abort()
00501 #endif
00502 #ifndef ABORT_ON_ASSERT_FAILURE
00503 #define ABORT_ON_ASSERT_FAILURE 1
00504 #endif
00505 #ifndef PROCEED_ON_ERROR
00506 #define PROCEED_ON_ERROR 0
00507 #endif
00508 #ifndef USE_LOCKS
00509 #define USE_LOCKS 0
00510 #endif
00511 #ifndef INSECURE
00512 #define INSECURE 0
00513 #endif
00514 #ifndef HAVE_MMAP
00515 #define HAVE_MMAP 1
00516 #endif
00517 #ifndef MMAP_CLEARS
00518 #define MMAP_CLEARS 1
00519 #endif
00520 #ifndef HAVE_MREMAP
00521 #ifdef linux
00522 #define HAVE_MREMAP 1
00523 #else
00524 #define HAVE_MREMAP 0
00525 #endif
00526 #endif
00527 #ifndef MALLOC_FAILURE_ACTION
00528 #define MALLOC_FAILURE_ACTION errno = ENOMEM;
00529 #endif
00530 #ifndef HAVE_MORECORE
00531 #if ONLY_MSPACES
00532 #define HAVE_MORECORE 0
00533 #else
00534 #define HAVE_MORECORE 1
00535 #endif
00536 #endif
00537 #if !HAVE_MORECORE
00538 #define MORECORE_CONTIGUOUS 0
00539 #else
00540 #ifndef MORECORE
00541 #define MORECORE sbrk
00542 #endif
00543 #ifndef MORECORE_CONTIGUOUS
00544 #define MORECORE_CONTIGUOUS 1
00545 #endif
00546 #endif
00547 #ifndef DEFAULT_GRANULARITY
00548 #if MORECORE_CONTIGUOUS
00549 #define DEFAULT_GRANULARITY (0)
00550 #else
00551 #define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
00552 #endif
00553 #endif
00554 #ifndef DEFAULT_TRIM_THRESHOLD
00555 #ifndef MORECORE_CANNOT_TRIM
00556 #define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
00557 #else
00558 #define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
00559 #endif
00560 #endif
00561 #ifndef DEFAULT_MMAP_THRESHOLD
00562 #if HAVE_MMAP
00563 #define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
00564 #else
00565 #define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
00566 #endif
00567 #endif
00568 #ifndef USE_BUILTIN_FFS
00569 #define USE_BUILTIN_FFS 0
00570 #endif
00571 #ifndef USE_DEV_RANDOM
00572 #define USE_DEV_RANDOM 0
00573 #endif
00574 #ifndef NO_MALLINFO
00575 #define NO_MALLINFO 0
00576 #endif
00577 #ifndef MALLINFO_FIELD_TYPE
00578 #define MALLINFO_FIELD_TYPE size_t
00579 #endif
00580
00581
00582
00583
00584
00585
00586
00587
00588 #define M_TRIM_THRESHOLD (-1)
00589 #define M_GRANULARITY (-2)
00590 #define M_MMAP_THRESHOLD (-3)
00591
00592
00593
00594 #if !NO_MALLINFO
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 #ifdef HAVE_USR_INCLUDE_MALLOC_H
00620 #include "/usr/include/malloc.h"
00621 #else
00622
00623 struct mallinfo {
00624 MALLINFO_FIELD_TYPE arena;
00625 MALLINFO_FIELD_TYPE ordblks;
00626 MALLINFO_FIELD_TYPE smblks;
00627 MALLINFO_FIELD_TYPE hblks;
00628 MALLINFO_FIELD_TYPE hblkhd;
00629 MALLINFO_FIELD_TYPE usmblks;
00630 MALLINFO_FIELD_TYPE fsmblks;
00631 MALLINFO_FIELD_TYPE uordblks;
00632 MALLINFO_FIELD_TYPE fordblks;
00633 MALLINFO_FIELD_TYPE keepcost;
00634 };
00635
00636 #endif
00637 #endif
00638
00639 #ifdef __cplusplus
00640 extern "C" {
00641 #endif
00642
00643 #if !ONLY_MSPACES
00644
00645
00646
00647 #ifndef USE_DL_PREFIX
00648 #define dlcalloc calloc
00649 #define dlfree free
00650 #define dlmalloc malloc
00651 #define dlmemalign memalign
00652 #define dlrealloc realloc
00653 #define dlvalloc valloc
00654 #define dlpvalloc pvalloc
00655 #define dlmallinfo mallinfo
00656 #define dlmallopt mallopt
00657 #define dlmalloc_trim malloc_trim
00658 #define dlmalloc_stats malloc_stats
00659 #define dlmalloc_usable_size malloc_usable_size
00660 #define dlmalloc_footprint malloc_footprint
00661 #define dlmalloc_max_footprint malloc_max_footprint
00662 #define dlindependent_calloc independent_calloc
00663 #define dlindependent_comalloc independent_comalloc
00664 #endif
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 void* dlmalloc(size_t);
00682
00683
00684
00685
00686
00687
00688
00689
00690 void dlfree(void*);
00691
00692
00693
00694
00695
00696
00697 void* dlcalloc(size_t, size_t);
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722 void* dlrealloc(void*, size_t);
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 void* dlmemalign(size_t, size_t);
00737
00738
00739
00740
00741
00742
00743 void* dlvalloc(size_t);
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 int dlmallopt(int, int);
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774 size_t dlmalloc_footprint(void);
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 size_t dlmalloc_max_footprint(void);
00788
00789 #if !NO_MALLINFO
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812 struct mallinfo dlmallinfo(void);
00813 #endif
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 void** dlindependent_calloc(size_t, size_t, void**);
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928 void** dlindependent_comalloc(size_t, size_t*, void**);
00929
00930
00931
00932
00933
00934
00935
00936 void* dlpvalloc(size_t);
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959 int dlmalloc_trim(size_t);
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975 size_t dlmalloc_usable_size(void*);
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 void dlmalloc_stats(void);
00997
00998 #endif
00999
01000 #if MSPACES
01001
01002
01003
01004
01005
01006 typedef void* mspace;
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 mspace create_mspace(size_t capacity, int locked);
01020
01021
01022
01023
01024
01025
01026
01027 size_t destroy_mspace(mspace msp);
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038 mspace create_mspace_with_base(void* base, size_t capacity, int locked);
01039
01040
01041
01042
01043
01044 void* mspace_malloc(mspace msp, size_t bytes);
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054 void mspace_free(mspace msp, void* mem);
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065 void* mspace_realloc(mspace msp, void* mem, size_t newsize);
01066
01067
01068
01069
01070
01071 void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
01072
01073
01074
01075
01076
01077 void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
01078
01079
01080
01081
01082
01083 void** mspace_independent_calloc(mspace msp, size_t n_elements,
01084 size_t elem_size, void* chunks[]);
01085
01086
01087
01088
01089
01090 void** mspace_independent_comalloc(mspace msp, size_t n_elements,
01091 size_t sizes[], void* chunks[]);
01092
01093
01094
01095
01096
01097 size_t mspace_footprint(mspace msp);
01098
01099
01100
01101
01102
01103 size_t mspace_max_footprint(mspace msp);
01104
01105
01106 #if !NO_MALLINFO
01107
01108
01109
01110
01111 struct mallinfo mspace_mallinfo(mspace msp);
01112 #endif
01113
01114
01115
01116
01117
01118 void mspace_malloc_stats(mspace msp);
01119
01120
01121
01122
01123
01124 int mspace_trim(mspace msp, size_t pad);
01125
01126
01127
01128
01129 int mspace_mallopt(int, int);
01130
01131 #endif
01132
01133 #ifdef __cplusplus
01134 };
01135 #endif
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 #ifdef WIN32
01150 #pragma warning( disable : 4146 )
01151 #endif
01152
01153 #include <stdio.h>
01154
01155 #ifndef LACKS_ERRNO_H
01156 #include <errno.h>
01157 #endif
01158 #if FOOTERS
01159 #include <time.h>
01160 #endif
01161 #ifndef LACKS_STDLIB_H
01162 #include <stdlib.h>
01163 #endif
01164 #ifdef DEBUG
01165 #if ABORT_ON_ASSERT_FAILURE
01166 #define assert(x) if(!(x)) ABORT
01167 #else
01168 #include <assert.h>
01169 #endif
01170 #else
01171 #define assert(x)
01172 #endif
01173 #ifndef LACKS_STRING_H
01174 #include <string.h>
01175 #endif
01176 #if USE_BUILTIN_FFS
01177 #ifndef LACKS_STRINGS_H
01178 #include <strings.h>
01179 #endif
01180 #endif
01181 #if HAVE_MMAP
01182 #ifndef LACKS_SYS_MMAN_H
01183 #include <sys/mman.h>
01184 #endif
01185 #ifndef LACKS_FCNTL_H
01186 #include <fcntl.h>
01187 #endif
01188 #endif
01189 #if HAVE_MORECORE
01190 #ifndef LACKS_UNISTD_H
01191 #include <unistd.h>
01192 #else
01193 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
01194 extern void* sbrk(ptrdiff_t);
01195 #endif
01196 #endif
01197 #endif
01198
01199 #ifndef WIN32
01200 #ifndef malloc_getpagesize
01201 # ifdef _SC_PAGESIZE
01202 # ifndef _SC_PAGE_SIZE
01203 # define _SC_PAGE_SIZE _SC_PAGESIZE
01204 # endif
01205 # endif
01206 # ifdef _SC_PAGE_SIZE
01207 # define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
01208 # else
01209 # if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
01210 extern size_t getpagesize();
01211 # define malloc_getpagesize getpagesize()
01212 # else
01213 # ifdef WIN32
01214 # define malloc_getpagesize getpagesize()
01215 # else
01216 # ifndef LACKS_SYS_PARAM_H
01217 # include <sys/param.h>
01218 # endif
01219 # ifdef EXEC_PAGESIZE
01220 # define malloc_getpagesize EXEC_PAGESIZE
01221 # else
01222 # ifdef NBPG
01223 # ifndef CLSIZE
01224 # define malloc_getpagesize NBPG
01225 # else
01226 # define malloc_getpagesize (NBPG * CLSIZE)
01227 # endif
01228 # else
01229 # ifdef NBPC
01230 # define malloc_getpagesize NBPC
01231 # else
01232 # ifdef PAGESIZE
01233 # define malloc_getpagesize PAGESIZE
01234 # else
01235 # define malloc_getpagesize ((size_t)4096U)
01236 # endif
01237 # endif
01238 # endif
01239 # endif
01240 # endif
01241 # endif
01242 # endif
01243 #endif
01244 #endif
01245
01246
01247
01248
01249 #define SIZE_T_SIZE (sizeof(size_t))
01250 #define SIZE_T_BITSIZE (sizeof(size_t) << 3)
01251
01252
01253
01254 #define SIZE_T_ZERO ((size_t)0)
01255 #define SIZE_T_ONE ((size_t)1)
01256 #define SIZE_T_TWO ((size_t)2)
01257 #define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1)
01258 #define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2)
01259 #define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
01260 #define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U)
01261
01262
01263 #define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE)
01264
01265
01266 #define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
01267
01268
01269 #define align_offset(A)\
01270 ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
01271 ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283 #define MFAIL ((void*)(MAX_SIZE_T))
01284 #define CMFAIL ((char*)(MFAIL))
01285
01286 #if !HAVE_MMAP
01287 #define IS_MMAPPED_BIT (SIZE_T_ZERO)
01288 #define USE_MMAP_BIT (SIZE_T_ZERO)
01289 #define CALL_MMAP(s) MFAIL
01290 #define CALL_MUNMAP(a, s) (-1)
01291 #define DIRECT_MMAP(s) MFAIL
01292
01293 #else
01294 #define IS_MMAPPED_BIT (SIZE_T_ONE)
01295 #define USE_MMAP_BIT (SIZE_T_ONE)
01296
01297 #ifndef WIN32
01298 #define CALL_MUNMAP(a, s) munmap((a), (s))
01299 #define MMAP_PROT (PROT_READ|PROT_WRITE)
01300 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
01301 #define MAP_ANONYMOUS MAP_ANON
01302 #endif
01303 #ifdef MAP_ANONYMOUS
01304 #define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
01305 #define CALL_MMAP(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
01306 #else
01307
01308
01309
01310
01311 #define MMAP_FLAGS (MAP_PRIVATE)
01312 static int dev_zero_fd = -1;
01313 #define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
01314 (dev_zero_fd = open("/dev/zero", O_RDWR), \
01315 mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
01316 mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
01317 #endif
01318
01319 #define DIRECT_MMAP(s) CALL_MMAP(s)
01320 #else
01321
01322
01323 static void* win32mmap(size_t size) {
01324 void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
01325 return (ptr != 0)? ptr: MFAIL;
01326 }
01327
01328
01329 static void* win32direct_mmap(size_t size) {
01330 void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
01331 PAGE_READWRITE);
01332 return (ptr != 0)? ptr: MFAIL;
01333 }
01334
01335
01336 static int win32munmap(void* ptr, size_t size) {
01337 MEMORY_BASIC_INFORMATION minfo;
01338 char* cptr = ptr;
01339 while (size) {
01340 if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
01341 return -1;
01342 if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
01343 minfo.State != MEM_COMMIT || minfo.RegionSize > size)
01344 return -1;
01345 if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
01346 return -1;
01347 cptr += minfo.RegionSize;
01348 size -= minfo.RegionSize;
01349 }
01350 return 0;
01351 }
01352
01353 #define CALL_MMAP(s) win32mmap(s)
01354 #define CALL_MUNMAP(a, s) win32munmap((a), (s))
01355 #define DIRECT_MMAP(s) win32direct_mmap(s)
01356 #endif
01357 #endif
01358
01359 #if HAVE_MMAP && HAVE_MREMAP
01360 #define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
01361 #else
01362 #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
01363 #endif
01364
01365 #if HAVE_MORECORE
01366 #define CALL_MORECORE(S) MORECORE(S)
01367 #else
01368 #define CALL_MORECORE(S) MFAIL
01369 #endif
01370
01371
01372 #define USE_NONCONTIGUOUS_BIT (4U)
01373
01374
01375 #define EXTERN_BIT (8U)
01376
01377
01378
01379
01380 #if USE_LOCKS
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396 #ifndef WIN32
01397
01398 #include <pthread.h>
01399 #define MLOCK_T pthread_mutex_t
01400 #define INITIAL_LOCK(l) pthread_mutex_init(l, NULL)
01401 #define ACQUIRE_LOCK(l) pthread_mutex_lock(l)
01402 #define RELEASE_LOCK(l) pthread_mutex_unlock(l)
01403
01404 #if HAVE_MORECORE
01405 static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER;
01406 #endif
01407
01408 static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER;
01409
01410 #else
01411
01412
01413
01414
01415
01416 #define MLOCK_T long
01417 static int win32_acquire_lock (MLOCK_T *sl) {
01418 for (;;) {
01419 #ifdef InterlockedCompareExchangePointer
01420 if (!InterlockedCompareExchange(sl, 1, 0))
01421 return 0;
01422 #else
01423 if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0))
01424 return 0;
01425 #endif
01426 Sleep (0);
01427 }
01428 }
01429
01430 static void win32_release_lock (MLOCK_T *sl) {
01431 InterlockedExchange (sl, 0);
01432 }
01433
01434 #define INITIAL_LOCK(l) *(l)=0
01435 #define ACQUIRE_LOCK(l) win32_acquire_lock(l)
01436 #define RELEASE_LOCK(l) win32_release_lock(l)
01437 #if HAVE_MORECORE
01438 static MLOCK_T morecore_mutex;
01439 #endif
01440 static MLOCK_T magic_init_mutex;
01441 #endif
01442
01443 #define USE_LOCK_BIT (2U)
01444 #else
01445 #define USE_LOCK_BIT (0U)
01446 #define INITIAL_LOCK(l)
01447 #endif
01448
01449 #if USE_LOCKS && HAVE_MORECORE
01450 #define ACQUIRE_MORECORE_LOCK() ACQUIRE_LOCK(&morecore_mutex);
01451 #define RELEASE_MORECORE_LOCK() RELEASE_LOCK(&morecore_mutex);
01452 #else
01453 #define ACQUIRE_MORECORE_LOCK()
01454 #define RELEASE_MORECORE_LOCK()
01455 #endif
01456
01457 #if USE_LOCKS
01458 #define ACQUIRE_MAGIC_INIT_LOCK() ACQUIRE_LOCK(&magic_init_mutex);
01459 #define RELEASE_MAGIC_INIT_LOCK() RELEASE_LOCK(&magic_init_mutex);
01460 #else
01461 #define ACQUIRE_MAGIC_INIT_LOCK()
01462 #define RELEASE_MAGIC_INIT_LOCK()
01463 #endif
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 struct malloc_chunk {
01604 size_t prev_foot;
01605 size_t head;
01606 struct malloc_chunk* fd;
01607 struct malloc_chunk* bk;
01608 };
01609
01610 typedef struct malloc_chunk mchunk;
01611 typedef struct malloc_chunk* mchunkptr;
01612 typedef struct malloc_chunk* sbinptr;
01613 typedef unsigned int bindex_t;
01614 typedef unsigned int binmap_t;
01615 typedef unsigned int flag_t;
01616
01617
01618
01619 #define MCHUNK_SIZE (sizeof(mchunk))
01620
01621 #if FOOTERS
01622 #define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
01623 #else
01624 #define CHUNK_OVERHEAD (SIZE_T_SIZE)
01625 #endif
01626
01627
01628 #define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
01629
01630 #define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES)
01631
01632
01633 #define MIN_CHUNK_SIZE\
01634 ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
01635
01636
01637 #define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES))
01638 #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
01639
01640 #define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A)))
01641
01642
01643 #define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2)
01644 #define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
01645
01646
01647 #define pad_request(req) \
01648 (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
01649
01650
01651 #define request2size(req) \
01652 (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665 #define PINUSE_BIT (SIZE_T_ONE)
01666 #define CINUSE_BIT (SIZE_T_TWO)
01667 #define INUSE_BITS (PINUSE_BIT|CINUSE_BIT)
01668
01669
01670 #define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE)
01671
01672
01673 #define cinuse(p) ((p)->head & CINUSE_BIT)
01674 #define pinuse(p) ((p)->head & PINUSE_BIT)
01675 #define chunksize(p) ((p)->head & ~(INUSE_BITS))
01676
01677 #define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT)
01678 #define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT)
01679
01680
01681 #define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
01682 #define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
01683
01684
01685 #define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS)))
01686 #define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
01687
01688
01689 #define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT)
01690
01691
01692 #define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot)
01693 #define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
01694
01695
01696 #define set_size_and_pinuse_of_free_chunk(p, s)\
01697 ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
01698
01699
01700 #define set_free_with_pinuse(p, s, n)\
01701 (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
01702
01703 #define is_mmapped(p)\
01704 (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT))
01705
01706
01707 #define overhead_for(p)\
01708 (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
01709
01710
01711 #if MMAP_CLEARS
01712 #define calloc_must_clear(p) (!is_mmapped(p))
01713 #else
01714 #define calloc_must_clear(p) (1)
01715 #endif
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808 struct malloc_tree_chunk {
01809
01810 size_t prev_foot;
01811 size_t head;
01812 struct malloc_tree_chunk* fd;
01813 struct malloc_tree_chunk* bk;
01814
01815 struct malloc_tree_chunk* child[2];
01816 struct malloc_tree_chunk* parent;
01817 bindex_t index;
01818 };
01819
01820 typedef struct malloc_tree_chunk tchunk;
01821 typedef struct malloc_tree_chunk* tchunkptr;
01822 typedef struct malloc_tree_chunk* tbinptr;
01823
01824
01825 #define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884 struct malloc_segment {
01885 char* base;
01886 size_t size;
01887 struct malloc_segment* next;
01888 flag_t sflags;
01889 };
01890
01891 #define is_mmapped_segment(S) ((S)->sflags & IS_MMAPPED_BIT)
01892 #define is_extern_segment(S) ((S)->sflags & EXTERN_BIT)
01893
01894 typedef struct malloc_segment msegment;
01895 typedef struct malloc_segment* msegmentptr;
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973 #define NSMALLBINS (32U)
01974 #define NTREEBINS (32U)
01975 #define SMALLBIN_SHIFT (3U)
01976 #define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT)
01977 #define TREEBIN_SHIFT (8U)
01978 #define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT)
01979 #define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE)
01980 #define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
01981
01982 struct malloc_state {
01983 binmap_t smallmap;
01984 binmap_t treemap;
01985 size_t dvsize;
01986 size_t topsize;
01987 char* least_addr;
01988 mchunkptr dv;
01989 mchunkptr top;
01990 size_t trim_check;
01991 size_t magic;
01992 mchunkptr smallbins[(NSMALLBINS+1)*2];
01993 tbinptr treebins[NTREEBINS];
01994 size_t footprint;
01995 size_t max_footprint;
01996 flag_t mflags;
01997 #if USE_LOCKS
01998 MLOCK_T mutex;
01999 #endif
02000 msegment seg;
02001 };
02002
02003 typedef struct malloc_state* mstate;
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013 struct malloc_params {
02014 size_t magic;
02015 size_t page_size;
02016 size_t granularity;
02017 size_t mmap_threshold;
02018 size_t trim_threshold;
02019 flag_t default_mflags;
02020 };
02021
02022 static struct malloc_params mparams;
02023
02024
02025 static struct malloc_state _gm_;
02026 #define gm (&_gm_)
02027 #define is_global(M) ((M) == &_gm_)
02028 #define is_initialized(M) ((M)->top != 0)
02029
02030
02031
02032
02033
02034 #define use_lock(M) ((M)->mflags & USE_LOCK_BIT)
02035 #define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT)
02036 #define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT)
02037
02038 #define use_mmap(M) ((M)->mflags & USE_MMAP_BIT)
02039 #define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT)
02040 #define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT)
02041
02042 #define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT)
02043 #define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT)
02044
02045 #define set_lock(M,L)\
02046 ((M)->mflags = (L)?\
02047 ((M)->mflags | USE_LOCK_BIT) :\
02048 ((M)->mflags & ~USE_LOCK_BIT))
02049
02050
02051 #define page_align(S)\
02052 (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))
02053
02054
02055 #define granularity_align(S)\
02056 (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))
02057
02058 #define is_page_aligned(S)\
02059 (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
02060 #define is_granularity_aligned(S)\
02061 (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
02062
02063
02064 #define segment_holds(S, A)\
02065 ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
02066
02067
02068 static msegmentptr segment_holding(mstate m, char* addr) {
02069 msegmentptr sp = &m->seg;
02070 for (;;) {
02071 if (addr >= sp->base && addr < sp->base + sp->size)
02072 return sp;
02073 if ((sp = sp->next) == 0)
02074 return 0;
02075 }
02076 }
02077
02078
02079 static int has_segment_link(mstate m, msegmentptr ss) {
02080 msegmentptr sp = &m->seg;
02081 for (;;) {
02082 if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
02083 return 1;
02084 if ((sp = sp->next) == 0)
02085 return 0;
02086 }
02087 }
02088
02089 #ifndef MORECORE_CANNOT_TRIM
02090 #define should_trim(M,s) ((s) > (M)->trim_check)
02091 #else
02092 #define should_trim(M,s) (0)
02093 #endif
02094
02095
02096
02097
02098
02099
02100 #define TOP_FOOT_SIZE\
02101 (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112 #if USE_LOCKS
02113
02114
02115 #define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())
02116
02117 #define PREACTION(M) ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
02118 #define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
02119 #else
02120
02121 #ifndef PREACTION
02122 #define PREACTION(M) (0)
02123 #endif
02124
02125 #ifndef POSTACTION
02126 #define POSTACTION(M)
02127 #endif
02128
02129 #endif
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139 #if PROCEED_ON_ERROR
02140
02141
02142 int malloc_corruption_error_count;
02143
02144
02145 static void reset_on_error(mstate m);
02146
02147 #define CORRUPTION_ERROR_ACTION(m) reset_on_error(m)
02148 #define USAGE_ERROR_ACTION(m, p)
02149
02150 #else
02151
02152 #ifndef CORRUPTION_ERROR_ACTION
02153 #define CORRUPTION_ERROR_ACTION(m) ABORT
02154 #endif
02155
02156 #ifndef USAGE_ERROR_ACTION
02157 #define USAGE_ERROR_ACTION(m,p) ABORT
02158 #endif
02159
02160 #endif
02161
02162
02163
02164 #if ! DEBUG
02165
02166 #define check_free_chunk(M,P)
02167 #define check_inuse_chunk(M,P)
02168 #define check_malloced_chunk(M,P,N)
02169 #define check_mmapped_chunk(M,P)
02170 #define check_malloc_state(M)
02171 #define check_top_chunk(M,P)
02172
02173 #else
02174 #define check_free_chunk(M,P) do_check_free_chunk(M,P)
02175 #define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P)
02176 #define check_top_chunk(M,P) do_check_top_chunk(M,P)
02177 #define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
02178 #define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P)
02179 #define check_malloc_state(M) do_check_malloc_state(M)
02180
02181 static void do_check_any_chunk(mstate m, mchunkptr p);
02182 static void do_check_top_chunk(mstate m, mchunkptr p);
02183 static void do_check_mmapped_chunk(mstate m, mchunkptr p);
02184 static void do_check_inuse_chunk(mstate m, mchunkptr p);
02185 static void do_check_free_chunk(mstate m, mchunkptr p);
02186 static void do_check_malloced_chunk(mstate m, void* mem, size_t s);
02187 static void do_check_tree(mstate m, tchunkptr t);
02188 static void do_check_treebin(mstate m, bindex_t i);
02189 static void do_check_smallbin(mstate m, bindex_t i);
02190 static void do_check_malloc_state(mstate m);
02191 static int bin_find(mstate m, mchunkptr x);
02192 static size_t traverse_and_check(mstate m);
02193 #endif
02194
02195
02196
02197 #define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
02198 #define small_index(s) ((s) >> SMALLBIN_SHIFT)
02199 #define small_index2size(i) ((i) << SMALLBIN_SHIFT)
02200 #define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE))
02201
02202
02203 #define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
02204 #define treebin_at(M,i) (&((M)->treebins[i]))
02205
02206
02207 #if defined(__GNUC__) && defined(i386)
02208 #define compute_tree_index(S, I)\
02209 {\
02210 size_t X = S >> TREEBIN_SHIFT;\
02211 if (X == 0)\
02212 I = 0;\
02213 else if (X > 0xFFFF)\
02214 I = NTREEBINS-1;\
02215 else {\
02216 unsigned int K;\
02217 __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm" (X));\
02218 I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
02219 }\
02220 }
02221 #else
02222 #define compute_tree_index(S, I)\
02223 {\
02224 size_t X = S >> TREEBIN_SHIFT;\
02225 if (X == 0)\
02226 I = 0;\
02227 else if (X > 0xFFFF)\
02228 I = NTREEBINS-1;\
02229 else {\
02230 unsigned int Y = (unsigned int)X;\
02231 unsigned int N = ((Y - 0x100) >> 16) & 8;\
02232 unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
02233 N += K;\
02234 N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
02235 K = 14 - N + ((Y <<= K) >> 15);\
02236 I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
02237 }\
02238 }
02239 #endif
02240
02241
02242 #define bit_for_tree_index(i) \
02243 (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
02244
02245
02246 #define leftshift_for_tree_index(i) \
02247 ((i == NTREEBINS-1)? 0 : \
02248 ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
02249
02250
02251 #define minsize_for_tree_index(i) \
02252 ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \
02253 (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
02254
02255
02256
02257
02258
02259 #define idx2bit(i) ((binmap_t)(1) << (i))
02260
02261
02262 #define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i))
02263 #define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i))
02264 #define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i))
02265
02266 #define mark_treemap(M,i) ((M)->treemap |= idx2bit(i))
02267 #define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i))
02268 #define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i))
02269
02270
02271
02272 #if defined(__GNUC__) && defined(i386)
02273 #define compute_bit2idx(X, I)\
02274 {\
02275 unsigned int J;\
02276 __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\
02277 I = (bindex_t)J;\
02278 }
02279
02280 #else
02281 #if USE_BUILTIN_FFS
02282 #define compute_bit2idx(X, I) I = ffs(X)-1
02283
02284 #else
02285 #define compute_bit2idx(X, I)\
02286 {\
02287 unsigned int Y = X - 1;\
02288 unsigned int K = Y >> (16-4) & 16;\
02289 unsigned int N = K; Y >>= K;\
02290 N += K = Y >> (8-3) & 8; Y >>= K;\
02291 N += K = Y >> (4-2) & 4; Y >>= K;\
02292 N += K = Y >> (2-1) & 2; Y >>= K;\
02293 N += K = Y >> (1-0) & 1; Y >>= K;\
02294 I = (bindex_t)(N + Y);\
02295 }
02296 #endif
02297 #endif
02298
02299
02300 #define least_bit(x) ((x) & -(x))
02301
02302
02303 #define left_bits(x) ((x<<1) | -(x<<1))
02304
02305
02306 #define same_or_left_bits(x) ((x) | -(x))
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337 #if !INSECURE
02338
02339 #define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
02340
02341 #define ok_next(p, n) ((char*)(p) < (char*)(n))
02342
02343 #define ok_cinuse(p) cinuse(p)
02344
02345 #define ok_pinuse(p) pinuse(p)
02346
02347 #else
02348 #define ok_address(M, a) (1)
02349 #define ok_next(b, n) (1)
02350 #define ok_cinuse(p) (1)
02351 #define ok_pinuse(p) (1)
02352 #endif
02353
02354 #if (FOOTERS && !INSECURE)
02355
02356 #define ok_magic(M) ((M)->magic == mparams.magic)
02357 #else
02358 #define ok_magic(M) (1)
02359 #endif
02360
02361
02362
02363 #if !INSECURE
02364 #if defined(__GNUC__) && __GNUC__ >= 3
02365 #define RTCHECK(e) __builtin_expect(e, 1)
02366 #else
02367 #define RTCHECK(e) (e)
02368 #endif
02369 #else
02370 #define RTCHECK(e) (1)
02371 #endif
02372
02373
02374
02375 #if !FOOTERS
02376
02377 #define mark_inuse_foot(M,p,s)
02378
02379
02380 #define set_inuse(M,p,s)\
02381 ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
02382 ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
02383
02384
02385 #define set_inuse_and_pinuse(M,p,s)\
02386 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
02387 ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
02388
02389
02390 #define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
02391 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
02392
02393 #else
02394
02395
02396 #define mark_inuse_foot(M,p,s)\
02397 (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
02398
02399 #define get_mstate_for(p)\
02400 ((mstate)(((mchunkptr)((char*)(p) +\
02401 (chunksize(p))))->prev_foot ^ mparams.magic))
02402
02403 #define set_inuse(M,p,s)\
02404 ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
02405 (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
02406 mark_inuse_foot(M,p,s))
02407
02408 #define set_inuse_and_pinuse(M,p,s)\
02409 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
02410 (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
02411 mark_inuse_foot(M,p,s))
02412
02413 #define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
02414 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
02415 mark_inuse_foot(M, p, s))
02416
02417 #endif
02418
02419
02420
02421
02422 static int init_mparams(void) {
02423 if (mparams.page_size == 0) {
02424 size_t s;
02425
02426 mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
02427 mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
02428 #if MORECORE_CONTIGUOUS
02429 mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
02430 #else
02431 mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
02432 #endif
02433
02434 #if (FOOTERS && !INSECURE)
02435 {
02436 #if USE_DEV_RANDOM
02437 int fd;
02438 unsigned char buf[sizeof(size_t)];
02439
02440 if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
02441 read(fd, buf, sizeof(buf)) == sizeof(buf)) {
02442 s = *((size_t *) buf);
02443 close(fd);
02444 }
02445 else
02446 #endif
02447 s = (size_t)(time(0) ^ (size_t)0x55555555U);
02448
02449 s |= (size_t)8U;
02450 s &= ~(size_t)7U;
02451
02452 }
02453 #else
02454 s = (size_t)0x58585858U;
02455 #endif
02456 ACQUIRE_MAGIC_INIT_LOCK();
02457 if (mparams.magic == 0) {
02458 mparams.magic = s;
02459
02460 INITIAL_LOCK(&gm->mutex);
02461 gm->mflags = mparams.default_mflags;
02462 }
02463 RELEASE_MAGIC_INIT_LOCK();
02464
02465 #ifndef WIN32
02466 mparams.page_size = malloc_getpagesize;
02467 mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
02468 DEFAULT_GRANULARITY : mparams.page_size);
02469 #else
02470 {
02471 SYSTEM_INFO system_info;
02472 GetSystemInfo(&system_info);
02473 mparams.page_size = system_info.dwPageSize;
02474 mparams.granularity = system_info.dwAllocationGranularity;
02475 }
02476 #endif
02477
02478
02479
02480
02481
02482
02483
02484 if ((sizeof(size_t) != sizeof(char*)) ||
02485 (MAX_SIZE_T < MIN_CHUNK_SIZE) ||
02486 (sizeof(int) < 4) ||
02487 (MALLOC_ALIGNMENT < (size_t)8U) ||
02488 ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) ||
02489 ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) ||
02490 ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||
02491 ((mparams.page_size & (mparams.page_size-SIZE_T_ONE)) != 0))
02492 ABORT;
02493 }
02494 return 0;
02495 }
02496
02497
02498 static int change_mparam(int param_number, int value) {
02499 size_t val = (size_t)value;
02500 init_mparams();
02501 switch(param_number) {
02502 case M_TRIM_THRESHOLD:
02503 mparams.trim_threshold = val;
02504 return 1;
02505 case M_GRANULARITY:
02506 if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
02507 mparams.granularity = val;
02508 return 1;
02509 }
02510 else
02511 return 0;
02512 case M_MMAP_THRESHOLD:
02513 mparams.mmap_threshold = val;
02514 return 1;
02515 default:
02516 return 0;
02517 }
02518 }
02519
02520 #if DEBUG
02521
02522
02523
02524 static void do_check_any_chunk(mstate m, mchunkptr p) {
02525 assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
02526 assert(ok_address(m, p));
02527 }
02528
02529
02530 static void do_check_top_chunk(mstate m, mchunkptr p) {
02531 msegmentptr sp = segment_holding(m, (char*)p);
02532 size_t sz = chunksize(p);
02533 assert(sp != 0);
02534 assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
02535 assert(ok_address(m, p));
02536 assert(sz == m->topsize);
02537 assert(sz > 0);
02538 assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
02539 assert(pinuse(p));
02540 assert(!next_pinuse(p));
02541 }
02542
02543
02544 static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
02545 size_t sz = chunksize(p);
02546 size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD);
02547 assert(is_mmapped(p));
02548 assert(use_mmap(m));
02549 assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
02550 assert(ok_address(m, p));
02551 assert(!is_small(sz));
02552 assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
02553 assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
02554 assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
02555 }
02556
02557
02558 static void do_check_inuse_chunk(mstate m, mchunkptr p) {
02559 do_check_any_chunk(m, p);
02560 assert(cinuse(p));
02561 assert(next_pinuse(p));
02562
02563 assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
02564 if (is_mmapped(p))
02565 do_check_mmapped_chunk(m, p);
02566 }
02567
02568
02569 static void do_check_free_chunk(mstate m, mchunkptr p) {
02570 size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
02571 mchunkptr next = chunk_plus_offset(p, sz);
02572 do_check_any_chunk(m, p);
02573 assert(!cinuse(p));
02574 assert(!next_pinuse(p));
02575 assert (!is_mmapped(p));
02576 if (p != m->dv && p != m->top) {
02577 if (sz >= MIN_CHUNK_SIZE) {
02578 assert((sz & CHUNK_ALIGN_MASK) == 0);
02579 assert(is_aligned(chunk2mem(p)));
02580 assert(next->prev_foot == sz);
02581 assert(pinuse(p));
02582 assert (next == m->top || cinuse(next));
02583 assert(p->fd->bk == p);
02584 assert(p->bk->fd == p);
02585 }
02586 else
02587 assert(sz == SIZE_T_SIZE);
02588 }
02589 }
02590
02591
02592 static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
02593 if (mem != 0) {
02594 mchunkptr p = mem2chunk(mem);
02595 size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
02596 do_check_inuse_chunk(m, p);
02597 assert((sz & CHUNK_ALIGN_MASK) == 0);
02598 assert(sz >= MIN_CHUNK_SIZE);
02599 assert(sz >= s);
02600
02601 assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
02602 }
02603 }
02604
02605
02606 static void do_check_tree(mstate m, tchunkptr t) {
02607 tchunkptr head = 0;
02608 tchunkptr u = t;
02609 bindex_t tindex = t->index;
02610 size_t tsize = chunksize(t);
02611 bindex_t idx;
02612 compute_tree_index(tsize, idx);
02613 assert(tindex == idx);
02614 assert(tsize >= MIN_LARGE_SIZE);
02615 assert(tsize >= minsize_for_tree_index(idx));
02616 assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
02617
02618 do {
02619 do_check_any_chunk(m, ((mchunkptr)u));
02620 assert(u->index == tindex);
02621 assert(chunksize(u) == tsize);
02622 assert(!cinuse(u));
02623 assert(!next_pinuse(u));
02624 assert(u->fd->bk == u);
02625 assert(u->bk->fd == u);
02626 if (u->parent == 0) {
02627 assert(u->child[0] == 0);
02628 assert(u->child[1] == 0);
02629 }
02630 else {
02631 assert(head == 0);
02632 head = u;
02633 assert(u->parent != u);
02634 assert (u->parent->child[0] == u ||
02635 u->parent->child[1] == u ||
02636 *((tbinptr*)(u->parent)) == u);
02637 if (u->child[0] != 0) {
02638 assert(u->child[0]->parent == u);
02639 assert(u->child[0] != u);
02640 do_check_tree(m, u->child[0]);
02641 }
02642 if (u->child[1] != 0) {
02643 assert(u->child[1]->parent == u);
02644 assert(u->child[1] != u);
02645 do_check_tree(m, u->child[1]);
02646 }
02647 if (u->child[0] != 0 && u->child[1] != 0) {
02648 assert(chunksize(u->child[0]) < chunksize(u->child[1]));
02649 }
02650 }
02651 u = u->fd;
02652 } while (u != t);
02653 assert(head != 0);
02654 }
02655
02656
02657 static void do_check_treebin(mstate m, bindex_t i) {
02658 tbinptr* tb = treebin_at(m, i);
02659 tchunkptr t = *tb;
02660 int empty = (m->treemap & (1U << i)) == 0;
02661 if (t == 0)
02662 assert(empty);
02663 if (!empty)
02664 do_check_tree(m, t);
02665 }
02666
02667
02668 static void do_check_smallbin(mstate m, bindex_t i) {
02669 sbinptr b = smallbin_at(m, i);
02670 mchunkptr p = b->bk;
02671 unsigned int empty = (m->smallmap & (1U << i)) == 0;
02672 if (p == b)
02673 assert(empty);
02674 if (!empty) {
02675 for (; p != b; p = p->bk) {
02676 size_t size = chunksize(p);
02677 mchunkptr q;
02678
02679 do_check_free_chunk(m, p);
02680
02681 assert(small_index(size) == i);
02682 assert(p->bk == b || chunksize(p->bk) == chunksize(p));
02683
02684 q = next_chunk(p);
02685 if (q->head != FENCEPOST_HEAD)
02686 do_check_inuse_chunk(m, q);
02687 }
02688 }
02689 }
02690
02691
02692 static int bin_find(mstate m, mchunkptr x) {
02693 size_t size = chunksize(x);
02694 if (is_small(size)) {
02695 bindex_t sidx = small_index(size);
02696 sbinptr b = smallbin_at(m, sidx);
02697 if (smallmap_is_marked(m, sidx)) {
02698 mchunkptr p = b;
02699 do {
02700 if (p == x)
02701 return 1;
02702 } while ((p = p->fd) != b);
02703 }
02704 }
02705 else {
02706 bindex_t tidx;
02707 compute_tree_index(size, tidx);
02708 if (treemap_is_marked(m, tidx)) {
02709 tchunkptr t = *treebin_at(m, tidx);
02710 size_t sizebits = size << leftshift_for_tree_index(tidx);
02711 while (t != 0 && chunksize(t) != size) {
02712 t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
02713 sizebits <<= 1;
02714 }
02715 if (t != 0) {
02716 tchunkptr u = t;
02717 do {
02718 if (u == (tchunkptr)x)
02719 return 1;
02720 } while ((u = u->fd) != t);
02721 }
02722 }
02723 }
02724 return 0;
02725 }
02726
02727
02728 static size_t traverse_and_check(mstate m) {
02729 size_t sum = 0;
02730 if (is_initialized(m)) {
02731 msegmentptr s = &m->seg;
02732 sum += m->topsize + TOP_FOOT_SIZE;
02733 while (s != 0) {
02734 mchunkptr q = align_as_chunk(s->base);
02735 mchunkptr lastq = 0;
02736 assert(pinuse(q));
02737 while (segment_holds(s, q) &&
02738 q != m->top && q->head != FENCEPOST_HEAD) {
02739 sum += chunksize(q);
02740 if (cinuse(q)) {
02741 assert(!bin_find(m, q));
02742 do_check_inuse_chunk(m, q);
02743 }
02744 else {
02745 assert(q == m->dv || bin_find(m, q));
02746 assert(lastq == 0 || cinuse(lastq));
02747 do_check_free_chunk(m, q);
02748 }
02749 lastq = q;
02750 q = next_chunk(q);
02751 }
02752 s = s->next;
02753 }
02754 }
02755 return sum;
02756 }
02757
02758
02759 static void do_check_malloc_state(mstate m) {
02760 bindex_t i;
02761 size_t total;
02762
02763 for (i = 0; i < NSMALLBINS; ++i)
02764 do_check_smallbin(m, i);
02765 for (i = 0; i < NTREEBINS; ++i)
02766 do_check_treebin(m, i);
02767
02768 if (m->dvsize != 0) {
02769 do_check_any_chunk(m, m->dv);
02770 assert(m->dvsize == chunksize(m->dv));
02771 assert(m->dvsize >= MIN_CHUNK_SIZE);
02772 assert(bin_find(m, m->dv) == 0);
02773 }
02774
02775 if (m->top != 0) {
02776 do_check_top_chunk(m, m->top);
02777 assert(m->topsize == chunksize(m->top));
02778 assert(m->topsize > 0);
02779 assert(bin_find(m, m->top) == 0);
02780 }
02781
02782 total = traverse_and_check(m);
02783 assert(total <= m->footprint);
02784 assert(m->footprint <= m->max_footprint);
02785 }
02786 #endif
02787
02788
02789
02790 #if !NO_MALLINFO
02791 static struct mallinfo internal_mallinfo(mstate m) {
02792 struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
02793 if (!PREACTION(m)) {
02794 check_malloc_state(m);
02795 if (is_initialized(m)) {
02796 size_t nfree = SIZE_T_ONE;
02797 size_t mfree = m->topsize + TOP_FOOT_SIZE;
02798 size_t sum = mfree;
02799 msegmentptr s = &m->seg;
02800 while (s != 0) {
02801 mchunkptr q = align_as_chunk(s->base);
02802 while (segment_holds(s, q) &&
02803 q != m->top && q->head != FENCEPOST_HEAD) {
02804 size_t sz = chunksize(q);
02805 sum += sz;
02806 if (!cinuse(q)) {
02807 mfree += sz;
02808 ++nfree;
02809 }
02810 q = next_chunk(q);
02811 }
02812 s = s->next;
02813 }
02814
02815 nm.arena = sum;
02816 nm.ordblks = nfree;
02817 nm.hblkhd = m->footprint - sum;
02818 nm.usmblks = m->max_footprint;
02819 nm.uordblks = m->footprint - mfree;
02820 nm.fordblks = mfree;
02821 nm.keepcost = m->topsize;
02822 }
02823
02824 POSTACTION(m);
02825 }
02826 return nm;
02827 }
02828 #endif
02829
02830 static void internal_malloc_stats(mstate m) {
02831 if (!PREACTION(m)) {
02832 size_t maxfp = 0;
02833 size_t fp = 0;
02834 size_t used = 0;
02835 check_malloc_state(m);
02836 if (is_initialized(m)) {
02837 msegmentptr s = &m->seg;
02838 maxfp = m->max_footprint;
02839 fp = m->footprint;
02840 used = fp - (m->topsize + TOP_FOOT_SIZE);
02841
02842 while (s != 0) {
02843 mchunkptr q = align_as_chunk(s->base);
02844 while (segment_holds(s, q) &&
02845 q != m->top && q->head != FENCEPOST_HEAD) {
02846 if (!cinuse(q))
02847 used -= chunksize(q);
02848 q = next_chunk(q);
02849 }
02850 s = s->next;
02851 }
02852 }
02853
02854 fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
02855 fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp));
02856 fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used));
02857
02858 POSTACTION(m);
02859 }
02860 }
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872 #define insert_small_chunk(M, P, S) {\
02873 bindex_t I = small_index(S);\
02874 mchunkptr B = smallbin_at(M, I);\
02875 mchunkptr F = B;\
02876 assert(S >= MIN_CHUNK_SIZE);\
02877 if (!smallmap_is_marked(M, I))\
02878 mark_smallmap(M, I);\
02879 else if (RTCHECK(ok_address(M, B->fd)))\
02880 F = B->fd;\
02881 else {\
02882 CORRUPTION_ERROR_ACTION(M);\
02883 }\
02884 B->fd = P;\
02885 F->bk = P;\
02886 P->fd = F;\
02887 P->bk = B;\
02888 }
02889
02890
02891 #define unlink_small_chunk(M, P, S) {\
02892 mchunkptr F = P->fd;\
02893 mchunkptr B = P->bk;\
02894 bindex_t I = small_index(S);\
02895 assert(P != B);\
02896 assert(P != F);\
02897 assert(chunksize(P) == small_index2size(I));\
02898 if (F == B)\
02899 clear_smallmap(M, I);\
02900 else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
02901 (B == smallbin_at(M,I) || ok_address(M, B)))) {\
02902 F->bk = B;\
02903 B->fd = F;\
02904 }\
02905 else {\
02906 CORRUPTION_ERROR_ACTION(M);\
02907 }\
02908 }
02909
02910
02911 #define unlink_first_small_chunk(M, B, P, I) {\
02912 mchunkptr F = P->fd;\
02913 assert(P != B);\
02914 assert(P != F);\
02915 assert(chunksize(P) == small_index2size(I));\
02916 if (B == F)\
02917 clear_smallmap(M, I);\
02918 else if (RTCHECK(ok_address(M, F))) {\
02919 B->fd = F;\
02920 F->bk = B;\
02921 }\
02922 else {\
02923 CORRUPTION_ERROR_ACTION(M);\
02924 }\
02925 }
02926
02927
02928
02929 #define replace_dv(M, P, S) {\
02930 size_t DVS = M->dvsize;\
02931 if (DVS != 0) {\
02932 mchunkptr DV = M->dv;\
02933 assert(is_small(DVS));\
02934 insert_small_chunk(M, DV, DVS);\
02935 }\
02936 M->dvsize = S;\
02937 M->dv = P;\
02938 }
02939
02940
02941
02942
02943 #define insert_large_chunk(M, X, S) {\
02944 tbinptr* H;\
02945 bindex_t I;\
02946 compute_tree_index(S, I);\
02947 H = treebin_at(M, I);\
02948 X->index = I;\
02949 X->child[0] = X->child[1] = 0;\
02950 if (!treemap_is_marked(M, I)) {\
02951 mark_treemap(M, I);\
02952 *H = X;\
02953 X->parent = (tchunkptr)H;\
02954 X->fd = X->bk = X;\
02955 }\
02956 else {\
02957 tchunkptr T = *H;\
02958 size_t K = S << leftshift_for_tree_index(I);\
02959 for (;;) {\
02960 if (chunksize(T) != S) {\
02961 tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
02962 K <<= 1;\
02963 if (*C != 0)\
02964 T = *C;\
02965 else if (RTCHECK(ok_address(M, C))) {\
02966 *C = X;\
02967 X->parent = T;\
02968 X->fd = X->bk = X;\
02969 break;\
02970 }\
02971 else {\
02972 CORRUPTION_ERROR_ACTION(M);\
02973 break;\
02974 }\
02975 }\
02976 else {\
02977 tchunkptr F = T->fd;\
02978 if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
02979 T->fd = F->bk = X;\
02980 X->fd = F;\
02981 X->bk = T;\
02982 X->parent = 0;\
02983 break;\
02984 }\
02985 else {\
02986 CORRUPTION_ERROR_ACTION(M);\
02987 break;\
02988 }\
02989 }\
02990 }\
02991 }\
02992 }
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011 #define unlink_large_chunk(M, X) {\
03012 tchunkptr XP = X->parent;\
03013 tchunkptr R;\
03014 if (X->bk != X) {\
03015 tchunkptr F = X->fd;\
03016 R = X->bk;\
03017 if (RTCHECK(ok_address(M, F))) {\
03018 F->bk = R;\
03019 R->fd = F;\
03020 }\
03021 else {\
03022 CORRUPTION_ERROR_ACTION(M);\
03023 }\
03024 }\
03025 else {\
03026 tchunkptr* RP;\
03027 if (((R = *(RP = &(X->child[1]))) != 0) ||\
03028 ((R = *(RP = &(X->child[0]))) != 0)) {\
03029 tchunkptr* CP;\
03030 while ((*(CP = &(R->child[1])) != 0) ||\
03031 (*(CP = &(R->child[0])) != 0)) {\
03032 R = *(RP = CP);\
03033 }\
03034 if (RTCHECK(ok_address(M, RP)))\
03035 *RP = 0;\
03036 else {\
03037 CORRUPTION_ERROR_ACTION(M);\
03038 }\
03039 }\
03040 }\
03041 if (XP != 0) {\
03042 tbinptr* H = treebin_at(M, X->index);\
03043 if (X == *H) {\
03044 if ((*H = R) == 0) \
03045 clear_treemap(M, X->index);\
03046 }\
03047 else if (RTCHECK(ok_address(M, XP))) {\
03048 if (XP->child[0] == X) \
03049 XP->child[0] = R;\
03050 else \
03051 XP->child[1] = R;\
03052 }\
03053 else\
03054 CORRUPTION_ERROR_ACTION(M);\
03055 if (R != 0) {\
03056 if (RTCHECK(ok_address(M, R))) {\
03057 tchunkptr C0, C1;\
03058 R->parent = XP;\
03059 if ((C0 = X->child[0]) != 0) {\
03060 if (RTCHECK(ok_address(M, C0))) {\
03061 R->child[0] = C0;\
03062 C0->parent = R;\
03063 }\
03064 else\
03065 CORRUPTION_ERROR_ACTION(M);\
03066 }\
03067 if ((C1 = X->child[1]) != 0) {\
03068 if (RTCHECK(ok_address(M, C1))) {\
03069 R->child[1] = C1;\
03070 C1->parent = R;\
03071 }\
03072 else\
03073 CORRUPTION_ERROR_ACTION(M);\
03074 }\
03075 }\
03076 else\
03077 CORRUPTION_ERROR_ACTION(M);\
03078 }\
03079 }\
03080 }
03081
03082
03083
03084 #define insert_chunk(M, P, S)\
03085 if (is_small(S)) insert_small_chunk(M, P, S)\
03086 else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
03087
03088 #define unlink_chunk(M, P, S)\
03089 if (is_small(S)) unlink_small_chunk(M, P, S)\
03090 else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
03091
03092
03093
03094
03095 #if ONLY_MSPACES
03096 #define internal_malloc(m, b) mspace_malloc(m, b)
03097 #define internal_free(m, mem) mspace_free(m,mem);
03098 #else
03099 #if MSPACES
03100 #define internal_malloc(m, b)\
03101 (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
03102 #define internal_free(m, mem)\
03103 if (m == gm) dlfree(mem); else mspace_free(m,mem);
03104 #else
03105 #define internal_malloc(m, b) dlmalloc(b)
03106 #define internal_free(m, mem) dlfree(mem)
03107 #endif
03108 #endif
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123 static void* mmap_alloc(mstate m, size_t nb) {
03124 size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
03125 if (mmsize > nb) {
03126 char* mm = (char*)(DIRECT_MMAP(mmsize));
03127 if (mm != CMFAIL) {
03128 size_t offset = align_offset(chunk2mem(mm));
03129 size_t psize = mmsize - offset - MMAP_FOOT_PAD;
03130 mchunkptr p = (mchunkptr)(mm + offset);
03131 p->prev_foot = offset | IS_MMAPPED_BIT;
03132 (p)->head = (psize|CINUSE_BIT);
03133 mark_inuse_foot(m, p, psize);
03134 chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
03135 chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
03136
03137 if (mm < m->least_addr)
03138 m->least_addr = mm;
03139 if ((m->footprint += mmsize) > m->max_footprint)
03140 m->max_footprint = m->footprint;
03141 assert(is_aligned(chunk2mem(p)));
03142 check_mmapped_chunk(m, p);
03143 return chunk2mem(p);
03144 }
03145 }
03146 return 0;
03147 }
03148
03149
03150 static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
03151 size_t oldsize = chunksize(oldp);
03152 if (is_small(nb))
03153 return 0;
03154
03155 if (oldsize >= nb + SIZE_T_SIZE &&
03156 (oldsize - nb) <= (mparams.granularity << 1))
03157 return oldp;
03158 else {
03159 size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
03160 size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
03161 size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
03162 CHUNK_ALIGN_MASK);
03163 char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
03164 oldmmsize, newmmsize, 1);
03165 if (cp != CMFAIL) {
03166 mchunkptr newp = (mchunkptr)(cp + offset);
03167 size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
03168 newp->head = (psize|CINUSE_BIT);
03169 mark_inuse_foot(m, newp, psize);
03170 chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
03171 chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
03172
03173 if (cp < m->least_addr)
03174 m->least_addr = cp;
03175 if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
03176 m->max_footprint = m->footprint;
03177 check_mmapped_chunk(m, newp);
03178 return newp;
03179 }
03180 }
03181 return 0;
03182 }
03183
03184
03185
03186
03187 static void init_top(mstate m, mchunkptr p, size_t psize) {
03188
03189 size_t offset = align_offset(chunk2mem(p));
03190 p = (mchunkptr)((char*)p + offset);
03191 psize -= offset;
03192
03193 m->top = p;
03194 m->topsize = psize;
03195 p->head = psize | PINUSE_BIT;
03196
03197 chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
03198 m->trim_check = mparams.trim_threshold;
03199 }
03200
03201
03202 static void init_bins(mstate m) {
03203
03204 bindex_t i;
03205 for (i = 0; i < NSMALLBINS; ++i) {
03206 sbinptr bin = smallbin_at(m,i);
03207 bin->fd = bin->bk = bin;
03208 }
03209 }
03210
03211 #if PROCEED_ON_ERROR
03212
03213
03214 static void reset_on_error(mstate m) {
03215 int i;
03216 ++malloc_corruption_error_count;
03217
03218 m->smallbins = m->treebins = 0;
03219 m->dvsize = m->topsize = 0;
03220 m->seg.base = 0;
03221 m->seg.size = 0;
03222 m->seg.next = 0;
03223 m->top = m->dv = 0;
03224 for (i = 0; i < NTREEBINS; ++i)
03225 *treebin_at(m, i) = 0;
03226 init_bins(m);
03227 }
03228 #endif
03229
03230
03231 static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
03232 size_t nb) {
03233 mchunkptr p = align_as_chunk(newbase);
03234 mchunkptr oldfirst = align_as_chunk(oldbase);
03235 size_t psize = (char*)oldfirst - (char*)p;
03236 mchunkptr q = chunk_plus_offset(p, nb);
03237 size_t qsize = psize - nb;
03238 set_size_and_pinuse_of_inuse_chunk(m, p, nb);
03239
03240 assert((char*)oldfirst > (char*)q);
03241 assert(pinuse(oldfirst));
03242 assert(qsize >= MIN_CHUNK_SIZE);
03243
03244
03245 if (oldfirst == m->top) {
03246 size_t tsize = m->topsize += qsize;
03247 m->top = q;
03248 q->head = tsize | PINUSE_BIT;
03249 check_top_chunk(m, q);
03250 }
03251 else if (oldfirst == m->dv) {
03252 size_t dsize = m->dvsize += qsize;
03253 m->dv = q;
03254 set_size_and_pinuse_of_free_chunk(q, dsize);
03255 }
03256 else {
03257 if (!cinuse(oldfirst)) {
03258 size_t nsize = chunksize(oldfirst);
03259 unlink_chunk(m, oldfirst, nsize);
03260 oldfirst = chunk_plus_offset(oldfirst, nsize);
03261 qsize += nsize;
03262 }
03263 set_free_with_pinuse(q, qsize, oldfirst);
03264 insert_chunk(m, q, qsize);
03265 check_free_chunk(m, q);
03266 }
03267
03268 check_malloced_chunk(m, chunk2mem(p), nb);
03269 return chunk2mem(p);
03270 }
03271
03272
03273
03274 static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
03275
03276 char* old_top = (char*)m->top;
03277 msegmentptr oldsp = segment_holding(m, old_top);
03278 char* old_end = oldsp->base + oldsp->size;
03279 size_t ssize = pad_request(sizeof(struct malloc_segment));
03280 char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
03281 size_t offset = align_offset(chunk2mem(rawsp));
03282 char* asp = rawsp + offset;
03283 char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
03284 mchunkptr sp = (mchunkptr)csp;
03285 msegmentptr ss = (msegmentptr)(chunk2mem(sp));
03286 mchunkptr tnext = chunk_plus_offset(sp, ssize);
03287 mchunkptr p = tnext;
03288 int nfences = 0;
03289
03290
03291 init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
03292
03293
03294 assert(is_aligned(ss));
03295 set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
03296 *ss = m->seg;
03297 m->seg.base = tbase;
03298 m->seg.size = tsize;
03299 m->seg.sflags = mmapped;
03300 m->seg.next = ss;
03301
03302
03303 for (;;) {
03304 mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
03305 p->head = FENCEPOST_HEAD;
03306 ++nfences;
03307 if ((char*)(&(nextp->head)) < old_end)
03308 p = nextp;
03309 else
03310 break;
03311 }
03312 assert(nfences >= 2);
03313
03314
03315 if (csp != old_top) {
03316 mchunkptr q = (mchunkptr)old_top;
03317 size_t psize = csp - old_top;
03318 mchunkptr tn = chunk_plus_offset(q, psize);
03319 set_free_with_pinuse(q, psize, tn);
03320 insert_chunk(m, q, psize);
03321 }
03322
03323 check_top_chunk(m, m->top);
03324 }
03325
03326
03327
03328
03329 static void* sys_alloc(mstate m, size_t nb) {
03330 char* tbase = CMFAIL;
03331 size_t tsize = 0;
03332 flag_t mmap_flag = 0;
03333
03334 init_mparams();
03335
03336
03337 if (use_mmap(m) && nb >= mparams.mmap_threshold) {
03338 void* mem = mmap_alloc(m, nb);
03339 if (mem != 0)
03340 return mem;
03341 }
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360 if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
03361 char* br = CMFAIL;
03362 msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
03363 size_t asize = 0;
03364 ACQUIRE_MORECORE_LOCK();
03365
03366 if (ss == 0) {
03367 char* base = (char*)CALL_MORECORE(0);
03368 if (base != CMFAIL) {
03369 asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
03370
03371 if (!is_page_aligned(base))
03372 asize += (page_align((size_t)base) - (size_t)base);
03373
03374 if (asize < HALF_MAX_SIZE_T &&
03375 (br = (char*)(CALL_MORECORE(asize))) == base) {
03376 tbase = base;
03377 tsize = asize;
03378 }
03379 }
03380 }
03381 else {
03382
03383 asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE);
03384
03385 if (asize < HALF_MAX_SIZE_T &&
03386 (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
03387 tbase = br;
03388 tsize = asize;
03389 }
03390 }
03391
03392 if (tbase == CMFAIL) {
03393 if (br != CMFAIL) {
03394 if (asize < HALF_MAX_SIZE_T &&
03395 asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
03396 size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize);
03397 if (esize < HALF_MAX_SIZE_T) {
03398 char* end = (char*)CALL_MORECORE(esize);
03399 if (end != CMFAIL)
03400 asize += esize;
03401 else {
03402 CALL_MORECORE(-asize);
03403 br = CMFAIL;
03404 }
03405 }
03406 }
03407 }
03408 if (br != CMFAIL) {
03409 tbase = br;
03410 tsize = asize;
03411 }
03412 else
03413 disable_contiguous(m);
03414 }
03415
03416 RELEASE_MORECORE_LOCK();
03417 }
03418
03419 if (HAVE_MMAP && tbase == CMFAIL) {
03420 size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
03421 size_t rsize = granularity_align(req);
03422 if (rsize > nb) {
03423 char* mp = (char*)(CALL_MMAP(rsize));
03424 if (mp != CMFAIL) {
03425 tbase = mp;
03426 tsize = rsize;
03427 mmap_flag = IS_MMAPPED_BIT;
03428 }
03429 }
03430 }
03431
03432 if (HAVE_MORECORE && tbase == CMFAIL) {
03433 size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
03434 if (asize < HALF_MAX_SIZE_T) {
03435 char* br = CMFAIL;
03436 char* end = CMFAIL;
03437 ACQUIRE_MORECORE_LOCK();
03438 br = (char*)(CALL_MORECORE(asize));
03439 end = (char*)(CALL_MORECORE(0));
03440 RELEASE_MORECORE_LOCK();
03441 if (br != CMFAIL && end != CMFAIL && br < end) {
03442 size_t ssize = end - br;
03443 if (ssize > nb + TOP_FOOT_SIZE) {
03444 tbase = br;
03445 tsize = ssize;
03446 }
03447 }
03448 }
03449 }
03450
03451 if (tbase != CMFAIL) {
03452
03453 if ((m->footprint += tsize) > m->max_footprint)
03454 m->max_footprint = m->footprint;
03455
03456 if (!is_initialized(m)) {
03457 m->seg.base = m->least_addr = tbase;
03458 m->seg.size = tsize;
03459 m->seg.sflags = mmap_flag;
03460 m->magic = mparams.magic;
03461 init_bins(m);
03462 if (is_global(m))
03463 init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
03464 else {
03465
03466 mchunkptr mn = next_chunk(mem2chunk(m));
03467 init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
03468 }
03469 }
03470
03471 else {
03472
03473 msegmentptr sp = &m->seg;
03474 while (sp != 0 && tbase != sp->base + sp->size)
03475 sp = sp->next;
03476 if (sp != 0 &&
03477 !is_extern_segment(sp) &&
03478 (sp->sflags & IS_MMAPPED_BIT) == mmap_flag &&
03479 segment_holds(sp, m->top)) {
03480 sp->size += tsize;
03481 init_top(m, m->top, m->topsize + tsize);
03482 }
03483 else {
03484 if (tbase < m->least_addr)
03485 m->least_addr = tbase;
03486 sp = &m->seg;
03487 while (sp != 0 && sp->base != tbase + tsize)
03488 sp = sp->next;
03489 if (sp != 0 &&
03490 !is_extern_segment(sp) &&
03491 (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) {
03492 char* oldbase = sp->base;
03493 sp->base = tbase;
03494 sp->size += tsize;
03495 return prepend_alloc(m, tbase, oldbase, nb);
03496 }
03497 else
03498 add_segment(m, tbase, tsize, mmap_flag);
03499 }
03500 }
03501
03502 if (nb < m->topsize) {
03503 size_t rsize = m->topsize -= nb;
03504 mchunkptr p = m->top;
03505 mchunkptr r = m->top = chunk_plus_offset(p, nb);
03506 r->head = rsize | PINUSE_BIT;
03507 set_size_and_pinuse_of_inuse_chunk(m, p, nb);
03508 check_top_chunk(m, m->top);
03509 check_malloced_chunk(m, chunk2mem(p), nb);
03510 return chunk2mem(p);
03511 }
03512 }
03513
03514 MALLOC_FAILURE_ACTION;
03515 return 0;
03516 }
03517
03518
03519
03520
03521 static size_t release_unused_segments(mstate m) {
03522 size_t released = 0;
03523 msegmentptr pred = &m->seg;
03524 msegmentptr sp = pred->next;
03525 while (sp != 0) {
03526 char* base = sp->base;
03527 size_t size = sp->size;
03528 msegmentptr next = sp->next;
03529 if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
03530 mchunkptr p = align_as_chunk(base);
03531 size_t psize = chunksize(p);
03532
03533 if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
03534 tchunkptr tp = (tchunkptr)p;
03535 assert(segment_holds(sp, (char*)sp));
03536 if (p == m->dv) {
03537 m->dv = 0;
03538 m->dvsize = 0;
03539 }
03540 else {
03541 unlink_large_chunk(m, tp);
03542 }
03543 if (CALL_MUNMAP(base, size) == 0) {
03544 released += size;
03545 m->footprint -= size;
03546
03547 sp = pred;
03548 sp->next = next;
03549 }
03550 else {
03551 insert_large_chunk(m, tp, psize);
03552 }
03553 }
03554 }
03555 pred = sp;
03556 sp = next;
03557 }
03558 return released;
03559 }
03560
03561 static int sys_trim(mstate m, size_t pad) {
03562 size_t released = 0;
03563 if (pad < MAX_REQUEST && is_initialized(m)) {
03564 pad += TOP_FOOT_SIZE;
03565
03566 if (m->topsize > pad) {
03567
03568 size_t unit = mparams.granularity;
03569 size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
03570 SIZE_T_ONE) * unit;
03571 msegmentptr sp = segment_holding(m, (char*)m->top);
03572
03573 if (!is_extern_segment(sp)) {
03574 if (is_mmapped_segment(sp)) {
03575 if (HAVE_MMAP &&
03576 sp->size >= extra &&
03577 !has_segment_link(m, sp)) {
03578 size_t newsize = sp->size - extra;
03579
03580 if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
03581 (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
03582 released = extra;
03583 }
03584 }
03585 }
03586 else if (HAVE_MORECORE) {
03587 if (extra >= HALF_MAX_SIZE_T)
03588 extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
03589 ACQUIRE_MORECORE_LOCK();
03590 {
03591
03592 char* old_br = (char*)(CALL_MORECORE(0));
03593 if (old_br == sp->base + sp->size) {
03594 char* rel_br = (char*)(CALL_MORECORE(-extra));
03595 char* new_br = (char*)(CALL_MORECORE(0));
03596 if (rel_br != CMFAIL && new_br < old_br)
03597 released = old_br - new_br;
03598 }
03599 }
03600 RELEASE_MORECORE_LOCK();
03601 }
03602 }
03603
03604 if (released != 0) {
03605 sp->size -= released;
03606 m->footprint -= released;
03607 init_top(m, m->top, m->topsize - released);
03608 check_top_chunk(m, m->top);
03609 }
03610 }
03611
03612
03613 if (HAVE_MMAP)
03614 released += release_unused_segments(m);
03615
03616
03617 if (released == 0)
03618 m->trim_check = MAX_SIZE_T;
03619 }
03620
03621 return (released != 0)? 1 : 0;
03622 }
03623
03624
03625
03626
03627 static void* tmalloc_large(mstate m, size_t nb) {
03628 tchunkptr v = 0;
03629 size_t rsize = -nb;
03630 tchunkptr t;
03631 bindex_t idx;
03632 compute_tree_index(nb, idx);
03633
03634 if ((t = *treebin_at(m, idx)) != 0) {
03635
03636 size_t sizebits = nb << leftshift_for_tree_index(idx);
03637 tchunkptr rst = 0;
03638 for (;;) {
03639 tchunkptr rt;
03640 size_t trem = chunksize(t) - nb;
03641 if (trem < rsize) {
03642 v = t;
03643 if ((rsize = trem) == 0)
03644 break;
03645 }
03646 rt = t->child[1];
03647 t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
03648 if (rt != 0 && rt != t)
03649 rst = rt;
03650 if (t == 0) {
03651 t = rst;
03652 break;
03653 }
03654 sizebits <<= 1;
03655 }
03656 }
03657
03658 if (t == 0 && v == 0) {
03659 binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
03660 if (leftbits != 0) {
03661 bindex_t i;
03662 binmap_t leastbit = least_bit(leftbits);
03663 compute_bit2idx(leastbit, i);
03664 t = *treebin_at(m, i);
03665 }
03666 }
03667
03668 while (t != 0) {
03669 size_t trem = chunksize(t) - nb;
03670 if (trem < rsize) {
03671 rsize = trem;
03672 v = t;
03673 }
03674 t = leftmost_child(t);
03675 }
03676
03677
03678 if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
03679 if (RTCHECK(ok_address(m, v))) {
03680 mchunkptr r = chunk_plus_offset(v, nb);
03681 assert(chunksize(v) == rsize + nb);
03682 if (RTCHECK(ok_next(v, r))) {
03683 unlink_large_chunk(m, v);
03684 if (rsize < MIN_CHUNK_SIZE)
03685 set_inuse_and_pinuse(m, v, (rsize + nb));
03686 else {
03687 set_size_and_pinuse_of_inuse_chunk(m, v, nb);
03688 set_size_and_pinuse_of_free_chunk(r, rsize);
03689 insert_chunk(m, r, rsize);
03690 }
03691 return chunk2mem(v);
03692 }
03693 }
03694 CORRUPTION_ERROR_ACTION(m);
03695 }
03696 return 0;
03697 }
03698
03699
03700 static void* tmalloc_small(mstate m, size_t nb) {
03701 tchunkptr t, v;
03702 size_t rsize;
03703 bindex_t i;
03704 binmap_t leastbit = least_bit(m->treemap);
03705 compute_bit2idx(leastbit, i);
03706
03707 v = t = *treebin_at(m, i);
03708 rsize = chunksize(t) - nb;
03709
03710 while ((t = leftmost_child(t)) != 0) {
03711 size_t trem = chunksize(t) - nb;
03712 if (trem < rsize) {
03713 rsize = trem;
03714 v = t;
03715 }
03716 }
03717
03718 if (RTCHECK(ok_address(m, v))) {
03719 mchunkptr r = chunk_plus_offset(v, nb);
03720 assert(chunksize(v) == rsize + nb);
03721 if (RTCHECK(ok_next(v, r))) {
03722 unlink_large_chunk(m, v);
03723 if (rsize < MIN_CHUNK_SIZE)
03724 set_inuse_and_pinuse(m, v, (rsize + nb));
03725 else {
03726 set_size_and_pinuse_of_inuse_chunk(m, v, nb);
03727 set_size_and_pinuse_of_free_chunk(r, rsize);
03728 replace_dv(m, r, rsize);
03729 }
03730 return chunk2mem(v);
03731 }
03732 }
03733
03734 CORRUPTION_ERROR_ACTION(m);
03735 return 0;
03736 }
03737
03738
03739
03740 static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
03741 if (bytes >= MAX_REQUEST) {
03742 MALLOC_FAILURE_ACTION;
03743 return 0;
03744 }
03745 if (!PREACTION(m)) {
03746 mchunkptr oldp = mem2chunk(oldmem);
03747 size_t oldsize = chunksize(oldp);
03748 mchunkptr next = chunk_plus_offset(oldp, oldsize);
03749 mchunkptr newp = 0;
03750 void* extra = 0;
03751
03752
03753
03754 if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
03755 ok_next(oldp, next) && ok_pinuse(next))) {
03756 size_t nb = request2size(bytes);
03757 if (is_mmapped(oldp))
03758 newp = mmap_resize(m, oldp, nb);
03759 else if (oldsize >= nb) {
03760 size_t rsize = oldsize - nb;
03761 newp = oldp;
03762 if (rsize >= MIN_CHUNK_SIZE) {
03763 mchunkptr remainder = chunk_plus_offset(newp, nb);
03764 set_inuse(m, newp, nb);
03765 set_inuse(m, remainder, rsize);
03766 extra = chunk2mem(remainder);
03767 }
03768 }
03769 else if (next == m->top && oldsize + m->topsize > nb) {
03770
03771 size_t newsize = oldsize + m->topsize;
03772 size_t newtopsize = newsize - nb;
03773 mchunkptr newtop = chunk_plus_offset(oldp, nb);
03774 set_inuse(m, oldp, nb);
03775 newtop->head = newtopsize |PINUSE_BIT;
03776 m->top = newtop;
03777 m->topsize = newtopsize;
03778 newp = oldp;
03779 }
03780 }
03781 else {
03782 USAGE_ERROR_ACTION(m, oldmem);
03783 POSTACTION(m);
03784 return 0;
03785 }
03786
03787 POSTACTION(m);
03788
03789 if (newp != 0) {
03790 if (extra != 0) {
03791 internal_free(m, extra);
03792 }
03793 check_inuse_chunk(m, newp);
03794 return chunk2mem(newp);
03795 }
03796 else {
03797 void* newmem = internal_malloc(m, bytes);
03798 if (newmem != 0) {
03799 size_t oc = oldsize - overhead_for(oldp);
03800 memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
03801 internal_free(m, oldmem);
03802 }
03803 return newmem;
03804 }
03805 }
03806 return 0;
03807 }
03808
03809
03810
03811 static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
03812 if (alignment <= MALLOC_ALIGNMENT)
03813 return internal_malloc(m, bytes);
03814 if (alignment < MIN_CHUNK_SIZE)
03815 alignment = MIN_CHUNK_SIZE;
03816 if ((alignment & (alignment-SIZE_T_ONE)) != 0) {
03817 size_t a = MALLOC_ALIGNMENT << 1;
03818 while (a < alignment) a <<= 1;
03819 alignment = a;
03820 }
03821
03822 if (bytes >= MAX_REQUEST - alignment) {
03823 if (m != 0) {
03824 MALLOC_FAILURE_ACTION;
03825 }
03826 }
03827 else {
03828 size_t nb = request2size(bytes);
03829 size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
03830 char* mem = (char*)internal_malloc(m, req);
03831 if (mem != 0) {
03832 void* leader = 0;
03833 void* trailer = 0;
03834 mchunkptr p = mem2chunk(mem);
03835
03836 if (PREACTION(m)) return 0;
03837 if ((((size_t)(mem)) % alignment) != 0) {
03838
03839
03840
03841
03842
03843
03844
03845
03846 char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
03847 alignment -
03848 SIZE_T_ONE)) &
03849 -alignment));
03850 char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
03851 br : br+alignment;
03852 mchunkptr newp = (mchunkptr)pos;
03853 size_t leadsize = pos - (char*)(p);
03854 size_t newsize = chunksize(p) - leadsize;
03855
03856 if (is_mmapped(p)) {
03857 newp->prev_foot = p->prev_foot + leadsize;
03858 newp->head = (newsize|CINUSE_BIT);
03859 }
03860 else {
03861 set_inuse(m, newp, newsize);
03862 set_inuse(m, p, leadsize);
03863 leader = chunk2mem(p);
03864 }
03865 p = newp;
03866 }
03867
03868
03869 if (!is_mmapped(p)) {
03870 size_t size = chunksize(p);
03871 if (size > nb + MIN_CHUNK_SIZE) {
03872 size_t remainder_size = size - nb;
03873 mchunkptr remainder = chunk_plus_offset(p, nb);
03874 set_inuse(m, p, nb);
03875 set_inuse(m, remainder, remainder_size);
03876 trailer = chunk2mem(remainder);
03877 }
03878 }
03879
03880 assert (chunksize(p) >= nb);
03881 assert((((size_t)(chunk2mem(p))) % alignment) == 0);
03882 check_inuse_chunk(m, p);
03883 POSTACTION(m);
03884 if (leader != 0) {
03885 internal_free(m, leader);
03886 }
03887 if (trailer != 0) {
03888 internal_free(m, trailer);
03889 }
03890 return chunk2mem(p);
03891 }
03892 }
03893 return 0;
03894 }
03895
03896
03897
03898 static void** ialloc(mstate m,
03899 size_t n_elements,
03900 size_t* sizes,
03901 int opts,
03902 void* chunks[]) {
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912 size_t element_size;
03913 size_t contents_size;
03914 size_t array_size;
03915 void* mem;
03916 mchunkptr p;
03917 size_t remainder_size;
03918 void** marray;
03919 mchunkptr array_chunk;
03920 flag_t was_enabled;
03921 size_t size;
03922 size_t i;
03923
03924
03925 if (chunks != 0) {
03926 if (n_elements == 0)
03927 return chunks;
03928 marray = chunks;
03929 array_size = 0;
03930 }
03931 else {
03932
03933 if (n_elements == 0)
03934 return (void**)internal_malloc(m, 0);
03935 marray = 0;
03936 array_size = request2size(n_elements * (sizeof(void*)));
03937 }
03938
03939
03940 if (opts & 0x1) {
03941 element_size = request2size(*sizes);
03942 contents_size = n_elements * element_size;
03943 }
03944 else {
03945 element_size = 0;
03946 contents_size = 0;
03947 for (i = 0; i != n_elements; ++i)
03948 contents_size += request2size(sizes[i]);
03949 }
03950
03951 size = contents_size + array_size;
03952
03953
03954
03955
03956
03957
03958 was_enabled = use_mmap(m);
03959 disable_mmap(m);
03960 mem = internal_malloc(m, size - CHUNK_OVERHEAD);
03961 if (was_enabled)
03962 enable_mmap(m);
03963 if (mem == 0)
03964 return 0;
03965
03966 if (PREACTION(m)) return 0;
03967 p = mem2chunk(mem);
03968 remainder_size = chunksize(p);
03969
03970 assert(!is_mmapped(p));
03971
03972 if (opts & 0x2) {
03973 memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
03974 }
03975
03976
03977 if (marray == 0) {
03978 size_t array_chunk_size;
03979 array_chunk = chunk_plus_offset(p, contents_size);
03980 array_chunk_size = remainder_size - contents_size;
03981 marray = (void**) (chunk2mem(array_chunk));
03982 set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
03983 remainder_size = contents_size;
03984 }
03985
03986
03987 for (i = 0; ; ++i) {
03988 marray[i] = chunk2mem(p);
03989 if (i != n_elements-1) {
03990 if (element_size != 0)
03991 size = element_size;
03992 else
03993 size = request2size(sizes[i]);
03994 remainder_size -= size;
03995 set_size_and_pinuse_of_inuse_chunk(m, p, size);
03996 p = chunk_plus_offset(p, size);
03997 }
03998 else {
03999 set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
04000 break;
04001 }
04002 }
04003
04004 #if DEBUG
04005 if (marray != chunks) {
04006
04007 if (element_size != 0) {
04008 assert(remainder_size == element_size);
04009 }
04010 else {
04011 assert(remainder_size == request2size(sizes[i]));
04012 }
04013 check_inuse_chunk(m, mem2chunk(marray));
04014 }
04015 for (i = 0; i != n_elements; ++i)
04016 check_inuse_chunk(m, mem2chunk(marray[i]));
04017
04018 #endif
04019
04020 POSTACTION(m);
04021 return marray;
04022 }
04023
04024
04025
04026
04027 #if !ONLY_MSPACES
04028
04029 void* dlmalloc(size_t bytes) {
04030
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047
04048
04049
04050
04051
04052
04053 if (!PREACTION(gm)) {
04054 void* mem;
04055 size_t nb;
04056 if (bytes <= MAX_SMALL_REQUEST) {
04057 bindex_t idx;
04058 binmap_t smallbits;
04059 nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
04060 idx = small_index(nb);
04061 smallbits = gm->smallmap >> idx;
04062
04063 if ((smallbits & 0x3U) != 0) {
04064 mchunkptr b, p;
04065 idx += ~smallbits & 1;
04066 b = smallbin_at(gm, idx);
04067 p = b->fd;
04068 assert(chunksize(p) == small_index2size(idx));
04069 unlink_first_small_chunk(gm, b, p, idx);
04070 set_inuse_and_pinuse(gm, p, small_index2size(idx));
04071 mem = chunk2mem(p);
04072 check_malloced_chunk(gm, mem, nb);
04073 goto postaction;
04074 }
04075
04076 else if (nb > gm->dvsize) {
04077 if (smallbits != 0) {
04078 mchunkptr b, p, r;
04079 size_t rsize;
04080 bindex_t i;
04081 binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
04082 binmap_t leastbit = least_bit(leftbits);
04083 compute_bit2idx(leastbit, i);
04084 b = smallbin_at(gm, i);
04085 p = b->fd;
04086 assert(chunksize(p) == small_index2size(i));
04087 unlink_first_small_chunk(gm, b, p, i);
04088 rsize = small_index2size(i) - nb;
04089
04090 if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
04091 set_inuse_and_pinuse(gm, p, small_index2size(i));
04092 else {
04093 set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
04094 r = chunk_plus_offset(p, nb);
04095 set_size_and_pinuse_of_free_chunk(r, rsize);
04096 replace_dv(gm, r, rsize);
04097 }
04098 mem = chunk2mem(p);
04099 check_malloced_chunk(gm, mem, nb);
04100 goto postaction;
04101 }
04102
04103 else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
04104 check_malloced_chunk(gm, mem, nb);
04105 goto postaction;
04106 }
04107 }
04108 }
04109 else if (bytes >= MAX_REQUEST)
04110 nb = MAX_SIZE_T;
04111 else {
04112 nb = pad_request(bytes);
04113 if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
04114 check_malloced_chunk(gm, mem, nb);
04115 goto postaction;
04116 }
04117 }
04118
04119 if (nb <= gm->dvsize) {
04120 size_t rsize = gm->dvsize - nb;
04121 mchunkptr p = gm->dv;
04122 if (rsize >= MIN_CHUNK_SIZE) {
04123 mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
04124 gm->dvsize = rsize;
04125 set_size_and_pinuse_of_free_chunk(r, rsize);
04126 set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
04127 }
04128 else {
04129 size_t dvs = gm->dvsize;
04130 gm->dvsize = 0;
04131 gm->dv = 0;
04132 set_inuse_and_pinuse(gm, p, dvs);
04133 }
04134 mem = chunk2mem(p);
04135 check_malloced_chunk(gm, mem, nb);
04136 goto postaction;
04137 }
04138
04139 else if (nb < gm->topsize) {
04140 size_t rsize = gm->topsize -= nb;
04141 mchunkptr p = gm->top;
04142 mchunkptr r = gm->top = chunk_plus_offset(p, nb);
04143 r->head = rsize | PINUSE_BIT;
04144 set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
04145 mem = chunk2mem(p);
04146 check_top_chunk(gm, gm->top);
04147 check_malloced_chunk(gm, mem, nb);
04148 goto postaction;
04149 }
04150
04151 mem = sys_alloc(gm, nb);
04152
04153 postaction:
04154 POSTACTION(gm);
04155 return mem;
04156 }
04157
04158 return 0;
04159 }
04160
04161 void dlfree(void* mem) {
04162
04163
04164
04165
04166
04167
04168 if (mem != 0) {
04169 mchunkptr p = mem2chunk(mem);
04170 #if FOOTERS
04171 mstate fm = get_mstate_for(p);
04172 if (!ok_magic(fm)) {
04173 USAGE_ERROR_ACTION(fm, p);
04174 return;
04175 }
04176 #else
04177 #define fm gm
04178 #endif
04179 if (!PREACTION(fm)) {
04180 check_inuse_chunk(fm, p);
04181 if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
04182 size_t psize = chunksize(p);
04183 mchunkptr next = chunk_plus_offset(p, psize);
04184 if (!pinuse(p)) {
04185 size_t prevsize = p->prev_foot;
04186 if ((prevsize & IS_MMAPPED_BIT) != 0) {
04187 prevsize &= ~IS_MMAPPED_BIT;
04188 psize += prevsize + MMAP_FOOT_PAD;
04189 if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
04190 fm->footprint -= psize;
04191 goto postaction;
04192 }
04193 else {
04194 mchunkptr prev = chunk_minus_offset(p, prevsize);
04195 psize += prevsize;
04196 p = prev;
04197 if (RTCHECK(ok_address(fm, prev))) {
04198 if (p != fm->dv) {
04199 unlink_chunk(fm, p, prevsize);
04200 }
04201 else if ((next->head & INUSE_BITS) == INUSE_BITS) {
04202 fm->dvsize = psize;
04203 set_free_with_pinuse(p, psize, next);
04204 goto postaction;
04205 }
04206 }
04207 else
04208 goto erroraction;
04209 }
04210 }
04211
04212 if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
04213 if (!cinuse(next)) {
04214 if (next == fm->top) {
04215 size_t tsize = fm->topsize += psize;
04216 fm->top = p;
04217 p->head = tsize | PINUSE_BIT;
04218 if (p == fm->dv) {
04219 fm->dv = 0;
04220 fm->dvsize = 0;
04221 }
04222 if (should_trim(fm, tsize))
04223 sys_trim(fm, 0);
04224 goto postaction;
04225 }
04226 else if (next == fm->dv) {
04227 size_t dsize = fm->dvsize += psize;
04228 fm->dv = p;
04229 set_size_and_pinuse_of_free_chunk(p, dsize);
04230 goto postaction;
04231 }
04232 else {
04233 size_t nsize = chunksize(next);
04234 psize += nsize;
04235 unlink_chunk(fm, next, nsize);
04236 set_size_and_pinuse_of_free_chunk(p, psize);
04237 if (p == fm->dv) {
04238 fm->dvsize = psize;
04239 goto postaction;
04240 }
04241 }
04242 }
04243 else
04244 set_free_with_pinuse(p, psize, next);
04245 insert_chunk(fm, p, psize);
04246 check_free_chunk(fm, p);
04247 goto postaction;
04248 }
04249 }
04250 erroraction:
04251 USAGE_ERROR_ACTION(fm, p);
04252 postaction:
04253 POSTACTION(fm);
04254 }
04255 }
04256 #if !FOOTERS
04257 #undef fm
04258 #endif
04259 }
04260
04261 void* dlcalloc(size_t n_elements, size_t elem_size) {
04262 void* mem;
04263 size_t req = 0;
04264 if (n_elements != 0) {
04265 req = n_elements * elem_size;
04266 if (((n_elements | elem_size) & ~(size_t)0xffff) &&
04267 (req / n_elements != elem_size))
04268 req = MAX_SIZE_T;
04269 }
04270 mem = dlmalloc(req);
04271 if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
04272 memset(mem, 0, req);
04273 return mem;
04274 }
04275
04276 void* dlrealloc(void* oldmem, size_t bytes) {
04277 if (oldmem == 0)
04278 return dlmalloc(bytes);
04279 #ifdef REALLOC_ZERO_BYTES_FREES
04280 if (bytes == 0) {
04281 dlfree(oldmem);
04282 return 0;
04283 }
04284 #endif
04285 else {
04286 #if ! FOOTERS
04287 mstate m = gm;
04288 #else
04289 mstate m = get_mstate_for(mem2chunk(oldmem));
04290 if (!ok_magic(m)) {
04291 USAGE_ERROR_ACTION(m, oldmem);
04292 return 0;
04293 }
04294 #endif
04295 return internal_realloc(m, oldmem, bytes);
04296 }
04297 }
04298
04299 void* dlmemalign(size_t alignment, size_t bytes) {
04300 return internal_memalign(gm, alignment, bytes);
04301 }
04302
04303 void** dlindependent_calloc(size_t n_elements, size_t elem_size,
04304 void* chunks[]) {
04305 size_t sz = elem_size;
04306 return ialloc(gm, n_elements, &sz, 3, chunks);
04307 }
04308
04309 void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
04310 void* chunks[]) {
04311 return ialloc(gm, n_elements, sizes, 0, chunks);
04312 }
04313
04314 void* dlvalloc(size_t bytes) {
04315 size_t pagesz;
04316 init_mparams();
04317 pagesz = mparams.page_size;
04318 return dlmemalign(pagesz, bytes);
04319 }
04320
04321 void* dlpvalloc(size_t bytes) {
04322 size_t pagesz;
04323 init_mparams();
04324 pagesz = mparams.page_size;
04325 return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
04326 }
04327
04328 int dlmalloc_trim(size_t pad) {
04329 int result = 0;
04330 if (!PREACTION(gm)) {
04331 result = sys_trim(gm, pad);
04332 POSTACTION(gm);
04333 }
04334 return result;
04335 }
04336
04337 size_t dlmalloc_footprint(void) {
04338 return gm->footprint;
04339 }
04340
04341 size_t dlmalloc_max_footprint(void) {
04342 return gm->max_footprint;
04343 }
04344
04345 #if !NO_MALLINFO
04346 struct mallinfo dlmallinfo(void) {
04347 return internal_mallinfo(gm);
04348 }
04349 #endif
04350
04351 void dlmalloc_stats() {
04352 internal_malloc_stats(gm);
04353 }
04354
04355 size_t dlmalloc_usable_size(void* mem) {
04356 if (mem != 0) {
04357 mchunkptr p = mem2chunk(mem);
04358 if (cinuse(p))
04359 return chunksize(p) - overhead_for(p);
04360 }
04361 return 0;
04362 }
04363
04364 int dlmallopt(int param_number, int value) {
04365 return change_mparam(param_number, value);
04366 }
04367
04368 #endif
04369
04370
04371
04372 #if MSPACES
04373
04374 static mstate init_user_mstate(char* tbase, size_t tsize) {
04375 size_t msize = pad_request(sizeof(struct malloc_state));
04376 mchunkptr mn;
04377 mchunkptr msp = align_as_chunk(tbase);
04378 mstate m = (mstate)(chunk2mem(msp));
04379 memset(m, 0, msize);
04380 INITIAL_LOCK(&m->mutex);
04381 msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
04382 m->seg.base = m->least_addr = tbase;
04383 m->seg.size = m->footprint = m->max_footprint = tsize;
04384 m->magic = mparams.magic;
04385 m->mflags = mparams.default_mflags;
04386 disable_contiguous(m);
04387 init_bins(m);
04388 mn = next_chunk(mem2chunk(m));
04389 init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
04390 check_top_chunk(m, m->top);
04391 return m;
04392 }
04393
04394 mspace create_mspace(size_t capacity, int locked) {
04395 mstate m = 0;
04396 size_t msize = pad_request(sizeof(struct malloc_state));
04397 init_mparams();
04398
04399 if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
04400 size_t rs = ((capacity == 0)? mparams.granularity :
04401 (capacity + TOP_FOOT_SIZE + msize));
04402 size_t tsize = granularity_align(rs);
04403 char* tbase = (char*)(CALL_MMAP(tsize));
04404 if (tbase != CMFAIL) {
04405 m = init_user_mstate(tbase, tsize);
04406 m->seg.sflags = IS_MMAPPED_BIT;
04407 set_lock(m, locked);
04408 }
04409 }
04410 return (mspace)m;
04411 }
04412
04413 mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
04414 mstate m = 0;
04415 size_t msize = pad_request(sizeof(struct malloc_state));
04416 init_mparams();
04417
04418 if (capacity > msize + TOP_FOOT_SIZE &&
04419 capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
04420 m = init_user_mstate((char*)base, capacity);
04421 m->seg.sflags = EXTERN_BIT;
04422 set_lock(m, locked);
04423 }
04424 return (mspace)m;
04425 }
04426
04427 size_t destroy_mspace(mspace msp) {
04428 size_t freed = 0;
04429 mstate ms = (mstate)msp;
04430 if (ok_magic(ms)) {
04431 msegmentptr sp = &ms->seg;
04432 while (sp != 0) {
04433 char* base = sp->base;
04434 size_t size = sp->size;
04435 flag_t flag = sp->sflags;
04436 sp = sp->next;
04437 if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
04438 CALL_MUNMAP(base, size) == 0)
04439 freed += size;
04440 }
04441 }
04442 else {
04443 USAGE_ERROR_ACTION(ms,ms);
04444 }
04445 return freed;
04446 }
04447
04448
04449
04450
04451
04452
04453
04454 void* mspace_malloc(mspace msp, size_t bytes) {
04455 mstate ms = (mstate)msp;
04456 if (!ok_magic(ms)) {
04457 USAGE_ERROR_ACTION(ms,ms);
04458 return 0;
04459 }
04460 if (!PREACTION(ms)) {
04461 void* mem;
04462 size_t nb;
04463 if (bytes <= MAX_SMALL_REQUEST) {
04464 bindex_t idx;
04465 binmap_t smallbits;
04466 nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
04467 idx = small_index(nb);
04468 smallbits = ms->smallmap >> idx;
04469
04470 if ((smallbits & 0x3U) != 0) {
04471 mchunkptr b, p;
04472 idx += ~smallbits & 1;
04473 b = smallbin_at(ms, idx);
04474 p = b->fd;
04475 assert(chunksize(p) == small_index2size(idx));
04476 unlink_first_small_chunk(ms, b, p, idx);
04477 set_inuse_and_pinuse(ms, p, small_index2size(idx));
04478 mem = chunk2mem(p);
04479 check_malloced_chunk(ms, mem, nb);
04480 goto postaction;
04481 }
04482
04483 else if (nb > ms->dvsize) {
04484 if (smallbits != 0) {
04485 mchunkptr b, p, r;
04486 size_t rsize;
04487 bindex_t i;
04488 binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
04489 binmap_t leastbit = least_bit(leftbits);
04490 compute_bit2idx(leastbit, i);
04491 b = smallbin_at(ms, i);
04492 p = b->fd;
04493 assert(chunksize(p) == small_index2size(i));
04494 unlink_first_small_chunk(ms, b, p, i);
04495 rsize = small_index2size(i) - nb;
04496
04497 if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
04498 set_inuse_and_pinuse(ms, p, small_index2size(i));
04499 else {
04500 set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
04501 r = chunk_plus_offset(p, nb);
04502 set_size_and_pinuse_of_free_chunk(r, rsize);
04503 replace_dv(ms, r, rsize);
04504 }
04505 mem = chunk2mem(p);
04506 check_malloced_chunk(ms, mem, nb);
04507 goto postaction;
04508 }
04509
04510 else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
04511 check_malloced_chunk(ms, mem, nb);
04512 goto postaction;
04513 }
04514 }
04515 }
04516 else if (bytes >= MAX_REQUEST)
04517 nb = MAX_SIZE_T;
04518 else {
04519 nb = pad_request(bytes);
04520 if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
04521 check_malloced_chunk(ms, mem, nb);
04522 goto postaction;
04523 }
04524 }
04525
04526 if (nb <= ms->dvsize) {
04527 size_t rsize = ms->dvsize - nb;
04528 mchunkptr p = ms->dv;
04529 if (rsize >= MIN_CHUNK_SIZE) {
04530 mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
04531 ms->dvsize = rsize;
04532 set_size_and_pinuse_of_free_chunk(r, rsize);
04533 set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
04534 }
04535 else {
04536 size_t dvs = ms->dvsize;
04537 ms->dvsize = 0;
04538 ms->dv = 0;
04539 set_inuse_and_pinuse(ms, p, dvs);
04540 }
04541 mem = chunk2mem(p);
04542 check_malloced_chunk(ms, mem, nb);
04543 goto postaction;
04544 }
04545
04546 else if (nb < ms->topsize) {
04547 size_t rsize = ms->topsize -= nb;
04548 mchunkptr p = ms->top;
04549 mchunkptr r = ms->top = chunk_plus_offset(p, nb);
04550 r->head = rsize | PINUSE_BIT;
04551 set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
04552 mem = chunk2mem(p);
04553 check_top_chunk(ms, ms->top);
04554 check_malloced_chunk(ms, mem, nb);
04555 goto postaction;
04556 }
04557
04558 mem = sys_alloc(ms, nb);
04559
04560 postaction:
04561 POSTACTION(ms);
04562 return mem;
04563 }
04564
04565 return 0;
04566 }
04567
04568 void mspace_free(mspace msp, void* mem) {
04569 if (mem != 0) {
04570 mchunkptr p = mem2chunk(mem);
04571 #if FOOTERS
04572 mstate fm = get_mstate_for(p);
04573 #else
04574 mstate fm = (mstate)msp;
04575 #endif
04576 if (!ok_magic(fm)) {
04577 USAGE_ERROR_ACTION(fm, p);
04578 return;
04579 }
04580 if (!PREACTION(fm)) {
04581 check_inuse_chunk(fm, p);
04582 if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
04583 size_t psize = chunksize(p);
04584 mchunkptr next = chunk_plus_offset(p, psize);
04585 if (!pinuse(p)) {
04586 size_t prevsize = p->prev_foot;
04587 if ((prevsize & IS_MMAPPED_BIT) != 0) {
04588 prevsize &= ~IS_MMAPPED_BIT;
04589 psize += prevsize + MMAP_FOOT_PAD;
04590 if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
04591 fm->footprint -= psize;
04592 goto postaction;
04593 }
04594 else {
04595 mchunkptr prev = chunk_minus_offset(p, prevsize);
04596 psize += prevsize;
04597 p = prev;
04598 if (RTCHECK(ok_address(fm, prev))) {
04599 if (p != fm->dv) {
04600 unlink_chunk(fm, p, prevsize);
04601 }
04602 else if ((next->head & INUSE_BITS) == INUSE_BITS) {
04603 fm->dvsize = psize;
04604 set_free_with_pinuse(p, psize, next);
04605 goto postaction;
04606 }
04607 }
04608 else
04609 goto erroraction;
04610 }
04611 }
04612
04613 if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
04614 if (!cinuse(next)) {
04615 if (next == fm->top) {
04616 size_t tsize = fm->topsize += psize;
04617 fm->top = p;
04618 p->head = tsize | PINUSE_BIT;
04619 if (p == fm->dv) {
04620 fm->dv = 0;
04621 fm->dvsize = 0;
04622 }
04623 if (should_trim(fm, tsize))
04624 sys_trim(fm, 0);
04625 goto postaction;
04626 }
04627 else if (next == fm->dv) {
04628 size_t dsize = fm->dvsize += psize;
04629 fm->dv = p;
04630 set_size_and_pinuse_of_free_chunk(p, dsize);
04631 goto postaction;
04632 }
04633 else {
04634 size_t nsize = chunksize(next);
04635 psize += nsize;
04636 unlink_chunk(fm, next, nsize);
04637 set_size_and_pinuse_of_free_chunk(p, psize);
04638 if (p == fm->dv) {
04639 fm->dvsize = psize;
04640 goto postaction;
04641 }
04642 }
04643 }
04644 else
04645 set_free_with_pinuse(p, psize, next);
04646 insert_chunk(fm, p, psize);
04647 check_free_chunk(fm, p);
04648 goto postaction;
04649 }
04650 }
04651 erroraction:
04652 USAGE_ERROR_ACTION(fm, p);
04653 postaction:
04654 POSTACTION(fm);
04655 }
04656 }
04657 }
04658
04659 void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
04660 void* mem;
04661 size_t req = 0;
04662 mstate ms = (mstate)msp;
04663 if (!ok_magic(ms)) {
04664 USAGE_ERROR_ACTION(ms,ms);
04665 return 0;
04666 }
04667 if (n_elements != 0) {
04668 req = n_elements * elem_size;
04669 if (((n_elements | elem_size) & ~(size_t)0xffff) &&
04670 (req / n_elements != elem_size))
04671 req = MAX_SIZE_T;
04672 }
04673 mem = internal_malloc(ms, req);
04674 if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
04675 memset(mem, 0, req);
04676 return mem;
04677 }
04678
04679 void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
04680 if (oldmem == 0)
04681 return mspace_malloc(msp, bytes);
04682 #ifdef REALLOC_ZERO_BYTES_FREES
04683 if (bytes == 0) {
04684 mspace_free(msp, oldmem);
04685 return 0;
04686 }
04687 #endif
04688 else {
04689 #if FOOTERS
04690 mchunkptr p = mem2chunk(oldmem);
04691 mstate ms = get_mstate_for(p);
04692 #else
04693 mstate ms = (mstate)msp;
04694 #endif
04695 if (!ok_magic(ms)) {
04696 USAGE_ERROR_ACTION(ms,ms);
04697 return 0;
04698 }
04699 return internal_realloc(ms, oldmem, bytes);
04700 }
04701 }
04702
04703 void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
04704 mstate ms = (mstate)msp;
04705 if (!ok_magic(ms)) {
04706 USAGE_ERROR_ACTION(ms,ms);
04707 return 0;
04708 }
04709 return internal_memalign(ms, alignment, bytes);
04710 }
04711
04712 void** mspace_independent_calloc(mspace msp, size_t n_elements,
04713 size_t elem_size, void* chunks[]) {
04714 size_t sz = elem_size;
04715 mstate ms = (mstate)msp;
04716 if (!ok_magic(ms)) {
04717 USAGE_ERROR_ACTION(ms,ms);
04718 return 0;
04719 }
04720 return ialloc(ms, n_elements, &sz, 3, chunks);
04721 }
04722
04723 void** mspace_independent_comalloc(mspace msp, size_t n_elements,
04724 size_t sizes[], void* chunks[]) {
04725 mstate ms = (mstate)msp;
04726 if (!ok_magic(ms)) {
04727 USAGE_ERROR_ACTION(ms,ms);
04728 return 0;
04729 }
04730 return ialloc(ms, n_elements, sizes, 0, chunks);
04731 }
04732
04733 int mspace_trim(mspace msp, size_t pad) {
04734 int result = 0;
04735 mstate ms = (mstate)msp;
04736 if (ok_magic(ms)) {
04737 if (!PREACTION(ms)) {
04738 result = sys_trim(ms, pad);
04739 POSTACTION(ms);
04740 }
04741 }
04742 else {
04743 USAGE_ERROR_ACTION(ms,ms);
04744 }
04745 return result;
04746 }
04747
04748 void mspace_malloc_stats(mspace msp) {
04749 mstate ms = (mstate)msp;
04750 if (ok_magic(ms)) {
04751 internal_malloc_stats(ms);
04752 }
04753 else {
04754 USAGE_ERROR_ACTION(ms,ms);
04755 }
04756 }
04757
04758 size_t mspace_footprint(mspace msp) {
04759 size_t result;
04760 mstate ms = (mstate)msp;
04761 if (ok_magic(ms)) {
04762 result = ms->footprint;
04763 }
04764 USAGE_ERROR_ACTION(ms,ms);
04765 return result;
04766 }
04767
04768
04769 size_t mspace_max_footprint(mspace msp) {
04770 size_t result;
04771 mstate ms = (mstate)msp;
04772 if (ok_magic(ms)) {
04773 result = ms->max_footprint;
04774 }
04775 USAGE_ERROR_ACTION(ms,ms);
04776 return result;
04777 }
04778
04779
04780 #if !NO_MALLINFO
04781 struct mallinfo mspace_mallinfo(mspace msp) {
04782 mstate ms = (mstate)msp;
04783 if (!ok_magic(ms)) {
04784 USAGE_ERROR_ACTION(ms,ms);
04785 }
04786 return internal_mallinfo(ms);
04787 }
04788 #endif
04789
04790 int mspace_mallopt(int param_number, int value) {
04791 return change_mparam(param_number, value);
04792 }
04793
04794 #endif
04795
04796
04797
04798
04799
04800
04801
04802
04803
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813
04814
04815
04816
04817
04818
04819
04820
04821
04822
04823
04824
04825
04826
04827
04828
04829
04830
04831
04832
04833
04834
04835
04836
04837
04838
04839
04840
04841
04842
04843
04844
04845
04846
04847
04848
04849
04850
04851
04852
04853
04854
04855
04856
04857
04858
04859
04860
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870
04871
04872
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891
04892
04893
04894
04895
04896
04897
04898
04899
04900
04901
04902
04903
04904
04905
04906
04907
04908
04909
04910
04911
04912
04913
04914
04915
04916
04917
04918
04919
04920
04921
04922
04923
04924
04925
04926
04927
04928
04929
04930
04931
04932
04933
04934
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979
04980
04981
04982
04983
04984
04985
04986
04987
04988
04989
04990
04991
04992
04993
04994
04995
04996
04997
04998
04999
05000
05001
05002
05003
05004
05005
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
05021
05022
05023
05024
05025
05026
05027
05028
05029
05030
05031
05032
05033
05034
05035
05036
05037
05038
05039
05040
05041
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053
05054
05055
05056
05057
05058
05059
05060
05061
05062
05063
05064
05065
05066
05067
05068 #endif