00001
00002
00003
00004
00005
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
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 #ifndef DLMALLOC_VERSION
00484 #define DLMALLOC_VERSION 20804
00485 #endif
00486
00487 #ifndef WIN32
00488 #ifdef _WIN32
00489 #define WIN32 1
00490 #endif
00491 #ifdef _WIN32_WCE
00492 #define LACKS_FCNTL_H
00493 #define WIN32 1
00494 #endif
00495 #endif
00496 #ifdef WIN32
00497 #define WIN32_LEAN_AND_MEAN
00498 #define _WIN32_WINNT 0x403
00499 #include <windows.h>
00500 #define HAVE_MMAP 1
00501 #define HAVE_MORECORE 0
00502 #define LACKS_UNISTD_H
00503 #define LACKS_SYS_PARAM_H
00504 #define LACKS_SYS_MMAN_H
00505 #define LACKS_STRING_H
00506 #define LACKS_STRINGS_H
00507 #define LACKS_SYS_TYPES_H
00508 #define LACKS_ERRNO_H
00509 #ifndef MALLOC_FAILURE_ACTION
00510 #define MALLOC_FAILURE_ACTION
00511 #endif
00512 #ifdef _WIN32_WCE
00513 #define MMAP_CLEARS 0
00514 #else
00515 #define MMAP_CLEARS 1
00516 #endif
00517 #endif
00518
00519 #if defined(DARWIN) || defined(_DARWIN)
00520
00521 #ifndef HAVE_MORECORE
00522 #define HAVE_MORECORE 0
00523 #define HAVE_MMAP 1
00524
00525 #ifndef MALLOC_ALIGNMENT
00526 #define MALLOC_ALIGNMENT ((size_t)16U)
00527 #endif
00528 #endif
00529 #endif
00530
00531 #ifndef LACKS_SYS_TYPES_H
00532 #include <sys/types.h>
00533 #endif
00534
00535
00536 #define MAX_SIZE_T (~(size_t)0)
00537
00538 #ifndef ONLY_MSPACES
00539 #define ONLY_MSPACES 0
00540 #else
00541 #define ONLY_MSPACES 1
00542 #endif
00543 #ifndef MSPACES
00544 #if ONLY_MSPACES
00545 #define MSPACES 1
00546 #else
00547 #define MSPACES 0
00548 #endif
00549 #endif
00550 #ifndef MALLOC_ALIGNMENT
00551 #define MALLOC_ALIGNMENT ((size_t)8U)
00552 #endif
00553 #ifndef FOOTERS
00554 #define FOOTERS 0
00555 #endif
00556 #ifndef ABORT
00557 #define ABORT abort()
00558 #endif
00559 #ifndef ABORT_ON_ASSERT_FAILURE
00560 #define ABORT_ON_ASSERT_FAILURE 1
00561 #endif
00562 #ifndef PROCEED_ON_ERROR
00563 #define PROCEED_ON_ERROR 0
00564 #endif
00565 #ifndef USE_LOCKS
00566 #define USE_LOCKS 0
00567 #endif
00568 #ifndef USE_SPIN_LOCKS
00569 #if USE_LOCKS && (defined(__GNUC__) && ((defined(__i386__) || defined(__x86_64__)))) || (defined(_MSC_VER) && _MSC_VER>=1310)
00570 #define USE_SPIN_LOCKS 1
00571 #else
00572 #define USE_SPIN_LOCKS 0
00573 #endif
00574 #endif
00575 #ifndef INSECURE
00576 #define INSECURE 0
00577 #endif
00578 #ifndef HAVE_MMAP
00579 #define HAVE_MMAP 1
00580 #endif
00581 #ifndef MMAP_CLEARS
00582 #define MMAP_CLEARS 1
00583 #endif
00584 #ifndef HAVE_MREMAP
00585 #ifdef linux
00586 #define HAVE_MREMAP 1
00587 #else
00588 #define HAVE_MREMAP 0
00589 #endif
00590 #endif
00591 #ifndef MALLOC_FAILURE_ACTION
00592 #define MALLOC_FAILURE_ACTION errno = ENOMEM;
00593 #endif
00594 #ifndef HAVE_MORECORE
00595 #if ONLY_MSPACES
00596 #define HAVE_MORECORE 0
00597 #else
00598 #define HAVE_MORECORE 1
00599 #endif
00600 #endif
00601 #if !HAVE_MORECORE
00602 #define MORECORE_CONTIGUOUS 0
00603 #else
00604 #define MORECORE_DEFAULT sbrk
00605 #ifndef MORECORE_CONTIGUOUS
00606 #define MORECORE_CONTIGUOUS 1
00607 #endif
00608 #endif
00609 #ifndef DEFAULT_GRANULARITY
00610 #if (MORECORE_CONTIGUOUS || defined(WIN32))
00611 #define DEFAULT_GRANULARITY (0)
00612 #else
00613 #define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
00614 #endif
00615 #endif
00616 #ifndef DEFAULT_TRIM_THRESHOLD
00617 #ifndef MORECORE_CANNOT_TRIM
00618 #define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
00619 #else
00620 #define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
00621 #endif
00622 #endif
00623 #ifndef DEFAULT_MMAP_THRESHOLD
00624 #if HAVE_MMAP
00625 #define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
00626 #else
00627 #define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
00628 #endif
00629 #endif
00630 #ifndef MAX_RELEASE_CHECK_RATE
00631 #if HAVE_MMAP
00632 #define MAX_RELEASE_CHECK_RATE 4095
00633 #else
00634 #define MAX_RELEASE_CHECK_RATE MAX_SIZE_T
00635 #endif
00636 #endif
00637 #ifndef USE_BUILTIN_FFS
00638 #define USE_BUILTIN_FFS 0
00639 #endif
00640 #ifndef USE_DEV_RANDOM
00641 #define USE_DEV_RANDOM 0
00642 #endif
00643 #ifndef NO_MALLINFO
00644 #define NO_MALLINFO 0
00645 #endif
00646 #ifndef MALLINFO_FIELD_TYPE
00647 #define MALLINFO_FIELD_TYPE size_t
00648 #endif
00649 #ifndef NO_SEGMENT_TRAVERSAL
00650 #define NO_SEGMENT_TRAVERSAL 0
00651 #endif
00652
00653
00654
00655
00656
00657
00658
00659
00660 #define M_TRIM_THRESHOLD (-1)
00661 #define M_GRANULARITY (-2)
00662 #define M_MMAP_THRESHOLD (-3)
00663
00664
00665
00666 #if !NO_MALLINFO
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691 #ifdef HAVE_USR_INCLUDE_MALLOC_H
00692 #include "/usr/include/malloc.h"
00693 #else
00694 #ifndef STRUCT_MALLINFO_DECLARED
00695 #define STRUCT_MALLINFO_DECLARED 1
00696 struct mallinfo {
00697 MALLINFO_FIELD_TYPE arena;
00698 MALLINFO_FIELD_TYPE ordblks;
00699 MALLINFO_FIELD_TYPE smblks;
00700 MALLINFO_FIELD_TYPE hblks;
00701 MALLINFO_FIELD_TYPE hblkhd;
00702 MALLINFO_FIELD_TYPE usmblks;
00703 MALLINFO_FIELD_TYPE fsmblks;
00704 MALLINFO_FIELD_TYPE uordblks;
00705 MALLINFO_FIELD_TYPE fordblks;
00706 MALLINFO_FIELD_TYPE keepcost;
00707 };
00708 #endif
00709 #endif
00710 #endif
00711
00712
00713
00714
00715
00716
00717 #ifndef FORCEINLINE
00718 #if defined(__GNUC__)
00719 #define FORCEINLINE __inline __attribute__ ((always_inline))
00720 #elif defined(_MSC_VER)
00721 #define FORCEINLINE __forceinline
00722 #endif
00723 #endif
00724 #ifndef NOINLINE
00725 #if defined(__GNUC__)
00726 #define NOINLINE __attribute__ ((noinline))
00727 #elif defined(_MSC_VER)
00728 #define NOINLINE __declspec(noinline)
00729 #else
00730 #define NOINLINE
00731 #endif
00732 #endif
00733
00734 #ifdef __cplusplus
00735 extern "C" {
00736 #ifndef FORCEINLINE
00737 #define FORCEINLINE inline
00738 #endif
00739 #endif
00740 #ifndef FORCEINLINE
00741 #define FORCEINLINE
00742 #endif
00743
00744 #if !ONLY_MSPACES
00745
00746
00747
00748 #ifndef USE_DL_PREFIX
00749 #define dlcalloc calloc
00750 #define dlfree free
00751 #define dlmalloc malloc
00752 #define dlmemalign memalign
00753 #define dlrealloc realloc
00754 #define dlvalloc valloc
00755 #define dlpvalloc pvalloc
00756 #define dlmallinfo mallinfo
00757 #define dlmallopt mallopt
00758 #define dlmalloc_trim malloc_trim
00759 #define dlmalloc_stats malloc_stats
00760 #define dlmalloc_usable_size malloc_usable_size
00761 #define dlmalloc_footprint malloc_footprint
00762 #define dlmalloc_max_footprint malloc_max_footprint
00763 #define dlindependent_calloc independent_calloc
00764 #define dlindependent_comalloc independent_comalloc
00765 #endif
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 void* dlmalloc(size_t);
00783
00784
00785
00786
00787
00788
00789
00790
00791 void dlfree(void*);
00792
00793
00794
00795
00796
00797
00798 void* dlcalloc(size_t, size_t);
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 void* dlrealloc(void*, size_t);
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 void* dlmemalign(size_t, size_t);
00838
00839
00840
00841
00842
00843
00844 void* dlvalloc(size_t);
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 int dlmallopt(int, int);
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879 size_t dlmalloc_footprint(void);
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 size_t dlmalloc_max_footprint(void);
00893
00894 #if !NO_MALLINFO
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917 struct mallinfo dlmallinfo(void);
00918 #endif
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972 void** dlindependent_calloc(size_t, size_t, void**);
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033 void** dlindependent_comalloc(size_t, size_t*, void**);
01034
01035
01036
01037
01038
01039
01040
01041 void* dlpvalloc(size_t);
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064 int dlmalloc_trim(size_t);
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085 void dlmalloc_stats(void);
01086
01087 #endif
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103 size_t dlmalloc_usable_size(void*);
01104
01105
01106 #if MSPACES
01107
01108
01109
01110
01111
01112 typedef void* mspace;
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125 mspace create_mspace(size_t capacity, int locked);
01126
01127
01128
01129
01130
01131
01132
01133 size_t destroy_mspace(mspace msp);
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144 mspace create_mspace_with_base(void* base, size_t capacity, int locked);
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155 int mspace_mmap_large_chunks(mspace msp, int enable);
01156
01157
01158
01159
01160
01161
01162 void* mspace_malloc(mspace msp, size_t bytes);
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172 void mspace_free(mspace msp, void* mem);
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183 void* mspace_realloc(mspace msp, void* mem, size_t newsize);
01184
01185
01186
01187
01188
01189 void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
01190
01191
01192
01193
01194
01195 void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
01196
01197
01198
01199
01200
01201 void** mspace_independent_calloc(mspace msp, size_t n_elements,
01202 size_t elem_size, void* chunks[]);
01203
01204
01205
01206
01207
01208 void** mspace_independent_comalloc(mspace msp, size_t n_elements,
01209 size_t sizes[], void* chunks[]);
01210
01211
01212
01213
01214
01215 size_t mspace_footprint(mspace msp);
01216
01217
01218
01219
01220
01221 size_t mspace_max_footprint(mspace msp);
01222
01223
01224 #if !NO_MALLINFO
01225
01226
01227
01228
01229 struct mallinfo mspace_mallinfo(mspace msp);
01230 #endif
01231
01232
01233
01234
01235 size_t mspace_usable_size(void* mem);
01236
01237
01238
01239
01240
01241 void mspace_malloc_stats(mspace msp);
01242
01243
01244
01245
01246
01247 int mspace_trim(mspace msp, size_t pad);
01248
01249
01250
01251
01252 int mspace_mallopt(int, int);
01253
01254 #endif
01255
01256 #ifdef __cplusplus
01257 };
01258 #endif
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272 #ifdef WIN32
01273 #pragma warning( disable : 4146 )
01274 #endif
01275
01276 #include <stdio.h>
01277
01278 #ifndef LACKS_ERRNO_H
01279 #include <errno.h>
01280 #endif
01281 #if FOOTERS
01282 #include <time.h>
01283 #endif
01284 #ifndef LACKS_STDLIB_H
01285 #include <stdlib.h>
01286 #endif
01287 #ifdef DEBUG
01288 #if ABORT_ON_ASSERT_FAILURE
01289 #define assert(x) if(!(x)) ABORT
01290 #else
01291 #include <assert.h>
01292 #endif
01293 #else
01294 #ifndef assert
01295 #define assert(x)
01296 #endif
01297 #define DEBUG 0
01298 #endif
01299 #ifndef LACKS_STRING_H
01300 #include <string.h>
01301 #endif
01302 #if USE_BUILTIN_FFS
01303 #ifndef LACKS_STRINGS_H
01304 #include <strings.h>
01305 #endif
01306 #endif
01307 #if HAVE_MMAP
01308 #ifndef LACKS_SYS_MMAN_H
01309 #include <sys/mman.h>
01310 #endif
01311 #ifndef LACKS_FCNTL_H
01312 #include <fcntl.h>
01313 #endif
01314 #endif
01315 #ifndef LACKS_UNISTD_H
01316 #include <unistd.h>
01317 #else
01318 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
01319 extern void* sbrk(ptrdiff_t);
01320 #endif
01321 #endif
01322
01323
01324 #if USE_LOCKS
01325 #ifndef WIN32
01326 #include <pthread.h>
01327 #if defined (__SVR4) && defined (__sun)
01328 #include <thread.h>
01329 #endif
01330 #else
01331 #ifndef _M_AMD64
01332
01333 #ifdef __cplusplus
01334 extern "C" {
01335 #endif
01336 LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp);
01337 LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value);
01338 #ifdef __cplusplus
01339 }
01340 #endif
01341 #endif
01342 #pragma intrinsic (_InterlockedCompareExchange)
01343 #pragma intrinsic (_InterlockedExchange)
01344 #define interlockedcompareexchange _InterlockedCompareExchange
01345 #define interlockedexchange _InterlockedExchange
01346 #endif
01347 #endif
01348
01349
01350 #if defined(_MSC_VER) && _MSC_VER>=1300
01351 #ifndef BitScanForward
01352 #ifdef __cplusplus
01353 extern "C" {
01354 #endif
01355 unsigned char _BitScanForward(unsigned long *index, unsigned long mask);
01356 unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
01357 #ifdef __cplusplus
01358 }
01359 #endif
01360
01361 #define BitScanForward _BitScanForward
01362 #define BitScanReverse _BitScanReverse
01363 #pragma intrinsic(_BitScanForward)
01364 #pragma intrinsic(_BitScanReverse)
01365 #endif
01366 #endif
01367
01368 #ifndef WIN32
01369 #ifndef malloc_getpagesize
01370 # ifdef _SC_PAGESIZE
01371 # ifndef _SC_PAGE_SIZE
01372 # define _SC_PAGE_SIZE _SC_PAGESIZE
01373 # endif
01374 # endif
01375 # ifdef _SC_PAGE_SIZE
01376 # define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
01377 # else
01378 # if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
01379 extern size_t getpagesize();
01380 # define malloc_getpagesize getpagesize()
01381 # else
01382 # ifdef WIN32
01383 # define malloc_getpagesize getpagesize()
01384 # else
01385 # ifndef LACKS_SYS_PARAM_H
01386 # include <sys/param.h>
01387 # endif
01388 # ifdef EXEC_PAGESIZE
01389 # define malloc_getpagesize EXEC_PAGESIZE
01390 # else
01391 # ifdef NBPG
01392 # ifndef CLSIZE
01393 # define malloc_getpagesize NBPG
01394 # else
01395 # define malloc_getpagesize (NBPG * CLSIZE)
01396 # endif
01397 # else
01398 # ifdef NBPC
01399 # define malloc_getpagesize NBPC
01400 # else
01401 # ifdef PAGESIZE
01402 # define malloc_getpagesize PAGESIZE
01403 # else
01404 # define malloc_getpagesize ((size_t)4096U)
01405 # endif
01406 # endif
01407 # endif
01408 # endif
01409 # endif
01410 # endif
01411 # endif
01412 #endif
01413 #endif
01414
01415
01416
01417
01418
01419
01420 #define SIZE_T_SIZE (sizeof(size_t))
01421 #define SIZE_T_BITSIZE (sizeof(size_t) << 3)
01422
01423
01424
01425 #define SIZE_T_ZERO ((size_t)0)
01426 #define SIZE_T_ONE ((size_t)1)
01427 #define SIZE_T_TWO ((size_t)2)
01428 #define SIZE_T_FOUR ((size_t)4)
01429 #define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1)
01430 #define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2)
01431 #define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
01432 #define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U)
01433
01434
01435 #define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE)
01436
01437
01438 #define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
01439
01440
01441 #define align_offset(A)\
01442 ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
01443 ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 #define MFAIL ((void*)(MAX_SIZE_T))
01456 #define CMFAIL ((char*)(MFAIL))
01457
01458 #if HAVE_MMAP
01459
01460 #ifndef WIN32
01461 #define MUNMAP_DEFAULT(a, s) munmap((a), (s))
01462 #define MMAP_PROT (PROT_READ|PROT_WRITE)
01463 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
01464 #define MAP_ANONYMOUS MAP_ANON
01465 #endif
01466 #ifdef MAP_ANONYMOUS
01467 #define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
01468 #define MMAP_DEFAULT(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
01469 #else
01470
01471
01472
01473
01474 #define MMAP_FLAGS (MAP_PRIVATE)
01475 static int dev_zero_fd = -1;
01476 #define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \
01477 (dev_zero_fd = open("/dev/zero", O_RDWR), \
01478 mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
01479 mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
01480 #endif
01481
01482 #define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s)
01483
01484 #else
01485
01486
01487 static FORCEINLINE void* win32mmap(size_t size) {
01488 void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
01489 return (ptr != 0)? ptr: MFAIL;
01490 }
01491
01492
01493 static FORCEINLINE void* win32direct_mmap(size_t size) {
01494 void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
01495 PAGE_READWRITE);
01496 return (ptr != 0)? ptr: MFAIL;
01497 }
01498
01499
01500 static FORCEINLINE int win32munmap(void* ptr, size_t size) {
01501 MEMORY_BASIC_INFORMATION minfo;
01502 char* cptr = (char*)ptr;
01503 while (size) {
01504 if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
01505 return -1;
01506 if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
01507 minfo.State != MEM_COMMIT || minfo.RegionSize > size)
01508 return -1;
01509 if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
01510 return -1;
01511 cptr += minfo.RegionSize;
01512 size -= minfo.RegionSize;
01513 }
01514 return 0;
01515 }
01516
01517 #define MMAP_DEFAULT(s) win32mmap(s)
01518 #define MUNMAP_DEFAULT(a, s) win32munmap((a), (s))
01519 #define DIRECT_MMAP_DEFAULT(s) win32direct_mmap(s)
01520 #endif
01521 #endif
01522
01523 #if HAVE_MREMAP
01524 #ifndef WIN32
01525 #define MREMAP_DEFAULT(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
01526 #endif
01527 #endif
01528
01529
01533 #if HAVE_MORECORE
01534 #ifdef MORECORE
01535 #define CALL_MORECORE(S) MORECORE(S)
01536 #else
01537 #define CALL_MORECORE(S) MORECORE_DEFAULT(S)
01538 #endif
01539 #else
01540 #define CALL_MORECORE(S) MFAIL
01541 #endif
01542
01546 #if HAVE_MMAP
01547 #define IS_MMAPPED_BIT (SIZE_T_ONE)
01548 #define USE_MMAP_BIT (SIZE_T_ONE)
01549
01550 #ifdef MMAP
01551 #define CALL_MMAP(s) MMAP(s)
01552 #else
01553 #define CALL_MMAP(s) MMAP_DEFAULT(s)
01554 #endif
01555 #ifdef MUNMAP
01556 #define CALL_MUNMAP(a, s) MUNMAP((a), (s))
01557 #else
01558 #define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s))
01559 #endif
01560 #ifdef DIRECT_MMAP
01561 #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s)
01562 #else
01563 #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s)
01564 #endif
01565 #else
01566 #define IS_MMAPPED_BIT (SIZE_T_ZERO)
01567 #define USE_MMAP_BIT (SIZE_T_ZERO)
01568
01569 #define MMAP(s) MFAIL
01570 #define MUNMAP(a, s) (-1)
01571 #define DIRECT_MMAP(s) MFAIL
01572 #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s)
01573 #define CALL_MMAP(s) MMAP(s)
01574 #define CALL_MUNMAP(a, s) MUNMAP((a), (s))
01575 #endif
01576
01580 #if HAVE_MMAP && HAVE_MREMAP
01581 #ifdef MREMAP
01582 #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv))
01583 #else
01584 #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv))
01585 #endif
01586 #else
01587 #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
01588 #endif
01589
01590
01591 #define USE_NONCONTIGUOUS_BIT (4U)
01592
01593
01594 #define EXTERN_BIT (8U)
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625 #if USE_LOCKS == 1
01626
01627 #if USE_SPIN_LOCKS
01628 #ifndef WIN32
01629
01630
01631 struct pthread_mlock_t {
01632 volatile unsigned int l;
01633 volatile unsigned int c;
01634 volatile pthread_t threadid;
01635 };
01636 #define MLOCK_T struct pthread_mlock_t
01637 #define CURRENT_THREAD pthread_self()
01638 #define INITIAL_LOCK(sl) (memset(sl, 0, sizeof(MLOCK_T)), 0)
01639 #define ACQUIRE_LOCK(sl) pthread_acquire_lock(sl)
01640 #define RELEASE_LOCK(sl) pthread_release_lock(sl)
01641 #define TRY_LOCK(sl) pthread_try_lock(sl)
01642 #define SPINS_PER_YIELD 63
01643
01644 static MLOCK_T malloc_global_mutex = { 0, 0, 0};
01645
01646 static FORCEINLINE int pthread_acquire_lock (MLOCK_T *sl) {
01647 int spins = 0;
01648 volatile unsigned int* lp = &sl->l;
01649 for (;;) {
01650 if (*lp != 0) {
01651 if (sl->threadid == CURRENT_THREAD) {
01652 ++sl->c;
01653 return 0;
01654 }
01655 }
01656 else {
01657
01658 int cmp = 0;
01659 int val = 1;
01660 int ret;
01661 __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
01662 : "=a" (ret)
01663 : "r" (val), "m" (*(lp)), "0"(cmp)
01664 : "memory", "cc");
01665 if (!ret) {
01666 assert(!sl->threadid);
01667 sl->c = 1;
01668 sl->threadid = CURRENT_THREAD;
01669 return 0;
01670 }
01671 if ((++spins & SPINS_PER_YIELD) == 0) {
01672 #if defined (__SVR4) && defined (__sun)
01673 thr_yield();
01674 #else
01675 #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
01676 sched_yield();
01677 #else
01678 ;
01679 #endif
01680 #endif
01681 }
01682 }
01683 }
01684 }
01685
01686 static FORCEINLINE void pthread_release_lock (MLOCK_T *sl) {
01687 assert(sl->l != 0);
01688 assert(sl->threadid == CURRENT_THREAD);
01689 if (--sl->c == 0) {
01690 sl->threadid = 0;
01691 volatile unsigned int* lp = &sl->l;
01692 int prev = 0;
01693 int ret;
01694 __asm__ __volatile__ ("lock; xchgl %0, %1"
01695 : "=r" (ret)
01696 : "m" (*(lp)), "0"(prev)
01697 : "memory");
01698 }
01699 }
01700
01701 static FORCEINLINE int pthread_try_lock (MLOCK_T *sl) {
01702 volatile unsigned int* lp = &sl->l;
01703 if (*lp != 0) {
01704 if (sl->threadid == CURRENT_THREAD) {
01705 ++sl->c;
01706 return 1;
01707 }
01708 }
01709 else {
01710 int cmp = 0;
01711 int val = 1;
01712 int ret;
01713 __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
01714 : "=a" (ret)
01715 : "r" (val), "m" (*(lp)), "0"(cmp)
01716 : "memory", "cc");
01717 if (!ret) {
01718 assert(!sl->threadid);
01719 sl->c = 1;
01720 sl->threadid = CURRENT_THREAD;
01721 return 1;
01722 }
01723 }
01724 return 0;
01725 }
01726
01727
01728 #else
01729
01730 struct win32_mlock_t
01731 {
01732 volatile long l;
01733 volatile unsigned int c;
01734 volatile long threadid;
01735 };
01736
01737 #define MLOCK_T struct win32_mlock_t
01738 #define CURRENT_THREAD win32_getcurrentthreadid()
01739 #define INITIAL_LOCK(sl) (memset(sl, 0, sizeof(MLOCK_T)), 0)
01740 #define ACQUIRE_LOCK(sl) win32_acquire_lock(sl)
01741 #define RELEASE_LOCK(sl) win32_release_lock(sl)
01742 #define TRY_LOCK(sl) win32_try_lock(sl)
01743 #define SPINS_PER_YIELD 63
01744
01745 static MLOCK_T malloc_global_mutex = { 0, 0, 0};
01746
01747 static FORCEINLINE long win32_getcurrentthreadid() {
01748 #ifdef _MSC_VER
01749 #if defined(_M_IX86)
01750 long *threadstruct=(long *)__readfsdword(0x18);
01751 long threadid=threadstruct[0x24/sizeof(long)];
01752 return threadid;
01753 #elif defined(_M_X64)
01754
01755 return GetCurrentThreadId();
01756 #else
01757 return GetCurrentThreadId();
01758 #endif
01759 #else
01760 return GetCurrentThreadId();
01761 #endif
01762 }
01763
01764 static FORCEINLINE int win32_acquire_lock (MLOCK_T *sl) {
01765 int spins = 0;
01766 for (;;) {
01767 if (sl->l != 0) {
01768 if (sl->threadid == CURRENT_THREAD) {
01769 ++sl->c;
01770 return 0;
01771 }
01772 }
01773 else {
01774 if (!interlockedexchange(&sl->l, 1)) {
01775 assert(!sl->threadid);
01776 sl->c=CURRENT_THREAD;
01777 sl->threadid = CURRENT_THREAD;
01778 sl->c = 1;
01779 return 0;
01780 }
01781 }
01782 if ((++spins & SPINS_PER_YIELD) == 0)
01783 SleepEx(0, FALSE);
01784 }
01785 }
01786
01787 static FORCEINLINE void win32_release_lock (MLOCK_T *sl) {
01788 assert(sl->threadid == CURRENT_THREAD);
01789 assert(sl->l != 0);
01790 if (--sl->c == 0) {
01791 sl->threadid = 0;
01792 interlockedexchange (&sl->l, 0);
01793 }
01794 }
01795
01796 static FORCEINLINE int win32_try_lock (MLOCK_T *sl) {
01797 if(sl->l != 0) {
01798 if (sl->threadid == CURRENT_THREAD) {
01799 ++sl->c;
01800 return 1;
01801 }
01802 }
01803 else {
01804 if (!interlockedexchange(&sl->l, 1)){
01805 assert(!sl->threadid);
01806 sl->threadid = CURRENT_THREAD;
01807 sl->c = 1;
01808 return 1;
01809 }
01810 }
01811 return 0;
01812 }
01813
01814 #endif
01815 #else
01816
01817 #ifndef WIN32
01818
01819
01820 #define MLOCK_T pthread_mutex_t
01821 #define CURRENT_THREAD pthread_self()
01822 #define INITIAL_LOCK(sl) pthread_init_lock(sl)
01823 #define ACQUIRE_LOCK(sl) pthread_mutex_lock(sl)
01824 #define RELEASE_LOCK(sl) pthread_mutex_unlock(sl)
01825 #define TRY_LOCK(sl) (!pthread_mutex_trylock(sl))
01826
01827 static MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER;
01828
01829
01830
01831 #ifdef linux
01832 #ifndef PTHREAD_MUTEX_RECURSIVE
01833 extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr,
01834 int __kind));
01835 #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
01836 #define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y)
01837 #endif
01838 #endif
01839
01840 static int pthread_init_lock (MLOCK_T *sl) {
01841 pthread_mutexattr_t attr;
01842 if (pthread_mutexattr_init(&attr)) return 1;
01843 if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1;
01844 if (pthread_mutex_init(sl, &attr)) return 1;
01845 if (pthread_mutexattr_destroy(&attr)) return 1;
01846 return 0;
01847 }
01848
01849 #else
01850
01851 #define MLOCK_T CRITICAL_SECTION
01852 #define CURRENT_THREAD GetCurrentThreadId()
01853 #define INITIAL_LOCK(s) (!InitializeCriticalSectionAndSpinCount((s), 0x80000000|4000))
01854 #define ACQUIRE_LOCK(s) (EnterCriticalSection(s), 0)
01855 #define RELEASE_LOCK(s) LeaveCriticalSection(s)
01856 #define TRY_LOCK(s) TryEnterCriticalSection(s)
01857 #define NEED_GLOBAL_LOCK_INIT
01858
01859 static MLOCK_T malloc_global_mutex;
01860 static volatile long malloc_global_mutex_status;
01861
01862
01863 static void init_malloc_global_mutex() {
01864 for (;;) {
01865 long stat = malloc_global_mutex_status;
01866 if (stat > 0)
01867 return;
01868
01869 if (stat == 0 &&
01870 interlockedcompareexchange(&malloc_global_mutex_status, -1, 0) == 0) {
01871 InitializeCriticalSection(&malloc_global_mutex);
01872 interlockedexchange(&malloc_global_mutex_status,1);
01873 return;
01874 }
01875 SleepEx(0, FALSE);
01876 }
01877 }
01878
01879 #endif
01880 #endif
01881 #endif
01882
01883
01884
01885 #if USE_LOCKS > 1
01886
01887
01888
01889
01890
01891
01892 #endif
01893
01894
01895
01896 #if USE_LOCKS
01897 #define USE_LOCK_BIT (2U)
01898 #else
01899 #define USE_LOCK_BIT (0U)
01900 #define INITIAL_LOCK(l)
01901 #endif
01902
01903 #if USE_LOCKS
01904 #define ACQUIRE_MALLOC_GLOBAL_LOCK() ACQUIRE_LOCK(&malloc_global_mutex);
01905 #define RELEASE_MALLOC_GLOBAL_LOCK() RELEASE_LOCK(&malloc_global_mutex);
01906 #else
01907 #define ACQUIRE_MALLOC_GLOBAL_LOCK()
01908 #define RELEASE_MALLOC_GLOBAL_LOCK()
01909 #endif
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
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049 struct malloc_chunk {
02050 size_t prev_foot;
02051 size_t head;
02052 struct malloc_chunk* fd;
02053 struct malloc_chunk* bk;
02054 };
02055
02056 typedef struct malloc_chunk mchunk;
02057 typedef struct malloc_chunk* mchunkptr;
02058 typedef struct malloc_chunk* sbinptr;
02059 typedef unsigned int bindex_t;
02060 typedef unsigned int binmap_t;
02061 typedef unsigned int flag_t;
02062
02063
02064
02065 #define MCHUNK_SIZE (sizeof(mchunk))
02066
02067 #if FOOTERS
02068 #define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
02069 #else
02070 #define CHUNK_OVERHEAD (SIZE_T_SIZE)
02071 #endif
02072
02073
02074 #define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
02075
02076 #define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES)
02077
02078
02079 #define MIN_CHUNK_SIZE\
02080 ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
02081
02082
02083 #define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES))
02084 #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
02085
02086 #define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A)))
02087
02088
02089 #define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2)
02090 #define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
02091
02092
02093 #define pad_request(req) \
02094 (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
02095
02096
02097 #define request2size(req) \
02098 (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113 #define PINUSE_BIT (SIZE_T_ONE)
02114 #define CINUSE_BIT (SIZE_T_TWO)
02115 #define FLAG4_BIT (SIZE_T_FOUR)
02116 #define INUSE_BITS (PINUSE_BIT|CINUSE_BIT)
02117 #define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT)
02118
02119
02120 #define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE)
02121
02122
02123 #define cinuse(p) ((p)->head & CINUSE_BIT)
02124 #define pinuse(p) ((p)->head & PINUSE_BIT)
02125 #define chunksize(p) ((p)->head & ~(FLAG_BITS))
02126
02127 #define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT)
02128 #define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT)
02129
02130
02131 #define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
02132 #define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
02133
02134
02135 #define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS)))
02136 #define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
02137
02138
02139 #define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT)
02140
02141
02142 #define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot)
02143 #define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
02144
02145
02146 #define set_size_and_pinuse_of_free_chunk(p, s)\
02147 ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
02148
02149
02150 #define set_free_with_pinuse(p, s, n)\
02151 (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
02152
02153 #define is_mmapped(p)\
02154 (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT))
02155
02156
02157 #define overhead_for(p)\
02158 (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
02159
02160
02161 #if MMAP_CLEARS
02162 #define calloc_must_clear(p) (!is_mmapped(p))
02163 #else
02164 #define calloc_must_clear(p) (1)
02165 #endif
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258 struct malloc_tree_chunk {
02259
02260 size_t prev_foot;
02261 size_t head;
02262 struct malloc_tree_chunk* fd;
02263 struct malloc_tree_chunk* bk;
02264
02265 struct malloc_tree_chunk* child[2];
02266 struct malloc_tree_chunk* parent;
02267 bindex_t index;
02268 };
02269
02270 typedef struct malloc_tree_chunk tchunk;
02271 typedef struct malloc_tree_chunk* tchunkptr;
02272 typedef struct malloc_tree_chunk* tbinptr;
02273
02274
02275 #define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
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 struct malloc_segment {
02335 char* base;
02336 size_t size;
02337 struct malloc_segment* next;
02338 flag_t sflags;
02339 };
02340
02341 #define is_mmapped_segment(S) ((S)->sflags & IS_MMAPPED_BIT)
02342 #define is_extern_segment(S) ((S)->sflags & EXTERN_BIT)
02343
02344 typedef struct malloc_segment msegment;
02345 typedef struct malloc_segment* msegmentptr;
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432 #define NSMALLBINS (32U)
02433 #define NTREEBINS (32U)
02434 #define SMALLBIN_SHIFT (3U)
02435 #define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT)
02436 #define TREEBIN_SHIFT (8U)
02437 #define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT)
02438 #define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE)
02439 #define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
02440
02441 struct malloc_state {
02442 binmap_t smallmap;
02443 binmap_t treemap;
02444 size_t dvsize;
02445 size_t topsize;
02446 char* least_addr;
02447 mchunkptr dv;
02448 mchunkptr top;
02449 size_t trim_check;
02450 size_t release_checks;
02451 size_t magic;
02452 mchunkptr smallbins[(NSMALLBINS+1)*2];
02453 tbinptr treebins[NTREEBINS];
02454 size_t footprint;
02455 size_t max_footprint;
02456 flag_t mflags;
02457 #if USE_LOCKS
02458 MLOCK_T mutex;
02459 #endif
02460 msegment seg;
02461 void* extp;
02462 size_t exts;
02463 };
02464
02465 typedef struct malloc_state* mstate;
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476 struct malloc_params {
02477 volatile size_t magic;
02478 size_t page_size;
02479 size_t granularity;
02480 size_t mmap_threshold;
02481 size_t trim_threshold;
02482 flag_t default_mflags;
02483 };
02484
02485 static struct malloc_params mparams;
02486
02487
02488 #define ensure_initialization() (mparams.magic != 0 || init_mparams())
02489
02490 #if !ONLY_MSPACES
02491
02492
02493 static struct malloc_state _gm_;
02494 #define gm (&_gm_)
02495 #define is_global(M) ((M) == &_gm_)
02496
02497 #endif
02498
02499 #define is_initialized(M) ((M)->top != 0)
02500
02501
02502
02503
02504
02505 #define use_lock(M) ((M)->mflags & USE_LOCK_BIT)
02506 #define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT)
02507 #define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT)
02508
02509 #define use_mmap(M) ((M)->mflags & USE_MMAP_BIT)
02510 #define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT)
02511 #define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT)
02512
02513 #define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT)
02514 #define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT)
02515
02516 #define set_lock(M,L)\
02517 ((M)->mflags = (L)?\
02518 ((M)->mflags | USE_LOCK_BIT) :\
02519 ((M)->mflags & ~USE_LOCK_BIT))
02520
02521
02522 #define page_align(S)\
02523 (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE))
02524
02525
02526 #define granularity_align(S)\
02527 (((S) + (mparams.granularity - SIZE_T_ONE))\
02528 & ~(mparams.granularity - SIZE_T_ONE))
02529
02530
02531
02532 #ifdef WIN32
02533 #define mmap_align(S) granularity_align(S)
02534 #else
02535 #define mmap_align(S) page_align(S)
02536 #endif
02537
02538
02539 #define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT)
02540
02541 #define is_page_aligned(S)\
02542 (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
02543 #define is_granularity_aligned(S)\
02544 (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
02545
02546
02547 #define segment_holds(S, A)\
02548 ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
02549
02550
02551 static msegmentptr segment_holding(mstate m, char* addr) {
02552 msegmentptr sp = &m->seg;
02553 for (;;) {
02554 if (addr >= sp->base && addr < sp->base + sp->size)
02555 return sp;
02556 if ((sp = sp->next) == 0)
02557 return 0;
02558 }
02559 }
02560
02561
02562 static int has_segment_link(mstate m, msegmentptr ss) {
02563 msegmentptr sp = &m->seg;
02564 for (;;) {
02565 if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
02566 return 1;
02567 if ((sp = sp->next) == 0)
02568 return 0;
02569 }
02570 }
02571
02572 #ifndef MORECORE_CANNOT_TRIM
02573 #define should_trim(M,s) ((s) > (M)->trim_check)
02574 #else
02575 #define should_trim(M,s) (0)
02576 #endif
02577
02578
02579
02580
02581
02582
02583 #define TOP_FOOT_SIZE\
02584 (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595 #if USE_LOCKS
02596
02597 #define PREACTION(M) ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
02598 #define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
02599 #else
02600
02601 #ifndef PREACTION
02602 #define PREACTION(M) (0)
02603 #endif
02604
02605 #ifndef POSTACTION
02606 #define POSTACTION(M)
02607 #endif
02608
02609 #endif
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619 #if PROCEED_ON_ERROR
02620
02621
02622 int malloc_corruption_error_count;
02623
02624
02625 static void reset_on_error(mstate m);
02626
02627 #define CORRUPTION_ERROR_ACTION(m) reset_on_error(m)
02628 #define USAGE_ERROR_ACTION(m, p)
02629
02630 #else
02631
02632 #ifndef CORRUPTION_ERROR_ACTION
02633 #define CORRUPTION_ERROR_ACTION(m) ABORT
02634 #endif
02635
02636 #ifndef USAGE_ERROR_ACTION
02637 #define USAGE_ERROR_ACTION(m,p) ABORT
02638 #endif
02639
02640 #endif
02641
02642
02643
02644 #if ! DEBUG
02645
02646 #define check_free_chunk(M,P)
02647 #define check_inuse_chunk(M,P)
02648 #define check_malloced_chunk(M,P,N)
02649 #define check_mmapped_chunk(M,P)
02650 #define check_malloc_state(M)
02651 #define check_top_chunk(M,P)
02652
02653 #else
02654 #define check_free_chunk(M,P) do_check_free_chunk(M,P)
02655 #define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P)
02656 #define check_top_chunk(M,P) do_check_top_chunk(M,P)
02657 #define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
02658 #define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P)
02659 #define check_malloc_state(M) do_check_malloc_state(M)
02660
02661 static void do_check_any_chunk(mstate m, mchunkptr p);
02662 static void do_check_top_chunk(mstate m, mchunkptr p);
02663 static void do_check_mmapped_chunk(mstate m, mchunkptr p);
02664 static void do_check_inuse_chunk(mstate m, mchunkptr p);
02665 static void do_check_free_chunk(mstate m, mchunkptr p);
02666 static void do_check_malloced_chunk(mstate m, void* mem, size_t s);
02667 static void do_check_tree(mstate m, tchunkptr t);
02668 static void do_check_treebin(mstate m, bindex_t i);
02669 static void do_check_smallbin(mstate m, bindex_t i);
02670 static void do_check_malloc_state(mstate m);
02671 static int bin_find(mstate m, mchunkptr x);
02672 static size_t traverse_and_check(mstate m);
02673 #endif
02674
02675
02676
02677 #define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
02678 #define small_index(s) ((s) >> SMALLBIN_SHIFT)
02679 #define small_index2size(i) ((i) << SMALLBIN_SHIFT)
02680 #define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE))
02681
02682
02683 #define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
02684 #define treebin_at(M,i) (&((M)->treebins[i]))
02685
02686
02687 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
02688 #define compute_tree_index(S, I)\
02689 {\
02690 unsigned int X = S >> TREEBIN_SHIFT;\
02691 if (X == 0)\
02692 I = 0;\
02693 else if (X > 0xFFFF)\
02694 I = NTREEBINS-1;\
02695 else {\
02696 unsigned int K;\
02697 __asm__("bsrl\t%1, %0\n\t" : "=r" (K) : "rm" (X));\
02698 I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
02699 }\
02700 }
02701
02702 #elif defined (__INTEL_COMPILER)
02703 #define compute_tree_index(S, I)\
02704 {\
02705 size_t X = S >> TREEBIN_SHIFT;\
02706 if (X == 0)\
02707 I = 0;\
02708 else if (X > 0xFFFF)\
02709 I = NTREEBINS-1;\
02710 else {\
02711 unsigned int K = _bit_scan_reverse (X); \
02712 I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
02713 }\
02714 }
02715
02716 #elif defined(_MSC_VER) && _MSC_VER>=1300
02717 #define compute_tree_index(S, I)\
02718 {\
02719 size_t X = S >> TREEBIN_SHIFT;\
02720 if (X == 0)\
02721 I = 0;\
02722 else if (X > 0xFFFF)\
02723 I = NTREEBINS-1;\
02724 else {\
02725 unsigned int K;\
02726 _BitScanReverse((DWORD *) &K, X);\
02727 I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
02728 }\
02729 }
02730
02731 #else
02732 #define compute_tree_index(S, I)\
02733 {\
02734 size_t X = S >> TREEBIN_SHIFT;\
02735 if (X == 0)\
02736 I = 0;\
02737 else if (X > 0xFFFF)\
02738 I = NTREEBINS-1;\
02739 else {\
02740 unsigned int Y = (unsigned int)X;\
02741 unsigned int N = ((Y - 0x100) >> 16) & 8;\
02742 unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
02743 N += K;\
02744 N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
02745 K = 14 - N + ((Y <<= K) >> 15);\
02746 I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
02747 }\
02748 }
02749 #endif
02750
02751
02752 #define bit_for_tree_index(i) \
02753 (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
02754
02755
02756 #define leftshift_for_tree_index(i) \
02757 ((i == NTREEBINS-1)? 0 : \
02758 ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
02759
02760
02761 #define minsize_for_tree_index(i) \
02762 ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \
02763 (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
02764
02765
02766
02767
02768
02769 #define idx2bit(i) ((binmap_t)(1) << (i))
02770
02771
02772 #define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i))
02773 #define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i))
02774 #define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i))
02775
02776 #define mark_treemap(M,i) ((M)->treemap |= idx2bit(i))
02777 #define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i))
02778 #define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i))
02779
02780
02781 #define least_bit(x) ((x) & -(x))
02782
02783
02784 #define left_bits(x) ((x<<1) | -(x<<1))
02785
02786
02787 #define same_or_left_bits(x) ((x) | -(x))
02788
02789
02790
02791 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
02792 #define compute_bit2idx(X, I)\
02793 {\
02794 unsigned int J;\
02795 __asm__("bsfl\t%1, %0\n\t" : "=r" (J) : "rm" (X));\
02796 I = (bindex_t)J;\
02797 }
02798
02799 #elif defined (__INTEL_COMPILER)
02800 #define compute_bit2idx(X, I)\
02801 {\
02802 unsigned int J;\
02803 J = _bit_scan_forward (X); \
02804 I = (bindex_t)J;\
02805 }
02806
02807 #elif defined(_MSC_VER) && _MSC_VER>=1300
02808 #define compute_bit2idx(X, I)\
02809 {\
02810 unsigned int J;\
02811 _BitScanForward((DWORD *) &J, X);\
02812 I = (bindex_t)J;\
02813 }
02814
02815 #elif USE_BUILTIN_FFS
02816 #define compute_bit2idx(X, I) I = ffs(X)-1
02817
02818 #else
02819 #define compute_bit2idx(X, I)\
02820 {\
02821 unsigned int Y = X - 1;\
02822 unsigned int K = Y >> (16-4) & 16;\
02823 unsigned int N = K; Y >>= K;\
02824 N += K = Y >> (8-3) & 8; Y >>= K;\
02825 N += K = Y >> (4-2) & 4; Y >>= K;\
02826 N += K = Y >> (2-1) & 2; Y >>= K;\
02827 N += K = Y >> (1-0) & 1; Y >>= K;\
02828 I = (bindex_t)(N + Y);\
02829 }
02830 #endif
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861 #if !INSECURE
02862
02863 #define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
02864
02865 #define ok_next(p, n) ((char*)(p) < (char*)(n))
02866
02867 #define ok_cinuse(p) cinuse(p)
02868
02869 #define ok_pinuse(p) pinuse(p)
02870
02871 #else
02872 #define ok_address(M, a) (1)
02873 #define ok_next(b, n) (1)
02874 #define ok_cinuse(p) (1)
02875 #define ok_pinuse(p) (1)
02876 #endif
02877
02878 #if (FOOTERS && !INSECURE)
02879
02880 #define ok_magic(M) ((M)->magic == mparams.magic)
02881 #else
02882 #define ok_magic(M) (1)
02883 #endif
02884
02885
02886
02887 #if !INSECURE
02888 #if defined(__GNUC__) && __GNUC__ >= 3
02889 #define RTCHECK(e) __builtin_expect(e, 1)
02890 #else
02891 #define RTCHECK(e) (e)
02892 #endif
02893 #else
02894 #define RTCHECK(e) (1)
02895 #endif
02896
02897
02898
02899 #if !FOOTERS
02900
02901 #define mark_inuse_foot(M,p,s)
02902
02903
02904 #define set_inuse(M,p,s)\
02905 ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
02906 ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
02907
02908
02909 #define set_inuse_and_pinuse(M,p,s)\
02910 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
02911 ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
02912
02913
02914 #define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
02915 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
02916
02917 #else
02918
02919
02920 #define mark_inuse_foot(M,p,s)\
02921 (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
02922
02923 #define get_mstate_for(p)\
02924 ((mstate)(((mchunkptr)((char*)(p) +\
02925 (chunksize(p))))->prev_foot ^ mparams.magic))
02926
02927 #define set_inuse(M,p,s)\
02928 ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
02929 (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
02930 mark_inuse_foot(M,p,s))
02931
02932 #define set_inuse_and_pinuse(M,p,s)\
02933 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
02934 (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
02935 mark_inuse_foot(M,p,s))
02936
02937 #define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
02938 ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
02939 mark_inuse_foot(M, p, s))
02940
02941 #endif
02942
02943
02944
02945
02946 static int init_mparams(void) {
02947 #ifdef NEED_GLOBAL_LOCK_INIT
02948 if (malloc_global_mutex_status <= 0)
02949 init_malloc_global_mutex();
02950 #endif
02951
02952 ACQUIRE_MALLOC_GLOBAL_LOCK();
02953 if (mparams.magic == 0) {
02954 size_t magic;
02955 size_t psize;
02956 size_t gsize;
02957
02958 #ifndef WIN32
02959 psize = malloc_getpagesize;
02960 gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize);
02961 #else
02962 {
02963 SYSTEM_INFO system_info;
02964 GetSystemInfo(&system_info);
02965 psize = system_info.dwPageSize;
02966 gsize = ((DEFAULT_GRANULARITY != 0)?
02967 DEFAULT_GRANULARITY : system_info.dwAllocationGranularity);
02968 }
02969 #endif
02970
02971
02972
02973
02974
02975
02976
02977 if ((sizeof(size_t) != sizeof(char*)) ||
02978 (MAX_SIZE_T < MIN_CHUNK_SIZE) ||
02979 (sizeof(int) < 4) ||
02980 (MALLOC_ALIGNMENT < (size_t)8U) ||
02981 ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) ||
02982 ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) ||
02983 ((gsize & (gsize-SIZE_T_ONE)) != 0) ||
02984 ((psize & (psize-SIZE_T_ONE)) != 0))
02985 ABORT;
02986
02987 mparams.granularity = gsize;
02988 mparams.page_size = psize;
02989 mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
02990 mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
02991 #if MORECORE_CONTIGUOUS
02992 mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
02993 #else
02994 mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
02995 #endif
02996
02997 #if !ONLY_MSPACES
02998
02999 gm->mflags = mparams.default_mflags;
03000 INITIAL_LOCK(&gm->mutex);
03001 #endif
03002
03003 #if (FOOTERS && !INSECURE)
03004 {
03005 #if USE_DEV_RANDOM
03006 int fd;
03007 unsigned char buf[sizeof(size_t)];
03008
03009 if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
03010 read(fd, buf, sizeof(buf)) == sizeof(buf)) {
03011 magic = *((size_t *) buf);
03012 close(fd);
03013 }
03014 else
03015 #endif
03016 #ifdef WIN32
03017 magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U);
03018 #else
03019 magic = (size_t)(time(0) ^ (size_t)0x55555555U);
03020 #endif
03021 magic |= (size_t)8U;
03022 magic &= ~(size_t)7U;
03023 }
03024 #else
03025 magic = (size_t)0x58585858U;
03026 #endif
03027
03028 mparams.magic = magic;
03029 }
03030
03031 RELEASE_MALLOC_GLOBAL_LOCK();
03032 return 1;
03033 }
03034
03035
03036 static int change_mparam(int param_number, int value) {
03037 size_t val = (value == -1)? MAX_SIZE_T : (size_t)value;
03038 ensure_initialization();
03039 switch(param_number) {
03040 case M_TRIM_THRESHOLD:
03041 mparams.trim_threshold = val;
03042 return 1;
03043 case M_GRANULARITY:
03044 if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
03045 mparams.granularity = val;
03046 return 1;
03047 }
03048 else
03049 return 0;
03050 case M_MMAP_THRESHOLD:
03051 mparams.mmap_threshold = val;
03052 return 1;
03053 default:
03054 return 0;
03055 }
03056 }
03057
03058 #if DEBUG
03059
03060
03061
03062 static void do_check_any_chunk(mstate m, mchunkptr p) {
03063 assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
03064 assert(ok_address(m, p));
03065 }
03066
03067
03068 static void do_check_top_chunk(mstate m, mchunkptr p) {
03069 msegmentptr sp = segment_holding(m, (char*)p);
03070 size_t sz = p->head & ~INUSE_BITS;
03071 assert(sp != 0);
03072 assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
03073 assert(ok_address(m, p));
03074 assert(sz == m->topsize);
03075 assert(sz > 0);
03076 assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
03077 assert(pinuse(p));
03078 assert(!pinuse(chunk_plus_offset(p, sz)));
03079 }
03080
03081
03082 static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
03083 size_t sz = chunksize(p);
03084 size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD);
03085 assert(is_mmapped(p));
03086 assert(use_mmap(m));
03087 assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
03088 assert(ok_address(m, p));
03089 assert(!is_small(sz));
03090 assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
03091 assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
03092 assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
03093 }
03094
03095
03096 static void do_check_inuse_chunk(mstate m, mchunkptr p) {
03097 do_check_any_chunk(m, p);
03098 assert(cinuse(p));
03099 assert(next_pinuse(p));
03100
03101 assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
03102 if (is_mmapped(p))
03103 do_check_mmapped_chunk(m, p);
03104 }
03105
03106
03107 static void do_check_free_chunk(mstate m, mchunkptr p) {
03108 size_t sz = chunksize(p);
03109 mchunkptr next = chunk_plus_offset(p, sz);
03110 do_check_any_chunk(m, p);
03111 assert(!cinuse(p));
03112 assert(!next_pinuse(p));
03113 assert (!is_mmapped(p));
03114 if (p != m->dv && p != m->top) {
03115 if (sz >= MIN_CHUNK_SIZE) {
03116 assert((sz & CHUNK_ALIGN_MASK) == 0);
03117 assert(is_aligned(chunk2mem(p)));
03118 assert(next->prev_foot == sz);
03119 assert(pinuse(p));
03120 assert (next == m->top || cinuse(next));
03121 assert(p->fd->bk == p);
03122 assert(p->bk->fd == p);
03123 }
03124 else
03125 assert(sz == SIZE_T_SIZE);
03126 }
03127 }
03128
03129
03130 static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
03131 if (mem != 0) {
03132 mchunkptr p = mem2chunk(mem);
03133 size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
03134 do_check_inuse_chunk(m, p);
03135 assert((sz & CHUNK_ALIGN_MASK) == 0);
03136 assert(sz >= MIN_CHUNK_SIZE);
03137 assert(sz >= s);
03138
03139 assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
03140 }
03141 }
03142
03143
03144 static void do_check_tree(mstate m, tchunkptr t) {
03145 tchunkptr head = 0;
03146 tchunkptr u = t;
03147 bindex_t tindex = t->index;
03148 size_t tsize = chunksize(t);
03149 bindex_t idx;
03150 compute_tree_index(tsize, idx);
03151 assert(tindex == idx);
03152 assert(tsize >= MIN_LARGE_SIZE);
03153 assert(tsize >= minsize_for_tree_index(idx));
03154 assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
03155
03156 do {
03157 do_check_any_chunk(m, ((mchunkptr)u));
03158 assert(u->index == tindex);
03159 assert(chunksize(u) == tsize);
03160 assert(!cinuse(u));
03161 assert(!next_pinuse(u));
03162 assert(u->fd->bk == u);
03163 assert(u->bk->fd == u);
03164 if (u->parent == 0) {
03165 assert(u->child[0] == 0);
03166 assert(u->child[1] == 0);
03167 }
03168 else {
03169 assert(head == 0);
03170 head = u;
03171 assert(u->parent != u);
03172 assert (u->parent->child[0] == u ||
03173 u->parent->child[1] == u ||
03174 *((tbinptr*)(u->parent)) == u);
03175 if (u->child[0] != 0) {
03176 assert(u->child[0]->parent == u);
03177 assert(u->child[0] != u);
03178 do_check_tree(m, u->child[0]);
03179 }
03180 if (u->child[1] != 0) {
03181 assert(u->child[1]->parent == u);
03182 assert(u->child[1] != u);
03183 do_check_tree(m, u->child[1]);
03184 }
03185 if (u->child[0] != 0 && u->child[1] != 0) {
03186 assert(chunksize(u->child[0]) < chunksize(u->child[1]));
03187 }
03188 }
03189 u = u->fd;
03190 } while (u != t);
03191 assert(head != 0);
03192 }
03193
03194
03195 static void do_check_treebin(mstate m, bindex_t i) {
03196 tbinptr* tb = treebin_at(m, i);
03197 tchunkptr t = *tb;
03198 int empty = (m->treemap & (1U << i)) == 0;
03199 if (t == 0)
03200 assert(empty);
03201 if (!empty)
03202 do_check_tree(m, t);
03203 }
03204
03205
03206 static void do_check_smallbin(mstate m, bindex_t i) {
03207 sbinptr b = smallbin_at(m, i);
03208 mchunkptr p = b->bk;
03209 unsigned int empty = (m->smallmap & (1U << i)) == 0;
03210 if (p == b)
03211 assert(empty);
03212 if (!empty) {
03213 for (; p != b; p = p->bk) {
03214 size_t size = chunksize(p);
03215 mchunkptr q;
03216
03217 do_check_free_chunk(m, p);
03218
03219 assert(small_index(size) == i);
03220 assert(p->bk == b || chunksize(p->bk) == chunksize(p));
03221
03222 q = next_chunk(p);
03223 if (q->head != FENCEPOST_HEAD)
03224 do_check_inuse_chunk(m, q);
03225 }
03226 }
03227 }
03228
03229
03230 static int bin_find(mstate m, mchunkptr x) {
03231 size_t size = chunksize(x);
03232 if (is_small(size)) {
03233 bindex_t sidx = small_index(size);
03234 sbinptr b = smallbin_at(m, sidx);
03235 if (smallmap_is_marked(m, sidx)) {
03236 mchunkptr p = b;
03237 do {
03238 if (p == x)
03239 return 1;
03240 } while ((p = p->fd) != b);
03241 }
03242 }
03243 else {
03244 bindex_t tidx;
03245 compute_tree_index(size, tidx);
03246 if (treemap_is_marked(m, tidx)) {
03247 tchunkptr t = *treebin_at(m, tidx);
03248 size_t sizebits = size << leftshift_for_tree_index(tidx);
03249 while (t != 0 && chunksize(t) != size) {
03250 t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
03251 sizebits <<= 1;
03252 }
03253 if (t != 0) {
03254 tchunkptr u = t;
03255 do {
03256 if (u == (tchunkptr)x)
03257 return 1;
03258 } while ((u = u->fd) != t);
03259 }
03260 }
03261 }
03262 return 0;
03263 }
03264
03265
03266 static size_t traverse_and_check(mstate m) {
03267 size_t sum = 0;
03268 if (is_initialized(m)) {
03269 msegmentptr s = &m->seg;
03270 sum += m->topsize + TOP_FOOT_SIZE;
03271 while (s != 0) {
03272 mchunkptr q = align_as_chunk(s->base);
03273 mchunkptr lastq = 0;
03274 assert(pinuse(q));
03275 while (segment_holds(s, q) &&
03276 q != m->top && q->head != FENCEPOST_HEAD) {
03277 sum += chunksize(q);
03278 if (cinuse(q)) {
03279 assert(!bin_find(m, q));
03280 do_check_inuse_chunk(m, q);
03281 }
03282 else {
03283 assert(q == m->dv || bin_find(m, q));
03284 assert(lastq == 0 || cinuse(lastq));
03285 do_check_free_chunk(m, q);
03286 }
03287 lastq = q;
03288 q = next_chunk(q);
03289 }
03290 s = s->next;
03291 }
03292 }
03293 return sum;
03294 }
03295
03296
03297 static void do_check_malloc_state(mstate m) {
03298 bindex_t i;
03299 size_t total;
03300
03301 for (i = 0; i < NSMALLBINS; ++i)
03302 do_check_smallbin(m, i);
03303 for (i = 0; i < NTREEBINS; ++i)
03304 do_check_treebin(m, i);
03305
03306 if (m->dvsize != 0) {
03307 do_check_any_chunk(m, m->dv);
03308 assert(m->dvsize == chunksize(m->dv));
03309 assert(m->dvsize >= MIN_CHUNK_SIZE);
03310 assert(bin_find(m, m->dv) == 0);
03311 }
03312
03313 if (m->top != 0) {
03314 do_check_top_chunk(m, m->top);
03315
03316 assert(m->topsize > 0);
03317 assert(bin_find(m, m->top) == 0);
03318 }
03319
03320 total = traverse_and_check(m);
03321 assert(total <= m->footprint);
03322 assert(m->footprint <= m->max_footprint);
03323 }
03324 #endif
03325
03326
03327
03328 #if !NO_MALLINFO
03329 static struct mallinfo internal_mallinfo(mstate m) {
03330 struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
03331 ensure_initialization();
03332 if (!PREACTION(m)) {
03333 check_malloc_state(m);
03334 if (is_initialized(m)) {
03335 size_t nfree = SIZE_T_ONE;
03336 size_t mfree = m->topsize + TOP_FOOT_SIZE;
03337 size_t sum = mfree;
03338 msegmentptr s = &m->seg;
03339 while (s != 0) {
03340 mchunkptr q = align_as_chunk(s->base);
03341 while (segment_holds(s, q) &&
03342 q != m->top && q->head != FENCEPOST_HEAD) {
03343 size_t sz = chunksize(q);
03344 sum += sz;
03345 if (!cinuse(q)) {
03346 mfree += sz;
03347 ++nfree;
03348 }
03349 q = next_chunk(q);
03350 }
03351 s = s->next;
03352 }
03353
03354 nm.arena = sum;
03355 nm.ordblks = nfree;
03356 nm.hblkhd = m->footprint - sum;
03357 nm.usmblks = m->max_footprint;
03358 nm.uordblks = m->footprint - mfree;
03359 nm.fordblks = mfree;
03360 nm.keepcost = m->topsize;
03361 }
03362
03363 POSTACTION(m);
03364 }
03365 return nm;
03366 }
03367 #endif
03368
03369 static void internal_malloc_stats(mstate m) {
03370 ensure_initialization();
03371 if (!PREACTION(m)) {
03372 size_t maxfp = 0;
03373 size_t fp = 0;
03374 size_t used = 0;
03375 check_malloc_state(m);
03376 if (is_initialized(m)) {
03377 msegmentptr s = &m->seg;
03378 maxfp = m->max_footprint;
03379 fp = m->footprint;
03380 used = fp - (m->topsize + TOP_FOOT_SIZE);
03381
03382 while (s != 0) {
03383 mchunkptr q = align_as_chunk(s->base);
03384 while (segment_holds(s, q) &&
03385 q != m->top && q->head != FENCEPOST_HEAD) {
03386 if (!cinuse(q))
03387 used -= chunksize(q);
03388 q = next_chunk(q);
03389 }
03390 s = s->next;
03391 }
03392 }
03393
03394 fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
03395 fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp));
03396 fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used));
03397
03398 POSTACTION(m);
03399 }
03400 }
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412 #define insert_small_chunk(M, P, S) {\
03413 bindex_t I = small_index(S);\
03414 mchunkptr B = smallbin_at(M, I);\
03415 mchunkptr F = B;\
03416 assert(S >= MIN_CHUNK_SIZE);\
03417 if (!smallmap_is_marked(M, I))\
03418 mark_smallmap(M, I);\
03419 else if (RTCHECK(ok_address(M, B->fd)))\
03420 F = B->fd;\
03421 else {\
03422 CORRUPTION_ERROR_ACTION(M);\
03423 }\
03424 B->fd = P;\
03425 F->bk = P;\
03426 P->fd = F;\
03427 P->bk = B;\
03428 }
03429
03430
03431 #define unlink_small_chunk(M, P, S) {\
03432 mchunkptr F = P->fd;\
03433 mchunkptr B = P->bk;\
03434 bindex_t I = small_index(S);\
03435 assert(P != B);\
03436 assert(P != F);\
03437 assert(chunksize(P) == small_index2size(I));\
03438 if (F == B)\
03439 clear_smallmap(M, I);\
03440 else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
03441 (B == smallbin_at(M,I) || ok_address(M, B)))) {\
03442 F->bk = B;\
03443 B->fd = F;\
03444 }\
03445 else {\
03446 CORRUPTION_ERROR_ACTION(M);\
03447 }\
03448 }
03449
03450
03451 #define unlink_first_small_chunk(M, B, P, I) {\
03452 mchunkptr F = P->fd;\
03453 assert(P != B);\
03454 assert(P != F);\
03455 assert(chunksize(P) == small_index2size(I));\
03456 if (B == F)\
03457 clear_smallmap(M, I);\
03458 else if (RTCHECK(ok_address(M, F))) {\
03459 B->fd = F;\
03460 F->bk = B;\
03461 }\
03462 else {\
03463 CORRUPTION_ERROR_ACTION(M);\
03464 }\
03465 }
03466
03467
03468
03469
03470
03471 #define replace_dv(M, P, S) {\
03472 size_t DVS = M->dvsize;\
03473 if (DVS != 0) {\
03474 mchunkptr DV = M->dv;\
03475 assert(is_small(DVS));\
03476 insert_small_chunk(M, DV, DVS);\
03477 }\
03478 M->dvsize = S;\
03479 M->dv = P;\
03480 }
03481
03482
03483
03484
03485 #define insert_large_chunk(M, X, S) {\
03486 tbinptr* H;\
03487 bindex_t I;\
03488 compute_tree_index(S, I);\
03489 H = treebin_at(M, I);\
03490 X->index = I;\
03491 X->child[0] = X->child[1] = 0;\
03492 if (!treemap_is_marked(M, I)) {\
03493 mark_treemap(M, I);\
03494 *H = X;\
03495 X->parent = (tchunkptr)H;\
03496 X->fd = X->bk = X;\
03497 }\
03498 else {\
03499 tchunkptr T = *H;\
03500 size_t K = S << leftshift_for_tree_index(I);\
03501 for (;;) {\
03502 if (chunksize(T) != S) {\
03503 tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
03504 K <<= 1;\
03505 if (*C != 0)\
03506 T = *C;\
03507 else if (RTCHECK(ok_address(M, C))) {\
03508 *C = X;\
03509 X->parent = T;\
03510 X->fd = X->bk = X;\
03511 break;\
03512 }\
03513 else {\
03514 CORRUPTION_ERROR_ACTION(M);\
03515 break;\
03516 }\
03517 }\
03518 else {\
03519 tchunkptr F = T->fd;\
03520 if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
03521 T->fd = F->bk = X;\
03522 X->fd = F;\
03523 X->bk = T;\
03524 X->parent = 0;\
03525 break;\
03526 }\
03527 else {\
03528 CORRUPTION_ERROR_ACTION(M);\
03529 break;\
03530 }\
03531 }\
03532 }\
03533 }\
03534 }
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553 #define unlink_large_chunk(M, X) {\
03554 tchunkptr XP = X->parent;\
03555 tchunkptr R;\
03556 if (X->bk != X) {\
03557 tchunkptr F = X->fd;\
03558 R = X->bk;\
03559 if (RTCHECK(ok_address(M, F))) {\
03560 F->bk = R;\
03561 R->fd = F;\
03562 }\
03563 else {\
03564 CORRUPTION_ERROR_ACTION(M);\
03565 }\
03566 }\
03567 else {\
03568 tchunkptr* RP;\
03569 if (((R = *(RP = &(X->child[1]))) != 0) ||\
03570 ((R = *(RP = &(X->child[0]))) != 0)) {\
03571 tchunkptr* CP;\
03572 while ((*(CP = &(R->child[1])) != 0) ||\
03573 (*(CP = &(R->child[0])) != 0)) {\
03574 R = *(RP = CP);\
03575 }\
03576 if (RTCHECK(ok_address(M, RP)))\
03577 *RP = 0;\
03578 else {\
03579 CORRUPTION_ERROR_ACTION(M);\
03580 }\
03581 }\
03582 }\
03583 if (XP != 0) {\
03584 tbinptr* H = treebin_at(M, X->index);\
03585 if (X == *H) {\
03586 if ((*H = R) == 0) \
03587 clear_treemap(M, X->index);\
03588 }\
03589 else if (RTCHECK(ok_address(M, XP))) {\
03590 if (XP->child[0] == X) \
03591 XP->child[0] = R;\
03592 else \
03593 XP->child[1] = R;\
03594 }\
03595 else\
03596 CORRUPTION_ERROR_ACTION(M);\
03597 if (R != 0) {\
03598 if (RTCHECK(ok_address(M, R))) {\
03599 tchunkptr C0, C1;\
03600 R->parent = XP;\
03601 if ((C0 = X->child[0]) != 0) {\
03602 if (RTCHECK(ok_address(M, C0))) {\
03603 R->child[0] = C0;\
03604 C0->parent = R;\
03605 }\
03606 else\
03607 CORRUPTION_ERROR_ACTION(M);\
03608 }\
03609 if ((C1 = X->child[1]) != 0) {\
03610 if (RTCHECK(ok_address(M, C1))) {\
03611 R->child[1] = C1;\
03612 C1->parent = R;\
03613 }\
03614 else\
03615 CORRUPTION_ERROR_ACTION(M);\
03616 }\
03617 }\
03618 else\
03619 CORRUPTION_ERROR_ACTION(M);\
03620 }\
03621 }\
03622 }
03623
03624
03625
03626 #define insert_chunk(M, P, S)\
03627 if (is_small(S)) insert_small_chunk(M, P, S)\
03628 else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
03629
03630 #define unlink_chunk(M, P, S)\
03631 if (is_small(S)) unlink_small_chunk(M, P, S)\
03632 else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
03633
03634
03635
03636
03637 #if ONLY_MSPACES
03638 #define internal_malloc(m, b) mspace_malloc(m, b)
03639 #define internal_free(m, mem) mspace_free(m,mem);
03640 #else
03641 #if MSPACES
03642 #define internal_malloc(m, b)\
03643 (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
03644 #define internal_free(m, mem)\
03645 if (m == gm) dlfree(mem); else mspace_free(m,mem);
03646 #else
03647 #define internal_malloc(m, b) dlmalloc(b)
03648 #define internal_free(m, mem) dlfree(mem)
03649 #endif
03650 #endif
03651
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665 static void* mmap_alloc(mstate m, size_t nb) {
03666 size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
03667 if (mmsize > nb) {
03668 char* mm = (char*)(CALL_DIRECT_MMAP(mmsize));
03669 if (mm != CMFAIL) {
03670 size_t offset = align_offset(chunk2mem(mm));
03671 size_t psize = mmsize - offset - MMAP_FOOT_PAD;
03672 mchunkptr p = (mchunkptr)(mm + offset);
03673 p->prev_foot = offset | IS_MMAPPED_BIT;
03674 (p)->head = (psize|CINUSE_BIT);
03675 mark_inuse_foot(m, p, psize);
03676 chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
03677 chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
03678
03679 if (mm < m->least_addr)
03680 m->least_addr = mm;
03681 if ((m->footprint += mmsize) > m->max_footprint)
03682 m->max_footprint = m->footprint;
03683 assert(is_aligned(chunk2mem(p)));
03684 check_mmapped_chunk(m, p);
03685 return chunk2mem(p);
03686 }
03687 }
03688 return 0;
03689 }
03690
03691
03692 static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
03693 size_t oldsize = chunksize(oldp);
03694 if (is_small(nb))
03695 return 0;
03696
03697 if (oldsize >= nb + SIZE_T_SIZE &&
03698 (oldsize - nb) <= (mparams.granularity << 1))
03699 return oldp;
03700 else {
03701 size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
03702 size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
03703 size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
03704 char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
03705 oldmmsize, newmmsize, 1);
03706 if (cp != CMFAIL) {
03707 mchunkptr newp = (mchunkptr)(cp + offset);
03708 size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
03709 newp->head = (psize|CINUSE_BIT);
03710 mark_inuse_foot(m, newp, psize);
03711 chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
03712 chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
03713
03714 if (cp < m->least_addr)
03715 m->least_addr = cp;
03716 if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
03717 m->max_footprint = m->footprint;
03718 check_mmapped_chunk(m, newp);
03719 return newp;
03720 }
03721 }
03722 return 0;
03723 }
03724
03725
03726
03727
03728 static void init_top(mstate m, mchunkptr p, size_t psize) {
03729
03730 size_t offset = align_offset(chunk2mem(p));
03731 p = (mchunkptr)((char*)p + offset);
03732 psize -= offset;
03733
03734 m->top = p;
03735 m->topsize = psize;
03736 p->head = psize | PINUSE_BIT;
03737
03738 chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
03739 m->trim_check = mparams.trim_threshold;
03740 }
03741
03742
03743 static void init_bins(mstate m) {
03744
03745 bindex_t i;
03746 for (i = 0; i < NSMALLBINS; ++i) {
03747 sbinptr bin = smallbin_at(m,i);
03748 bin->fd = bin->bk = bin;
03749 }
03750 }
03751
03752 #if PROCEED_ON_ERROR
03753
03754
03755 static void reset_on_error(mstate m) {
03756 int i;
03757 ++malloc_corruption_error_count;
03758
03759 m->smallbins = m->treebins = 0;
03760 m->dvsize = m->topsize = 0;
03761 m->seg.base = 0;
03762 m->seg.size = 0;
03763 m->seg.next = 0;
03764 m->top = m->dv = 0;
03765 for (i = 0; i < NTREEBINS; ++i)
03766 *treebin_at(m, i) = 0;
03767 init_bins(m);
03768 }
03769 #endif
03770
03771
03772 static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
03773 size_t nb) {
03774 mchunkptr p = align_as_chunk(newbase);
03775 mchunkptr oldfirst = align_as_chunk(oldbase);
03776 size_t psize = (char*)oldfirst - (char*)p;
03777 mchunkptr q = chunk_plus_offset(p, nb);
03778 size_t qsize = psize - nb;
03779 set_size_and_pinuse_of_inuse_chunk(m, p, nb);
03780
03781 assert((char*)oldfirst > (char*)q);
03782 assert(pinuse(oldfirst));
03783 assert(qsize >= MIN_CHUNK_SIZE);
03784
03785
03786 if (oldfirst == m->top) {
03787 size_t tsize = m->topsize += qsize;
03788 m->top = q;
03789 q->head = tsize | PINUSE_BIT;
03790 check_top_chunk(m, q);
03791 }
03792 else if (oldfirst == m->dv) {
03793 size_t dsize = m->dvsize += qsize;
03794 m->dv = q;
03795 set_size_and_pinuse_of_free_chunk(q, dsize);
03796 }
03797 else {
03798 if (!cinuse(oldfirst)) {
03799 size_t nsize = chunksize(oldfirst);
03800 unlink_chunk(m, oldfirst, nsize);
03801 oldfirst = chunk_plus_offset(oldfirst, nsize);
03802 qsize += nsize;
03803 }
03804 set_free_with_pinuse(q, qsize, oldfirst);
03805 insert_chunk(m, q, qsize);
03806 check_free_chunk(m, q);
03807 }
03808
03809 check_malloced_chunk(m, chunk2mem(p), nb);
03810 return chunk2mem(p);
03811 }
03812
03813
03814 static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
03815
03816 char* old_top = (char*)m->top;
03817 msegmentptr oldsp = segment_holding(m, old_top);
03818 char* old_end = oldsp->base + oldsp->size;
03819 size_t ssize = pad_request(sizeof(struct malloc_segment));
03820 char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
03821 size_t offset = align_offset(chunk2mem(rawsp));
03822 char* asp = rawsp + offset;
03823 char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
03824 mchunkptr sp = (mchunkptr)csp;
03825 msegmentptr ss = (msegmentptr)(chunk2mem(sp));
03826 mchunkptr tnext = chunk_plus_offset(sp, ssize);
03827 mchunkptr p = tnext;
03828 int nfences = 0;
03829
03830
03831 init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
03832
03833
03834 assert(is_aligned(ss));
03835 set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
03836 *ss = m->seg;
03837 m->seg.base = tbase;
03838 m->seg.size = tsize;
03839 m->seg.sflags = mmapped;
03840 m->seg.next = ss;
03841
03842
03843 for (;;) {
03844 mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
03845 p->head = FENCEPOST_HEAD;
03846 ++nfences;
03847 if ((char*)(&(nextp->head)) < old_end)
03848 p = nextp;
03849 else
03850 break;
03851 }
03852 assert(nfences >= 2);
03853
03854
03855 if (csp != old_top) {
03856 mchunkptr q = (mchunkptr)old_top;
03857 size_t psize = csp - old_top;
03858 mchunkptr tn = chunk_plus_offset(q, psize);
03859 set_free_with_pinuse(q, psize, tn);
03860 insert_chunk(m, q, psize);
03861 }
03862
03863 check_top_chunk(m, m->top);
03864 }
03865
03866
03867
03868
03869 static void* sys_alloc(mstate m, size_t nb) {
03870 char* tbase = CMFAIL;
03871 size_t tsize = 0;
03872 flag_t mmap_flag = 0;
03873
03874 ensure_initialization();
03875
03876
03877 if (use_mmap(m) && nb >= mparams.mmap_threshold) {
03878 void* mem = mmap_alloc(m, nb);
03879 if (mem != 0)
03880 return mem;
03881 }
03882
03883
03884
03885
03886
03887
03888
03889
03890
03891
03892
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905 if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
03906 char* br = CMFAIL;
03907 msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
03908 size_t asize = 0;
03909 ACQUIRE_MALLOC_GLOBAL_LOCK();
03910
03911 if (ss == 0) {
03912 char* base = (char*)CALL_MORECORE(0);
03913 if (base != CMFAIL) {
03914 asize = granularity_align(nb + SYS_ALLOC_PADDING);
03915
03916 if (!is_page_aligned(base))
03917 asize += (page_align((size_t)base) - (size_t)base);
03918
03919 if (asize < HALF_MAX_SIZE_T &&
03920 (br = (char*)(CALL_MORECORE(asize))) == base) {
03921 tbase = base;
03922 tsize = asize;
03923 }
03924 }
03925 }
03926 else {
03927
03928 asize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING);
03929
03930 if (asize < HALF_MAX_SIZE_T &&
03931 (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
03932 tbase = br;
03933 tsize = asize;
03934 }
03935 }
03936
03937 if (tbase == CMFAIL) {
03938 if (br != CMFAIL) {
03939 if (asize < HALF_MAX_SIZE_T &&
03940 asize < nb + SYS_ALLOC_PADDING) {
03941 size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - asize);
03942 if (esize < HALF_MAX_SIZE_T) {
03943 char* end = (char*)CALL_MORECORE(esize);
03944 if (end != CMFAIL)
03945 asize += esize;
03946 else {
03947 (void) CALL_MORECORE(-asize);
03948 br = CMFAIL;
03949 }
03950 }
03951 }
03952 }
03953 if (br != CMFAIL) {
03954 tbase = br;
03955 tsize = asize;
03956 }
03957 else
03958 disable_contiguous(m);
03959 }
03960
03961 RELEASE_MALLOC_GLOBAL_LOCK();
03962 }
03963
03964 if (HAVE_MMAP && tbase == CMFAIL) {
03965 size_t rsize = granularity_align(nb + SYS_ALLOC_PADDING);
03966 if (rsize > nb) {
03967 char* mp = (char*)(CALL_MMAP(rsize));
03968 if (mp != CMFAIL) {
03969 tbase = mp;
03970 tsize = rsize;
03971 mmap_flag = IS_MMAPPED_BIT;
03972 }
03973 }
03974 }
03975
03976 if (HAVE_MORECORE && tbase == CMFAIL) {
03977 size_t asize = granularity_align(nb + SYS_ALLOC_PADDING);
03978 if (asize < HALF_MAX_SIZE_T) {
03979 char* br = CMFAIL;
03980 char* end = CMFAIL;
03981 ACQUIRE_MALLOC_GLOBAL_LOCK();
03982 br = (char*)(CALL_MORECORE(asize));
03983 end = (char*)(CALL_MORECORE(0));
03984 RELEASE_MALLOC_GLOBAL_LOCK();
03985 if (br != CMFAIL && end != CMFAIL && br < end) {
03986 size_t ssize = end - br;
03987 if (ssize > nb + TOP_FOOT_SIZE) {
03988 tbase = br;
03989 tsize = ssize;
03990 }
03991 }
03992 }
03993 }
03994
03995 if (tbase != CMFAIL) {
03996
03997 if ((m->footprint += tsize) > m->max_footprint)
03998 m->max_footprint = m->footprint;
03999
04000 if (!is_initialized(m)) {
04001 m->seg.base = m->least_addr = tbase;
04002 m->seg.size = tsize;
04003 m->seg.sflags = mmap_flag;
04004 m->magic = mparams.magic;
04005 m->release_checks = MAX_RELEASE_CHECK_RATE;
04006 init_bins(m);
04007 #if !ONLY_MSPACES
04008 if (is_global(m))
04009 init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
04010 else
04011 #endif
04012 {
04013
04014 mchunkptr mn = next_chunk(mem2chunk(m));
04015 init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
04016 }
04017 }
04018
04019 else {
04020
04021 msegmentptr sp = &m->seg;
04022
04023 while (sp != 0 && tbase != sp->base + sp->size)
04024 sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
04025 if (sp != 0 &&
04026 !is_extern_segment(sp) &&
04027 (sp->sflags & IS_MMAPPED_BIT) == mmap_flag &&
04028 segment_holds(sp, m->top)) {
04029 sp->size += tsize;
04030 init_top(m, m->top, m->topsize + tsize);
04031 }
04032 else {
04033 if (tbase < m->least_addr)
04034 m->least_addr = tbase;
04035 sp = &m->seg;
04036 while (sp != 0 && sp->base != tbase + tsize)
04037 sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next;
04038 if (sp != 0 &&
04039 !is_extern_segment(sp) &&
04040 (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) {
04041 char* oldbase = sp->base;
04042 sp->base = tbase;
04043 sp->size += tsize;
04044 return prepend_alloc(m, tbase, oldbase, nb);
04045 }
04046 else
04047 add_segment(m, tbase, tsize, mmap_flag);
04048 }
04049 }
04050
04051 if (nb < m->topsize) {
04052 size_t rsize = m->topsize -= nb;
04053 mchunkptr p = m->top;
04054 mchunkptr r = m->top = chunk_plus_offset(p, nb);
04055 r->head = rsize | PINUSE_BIT;
04056 set_size_and_pinuse_of_inuse_chunk(m, p, nb);
04057 check_top_chunk(m, m->top);
04058 check_malloced_chunk(m, chunk2mem(p), nb);
04059 return chunk2mem(p);
04060 }
04061 }
04062
04063 MALLOC_FAILURE_ACTION;
04064 return 0;
04065 }
04066
04067
04068
04069
04070 static size_t release_unused_segments(mstate m) {
04071 size_t released = 0;
04072 int nsegs = 0;
04073 msegmentptr pred = &m->seg;
04074 msegmentptr sp = pred->next;
04075 while (sp != 0) {
04076 char* base = sp->base;
04077 size_t size = sp->size;
04078 msegmentptr next = sp->next;
04079 ++nsegs;
04080 if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
04081 mchunkptr p = align_as_chunk(base);
04082 size_t psize = chunksize(p);
04083
04084 if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
04085 tchunkptr tp = (tchunkptr)p;
04086 assert(segment_holds(sp, (char*)sp));
04087 if (p == m->dv) {
04088 m->dv = 0;
04089 m->dvsize = 0;
04090 }
04091 else {
04092 unlink_large_chunk(m, tp);
04093 }
04094 if (CALL_MUNMAP(base, size) == 0) {
04095 released += size;
04096 m->footprint -= size;
04097
04098 sp = pred;
04099 sp->next = next;
04100 }
04101 else {
04102 insert_large_chunk(m, tp, psize);
04103 }
04104 }
04105 }
04106 if (NO_SEGMENT_TRAVERSAL)
04107 break;
04108 pred = sp;
04109 sp = next;
04110 }
04111
04112 m->release_checks = ((nsegs > MAX_RELEASE_CHECK_RATE)?
04113 nsegs : MAX_RELEASE_CHECK_RATE);
04114 return released;
04115 }
04116
04117 static int sys_trim(mstate m, size_t pad) {
04118 size_t released = 0;
04119 ensure_initialization();
04120 if (pad < MAX_REQUEST && is_initialized(m)) {
04121 pad += TOP_FOOT_SIZE;
04122
04123 if (m->topsize > pad) {
04124
04125 size_t unit = mparams.granularity;
04126 size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
04127 SIZE_T_ONE) * unit;
04128 msegmentptr sp = segment_holding(m, (char*)m->top);
04129
04130 if (!is_extern_segment(sp)) {
04131 if (is_mmapped_segment(sp)) {
04132 if (HAVE_MMAP &&
04133 sp->size >= extra &&
04134 !has_segment_link(m, sp)) {
04135 size_t newsize = sp->size - extra;
04136
04137 if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
04138 (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
04139 released = extra;
04140 }
04141 }
04142 }
04143 else if (HAVE_MORECORE) {
04144 if (extra >= HALF_MAX_SIZE_T)
04145 extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
04146 ACQUIRE_MALLOC_GLOBAL_LOCK();
04147 {
04148
04149 char* old_br = (char*)(CALL_MORECORE(0));
04150 if (old_br == sp->base + sp->size) {
04151 char* rel_br = (char*)(CALL_MORECORE(-extra));
04152 char* new_br = (char*)(CALL_MORECORE(0));
04153 if (rel_br != CMFAIL && new_br < old_br)
04154 released = old_br - new_br;
04155 }
04156 }
04157 RELEASE_MALLOC_GLOBAL_LOCK();
04158 }
04159 }
04160
04161 if (released != 0) {
04162 sp->size -= released;
04163 m->footprint -= released;
04164 init_top(m, m->top, m->topsize - released);
04165 check_top_chunk(m, m->top);
04166 }
04167 }
04168
04169
04170 if (HAVE_MMAP)
04171 released += release_unused_segments(m);
04172
04173
04174 if (released == 0 && m->topsize > m->trim_check)
04175 m->trim_check = MAX_SIZE_T;
04176 }
04177
04178 return (released != 0)? 1 : 0;
04179 }
04180
04181
04182
04183
04184
04185 static void* tmalloc_large(mstate m, size_t nb) {
04186 tchunkptr v = 0;
04187 size_t rsize = -nb;
04188 tchunkptr t;
04189 bindex_t idx;
04190 compute_tree_index(nb, idx);
04191 if ((t = *treebin_at(m, idx)) != 0) {
04192
04193 size_t sizebits = nb << leftshift_for_tree_index(idx);
04194 tchunkptr rst = 0;
04195 for (;;) {
04196 tchunkptr rt;
04197 size_t trem = chunksize(t) - nb;
04198 if (trem < rsize) {
04199 v = t;
04200 if ((rsize = trem) == 0)
04201 break;
04202 }
04203 rt = t->child[1];
04204 t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
04205 if (rt != 0 && rt != t)
04206 rst = rt;
04207 if (t == 0) {
04208 t = rst;
04209 break;
04210 }
04211 sizebits <<= 1;
04212 }
04213 }
04214 if (t == 0 && v == 0) {
04215 binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
04216 if (leftbits != 0) {
04217 bindex_t i;
04218 binmap_t leastbit = least_bit(leftbits);
04219 compute_bit2idx(leastbit, i);
04220 t = *treebin_at(m, i);
04221 }
04222 }
04223
04224 while (t != 0) {
04225 size_t trem = chunksize(t) - nb;
04226 if (trem < rsize) {
04227 rsize = trem;
04228 v = t;
04229 }
04230 t = leftmost_child(t);
04231 }
04232
04233
04234 if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
04235 if (RTCHECK(ok_address(m, v))) {
04236 mchunkptr r = chunk_plus_offset(v, nb);
04237 assert(chunksize(v) == rsize + nb);
04238 if (RTCHECK(ok_next(v, r))) {
04239 unlink_large_chunk(m, v);
04240 if (rsize < MIN_CHUNK_SIZE)
04241 set_inuse_and_pinuse(m, v, (rsize + nb));
04242 else {
04243 set_size_and_pinuse_of_inuse_chunk(m, v, nb);
04244 set_size_and_pinuse_of_free_chunk(r, rsize);
04245 insert_chunk(m, r, rsize);
04246 }
04247 return chunk2mem(v);
04248 }
04249 }
04250 CORRUPTION_ERROR_ACTION(m);
04251 }
04252 return 0;
04253 }
04254
04255
04256 static void* tmalloc_small(mstate m, size_t nb) {
04257 tchunkptr t, v;
04258 size_t rsize;
04259 bindex_t i;
04260 binmap_t leastbit = least_bit(m->treemap);
04261 compute_bit2idx(leastbit, i);
04262 v = t = *treebin_at(m, i);
04263 rsize = chunksize(t) - nb;
04264
04265 while ((t = leftmost_child(t)) != 0) {
04266 size_t trem = chunksize(t) - nb;
04267 if (trem < rsize) {
04268 rsize = trem;
04269 v = t;
04270 }
04271 }
04272
04273 if (RTCHECK(ok_address(m, v))) {
04274 mchunkptr r = chunk_plus_offset(v, nb);
04275 assert(chunksize(v) == rsize + nb);
04276 if (RTCHECK(ok_next(v, r))) {
04277 unlink_large_chunk(m, v);
04278 if (rsize < MIN_CHUNK_SIZE)
04279 set_inuse_and_pinuse(m, v, (rsize + nb));
04280 else {
04281 set_size_and_pinuse_of_inuse_chunk(m, v, nb);
04282 set_size_and_pinuse_of_free_chunk(r, rsize);
04283 replace_dv(m, r, rsize);
04284 }
04285 return chunk2mem(v);
04286 }
04287 }
04288
04289 CORRUPTION_ERROR_ACTION(m);
04290 return 0;
04291 }
04292
04293
04294
04295 static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
04296 if (bytes >= MAX_REQUEST) {
04297 MALLOC_FAILURE_ACTION;
04298 return 0;
04299 }
04300 if (!PREACTION(m)) {
04301 mchunkptr oldp = mem2chunk(oldmem);
04302 size_t oldsize = chunksize(oldp);
04303 mchunkptr next = chunk_plus_offset(oldp, oldsize);
04304 mchunkptr newp = 0;
04305 void* extra = 0;
04306
04307
04308
04309 if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
04310 ok_next(oldp, next) && ok_pinuse(next))) {
04311 size_t nb = request2size(bytes);
04312 if (is_mmapped(oldp))
04313 newp = mmap_resize(m, oldp, nb);
04314 else if (oldsize >= nb) {
04315 size_t rsize = oldsize - nb;
04316 newp = oldp;
04317 if (rsize >= MIN_CHUNK_SIZE) {
04318 mchunkptr remainder = chunk_plus_offset(newp, nb);
04319 set_inuse(m, newp, nb);
04320 set_inuse(m, remainder, rsize);
04321 extra = chunk2mem(remainder);
04322 }
04323 }
04324 else if (next == m->top && oldsize + m->topsize > nb) {
04325
04326 size_t newsize = oldsize + m->topsize;
04327 size_t newtopsize = newsize - nb;
04328 mchunkptr newtop = chunk_plus_offset(oldp, nb);
04329 set_inuse(m, oldp, nb);
04330 newtop->head = newtopsize |PINUSE_BIT;
04331 m->top = newtop;
04332 m->topsize = newtopsize;
04333 newp = oldp;
04334 }
04335 }
04336 else {
04337 USAGE_ERROR_ACTION(m, oldmem);
04338 POSTACTION(m);
04339 return 0;
04340 }
04341
04342 POSTACTION(m);
04343
04344 if (newp != 0) {
04345 if (extra != 0) {
04346 internal_free(m, extra);
04347 }
04348 check_inuse_chunk(m, newp);
04349 return chunk2mem(newp);
04350 }
04351 else {
04352 void* newmem = internal_malloc(m, bytes);
04353 if (newmem != 0) {
04354 size_t oc = oldsize - overhead_for(oldp);
04355 memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
04356 internal_free(m, oldmem);
04357 }
04358 return newmem;
04359 }
04360 }
04361 return 0;
04362 }
04363
04364
04365
04366 static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
04367 if (alignment <= MALLOC_ALIGNMENT)
04368 return internal_malloc(m, bytes);
04369 if (alignment < MIN_CHUNK_SIZE)
04370 alignment = MIN_CHUNK_SIZE;
04371 if ((alignment & (alignment-SIZE_T_ONE)) != 0) {
04372 size_t a = MALLOC_ALIGNMENT << 1;
04373 while (a < alignment) a <<= 1;
04374 alignment = a;
04375 }
04376
04377 if (bytes >= MAX_REQUEST - alignment) {
04378 if (m != 0) {
04379 MALLOC_FAILURE_ACTION;
04380 }
04381 }
04382 else {
04383 size_t nb = request2size(bytes);
04384 size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
04385 char* mem = (char*)internal_malloc(m, req);
04386 if (mem != 0) {
04387 void* leader = 0;
04388 void* trailer = 0;
04389 mchunkptr p = mem2chunk(mem);
04390
04391 if (PREACTION(m)) return 0;
04392 if ((((size_t)(mem)) % alignment) != 0) {
04393
04394
04395
04396
04397
04398
04399
04400
04401 char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
04402 alignment -
04403 SIZE_T_ONE)) &
04404 -alignment));
04405 char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
04406 br : br+alignment;
04407 mchunkptr newp = (mchunkptr)pos;
04408 size_t leadsize = pos - (char*)(p);
04409 size_t newsize = chunksize(p) - leadsize;
04410
04411 if (is_mmapped(p)) {
04412 newp->prev_foot = p->prev_foot + leadsize;
04413 newp->head = (newsize|CINUSE_BIT);
04414 }
04415 else {
04416 set_inuse(m, newp, newsize);
04417 set_inuse(m, p, leadsize);
04418 leader = chunk2mem(p);
04419 }
04420 p = newp;
04421 }
04422
04423
04424 if (!is_mmapped(p)) {
04425 size_t size = chunksize(p);
04426 if (size > nb + MIN_CHUNK_SIZE) {
04427 size_t remainder_size = size - nb;
04428 mchunkptr remainder = chunk_plus_offset(p, nb);
04429 set_inuse(m, p, nb);
04430 set_inuse(m, remainder, remainder_size);
04431 trailer = chunk2mem(remainder);
04432 }
04433 }
04434
04435 assert (chunksize(p) >= nb);
04436 assert((((size_t)(chunk2mem(p))) % alignment) == 0);
04437 check_inuse_chunk(m, p);
04438 POSTACTION(m);
04439 if (leader != 0) {
04440 internal_free(m, leader);
04441 }
04442 if (trailer != 0) {
04443 internal_free(m, trailer);
04444 }
04445 return chunk2mem(p);
04446 }
04447 }
04448 return 0;
04449 }
04450
04451
04452
04453 static void** ialloc(mstate m,
04454 size_t n_elements,
04455 size_t* sizes,
04456 int opts,
04457 void* chunks[]) {
04458
04459
04460
04461
04462
04463
04464
04465
04466
04467 size_t element_size;
04468 size_t contents_size;
04469 size_t array_size;
04470 void* mem;
04471 mchunkptr p;
04472 size_t remainder_size;
04473 void** marray;
04474 mchunkptr array_chunk;
04475 flag_t was_enabled;
04476 size_t size;
04477 size_t i;
04478
04479 ensure_initialization();
04480
04481 if (chunks != 0) {
04482 if (n_elements == 0)
04483 return chunks;
04484 marray = chunks;
04485 array_size = 0;
04486 }
04487 else {
04488
04489 if (n_elements == 0)
04490 return (void**)internal_malloc(m, 0);
04491 marray = 0;
04492 array_size = request2size(n_elements * (sizeof(void*)));
04493 }
04494
04495
04496 if (opts & 0x1) {
04497 element_size = request2size(*sizes);
04498 contents_size = n_elements * element_size;
04499 }
04500 else {
04501 element_size = 0;
04502 contents_size = 0;
04503 for (i = 0; i != n_elements; ++i)
04504 contents_size += request2size(sizes[i]);
04505 }
04506
04507 size = contents_size + array_size;
04508
04509
04510
04511
04512
04513
04514 was_enabled = use_mmap(m);
04515 disable_mmap(m);
04516 mem = internal_malloc(m, size - CHUNK_OVERHEAD);
04517 if (was_enabled)
04518 enable_mmap(m);
04519 if (mem == 0)
04520 return 0;
04521
04522 if (PREACTION(m)) return 0;
04523 p = mem2chunk(mem);
04524 remainder_size = chunksize(p);
04525
04526 assert(!is_mmapped(p));
04527
04528 if (opts & 0x2) {
04529 memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
04530 }
04531
04532
04533 if (marray == 0) {
04534 size_t array_chunk_size;
04535 array_chunk = chunk_plus_offset(p, contents_size);
04536 array_chunk_size = remainder_size - contents_size;
04537 marray = (void**) (chunk2mem(array_chunk));
04538 set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
04539 remainder_size = contents_size;
04540 }
04541
04542
04543 for (i = 0; ; ++i) {
04544 marray[i] = chunk2mem(p);
04545 if (i != n_elements-1) {
04546 if (element_size != 0)
04547 size = element_size;
04548 else
04549 size = request2size(sizes[i]);
04550 remainder_size -= size;
04551 set_size_and_pinuse_of_inuse_chunk(m, p, size);
04552 p = chunk_plus_offset(p, size);
04553 }
04554 else {
04555 set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
04556 break;
04557 }
04558 }
04559
04560 #if DEBUG
04561 if (marray != chunks) {
04562
04563 if (element_size != 0) {
04564 assert(remainder_size == element_size);
04565 }
04566 else {
04567 assert(remainder_size == request2size(sizes[i]));
04568 }
04569 check_inuse_chunk(m, mem2chunk(marray));
04570 }
04571 for (i = 0; i != n_elements; ++i)
04572 check_inuse_chunk(m, mem2chunk(marray[i]));
04573
04574 #endif
04575
04576 POSTACTION(m);
04577 return marray;
04578 }
04579
04580
04581
04582
04583 #if !ONLY_MSPACES
04584
04585 void* dlmalloc(size_t bytes) {
04586
04587
04588
04589
04590
04591
04592
04593
04594
04595
04596
04597
04598
04599
04600
04601
04602
04603
04604
04605
04606
04607
04608
04609 #if USE_LOCKS
04610 ensure_initialization();
04611 #endif
04612
04613 if (!PREACTION(gm)) {
04614 void* mem;
04615 size_t nb;
04616 if (bytes <= MAX_SMALL_REQUEST) {
04617 bindex_t idx;
04618 binmap_t smallbits;
04619 nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
04620 idx = small_index(nb);
04621 smallbits = gm->smallmap >> idx;
04622
04623 if ((smallbits & 0x3U) != 0) {
04624 mchunkptr b, p;
04625 idx += ~smallbits & 1;
04626 b = smallbin_at(gm, idx);
04627 p = b->fd;
04628 assert(chunksize(p) == small_index2size(idx));
04629 unlink_first_small_chunk(gm, b, p, idx);
04630 set_inuse_and_pinuse(gm, p, small_index2size(idx));
04631 mem = chunk2mem(p);
04632 check_malloced_chunk(gm, mem, nb);
04633 goto postaction;
04634 }
04635
04636 else if (nb > gm->dvsize) {
04637 if (smallbits != 0) {
04638 mchunkptr b, p, r;
04639 size_t rsize;
04640 bindex_t i;
04641 binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
04642 binmap_t leastbit = least_bit(leftbits);
04643 compute_bit2idx(leastbit, i);
04644 b = smallbin_at(gm, i);
04645 p = b->fd;
04646 assert(chunksize(p) == small_index2size(i));
04647 unlink_first_small_chunk(gm, b, p, i);
04648 rsize = small_index2size(i) - nb;
04649
04650 if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
04651 set_inuse_and_pinuse(gm, p, small_index2size(i));
04652 else {
04653 set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
04654 r = chunk_plus_offset(p, nb);
04655 set_size_and_pinuse_of_free_chunk(r, rsize);
04656 replace_dv(gm, r, rsize);
04657 }
04658 mem = chunk2mem(p);
04659 check_malloced_chunk(gm, mem, nb);
04660 goto postaction;
04661 }
04662
04663 else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
04664 check_malloced_chunk(gm, mem, nb);
04665 goto postaction;
04666 }
04667 }
04668 }
04669 else if (bytes >= MAX_REQUEST)
04670 nb = MAX_SIZE_T;
04671 else {
04672 nb = pad_request(bytes);
04673 if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
04674 check_malloced_chunk(gm, mem, nb);
04675 goto postaction;
04676 }
04677 }
04678
04679 if (nb <= gm->dvsize) {
04680 size_t rsize = gm->dvsize - nb;
04681 mchunkptr p = gm->dv;
04682 if (rsize >= MIN_CHUNK_SIZE) {
04683 mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
04684 gm->dvsize = rsize;
04685 set_size_and_pinuse_of_free_chunk(r, rsize);
04686 set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
04687 }
04688 else {
04689 size_t dvs = gm->dvsize;
04690 gm->dvsize = 0;
04691 gm->dv = 0;
04692 set_inuse_and_pinuse(gm, p, dvs);
04693 }
04694 mem = chunk2mem(p);
04695 check_malloced_chunk(gm, mem, nb);
04696 goto postaction;
04697 }
04698
04699 else if (nb < gm->topsize) {
04700 size_t rsize = gm->topsize -= nb;
04701 mchunkptr p = gm->top;
04702 mchunkptr r = gm->top = chunk_plus_offset(p, nb);
04703 r->head = rsize | PINUSE_BIT;
04704 set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
04705 mem = chunk2mem(p);
04706 check_top_chunk(gm, gm->top);
04707 check_malloced_chunk(gm, mem, nb);
04708 goto postaction;
04709 }
04710
04711 mem = sys_alloc(gm, nb);
04712
04713 postaction:
04714 POSTACTION(gm);
04715 return mem;
04716 }
04717
04718 return 0;
04719 }
04720
04721 void dlfree(void* mem) {
04722
04723
04724
04725
04726
04727
04728 if (mem != 0) {
04729 mchunkptr p = mem2chunk(mem);
04730 #if FOOTERS
04731 mstate fm = get_mstate_for(p);
04732 if (!ok_magic(fm)) {
04733 USAGE_ERROR_ACTION(fm, p);
04734 return;
04735 }
04736 #else
04737 #define fm gm
04738 #endif
04739 if (!PREACTION(fm)) {
04740 check_inuse_chunk(fm, p);
04741 if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
04742 size_t psize = chunksize(p);
04743 mchunkptr next = chunk_plus_offset(p, psize);
04744 if (!pinuse(p)) {
04745 size_t prevsize = p->prev_foot;
04746 if ((prevsize & IS_MMAPPED_BIT) != 0) {
04747 prevsize &= ~IS_MMAPPED_BIT;
04748 psize += prevsize + MMAP_FOOT_PAD;
04749 if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
04750 fm->footprint -= psize;
04751 goto postaction;
04752 }
04753 else {
04754 mchunkptr prev = chunk_minus_offset(p, prevsize);
04755 psize += prevsize;
04756 p = prev;
04757 if (RTCHECK(ok_address(fm, prev))) {
04758 if (p != fm->dv) {
04759 unlink_chunk(fm, p, prevsize);
04760 }
04761 else if ((next->head & INUSE_BITS) == INUSE_BITS) {
04762 fm->dvsize = psize;
04763 set_free_with_pinuse(p, psize, next);
04764 goto postaction;
04765 }
04766 }
04767 else
04768 goto erroraction;
04769 }
04770 }
04771
04772 if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
04773 if (!cinuse(next)) {
04774 if (next == fm->top) {
04775 size_t tsize = fm->topsize += psize;
04776 fm->top = p;
04777 p->head = tsize | PINUSE_BIT;
04778 if (p == fm->dv) {
04779 fm->dv = 0;
04780 fm->dvsize = 0;
04781 }
04782 if (should_trim(fm, tsize))
04783 sys_trim(fm, 0);
04784 goto postaction;
04785 }
04786 else if (next == fm->dv) {
04787 size_t dsize = fm->dvsize += psize;
04788 fm->dv = p;
04789 set_size_and_pinuse_of_free_chunk(p, dsize);
04790 goto postaction;
04791 }
04792 else {
04793 size_t nsize = chunksize(next);
04794 psize += nsize;
04795 unlink_chunk(fm, next, nsize);
04796 set_size_and_pinuse_of_free_chunk(p, psize);
04797 if (p == fm->dv) {
04798 fm->dvsize = psize;
04799 goto postaction;
04800 }
04801 }
04802 }
04803 else
04804 set_free_with_pinuse(p, psize, next);
04805
04806 if (is_small(psize)) {
04807 insert_small_chunk(fm, p, psize);
04808 check_free_chunk(fm, p);
04809 }
04810 else {
04811 tchunkptr tp = (tchunkptr)p;
04812 insert_large_chunk(fm, tp, psize);
04813 check_free_chunk(fm, p);
04814 if (--fm->release_checks == 0)
04815 release_unused_segments(fm);
04816 }
04817 goto postaction;
04818 }
04819 }
04820 erroraction:
04821 USAGE_ERROR_ACTION(fm, p);
04822 postaction:
04823 POSTACTION(fm);
04824 }
04825 }
04826 #if !FOOTERS
04827 #undef fm
04828 #endif
04829 }
04830
04831 void* dlcalloc(size_t n_elements, size_t elem_size) {
04832 void* mem;
04833 size_t req = 0;
04834 if (n_elements != 0) {
04835 req = n_elements * elem_size;
04836 if (((n_elements | elem_size) & ~(size_t)0xffff) &&
04837 (req / n_elements != elem_size))
04838 req = MAX_SIZE_T;
04839 }
04840 mem = dlmalloc(req);
04841 if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
04842 memset(mem, 0, req);
04843 return mem;
04844 }
04845
04846 void* dlrealloc(void* oldmem, size_t bytes) {
04847 if (oldmem == 0)
04848 return dlmalloc(bytes);
04849 #ifdef REALLOC_ZERO_BYTES_FREES
04850 if (bytes == 0) {
04851 dlfree(oldmem);
04852 return 0;
04853 }
04854 #endif
04855 else {
04856 #if ! FOOTERS
04857 mstate m = gm;
04858 #else
04859 mstate m = get_mstate_for(mem2chunk(oldmem));
04860 if (!ok_magic(m)) {
04861 USAGE_ERROR_ACTION(m, oldmem);
04862 return 0;
04863 }
04864 #endif
04865 return internal_realloc(m, oldmem, bytes);
04866 }
04867 }
04868
04869 void* dlmemalign(size_t alignment, size_t bytes) {
04870 return internal_memalign(gm, alignment, bytes);
04871 }
04872
04873 void** dlindependent_calloc(size_t n_elements, size_t elem_size,
04874 void* chunks[]) {
04875 size_t sz = elem_size;
04876 return ialloc(gm, n_elements, &sz, 3, chunks);
04877 }
04878
04879 void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
04880 void* chunks[]) {
04881 return ialloc(gm, n_elements, sizes, 0, chunks);
04882 }
04883
04884 void* dlvalloc(size_t bytes) {
04885 size_t pagesz;
04886 ensure_initialization();
04887 pagesz = mparams.page_size;
04888 return dlmemalign(pagesz, bytes);
04889 }
04890
04891 void* dlpvalloc(size_t bytes) {
04892 size_t pagesz;
04893 ensure_initialization();
04894 pagesz = mparams.page_size;
04895 return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
04896 }
04897
04898 int dlmalloc_trim(size_t pad) {
04899 ensure_initialization();
04900 int result = 0;
04901 if (!PREACTION(gm)) {
04902 result = sys_trim(gm, pad);
04903 POSTACTION(gm);
04904 }
04905 return result;
04906 }
04907
04908 size_t dlmalloc_footprint(void) {
04909 return gm->footprint;
04910 }
04911
04912 size_t dlmalloc_max_footprint(void) {
04913 return gm->max_footprint;
04914 }
04915
04916 #if !NO_MALLINFO
04917 struct mallinfo dlmallinfo(void) {
04918 return internal_mallinfo(gm);
04919 }
04920 #endif
04921
04922 void dlmalloc_stats() {
04923 internal_malloc_stats(gm);
04924 }
04925
04926 int dlmallopt(int param_number, int value) {
04927 return change_mparam(param_number, value);
04928 }
04929
04930 #endif
04931
04932 size_t dlmalloc_usable_size(void* mem) {
04933 if (mem != 0) {
04934 mchunkptr p = mem2chunk(mem);
04935 if (cinuse(p))
04936 return chunksize(p) - overhead_for(p);
04937 }
04938 return 0;
04939 }
04940
04941
04942
04943 #if MSPACES
04944
04945 static mstate init_user_mstate(char* tbase, size_t tsize) {
04946 size_t msize = pad_request(sizeof(struct malloc_state));
04947 mchunkptr mn;
04948 mchunkptr msp = align_as_chunk(tbase);
04949 mstate m = (mstate)(chunk2mem(msp));
04950 memset(m, 0, msize);
04951 INITIAL_LOCK(&m->mutex);
04952 msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
04953 m->seg.base = m->least_addr = tbase;
04954 m->seg.size = m->footprint = m->max_footprint = tsize;
04955 m->magic = mparams.magic;
04956 m->release_checks = MAX_RELEASE_CHECK_RATE;
04957 m->mflags = mparams.default_mflags;
04958 m->extp = 0;
04959 m->exts = 0;
04960 disable_contiguous(m);
04961 init_bins(m);
04962 mn = next_chunk(mem2chunk(m));
04963 init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
04964 check_top_chunk(m, m->top);
04965 return m;
04966 }
04967
04968 mspace create_mspace(size_t capacity, int locked) {
04969 mstate m = 0;
04970 size_t msize;
04971 ensure_initialization();
04972 msize = pad_request(sizeof(struct malloc_state));
04973 if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
04974 size_t rs = ((capacity == 0)? mparams.granularity :
04975 (capacity + TOP_FOOT_SIZE + msize));
04976 size_t tsize = granularity_align(rs);
04977 char* tbase = (char*)(CALL_MMAP(tsize));
04978 if (tbase != CMFAIL) {
04979 m = init_user_mstate(tbase, tsize);
04980 m->seg.sflags = IS_MMAPPED_BIT;
04981 set_lock(m, locked);
04982 }
04983 }
04984 return (mspace)m;
04985 }
04986
04987 mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
04988 mstate m = 0;
04989 size_t msize;
04990 ensure_initialization();
04991 msize = pad_request(sizeof(struct malloc_state));
04992 if (capacity > msize + TOP_FOOT_SIZE &&
04993 capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
04994 m = init_user_mstate((char*)base, capacity);
04995 m->seg.sflags = EXTERN_BIT;
04996 set_lock(m, locked);
04997 }
04998 return (mspace)m;
04999 }
05000
05001 int mspace_mmap_large_chunks(mspace msp, int enable) {
05002 int ret = 0;
05003 mstate ms = (mstate)msp;
05004 if (!PREACTION(ms)) {
05005 if (use_mmap(ms))
05006 ret = 1;
05007 if (enable)
05008 enable_mmap(ms);
05009 else
05010 disable_mmap(ms);
05011 POSTACTION(ms);
05012 }
05013 return ret;
05014 }
05015
05016 size_t destroy_mspace(mspace msp) {
05017 size_t freed = 0;
05018 mstate ms = (mstate)msp;
05019 if (ok_magic(ms)) {
05020 msegmentptr sp = &ms->seg;
05021 while (sp != 0) {
05022 char* base = sp->base;
05023 size_t size = sp->size;
05024 flag_t flag = sp->sflags;
05025 sp = sp->next;
05026 if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
05027 CALL_MUNMAP(base, size) == 0)
05028 freed += size;
05029 }
05030 }
05031 else {
05032 USAGE_ERROR_ACTION(ms,ms);
05033 }
05034 return freed;
05035 }
05036
05037
05038
05039
05040
05041
05042
05043 void* mspace_malloc(mspace msp, size_t bytes) {
05044 mstate ms = (mstate)msp;
05045 if (!ok_magic(ms)) {
05046 USAGE_ERROR_ACTION(ms,ms);
05047 return 0;
05048 }
05049 if (!PREACTION(ms)) {
05050 void* mem;
05051 size_t nb;
05052 if (bytes <= MAX_SMALL_REQUEST) {
05053 bindex_t idx;
05054 binmap_t smallbits;
05055 nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
05056 idx = small_index(nb);
05057 smallbits = ms->smallmap >> idx;
05058
05059 if ((smallbits & 0x3U) != 0) {
05060 mchunkptr b, p;
05061 idx += ~smallbits & 1;
05062 b = smallbin_at(ms, idx);
05063 p = b->fd;
05064 assert(chunksize(p) == small_index2size(idx));
05065 unlink_first_small_chunk(ms, b, p, idx);
05066 set_inuse_and_pinuse(ms, p, small_index2size(idx));
05067 mem = chunk2mem(p);
05068 check_malloced_chunk(ms, mem, nb);
05069 goto postaction;
05070 }
05071
05072 else if (nb > ms->dvsize) {
05073 if (smallbits != 0) {
05074 mchunkptr b, p, r;
05075 size_t rsize;
05076 bindex_t i;
05077 binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
05078 binmap_t leastbit = least_bit(leftbits);
05079 compute_bit2idx(leastbit, i);
05080 b = smallbin_at(ms, i);
05081 p = b->fd;
05082 assert(chunksize(p) == small_index2size(i));
05083 unlink_first_small_chunk(ms, b, p, i);
05084 rsize = small_index2size(i) - nb;
05085
05086 if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
05087 set_inuse_and_pinuse(ms, p, small_index2size(i));
05088 else {
05089 set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
05090 r = chunk_plus_offset(p, nb);
05091 set_size_and_pinuse_of_free_chunk(r, rsize);
05092 replace_dv(ms, r, rsize);
05093 }
05094 mem = chunk2mem(p);
05095 check_malloced_chunk(ms, mem, nb);
05096 goto postaction;
05097 }
05098
05099 else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
05100 check_malloced_chunk(ms, mem, nb);
05101 goto postaction;
05102 }
05103 }
05104 }
05105 else if (bytes >= MAX_REQUEST)
05106 nb = MAX_SIZE_T;
05107 else {
05108 nb = pad_request(bytes);
05109 if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
05110 check_malloced_chunk(ms, mem, nb);
05111 goto postaction;
05112 }
05113 }
05114
05115 if (nb <= ms->dvsize) {
05116 size_t rsize = ms->dvsize - nb;
05117 mchunkptr p = ms->dv;
05118 if (rsize >= MIN_CHUNK_SIZE) {
05119 mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
05120 ms->dvsize = rsize;
05121 set_size_and_pinuse_of_free_chunk(r, rsize);
05122 set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
05123 }
05124 else {
05125 size_t dvs = ms->dvsize;
05126 ms->dvsize = 0;
05127 ms->dv = 0;
05128 set_inuse_and_pinuse(ms, p, dvs);
05129 }
05130 mem = chunk2mem(p);
05131 check_malloced_chunk(ms, mem, nb);
05132 goto postaction;
05133 }
05134
05135 else if (nb < ms->topsize) {
05136 size_t rsize = ms->topsize -= nb;
05137 mchunkptr p = ms->top;
05138 mchunkptr r = ms->top = chunk_plus_offset(p, nb);
05139 r->head = rsize | PINUSE_BIT;
05140 set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
05141 mem = chunk2mem(p);
05142 check_top_chunk(ms, ms->top);
05143 check_malloced_chunk(ms, mem, nb);
05144 goto postaction;
05145 }
05146
05147 mem = sys_alloc(ms, nb);
05148
05149 postaction:
05150 POSTACTION(ms);
05151 return mem;
05152 }
05153
05154 return 0;
05155 }
05156
05157 void mspace_free(mspace msp, void* mem) {
05158 if (mem != 0) {
05159 mchunkptr p = mem2chunk(mem);
05160 #if FOOTERS
05161 mstate fm = get_mstate_for(p);
05162 #else
05163 mstate fm = (mstate)msp;
05164 #endif
05165 if (!ok_magic(fm)) {
05166 USAGE_ERROR_ACTION(fm, p);
05167 return;
05168 }
05169 if (!PREACTION(fm)) {
05170 check_inuse_chunk(fm, p);
05171 if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
05172 size_t psize = chunksize(p);
05173 mchunkptr next = chunk_plus_offset(p, psize);
05174 if (!pinuse(p)) {
05175 size_t prevsize = p->prev_foot;
05176 if ((prevsize & IS_MMAPPED_BIT) != 0) {
05177 prevsize &= ~IS_MMAPPED_BIT;
05178 psize += prevsize + MMAP_FOOT_PAD;
05179 if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
05180 fm->footprint -= psize;
05181 goto postaction;
05182 }
05183 else {
05184 mchunkptr prev = chunk_minus_offset(p, prevsize);
05185 psize += prevsize;
05186 p = prev;
05187 if (RTCHECK(ok_address(fm, prev))) {
05188 if (p != fm->dv) {
05189 unlink_chunk(fm, p, prevsize);
05190 }
05191 else if ((next->head & INUSE_BITS) == INUSE_BITS) {
05192 fm->dvsize = psize;
05193 set_free_with_pinuse(p, psize, next);
05194 goto postaction;
05195 }
05196 }
05197 else
05198 goto erroraction;
05199 }
05200 }
05201
05202 if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
05203 if (!cinuse(next)) {
05204 if (next == fm->top) {
05205 size_t tsize = fm->topsize += psize;
05206 fm->top = p;
05207 p->head = tsize | PINUSE_BIT;
05208 if (p == fm->dv) {
05209 fm->dv = 0;
05210 fm->dvsize = 0;
05211 }
05212 if (should_trim(fm, tsize))
05213 sys_trim(fm, 0);
05214 goto postaction;
05215 }
05216 else if (next == fm->dv) {
05217 size_t dsize = fm->dvsize += psize;
05218 fm->dv = p;
05219 set_size_and_pinuse_of_free_chunk(p, dsize);
05220 goto postaction;
05221 }
05222 else {
05223 size_t nsize = chunksize(next);
05224 psize += nsize;
05225 unlink_chunk(fm, next, nsize);
05226 set_size_and_pinuse_of_free_chunk(p, psize);
05227 if (p == fm->dv) {
05228 fm->dvsize = psize;
05229 goto postaction;
05230 }
05231 }
05232 }
05233 else
05234 set_free_with_pinuse(p, psize, next);
05235
05236 if (is_small(psize)) {
05237 insert_small_chunk(fm, p, psize);
05238 check_free_chunk(fm, p);
05239 }
05240 else {
05241 tchunkptr tp = (tchunkptr)p;
05242 insert_large_chunk(fm, tp, psize);
05243 check_free_chunk(fm, p);
05244 if (--fm->release_checks == 0)
05245 release_unused_segments(fm);
05246 }
05247 goto postaction;
05248 }
05249 }
05250 erroraction:
05251 USAGE_ERROR_ACTION(fm, p);
05252 postaction:
05253 POSTACTION(fm);
05254 }
05255 }
05256 }
05257
05258 void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
05259 void* mem;
05260 size_t req = 0;
05261 mstate ms = (mstate)msp;
05262 if (!ok_magic(ms)) {
05263 USAGE_ERROR_ACTION(ms,ms);
05264 return 0;
05265 }
05266 if (n_elements != 0) {
05267 req = n_elements * elem_size;
05268 if (((n_elements | elem_size) & ~(size_t)0xffff) &&
05269 (req / n_elements != elem_size))
05270 req = MAX_SIZE_T;
05271 }
05272 mem = internal_malloc(ms, req);
05273 if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
05274 memset(mem, 0, req);
05275 return mem;
05276 }
05277
05278 void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
05279 if (oldmem == 0)
05280 return mspace_malloc(msp, bytes);
05281 #ifdef REALLOC_ZERO_BYTES_FREES
05282 if (bytes == 0) {
05283 mspace_free(msp, oldmem);
05284 return 0;
05285 }
05286 #endif
05287 else {
05288 #if FOOTERS
05289 mchunkptr p = mem2chunk(oldmem);
05290 mstate ms = get_mstate_for(p);
05291 #else
05292 mstate ms = (mstate)msp;
05293 #endif
05294 if (!ok_magic(ms)) {
05295 USAGE_ERROR_ACTION(ms,ms);
05296 return 0;
05297 }
05298 return internal_realloc(ms, oldmem, bytes);
05299 }
05300 }
05301
05302 void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
05303 mstate ms = (mstate)msp;
05304 if (!ok_magic(ms)) {
05305 USAGE_ERROR_ACTION(ms,ms);
05306 return 0;
05307 }
05308 return internal_memalign(ms, alignment, bytes);
05309 }
05310
05311 void** mspace_independent_calloc(mspace msp, size_t n_elements,
05312 size_t elem_size, void* chunks[]) {
05313 size_t sz = elem_size;
05314 mstate ms = (mstate)msp;
05315 if (!ok_magic(ms)) {
05316 USAGE_ERROR_ACTION(ms,ms);
05317 return 0;
05318 }
05319 return ialloc(ms, n_elements, &sz, 3, chunks);
05320 }
05321
05322 void** mspace_independent_comalloc(mspace msp, size_t n_elements,
05323 size_t sizes[], void* chunks[]) {
05324 mstate ms = (mstate)msp;
05325 if (!ok_magic(ms)) {
05326 USAGE_ERROR_ACTION(ms,ms);
05327 return 0;
05328 }
05329 return ialloc(ms, n_elements, sizes, 0, chunks);
05330 }
05331
05332 int mspace_trim(mspace msp, size_t pad) {
05333 int result = 0;
05334 mstate ms = (mstate)msp;
05335 if (ok_magic(ms)) {
05336 if (!PREACTION(ms)) {
05337 result = sys_trim(ms, pad);
05338 POSTACTION(ms);
05339 }
05340 }
05341 else {
05342 USAGE_ERROR_ACTION(ms,ms);
05343 }
05344 return result;
05345 }
05346
05347 void mspace_malloc_stats(mspace msp) {
05348 mstate ms = (mstate)msp;
05349 if (ok_magic(ms)) {
05350 internal_malloc_stats(ms);
05351 }
05352 else {
05353 USAGE_ERROR_ACTION(ms,ms);
05354 }
05355 }
05356
05357 size_t mspace_footprint(mspace msp) {
05358 size_t result = 0;
05359 mstate ms = (mstate)msp;
05360 if (ok_magic(ms)) {
05361 result = ms->footprint;
05362 }
05363 else {
05364 USAGE_ERROR_ACTION(ms,ms);
05365 }
05366 return result;
05367 }
05368
05369
05370 size_t mspace_max_footprint(mspace msp) {
05371 size_t result = 0;
05372 mstate ms = (mstate)msp;
05373 if (ok_magic(ms)) {
05374 result = ms->max_footprint;
05375 }
05376 else {
05377 USAGE_ERROR_ACTION(ms,ms);
05378 }
05379 return result;
05380 }
05381
05382
05383 #if !NO_MALLINFO
05384 struct mallinfo mspace_mallinfo(mspace msp) {
05385 mstate ms = (mstate)msp;
05386 if (!ok_magic(ms)) {
05387 USAGE_ERROR_ACTION(ms,ms);
05388 }
05389 return internal_mallinfo(ms);
05390 }
05391 #endif
05392
05393 size_t mspace_usable_size(void* mem) {
05394 if (mem != 0) {
05395 mchunkptr p = mem2chunk(mem);
05396 if (cinuse(p))
05397 return chunksize(p) - overhead_for(p);
05398 }
05399 return 0;
05400 }
05401
05402 int mspace_mallopt(int param_number, int value) {
05403 return change_mparam(param_number, value);
05404 }
05405
05406 #endif
05407
05408
05409
05410
05411
05412
05413
05414
05415
05416
05417
05418
05419
05420
05421
05422
05423
05424
05425
05426
05427
05428
05429
05430
05431
05432
05433
05434
05435
05436
05437
05438
05439
05440
05441
05442
05443
05444
05445
05446
05447
05448
05449
05450
05451
05452
05453
05454
05455
05456
05457
05458
05459
05460
05461
05462
05463
05464
05465
05466
05467
05468
05469
05470
05471
05472
05473
05474
05475
05476
05477
05478
05479
05480
05481
05482
05483
05484
05485
05486
05487
05488
05489
05490
05491
05492
05493
05494
05495
05496
05497
05498
05499
05500
05501
05502
05503
05504
05505
05506
05507
05508
05509
05510
05511
05512
05513
05514
05515
05516
05517
05518
05519
05520
05521
05522
05523
05524
05525
05526
05527
05528
05529
05530
05531
05532
05533
05534
05535
05536
05537
05538
05539
05540
05541
05542
05543
05544
05545
05546
05547
05548
05549
05550
05551
05552
05553
05554
05555
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566
05567
05568
05569
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583
05584
05585
05586
05587
05588
05589
05590
05591
05592
05593
05594
05595
05596
05597
05598
05599
05600
05601
05602
05603
05604
05605
05606
05607
05608
05609
05610
05611
05612
05613
05614
05615
05616
05617
05618
05619
05620
05621
05622
05623
05624
05625
05626
05627
05628
05629
05630
05631
05632
05633
05634
05635
05636
05637
05638
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648
05649
05650
05651
05652
05653
05654
05655
05656
05657
05658
05659
05660
05661
05662
05663
05664
05665
05666
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683
05684
05685
05686
05687
05688
05689
05690
05691
05692
05693
05694