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 #include <sys/types.h>
00045 #if defined(BUILD_OS_DARWIN)
00046 #include <stdlib.h>
00047 #else
00048 #include <malloc.h>
00049 #endif
00050 #include <bstring.h>
00051 #include "defs.h"
00052 #include "mempool.h"
00053 #include "tracing.h"
00054 #include "erglob.h"
00055
00056 #ifdef KEY
00057 #ifndef NO_VALGRIND
00058 #include <memcheck.h>
00059
00060 #ifdef VALGRIND_MAKE_MEM_NOACCESS
00061 #define VALGRIND_MAKE_NOACCESS(ptr, size) \
00062 VALGRIND_MAKE_MEM_NOACCESS(ptr, size)
00063 #endif
00064
00065 #ifdef VALGRIND_MAKE_MEM_DEFINED
00066 #define VALGRIND_MAKE_READABLE(ptr, size) \
00067 VALGRIND_MAKE_MEM_DEFINED(ptr, size)
00068 #endif
00069
00070 #ifdef VALGRIND_MAKE_MEM_UNDEFINED
00071 #define VALGRIND_MAKE_WRITABLE(ptr, size) \
00072 VALGRIND_MAKE_MEM_UNDEFINED(ptr, size)
00073 #endif
00074
00075
00076
00077
00078
00079
00080 #ifndef VALGRIND_CREATE_MEMPOOL
00081 #define NO_VALGRIND
00082 #endif
00083
00084 #endif
00085 #endif
00086
00087 #ifdef NO_VALGRIND
00088 #define REDZONE_SIZE 0
00089 #else
00090 static int redzone_size = 0;
00091 #define REDZONE_SIZE redzone_size
00092 #endif
00093
00094
00095
00096
00097
00098 #define MEM_POOL_INIT_IN_PROGRESS (-1)
00099
00100
00101
00102
00103
00104
00105 #define BLOCK_SIZE 0x2000
00106
00107
00108
00109
00110 #define MIN_LARGE_BLOCK_SIZE 0x800
00111
00112
00113
00114 #ifdef Is_True_On
00115 #define ZAP_ON_FREE (1)
00116 #endif
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 MEM_POOL MEM_local_pool;
00127 MEM_POOL MEM_src_pool;
00128 MEM_POOL MEM_pu_pool;
00129 MEM_POOL MEM_phase_pool;
00130
00131 MEM_POOL *MEM_local_pool_ptr = &MEM_local_pool;
00132 MEM_POOL *MEM_src_pool_ptr = &MEM_src_pool;
00133 MEM_POOL *MEM_pu_pool_ptr = &MEM_pu_pool;
00134 MEM_POOL *MEM_phase_pool_ptr = &MEM_phase_pool;
00135
00136
00137
00138
00139
00140 MEM_POOL MEM_local_nz_pool;
00141 MEM_POOL MEM_src_nz_pool;
00142 MEM_POOL MEM_pu_nz_pool;
00143 MEM_POOL MEM_phase_nz_pool;
00144
00145 MEM_POOL *MEM_local_nz_pool_ptr = &MEM_local_nz_pool;
00146 MEM_POOL *MEM_src_nz_pool_ptr = &MEM_src_nz_pool;
00147 MEM_POOL *MEM_pu_nz_pool_ptr = &MEM_pu_nz_pool;
00148 MEM_POOL *MEM_phase_nz_pool_ptr = &MEM_phase_nz_pool;
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 struct mem_block {
00161 size_t avail;
00162
00163
00164 MEM_PTR ptr;
00165
00166 MEM_BLOCK *rest;
00167
00168
00169 };
00170
00171 #define MEM_BLOCK_avail(x) ((x)->avail)
00172 #define MEM_BLOCK_ptr(x) ((x)->ptr)
00173 #define MEM_BLOCK_rest(x) ((x)->rest)
00174
00175 #define MEM_BLOCK_first_ptr(x) \
00176 (MEM_PTR) (((char *) (x)) + PAD_TO_ALIGN(sizeof(MEM_BLOCK)))
00177
00178
00179
00180
00181
00182
00183 typedef struct mem_large_block MEM_LARGE_BLOCK;
00184 struct mem_large_block {
00185 MEM_LARGE_BLOCK *next;
00186 MEM_LARGE_BLOCK *prev;
00187 MEM_POOL_BLOCKS *base;
00188 MEM_PTR ptr;
00189 };
00190
00191 #define MEM_LARGE_BLOCK_next(x) ((x)->next)
00192 #define MEM_LARGE_BLOCK_prev(x) ((x)->prev)
00193 #define MEM_LARGE_BLOCK_base(x) ((x)->base)
00194 #define MEM_LARGE_BLOCK_ptr(x) ((x)->ptr)
00195 #define MEM_LARGE_BLOCK_OVERHEAD (PAD_TO_ALIGN(sizeof(MEM_LARGE_BLOCK)))
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 static void
00209 MEM_LARGE_BLOCK_zap(MEM_LARGE_BLOCK *block)
00210 {
00211 MEM_LARGE_BLOCK_base(block) = NULL;
00212 MEM_LARGE_BLOCK_ptr(block) = NULL;
00213 }
00214
00215 static void
00216 MEM_LARGE_BLOCK_free(MEM_LARGE_BLOCK *block)
00217 {
00218 MEM_LARGE_BLOCK_zap(block);
00219 free(block);
00220 }
00221
00222 static MEM_LARGE_BLOCK *
00223 MEM_LARGE_BLOCK_realloc(MEM_LARGE_BLOCK *old_block, INT64 new_size)
00224 {
00225 MEM_POOL_BLOCKS * const base = MEM_LARGE_BLOCK_base(old_block);
00226 MEM_PTR const ptr = MEM_LARGE_BLOCK_ptr(old_block);
00227 MEM_LARGE_BLOCK * new_block;
00228
00229 MEM_LARGE_BLOCK_zap(old_block);
00230 new_block = (MEM_LARGE_BLOCK *)realloc(old_block, new_size);
00231 if (new_block != NULL)
00232 {
00233 MEM_LARGE_BLOCK_base(new_block) = base;
00234 MEM_LARGE_BLOCK_ptr(new_block) = ptr;
00235 }
00236 return new_block;
00237 }
00238
00239
00240
00241
00242
00243 typedef struct int_list INT_LIST;
00244
00245 struct int_list {
00246 INT32 first;
00247
00248 INT_LIST *rest;
00249
00250 };
00251
00252 #define INT_LIST_first(x) ((x)->first)
00253 #define INT_LIST_rest(x) ((x)->rest)
00254
00255 static INT_LIST *free_int_lists;
00256
00257
00258
00259
00260
00261
00262 struct mem_stat {
00263 const char *file;
00264
00265 INT32 line;
00266
00267 INT32 total;
00268
00269
00270 INT32 current;
00271
00272
00273 INT32 max_t;
00274
00275
00276
00277 INT32 max_s;
00278
00279
00280
00281 INT32 last;
00282
00283
00284 INT32 last_grew;
00285
00286
00287
00288 INT32 last_shrank;
00289
00290
00291
00292 INT32 count;
00293
00294 MEM_STAT *hash_list_rest;
00295
00296
00297 MEM_STAT *pool_list_rest;
00298
00299
00300 INT_LIST *saved_current;
00301
00302
00303
00304 MEM_POOL *pool;
00305
00306 };
00307
00308 #define MEM_STAT_file(x) ((x)->file)
00309 #define MEM_STAT_line(x) ((x)->line)
00310 #define MEM_STAT_total(x) ((x)->total)
00311 #define MEM_STAT_current(x) ((x)->current)
00312 #define MEM_STAT_max_t(x) ((x)->max_t)
00313 #define MEM_STAT_max_s(x) ((x)->max_s)
00314 #define MEM_STAT_last(x) ((x)->last)
00315 #define MEM_STAT_last_grew(x) ((x)->last_grew)
00316 #define MEM_STAT_last_shrank(x) ((x)->last_shrank)
00317 #define MEM_STAT_count(x) ((x)->count)
00318 #define MEM_STAT_hash_list_rest(x) ((x)->hash_list_rest)
00319 #define MEM_STAT_pool_list_rest(x) ((x)->pool_list_rest)
00320 #define MEM_STAT_saved_current(x) ((x)->saved_current)
00321 #define MEM_STAT_pool(x) ((x)->pool)
00322
00323
00324
00325
00326
00327
00328
00329 struct mem_pool_blocks {
00330 MEM_BLOCK *block;
00331
00332 MEM_LARGE_BLOCK *large_block;
00333
00334 MEM_BLOCK *base_block;
00335
00336
00337 MEM_PTR *base_ptr;
00338
00339 size_t base_avail;
00340
00341
00342 MEM_POOL_BLOCKS *rest;
00343
00344
00345
00346
00347 };
00348
00349 #define MEM_POOL_BLOCKS_block(x) ((x)->block)
00350 #define MEM_POOL_BLOCKS_large_block(x) ((x)->large_block)
00351 #define MEM_POOL_BLOCKS_base_block(x) ((x)->base_block)
00352 #define MEM_POOL_BLOCKS_base_ptr(x) ((x)->base_ptr)
00353 #define MEM_POOL_BLOCKS_base_avail(x) ((x)->base_avail)
00354 #define MEM_POOL_BLOCKS_rest(x) ((x)->rest)
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 struct mem_pure_stack {
00399 MEM_PTR last_alloc;
00400 MEM_PURE_STACK *prev_stack;
00401
00402
00403 };
00404
00405 #define MEM_PURE_STACK_last_alloc(x) ((x)->last_alloc)
00406 #define MEM_PURE_STACK_prev_stack(x) ((x)->prev_stack)
00407 #define MEM_POOL_last_alloc(x) \
00408 MEM_PURE_STACK_last_alloc(MEM_POOL_pure_stack(x))
00409 #define MEM_POOL_prev_stack(x) \
00410 MEM_PURE_STACK_prev_stack(MEM_POOL_pure_stack(x))
00411 BOOL purify_pools = FALSE;
00412 static BOOL purify_pools_trace = FALSE;
00413 static BOOL purify_pools_trace_x = FALSE;
00414 static void PURIFY_OPT_Initialize(void);
00415
00416 #define MAGIC_NUM 0xabcd
00417
00418
00419
00420
00421 #define MEM_POOL_name(x) ((x)->name)
00422 #define MEM_POOL_blocks(x) ((x)->blocks)
00423 #define MEM_POOL_bz(x) ((x)->bz)
00424 #define MEM_POOL_rest(x) ((x)->rest)
00425 #define MEM_POOL_pure_stack(x) ((x)->pure_stack)
00426 #define MEM_POOL_frozen(x) ((x)->frozen)
00427 #define MEM_POOL_magic_num(x) ((x)->magic_num)
00428 #define MEM_POOL_alloc_site_list(x) ((x)->alloc_site_list)
00429
00430 #define MEM_POOL_block(x) \
00431 MEM_POOL_BLOCKS_block(MEM_POOL_blocks(x))
00432 #define MEM_POOL_large_block(x) \
00433 MEM_POOL_BLOCKS_large_block(MEM_POOL_blocks(x))
00434
00435
00436
00437
00438
00439 static MEM_POOL_BLOCKS *free_mem_pool_blocks_list;
00440
00441
00442
00443 static MEM_POOL_BLOCKS overhead_blocks;
00444
00445
00446
00447 static MEM_POOL mem_overhead_pool =
00448
00449
00450 {
00451 "memory overhead",
00452 &overhead_blocks,
00453 NULL,
00454 NULL,
00455 TRUE,
00456 FALSE,
00457 MAGIC_NUM,
00458 NULL
00459 };
00460
00461 static MEM_POOL *The_Default_Mem_Pool;
00462
00463
00464
00465 #define PAD_TO_ALIGN(size) (((size) + 7) & (~0U << 3))
00466
00467
00468
00469
00470 static BOOL mem_tracing_enabled = FALSE;
00471 #ifdef Is_True_On
00472 static MEM_POOL *initialized_pools =
00473
00474
00475 &mem_overhead_pool;
00476 #endif
00477
00478 #define N_BUCKETS 503
00479
00480 static MEM_STAT *call_site_hash_tab[N_BUCKETS];
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 static UINT32
00496 Hash(
00497 INT32 line,
00498 const char *file
00499 )
00500 {
00501 const char *p;
00502 UINT32 result = line;
00503
00504
00505
00506
00507 for ( p = file; *p; ++p )
00508 result = ((result << 1) ^ (result >> 1) ^ *p) + *p;
00509
00510 return result % N_BUCKETS;
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527 static MEM_STAT*
00528 Hash_Get(
00529 UINT32 hn,
00530 MEM_POOL *pool,
00531 INT32 line,
00532 const char *file
00533 )
00534 {
00535 MEM_STAT *as;
00536
00537 for ( as = call_site_hash_tab[hn];
00538 as != NULL;
00539 as = MEM_STAT_hash_list_rest(as)
00540 ) {
00541 if ( MEM_STAT_line(as) == line
00542 && strcmp(MEM_STAT_file(as),file) == 0
00543 && MEM_STAT_pool(as) == pool
00544 ) {
00545 return as;
00546 }
00547 }
00548
00549 return NULL;
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 static void
00568 Site_Account_Alloc(
00569 MEM_POOL *pool,
00570 size_t old_size,
00571 size_t new_size
00572 MEM_STAT_ARGS(line,file)
00573 )
00574 {
00575 INT32 size = new_size - old_size;
00576 UINT32 hn = Hash(line,file);
00577 MEM_STAT *ms = Hash_Get(hn,pool,line,file);
00578
00579 if ( ms == NULL ) {
00580 ms = (MEM_STAT *) calloc(1,sizeof(MEM_STAT));
00581
00582 MEM_STAT_pool(ms) = pool;
00583 MEM_STAT_line(ms) = line;
00584 MEM_STAT_file(ms) = file;
00585 MEM_STAT_hash_list_rest(ms) = call_site_hash_tab[hn];
00586 call_site_hash_tab[hn] = ms;
00587 MEM_STAT_pool_list_rest(ms) = MEM_POOL_alloc_site_list(pool);
00588 MEM_POOL_alloc_site_list(pool) = ms;
00589 }
00590
00591 MEM_STAT_current(ms) += size;
00592 MEM_STAT_total(ms) += size;
00593 if ( size > MEM_STAT_last(ms) )
00594 ++MEM_STAT_last_grew(ms);
00595 else if ( size < MEM_STAT_last(ms) )
00596 ++MEM_STAT_last_shrank(ms);
00597 MEM_STAT_max_t(ms) = Max(MEM_STAT_max_t(ms),MEM_STAT_current(ms));
00598 MEM_STAT_max_s(ms) = Max(MEM_STAT_max_s(ms),size);
00599 MEM_STAT_last(ms) = size;
00600 ++MEM_STAT_count(ms);
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 static void
00617 Site_Account_Pop(
00618 MEM_POOL *pool
00619 MEM_STAT_ARGS(line,file)
00620 )
00621 {
00622 MEM_STAT *ms;
00623
00624 for ( ms = MEM_POOL_alloc_site_list(pool);
00625 ms != NULL;
00626 ms = MEM_STAT_pool_list_rest(ms)
00627 ) {
00628 INT_LIST *tmp = MEM_STAT_saved_current(ms);
00629
00630 if ( tmp == NULL ) {
00631
00632
00633
00634 MEM_STAT_current(ms) = 0;
00635 }
00636 else {
00637 MEM_STAT_current(ms) = INT_LIST_first(tmp);
00638 MEM_STAT_saved_current(ms) = INT_LIST_rest(tmp);
00639 INT_LIST_rest(tmp) = free_int_lists;
00640 free_int_lists = tmp;
00641 }
00642 }
00643 }
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 static void
00657 Site_Account_Push(
00658 MEM_POOL *pool
00659 MEM_STAT_ARGS(line,file)
00660 )
00661 {
00662 MEM_STAT *ms;
00663
00664 for ( ms = MEM_POOL_alloc_site_list(pool);
00665 ms != NULL;
00666 ms = MEM_STAT_pool_list_rest(ms)
00667 ) {
00668 INT_LIST *il;
00669
00670 if ( free_int_lists == NULL )
00671 il = TYPE_MEM_POOL_ALLOC(INT_LIST,&mem_overhead_pool);
00672 else {
00673 il = free_int_lists;
00674
00675 free_int_lists = INT_LIST_rest(il);
00676 }
00677
00678 INT_LIST_rest(il) = MEM_STAT_saved_current(ms);
00679 MEM_STAT_saved_current(ms) = il;
00680 INT_LIST_first(il) = MEM_STAT_current(ms);
00681 }
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 static INT32
00694 Field_Size(
00695 INT32 i
00696 )
00697 {
00698 char buff[100];
00699
00700
00701
00702
00703 sprintf(buff,"%d",i);
00704 return strlen(buff);
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 typedef INT (*QSORT_FUNC) (const void *, const void *);
00721
00722 static INT
00723 MEM_STAT_Sort(
00724 MEM_STAT **as1p,
00725 MEM_STAT **as2p
00726 )
00727 {
00728 MEM_STAT *as1 = *as1p;
00729 MEM_STAT *as2 = *as2p;
00730
00731 return MEM_STAT_max_t(as2) - MEM_STAT_max_t(as1);
00732 }
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743 static BOOL
00744 MEM_STAT_In_List(
00745 MEM_POOL *list,
00746 MEM_POOL *pool
00747 )
00748 {
00749 for ( ;
00750 list != NULL;
00751 list = MEM_POOL_rest(list)
00752 ) {
00753 if ( list == pool )
00754 return ( TRUE );
00755 }
00756
00757 return ( FALSE );
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 INT32
00773 MEM_POOL_Report(
00774 MEM_POOL *pool,
00775 INT32 used_total
00776 )
00777 {
00778 MEM_STAT *as;
00779 MEM_STAT **as_vec;
00780 INT32 i;
00781 INT32 total_current = 0;
00782 INT32 total_allocated = 0;
00783 INT32 max_allocated = 0;
00784 INT32 current_fs = 3;
00785 INT32 total_fs = 3;
00786 INT32 max_t_fs = 4;
00787 INT32 max_s_fs = 4;
00788 INT32 count_fs = 5;
00789 INT32 last_grew_fs = 4;
00790 INT32 last_shrank_fs = 6;
00791 INT32 site_count = 0;
00792
00793 Is_True (MEM_POOL_magic_num(pool) == MAGIC_NUM,
00794 ("Report from un-initialized MEM_POOL %s\n", MEM_POOL_name(pool)));
00795
00796 fprintf(TFile,"----- %s callsites\n",MEM_POOL_name(pool));
00797
00798
00799
00800 for ( as = MEM_POOL_alloc_site_list(pool);
00801 as != NULL;
00802 as = MEM_STAT_pool_list_rest(as)
00803 ) {
00804 current_fs = Max(current_fs,Field_Size(MEM_STAT_current(as)));
00805 total_fs = Max(total_fs,Field_Size(MEM_STAT_total(as)));
00806 max_t_fs = Max(max_t_fs,Field_Size(MEM_STAT_max_t(as)));
00807 max_s_fs = Max(max_s_fs,Field_Size(MEM_STAT_max_s(as)));
00808 count_fs = Max(count_fs,Field_Size(MEM_STAT_count(as)));
00809 last_grew_fs = Max(last_grew_fs,
00810 Field_Size(MEM_STAT_last_grew(as)));
00811 last_shrank_fs = Max(last_shrank_fs,
00812 Field_Size(MEM_STAT_last_shrank(as)));
00813
00814 ++site_count;
00815 }
00816
00817
00818
00819 MEM_POOL_Push(&mem_overhead_pool);
00820 as_vec = TYPE_MEM_POOL_ALLOC_N(MEM_STAT *,&mem_overhead_pool,
00821 site_count);
00822
00823 for ( as = MEM_POOL_alloc_site_list(pool), i = 0;
00824 as != NULL;
00825 as = MEM_STAT_pool_list_rest(as), ++i
00826 ) {
00827 as_vec[i] = as;
00828 }
00829
00830 qsort((void*)as_vec,site_count,
00831 sizeof(MEM_STAT*),
00832 (QSORT_FUNC) MEM_STAT_Sort);
00833
00834
00835
00836 fprintf(TFile,"%*s %*s %*s %*s %*s %*s %*s Site\n",
00837 max_t_fs,
00838 "maxt",
00839 current_fs,
00840 "cur",
00841 total_fs,
00842 "tot",
00843 max_s_fs,
00844 "maxs",
00845 count_fs,
00846 "count",
00847 last_grew_fs,
00848 "grew",
00849 last_shrank_fs,
00850 "shrank");
00851
00852
00853
00854 for ( i = 0; i < site_count; ++i ) {
00855 as = as_vec[i];
00856
00857 fprintf(TFile,"%*d %*d %*d %*d %*d %*d %*d %s %d\n",
00858 max_t_fs,
00859 (INT)MEM_STAT_max_t(as),
00860 current_fs,
00861 (INT)MEM_STAT_current(as),
00862 total_fs,
00863 (INT)MEM_STAT_total(as),
00864 max_s_fs,
00865 (INT)MEM_STAT_max_s(as),
00866 count_fs,
00867 MEM_STAT_count(as),
00868 last_grew_fs,
00869 MEM_STAT_last_grew(as),
00870 last_shrank_fs,
00871 MEM_STAT_last_shrank(as),
00872 MEM_STAT_file(as),
00873 MEM_STAT_line(as));
00874 total_current += MEM_STAT_current(as);
00875 total_allocated += MEM_STAT_total(as);
00876 max_allocated += MEM_STAT_max_t(as);
00877 }
00878
00879 MEM_POOL_Pop(&mem_overhead_pool);
00880
00881 fprintf(TFile,"++++ Allocated for %s pool: total=%d, max=%d, current=%d (%d%%used)\n",
00882 MEM_POOL_name(pool),
00883 total_allocated,
00884 max_allocated,
00885 total_current,
00886 (INT) (100.0 * ( ((double) total_current)
00887 / ((double) used_total))));
00888 return total_allocated;
00889 }
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900 void
00901 MEM_Trace(void)
00902 {
00903 #ifdef Is_True_On
00904
00905 #if defined(linux) || defined(MEM_STATS)
00906 MEM_POOL *pool;
00907 struct mallinfo mi = mallinfo();
00908 INT32 used_total = mi.usmblks + mi.uordblks;
00909 INT32 total_allocated = 0;
00910
00911 fprintf(TFile,"arena %10d\n",mi.arena);
00912 fprintf(TFile,"ordblks %10d\n",mi.ordblks);
00913 fprintf(TFile,"smblks %10d\n",mi.smblks);
00914 fprintf(TFile,"hblkhd %10d\n",mi.hblkhd);
00915 fprintf(TFile,"hblks %10d\n",mi.hblks);
00916 fprintf(TFile,"usmblks %10d\n",mi.usmblks);
00917 fprintf(TFile,"fsmblks %10d\n",mi.fsmblks);
00918 fprintf(TFile,"uordblks %10d\n",mi.uordblks);
00919 fprintf(TFile,"fordblks %10d\n",mi.fordblks);
00920 fprintf(TFile,"keepcost %10d\n",mi.keepcost);
00921
00922 for ( pool = initialized_pools;
00923 pool != NULL;
00924 pool = MEM_POOL_rest(pool)
00925 ) {
00926 total_allocated += MEM_POOL_Report(pool,used_total);
00927 }
00928 fprintf(TFile,"++++ Total Allocated = %d\n",total_allocated);
00929 #else
00930 fprintf(TFile,
00931 "MEM_Trace: Not available; compiler not compiled with MEM_STATS\n");
00932 #endif
00933 #else
00934 fprintf(TFile,
00935 "MEM_Trace: Not available; compiler not compiled with Is_True_On\n");
00936 #endif
00937 }
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948 void
00949 Trace_Memory_Allocation (
00950 const INT phase,
00951 const char *const pname )
00952 {
00953 if ( Get_Trace ( TKIND_ALLOC, phase ) ) {
00954 fprintf ( TFile,
00955 "\n%s%s\tMemory allocation information after %s\n%s%s\n",
00956 DBar, DBar, pname, DBar, DBar );
00957 MEM_Trace ();
00958 }
00959 }
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 void
00971 MEM_Tracing_Enable(void)
00972 {
00973 #ifdef Is_True_On
00974 mem_tracing_enabled = TRUE;
00975 #endif
00976 }
00977
00978
00979
00980 #if Is_True_On
00981 const char *special_address = NULL;
00982 const char *special_address_owner = "NOBODY";
00983 #endif
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 static MEM_PTR
00997 Allocate_Block (MEM_POOL *pool)
00998 {
00999 MEM_BLOCK *block = (MEM_BLOCK *)
01000 malloc (BLOCK_SIZE + PAD_TO_ALIGN(sizeof(MEM_BLOCK)));
01001
01002 if (block == NULL)
01003 ErrMsg (EC_No_Mem, "Allocate_Block");
01004
01005 if ( MEM_POOL_bz(pool) )
01006 BZERO (block, BLOCK_SIZE + PAD_TO_ALIGN(sizeof(MEM_BLOCK)));
01007
01008 #ifdef ZAP_ON_FREE
01009 else
01010 memset(((char *) block), 0xa5,
01011 BLOCK_SIZE + PAD_TO_ALIGN(sizeof(MEM_BLOCK)));
01012 #endif
01013
01014 MEM_BLOCK_avail(block) = BLOCK_SIZE;
01015 MEM_BLOCK_ptr(block) = MEM_BLOCK_first_ptr(block);
01016 MEM_BLOCK_rest(block) = MEM_POOL_block(pool);
01017 MEM_POOL_block(pool) = block;
01018
01019 #if Is_True_On
01020 if (special_address >= ((char *) MEM_BLOCK_ptr(block)) &&
01021 special_address < (((char *) MEM_BLOCK_ptr(block)) +
01022 MEM_BLOCK_avail(block))) {
01023 fprintf(TFile, "Pool %s given %llu bytes from 0x%p to 0x%p\n",
01024 MEM_POOL_name(pool), (UINT64)MEM_BLOCK_avail(block),
01025 (char *) MEM_BLOCK_ptr(block),
01026 ((char *) MEM_BLOCK_ptr(block)) + MEM_BLOCK_avail(block));
01027 special_address_owner = MEM_POOL_name(pool);
01028 }
01029 #endif
01030
01031 #ifdef KEY
01032 #ifndef NO_VALGRIND
01033
01034 VALGRIND_MAKE_NOACCESS(MEM_BLOCK_first_ptr(block), BLOCK_SIZE);
01035 #endif
01036 #endif
01037
01038 return block;
01039 }
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053 static MEM_PTR
01054 Allocate_Large_Block (MEM_POOL *pool, INT32 size)
01055 {
01056 MEM_LARGE_BLOCK *block;
01057 size += MEM_LARGE_BLOCK_OVERHEAD;
01058 block = (MEM_LARGE_BLOCK *) malloc (size);
01059
01060 if (block == NULL)
01061 ErrMsg (EC_No_Mem, "Allocate_Large_Block");
01062
01063 if ( MEM_POOL_bz(pool) ) {
01064 BZERO (block, size);
01065 }
01066
01067 #ifdef ZAP_ON_FREE
01068 else
01069 memset(((char *) block), 0xa5, size);
01070 #endif
01071
01072 MEM_LARGE_BLOCK_ptr(block) = (MEM_PTR)
01073 (((char *)block) + MEM_LARGE_BLOCK_OVERHEAD);
01074 MEM_LARGE_BLOCK_base(block) = MEM_POOL_blocks(pool);
01075 MEM_LARGE_BLOCK_next(block) = MEM_POOL_large_block(pool);
01076 MEM_LARGE_BLOCK_prev(block) = NULL;
01077 if (MEM_LARGE_BLOCK_next(block) != NULL)
01078 MEM_LARGE_BLOCK_prev(MEM_LARGE_BLOCK_next(block)) = block;
01079 MEM_POOL_large_block(pool) = block;
01080
01081 return MEM_LARGE_BLOCK_ptr(block);
01082 }
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098 static MEM_PTR
01099 Raw_Allocate(
01100 MEM_POOL *pool,
01101 INT32 size
01102 )
01103 {
01104 MEM_PTR *result;
01105
01106 if (size <= MIN_LARGE_BLOCK_SIZE) {
01107 MEM_BLOCK *b = MEM_POOL_block(pool);
01108
01109 if (b == NULL || MEM_BLOCK_avail(b) < size) {
01110 b = Allocate_Block (pool);
01111 }
01112
01113 result = MEM_BLOCK_ptr(b) + REDZONE_SIZE;
01114 MEM_BLOCK_ptr(b) = (MEM_PTR) (((char*) MEM_BLOCK_ptr(b)) + size + (REDZONE_SIZE*2));
01115 MEM_BLOCK_avail(b) -= size + (REDZONE_SIZE*2);
01116
01117 #ifdef KEY
01118 #ifndef NO_VALGRIND
01119
01120 VALGRIND_MEMPOOL_ALLOC(MEM_POOL_blocks(pool), result, size);
01121 #endif
01122 #endif
01123
01124 return result;
01125 } else
01126 return Allocate_Large_Block (pool, size);
01127 }
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141 MEM_PTR
01142 MEM_POOL_Alloc_P
01143 (
01144 MEM_POOL *pool,
01145 size_t size
01146 MEM_STAT_ARGS(line,file)
01147 )
01148 {
01149
01150 if (pool == Default_Mem_Pool) pool = The_Default_Mem_Pool;
01151 if (pool == Malloc_Mem_Pool) {
01152 MEM_PTR p = malloc(size);
01153 if (p == NULL)
01154 ErrMsg (EC_No_Mem, "MEM_POOL_Alloc");
01155 return p;
01156 }
01157
01158 Is_True (MEM_POOL_magic_num(pool) == MAGIC_NUM,
01159 ("Alloc from un-initialized MEM_POOL %s (%p) from %s line %d\n",
01160 MEM_POOL_name(pool), pool, file, line));
01161
01162 #ifdef JUST_USE_MALLOC
01163 return calloc(1,size);
01164 #endif
01165
01166 if (purify_pools) {
01167 MEM_PTR ret_val;
01168
01169
01170
01171 if (!MEM_POOL_blocks(pool)) {
01172 DevWarn("Allocation from %s before MEM_POOL_Push(%s)",
01173 MEM_POOL_name(pool), MEM_POOL_name(pool));
01174 MEM_POOL_blocks(pool) = (MEM_POOL_BLOCKS *) TRUE;
01175 }
01176
01177 ret_val = calloc(1,size+8);
01178 Is_True (ret_val, ("MEM_POOL_Alloc: calloc returned NULL"));
01179 Is_True (MEM_POOL_pure_stack(pool), ("MEM_POOL_Alloc %s: missing stack",
01180 MEM_POOL_name(pool)));
01181 *(MEM_PTR*)ret_val = MEM_POOL_last_alloc(pool);
01182 MEM_POOL_last_alloc(pool) = ret_val;
01183 if (purify_pools_trace)
01184 printf ("pool %s, alloc 0x%p, size %llu, (0x%p - 0x%p)\n",
01185 MEM_POOL_name(pool), (char *)ret_val+8, (UINT64)size,
01186 (char *)ret_val+8, (char *)ret_val+size);
01187 return ((MEM_PTR) ((size_t)ret_val+8));
01188 }
01189
01190 Is_True(MEM_POOL_blocks(pool) != NULL,
01191 ("Alloc with uninitialized MEM_POOL"));
01192 #ifdef Is_True_On
01193 if ( mem_tracing_enabled )
01194 Site_Account_Alloc(pool,0,size,line,file);
01195 #endif
01196
01197
01198
01199 size = PAD_TO_ALIGN(size);
01200
01201 return Raw_Allocate(pool,size);
01202 }
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214 MEM_PTR
01215 MEM_POOL_Realloc_P
01216 (
01217 MEM_POOL *pool,
01218 MEM_PTR old_block,
01219 size_t old_size,
01220 size_t new_size
01221 MEM_STAT_ARGS(line,file)
01222 )
01223 {
01224 MEM_PTR result;
01225
01226 if (pool == Default_Mem_Pool) pool = The_Default_Mem_Pool;
01227 if (pool == Malloc_Mem_Pool) {
01228 MEM_PTR p = realloc(old_block,new_size);
01229 if (p == NULL)
01230 ErrMsg (EC_No_Mem, "MEM_POOL_Realloc");
01231 return p;
01232 }
01233
01234 Is_True (MEM_POOL_magic_num(pool) == MAGIC_NUM,
01235 ("Realloc from un-initialized MEM_POOL %s\n", MEM_POOL_name(pool)));
01236
01237 #ifdef JUST_USE_MALLOC
01238 result = realloc(old_block,new_size);
01239 #ifdef KEY
01240 if (purify_pools_trace)
01241 if (result != old_block)
01242 printf ("pool %s, freed block 0x%p\n", MEM_POOL_name(pool), old_block);
01243 #endif
01244 if ( old_size < new_size )
01245 BZERO((char*)result + old_size,new_size - old_size);
01246 return result;
01247 #endif
01248
01249 if (purify_pools) {
01250 MEM_PTR ret_val = NULL;
01251 BOOL foundit = FALSE;
01252
01253 if (!MEM_POOL_blocks(pool)) {
01254 DevWarn("Realloc from %s before MEM_POOL_Push(%s)",
01255 MEM_POOL_name(pool), MEM_POOL_name(pool));
01256 MEM_POOL_blocks(pool) = (MEM_POOL_BLOCKS *) TRUE;
01257 }
01258
01259
01260 if (old_block) {
01261
01262 MEM_PURE_STACK* tmp_stack = MEM_POOL_pure_stack(pool);
01263 MEM_PTR cur = (MEM_PTR) ((size_t) old_block - 8);
01264 Is_True (tmp_stack, ("MEM_POOL_Realloc %s: missing stack",
01265 MEM_POOL_name(pool)));
01266 while (tmp_stack) {
01267 MEM_PTR tmp = MEM_PURE_STACK_last_alloc(tmp_stack);
01268 MEM_PTR prev = NULL;
01269
01270 while (tmp && (tmp != cur)) {
01271 prev = tmp;
01272 tmp = *((MEM_PTR*) tmp);
01273 }
01274 if (tmp) {
01275 foundit = TRUE;
01276
01277 if (prev) *(MEM_PTR*) prev = *(MEM_PTR*) tmp;
01278 else MEM_PURE_STACK_last_alloc(tmp_stack) = *(MEM_PTR*) tmp;
01279 break;
01280 }
01281 tmp_stack = MEM_PURE_STACK_prev_stack(tmp_stack);
01282 }
01283 }
01284 if (old_block && !foundit) {
01285 DevWarn ("Realloc without a previous alloc, pool %s, 0x%p",
01286 MEM_POOL_name(pool), old_block);
01287
01288 ret_val = (MEM_PTR) malloc (new_size+8);
01289 BCOPY(old_block, (MEM_PTR) (((size_t) ret_val)+8), old_size);
01290 }
01291 else {
01292
01293 ret_val = (MEM_PTR)
01294 realloc((MEM_PTR) (old_block ? (size_t) old_block-8 : 0),
01295 new_size+8);
01296 #ifdef KEY
01297 if (purify_pools_trace)
01298 if (ret_val != old_block && old_block != 0)
01299 printf ("pool %s, freed block 0x%p\n", MEM_POOL_name(pool), old_block);
01300 #endif
01301 }
01302 if (new_size > 0) {
01303 FmtAssert (ret_val, ("oops - realloc returned NULL, pool %s\n",
01304 MEM_POOL_name(pool)));
01305 *(MEM_PTR*) ret_val = MEM_POOL_last_alloc(pool);
01306 MEM_POOL_last_alloc(pool) = ret_val;
01307 ret_val = (MEM_PTR) ((size_t) ret_val + 8);
01308 if ( old_size < new_size )
01309 BZERO((char*)ret_val + old_size,new_size - old_size);
01310 }
01311 if (purify_pools_trace)
01312 printf ("pool %s, realloc 0x%p, new size %llu, (0x%p - 0x%p)\n",
01313 MEM_POOL_name(pool), ret_val, (UINT64)new_size,
01314 ret_val, (char *)ret_val + new_size - 8);
01315 return ret_val;
01316 }
01317
01318 Is_True(MEM_POOL_blocks(pool) != NULL,
01319 ("Alloc with uninitialized MEM_POOL"));
01320 #ifdef Is_True_On
01321 if ( mem_tracing_enabled )
01322 Site_Account_Alloc(pool,old_size,new_size,line,file);
01323 #endif
01324
01325
01326
01327 old_size = PAD_TO_ALIGN(old_size);
01328 new_size = PAD_TO_ALIGN(new_size);
01329
01330
01331
01332 if ( new_size == old_size )
01333 return old_block;
01334
01335 #if 0
01336 #ifdef Is_True_On
01337 if (new_size < old_size)
01338 DevWarn ("MEMORY: shrinking an object in (%s) from %d to %d bytes",
01339 MEM_POOL_name(pool), old_size, new_size);
01340 else if (new_size < old_size * 1.5 && old_size > 256)
01341 DevWarn ("MEMORY: small grow from %d to %d bytes (mempool: %s)",
01342 old_size, new_size, MEM_POOL_name(pool));
01343 #endif
01344 #endif
01345
01346 if (old_size <= MIN_LARGE_BLOCK_SIZE) {
01347 if (new_size < old_size)
01348 return old_block;
01349 else {
01350 result = Raw_Allocate (pool, new_size);
01351 BCOPY (old_block, result, old_size);
01352 return result;
01353 }
01354 } else {
01355 MEM_LARGE_BLOCK *large_block = (MEM_LARGE_BLOCK *)
01356 (((char *) old_block) - MEM_LARGE_BLOCK_OVERHEAD);
01357 if (MEM_LARGE_BLOCK_ptr(large_block) == (MEM_PTR) old_block &&
01358 MEM_LARGE_BLOCK_base(large_block) == MEM_POOL_blocks(pool)) {
01359
01360 if (new_size <= MIN_LARGE_BLOCK_SIZE) {
01361 result = Raw_Allocate (pool, new_size);
01362 BCOPY (old_block, result, new_size);
01363 MEM_POOL_FREE (pool, old_block);
01364 return result;
01365 } else {
01366 MEM_LARGE_BLOCK *p =
01367 (MEM_LARGE_BLOCK *)(((char *)old_block) - MEM_LARGE_BLOCK_OVERHEAD);
01368
01369 large_block =
01370 MEM_LARGE_BLOCK_realloc(p, new_size + MEM_LARGE_BLOCK_OVERHEAD);
01371 #ifdef KEY
01372 if (purify_pools_trace)
01373 if (p != large_block && p != 0)
01374 printf ("pool %s, freed block 0x%p\n", MEM_POOL_name(pool), p);
01375 #endif
01376
01377 if (large_block == NULL)
01378 ErrMsg (EC_No_Mem, "MEM_POOL_Realloc");
01379 MEM_LARGE_BLOCK_ptr(large_block) = (MEM_PTR)
01380 (((char *)large_block) + MEM_LARGE_BLOCK_OVERHEAD);
01381 if (MEM_POOL_bz(pool)) {
01382 BZERO (((char *) MEM_LARGE_BLOCK_ptr(large_block)) + old_size,
01383 new_size - old_size);
01384 }
01385 p = MEM_LARGE_BLOCK_prev(large_block);
01386 if (p == NULL)
01387 MEM_POOL_large_block(pool) = large_block;
01388 else
01389 MEM_LARGE_BLOCK_next(p) = large_block;
01390 p = MEM_LARGE_BLOCK_next(large_block);
01391 if (p)
01392 MEM_LARGE_BLOCK_prev(p) = large_block;
01393 return MEM_LARGE_BLOCK_ptr(large_block);
01394 }
01395 } else {
01396 result = Raw_Allocate (pool, new_size);
01397 if (new_size > old_size)
01398 BCOPY (old_block, result, old_size);
01399 else
01400 BCOPY (old_block, result, new_size);
01401 return result;
01402 }
01403 }
01404 }
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419 void
01420 MEM_POOL_Push_P
01421 (
01422 MEM_POOL *pool
01423 MEM_STAT_ARGS(line,file)
01424 )
01425 {
01426 MEM_POOL_BLOCKS *pb;
01427
01428 Is_True (MEM_POOL_magic_num(pool) == MAGIC_NUM,
01429 ("Push before Initialize in MEM_POOL %s\n", MEM_POOL_name(pool)));
01430
01431 FmtAssert(MEM_POOL_frozen(pool) == FALSE, ("Pushing a frozen pool - %s.",
01432 MEM_POOL_name(pool)));
01433 if (pool == Default_Mem_Pool) pool = The_Default_Mem_Pool;
01434 if (pool == Malloc_Mem_Pool) return;
01435 #ifdef JUST_USE_MALLOC
01436 return;
01437 #endif
01438
01439 if (purify_pools) {
01440 MEM_PURE_STACK* tmp = (MEM_PURE_STACK*) malloc(sizeof(MEM_PURE_STACK));
01441 Is_True (tmp, ("MEM_POOL_Push %s: malloc stack returned NULL",
01442 MEM_POOL_name(pool)));
01443 MEM_PURE_STACK_last_alloc(tmp) = NULL;
01444 MEM_PURE_STACK_prev_stack(tmp) = MEM_POOL_pure_stack(pool);
01445 MEM_POOL_pure_stack(pool) = tmp;
01446 if (purify_pools_trace_x) {
01447 if (MEM_POOL_blocks(pool) == (MEM_POOL_BLOCKS *) MEM_POOL_INIT_IN_PROGRESS) {
01448 (void) printf("MEM_POOL_Push %s 0x%p<-- free push (called by M_P_Initialize)\n",
01449 MEM_POOL_name(pool), pool);
01450 }
01451 else {
01452 (void) printf ("MEM_POOL_Push %s 0x%p\n", MEM_POOL_name(pool), pool);
01453 }
01454 }
01455
01456
01457
01458
01459 MEM_POOL_blocks(pool) = (MEM_POOL_BLOCKS *) TRUE;
01460 return;
01461 }
01462
01463 #ifdef Is_True_On
01464 if ( mem_tracing_enabled )
01465 Site_Account_Push(pool,line,file);
01466 #endif
01467
01468 if ( free_mem_pool_blocks_list != NULL ) {
01469
01470
01471 pb = free_mem_pool_blocks_list;
01472 free_mem_pool_blocks_list = MEM_POOL_BLOCKS_rest(pb);
01473 #ifdef KEY
01474 #ifndef NO_VALGRIND
01475 VALGRIND_MAKE_READABLE(pb, sizeof(MEM_POOL_BLOCKS));
01476 VALGRIND_MAKE_WRITABLE(pb, sizeof(MEM_POOL_BLOCKS));
01477 #endif
01478 #endif
01479 } else {
01480
01481
01482 pb = TYPE_MEM_POOL_ALLOC(MEM_POOL_BLOCKS,&mem_overhead_pool);
01483 }
01484
01485 MEM_POOL_BLOCKS_rest(pb) = MEM_POOL_blocks(pool);
01486 MEM_POOL_BLOCKS_large_block(pb) = NULL;
01487 if (MEM_POOL_BLOCKS_rest(pb) == NULL) {
01488 MEM_POOL_BLOCKS_block(pb) = NULL;
01489 MEM_POOL_BLOCKS_base_block(pb) = NULL;
01490 MEM_POOL_BLOCKS_base_ptr(pb) = NULL;
01491 MEM_POOL_BLOCKS_base_avail(pb) = 0;
01492 } else {
01493 MEM_POOL_BLOCKS *p = MEM_POOL_BLOCKS_rest(pb);
01494 MEM_POOL_BLOCKS_block(pb) = MEM_POOL_BLOCKS_block(p);
01495 MEM_POOL_BLOCKS_base_block(pb) = MEM_POOL_BLOCKS_block(p);
01496 if (MEM_POOL_BLOCKS_block(p)) {
01497 MEM_POOL_BLOCKS_base_ptr(pb) = MEM_BLOCK_ptr(MEM_POOL_BLOCKS_block(p));
01498 MEM_POOL_BLOCKS_base_avail(pb) =
01499 MEM_BLOCK_avail(MEM_POOL_BLOCKS_block(p));
01500 } else {
01501 MEM_POOL_BLOCKS_base_ptr(pb) = NULL;
01502 MEM_POOL_BLOCKS_base_avail(pb) = 0;
01503 }
01504 }
01505 MEM_POOL_blocks(pool) = pb;
01506
01507 #ifdef KEY
01508 #ifndef NO_VALGRIND
01509 VALGRIND_CREATE_MEMPOOL(pb, REDZONE_SIZE, MEM_POOL_bz(pool));
01510 #endif
01511 #endif
01512 }
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527 void
01528 MEM_POOL_Push_Freeze_P
01529 (
01530 MEM_POOL *pool
01531 MEM_STAT_ARGS(line,file)
01532 )
01533 {
01534 Is_True (MEM_POOL_magic_num(pool) == MAGIC_NUM,
01535 ("Push_Freeze before Initialize in MEM_POOL %s\n", MEM_POOL_name(pool)));
01536 FmtAssert (MEM_POOL_frozen(pool) == FALSE,
01537 ("Cannot Push_Freeze a frozen pool - %s.", MEM_POOL_name(pool)));
01538 if (purify_pools_trace_x)
01539 printf ("MEM_POOL_Push_Freeze %s -- \n", MEM_POOL_name(pool));
01540 MEM_POOL_Push_P (pool, line, file);
01541 MEM_POOL_frozen(pool) = TRUE;
01542 }
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557 void
01558 MEM_POOL_Pop_P
01559 (
01560 MEM_POOL *pool
01561 MEM_STAT_ARGS(line,file)
01562 )
01563 {
01564 MEM_BLOCK *bp, *next_bp;
01565 MEM_LARGE_BLOCK *lbp, *next_lbp;
01566 MEM_POOL_BLOCKS *bsp;
01567
01568 Is_True (MEM_POOL_magic_num(pool) == MAGIC_NUM,
01569 ("Pop before Initialize in MEM_POOL %s\n", MEM_POOL_name(pool)));
01570
01571 FmtAssert(MEM_POOL_frozen(pool) == FALSE, ("Popping a frozen pool - %s.",
01572 MEM_POOL_name(pool)));
01573 if (pool == Default_Mem_Pool) pool = The_Default_Mem_Pool;
01574 if (pool == Malloc_Mem_Pool) return;
01575
01576 #ifdef JUST_USE_MALLOC
01577 return;
01578 #endif
01579 if (purify_pools) {
01580 MEM_PURE_STACK *tmp_stack;
01581 MEM_PTR tmp = NULL;
01582 MEM_PTR next = NULL;
01583 Is_True (MEM_POOL_pure_stack(pool),
01584 ("Pop, but no push stack on %s", MEM_POOL_name(pool)));
01585 if (purify_pools_trace_x)
01586 printf ("MEM_POOL_Pop %s 0x%p\n", MEM_POOL_name(pool), pool);
01587 tmp = MEM_POOL_last_alloc(pool);
01588 while (tmp) {
01589 next = (*(MEM_PTR*) tmp);
01590 if (purify_pools_trace) printf ("pool %s, pop-free 0x%p\n",
01591 MEM_POOL_name(pool), (char *)tmp+8);
01592 free (tmp);
01593 tmp = next;
01594 }
01595 tmp_stack = MEM_POOL_prev_stack(pool);
01596 free (MEM_POOL_pure_stack(pool));
01597 MEM_POOL_pure_stack(pool) = tmp_stack;
01598 return;
01599 }
01600
01601 bsp = MEM_POOL_blocks(pool);
01602
01603 FmtAssert(MEM_POOL_blocks(pool),("Freeing an uninitialized pool."));
01604
01605 #ifdef Is_True_On
01606 if ( mem_tracing_enabled )
01607 Site_Account_Pop(pool,line,file);
01608 #endif
01609
01610 for (bp = MEM_POOL_BLOCKS_block(bsp); bp; bp = next_bp) {
01611 next_bp = MEM_BLOCK_rest(bp);
01612
01613 #if Is_True_On
01614 if (special_address >= (char *) MEM_BLOCK_first_ptr(bp) &&
01615 special_address < ((char *) MEM_BLOCK_ptr(bp) +
01616 MEM_BLOCK_avail(bp))) {
01617 fprintf(TFile, "Pool %s freed %llu bytes from 0x%p to 0x%p\n",
01618 MEM_POOL_name(pool),
01619 (UINT64)(MEM_BLOCK_avail(bp) +
01620 (char *) MEM_BLOCK_ptr(bp) -
01621 (char *) MEM_BLOCK_first_ptr(bp)),
01622 (char *) MEM_BLOCK_first_ptr(bp),
01623 (char *) MEM_BLOCK_ptr(bp) + MEM_BLOCK_avail(bp));
01624 special_address_owner = "NOBODY";
01625 }
01626 #endif
01627
01628 if (bp == MEM_POOL_BLOCKS_base_block(bsp)) {
01629 MEM_BLOCK_ptr(bp) = MEM_POOL_BLOCKS_base_ptr(bsp);
01630 MEM_BLOCK_avail(bp) = MEM_POOL_BLOCKS_base_avail(bsp);
01631 if (MEM_POOL_bz(pool)) {
01632 #ifdef KEY
01633 #ifndef NO_VALGRIND
01634 VALGRIND_MAKE_WRITABLE(MEM_BLOCK_ptr(bp), MEM_BLOCK_avail(bp));
01635 #endif
01636 #endif
01637 BZERO (MEM_BLOCK_ptr(bp), MEM_BLOCK_avail(bp));
01638 #ifdef KEY
01639 #ifndef NO_VALGRIND
01640 VALGRIND_MAKE_NOACCESS(MEM_BLOCK_ptr(bp), MEM_BLOCK_avail(bp));
01641 #endif
01642 #endif
01643 }
01644 break;
01645 }
01646 free (bp);
01647 }
01648
01649 for (lbp = MEM_POOL_BLOCKS_large_block(bsp); lbp; lbp = next_lbp) {
01650 next_lbp = MEM_LARGE_BLOCK_next(lbp);
01651 MEM_LARGE_BLOCK_free(lbp);
01652 }
01653
01654
01655
01656
01657
01658
01659
01660
01661 if ( MEM_POOL_BLOCKS_rest(bsp) != NULL ) {
01662 MEM_POOL_blocks(pool) = MEM_POOL_BLOCKS_rest(bsp);
01663 MEM_POOL_BLOCKS_rest(bsp) = free_mem_pool_blocks_list;
01664 free_mem_pool_blocks_list = bsp;
01665 #ifdef KEY
01666 #ifndef NO_VALGRIND
01667
01668 VALGRIND_DESTROY_MEMPOOL(bsp);
01669 #endif
01670 #endif
01671 } else {
01672 #ifdef KEY
01673 #ifndef NO_VALGRIND
01674 VALGRIND_MAKE_WRITABLE(bsp, sizeof(MEM_POOL_BLOCKS));
01675 #endif
01676 #endif
01677 BZERO (bsp, sizeof(MEM_POOL_BLOCKS));
01678 #ifdef KEY
01679 #ifndef NO_VALGRIND
01680 VALGRIND_MAKE_NOACCESS(bsp, sizeof(MEM_POOL_BLOCKS));
01681
01682
01683 VALGRIND_DESTROY_MEMPOOL(bsp);
01684 VALGRIND_CREATE_MEMPOOL(bsp, REDZONE_SIZE, MEM_POOL_bz(pool));
01685 #endif
01686 #endif
01687 }
01688 }
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703 void
01704 MEM_POOL_Pop_Unfreeze_P
01705 (
01706 MEM_POOL *pool
01707 MEM_STAT_ARGS(line,file)
01708 )
01709 {
01710 Is_True (MEM_POOL_magic_num(pool) == MAGIC_NUM,
01711 ("Pop_Unfreeze before Initialize in MEM_POOL %s\n", MEM_POOL_name(pool)));
01712 FmtAssert (MEM_POOL_frozen(pool) == TRUE,
01713 ("Cannot Pop_Unfreeze a non-frozen pool - %s.",
01714 MEM_POOL_name(pool)));
01715 MEM_POOL_frozen(pool) = FALSE;
01716 if (purify_pools_trace_x)
01717 printf ("MEM_POOL_Pop_Unfreeze %s -- \n", MEM_POOL_name(pool));
01718 MEM_POOL_Pop_P (pool, line, file);
01719 }
01720
01721 void MEM_POOL_Set_Default(MEM_POOL *pool)
01722 {
01723 The_Default_Mem_Pool = pool;
01724 }
01725
01726 void MEM_POOL_FREE(MEM_POOL *pool, void *data)
01727 {
01728 MEM_LARGE_BLOCK *large_block;
01729
01730 if (data == NULL)
01731 return;
01732
01733 if (pool == Default_Mem_Pool) pool = The_Default_Mem_Pool;
01734 if (pool == Malloc_Mem_Pool) {
01735 free(data);
01736 return;
01737 }
01738
01739 Is_True (MEM_POOL_magic_num(pool) == MAGIC_NUM,
01740 ("Free into un-initialized MEM_POOL %s\n", MEM_POOL_name(pool)));
01741
01742 #ifdef JUST_USE_MALLOC
01743 return;
01744 #endif
01745 if (data && purify_pools) {
01746 BOOL foundit = FALSE;
01747
01748 MEM_PURE_STACK* tmp_stack = MEM_POOL_pure_stack(pool);
01749 MEM_PTR cur = (MEM_PTR) ((size_t) data - 8);
01750 Is_True (tmp_stack, ("MEM_POOL_Realloc %s: missing stack",
01751 MEM_POOL_name(pool)));
01752 while (tmp_stack) {
01753 MEM_PTR tmp = MEM_PURE_STACK_last_alloc(tmp_stack);
01754 MEM_PTR prev = NULL;
01755
01756 while (tmp && (tmp != cur)) {
01757 prev = tmp;
01758 tmp = *((MEM_PTR*) tmp);
01759 }
01760 if (tmp) {
01761 foundit = TRUE;
01762
01763 if (prev) *(MEM_PTR*) prev = *(MEM_PTR*) tmp;
01764 else MEM_PURE_STACK_last_alloc(tmp_stack) = *(MEM_PTR*) tmp;
01765 break;
01766 }
01767 tmp_stack = MEM_PURE_STACK_prev_stack(tmp_stack);
01768 }
01769 if (purify_pools_trace)
01770 printf ("pool %s, free 0x%p\n", MEM_POOL_name(pool), data);
01771 if (!foundit) {
01772
01773 free (cur);
01774 FmtAssert(FALSE,("MEM_POOL_FREE: pool %s, could not find pointer 0x%p\n",
01775 MEM_POOL_name(pool), data));
01776 }
01777 free (cur);
01778 return;
01779 }
01780
01781 large_block = (MEM_LARGE_BLOCK *)
01782 (((char *) data) - MEM_LARGE_BLOCK_OVERHEAD);
01783 if (MEM_LARGE_BLOCK_ptr(large_block) == (MEM_PTR) data) {
01784 MEM_LARGE_BLOCK *prev;
01785 MEM_LARGE_BLOCK *next;
01786 if (MEM_LARGE_BLOCK_base(large_block) != MEM_POOL_blocks(pool))
01787 return;
01788
01789 prev = MEM_LARGE_BLOCK_prev(large_block);
01790 next = MEM_LARGE_BLOCK_next(large_block);
01791 if (prev == NULL)
01792 MEM_POOL_large_block(pool) = next;
01793 else
01794 MEM_LARGE_BLOCK_next(prev) = next;
01795
01796 if (next)
01797 MEM_LARGE_BLOCK_prev(next) = prev;
01798
01799 MEM_LARGE_BLOCK_free(large_block);
01800 }
01801
01802 }
01803
01804 #ifdef Is_True_On
01805 static void
01806 trace_initialized_pool (char *msg, char *pname)
01807 {
01808 MEM_POOL **listp = &initialized_pools;
01809 printf("<%s %s> initialized_pools: ", msg, pname);
01810 while (*listp != NULL) {
01811 printf(", %s", MEM_POOL_name(*listp));
01812 listp = &MEM_POOL_rest(*listp);
01813 }
01814 printf("\n");
01815 }
01816 #endif
01817
01818 void MEM_POOL_Delete(MEM_POOL *pool)
01819 {
01820 MEM_POOL_BLOCKS *bsp;
01821
01822 if (pool == Default_Mem_Pool) pool = The_Default_Mem_Pool;
01823 if (pool == Malloc_Mem_Pool) return;
01824
01825 #ifdef Is_True_On
01826
01827
01828
01829
01830
01831
01832
01833 if ( mem_tracing_enabled ) {
01834 MEM_POOL **listp = &initialized_pools;
01835
01836 if (*listp == pool) {
01837 initialized_pools = MEM_POOL_rest(pool);
01838 }
01839 else {
01840 while (*listp && MEM_POOL_rest(*listp)) {
01841 if (MEM_POOL_rest(*listp) == pool) break;
01842 listp = &MEM_POOL_rest(*listp);
01843 }
01844 if (*listp && MEM_POOL_rest(*listp)) {
01845
01846 MEM_POOL_rest(*listp) = MEM_POOL_rest(pool);
01847 }
01848 else {
01849 DevWarn("didn't find pool %s in initialized_pools", MEM_POOL_name(pool));
01850 }
01851 }
01852 Is_True(!MEM_STAT_In_List( initialized_pools, pool ),
01853 ("Pool still in initialized list"));
01854 }
01855 #endif
01856
01857 Is_True (MEM_POOL_magic_num(pool) == MAGIC_NUM,
01858 ("Deleting a pool that has not been initialized: %s\n",
01859 MEM_POOL_name(pool)));
01860
01861 if (purify_pools) {
01862
01863 #ifndef TODO_REMOVE_FREE_PUSH
01864 if (!MEM_POOL_pure_stack(pool)) {
01865 DevWarn("During MEM_POOL_Delete: Too many pops on %s.",
01866 MEM_POOL_name(pool));
01867 }
01868 else {
01869 MEM_POOL_Pop(pool);
01870 #endif
01871 if (MEM_POOL_pure_stack(pool)) {
01872 DevWarn("During MEM_POOL_Delete: Too few pops on %s.",
01873 MEM_POOL_name(pool));
01874 while (MEM_POOL_pure_stack(pool))
01875 MEM_POOL_Pop(pool);
01876 }
01877 #ifndef TODO_REMOVE_FREE_PUSH
01878 }
01879 #endif
01880 if (purify_pools_trace_x)
01881 printf ("MEM_POOL_Delete %s 0x%p\n", MEM_POOL_name(pool), pool);
01882 MEM_POOL_magic_num(pool) = 0;
01883 return;
01884 }
01885
01886
01887
01888
01889
01890 while (MEM_POOL_BLOCKS_rest(MEM_POOL_blocks(pool)) != NULL)
01891 MEM_POOL_Pop(pool);
01892 MEM_POOL_Pop(pool);
01893 bsp = MEM_POOL_blocks(pool);
01894 MEM_POOL_BLOCKS_rest(bsp) = free_mem_pool_blocks_list;
01895 free_mem_pool_blocks_list = bsp;
01896
01897 BZERO (pool, sizeof(MEM_POOL));
01898 MEM_POOL_magic_num(pool) = 0;
01899 }
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917 void
01918 MEM_POOL_Initialize_P
01919 (
01920 MEM_POOL *pool,
01921 const char *name,
01922 BOOL bzero
01923 MEM_STAT_ARGS(line,file)
01924 )
01925 {
01926
01927 PURIFY_OPT_Initialize();
01928
01929 #ifdef KEY
01930 #ifndef NO_VALGRIND
01931 static BOOL mem_overhead_pool_initialized = FALSE;
01932 if(RUNNING_ON_VALGRIND && (mem_overhead_pool_initialized == FALSE)) {
01933 mem_overhead_pool_initialized = TRUE;
01934 redzone_size = 8;
01935 VALGRIND_CREATE_MEMPOOL(MEM_POOL_blocks(&mem_overhead_pool),
01936 REDZONE_SIZE, MEM_POOL_bz(&mem_overhead_pool));
01937 }
01938 #endif
01939 #endif
01940
01941 if (pool == Default_Mem_Pool) pool = The_Default_Mem_Pool;
01942 if (pool == Malloc_Mem_Pool) return;
01943 MEM_POOL_name(pool) = name;
01944 MEM_POOL_blocks(pool) = NULL;
01945 MEM_POOL_pure_stack(pool) = NULL;
01946
01947
01948
01949
01950
01951
01952
01953
01954 if (MEM_POOL_magic_num(pool) == MAGIC_NUM
01955 && (MEM_POOL_bz(pool) & 0xe) == 0
01956 && (MEM_POOL_frozen(pool) & 0xe) == 0)
01957 {
01958 DevWarn("Initialization of a potentially already initialized pool: %s (%p) from %s line %d",
01959 MEM_POOL_name(pool), pool, file, line);
01960 }
01961 MEM_POOL_magic_num(pool) = MAGIC_NUM;
01962 MEM_POOL_bz(pool) = bzero;
01963 MEM_POOL_frozen(pool) = FALSE;
01964
01965 if (purify_pools_trace_x)
01966 printf ("MEM_POOL_Initialize %s 0x%p\n", MEM_POOL_name(pool), pool);
01967
01968 #ifdef Is_True_On
01969 MEM_POOL_alloc_site_list(pool) = NULL;
01970 if ( mem_tracing_enabled ) {
01971 if ( ! MEM_STAT_In_List( initialized_pools, pool ) ) {
01972
01973 MEM_POOL_rest(pool) = initialized_pools;
01974 initialized_pools = pool;
01975 }
01976 }
01977 #endif
01978
01979 if (purify_pools) {
01980 MEM_POOL_blocks(pool) = (MEM_POOL_BLOCKS *) MEM_POOL_INIT_IN_PROGRESS;
01981 }
01982
01983 #ifndef TODO_REMOVE_FREE_PUSH
01984 MEM_POOL_Push(pool);
01985 #endif
01986
01987 if (purify_pools) {
01988
01989
01990
01991 MEM_POOL_blocks(pool) = NULL;
01992 }
01993 }
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006 static void
02007 PURIFY_OPT_Initialize(void)
02008 {
02009 static BOOL initialized = FALSE;
02010 if ( initialized == FALSE ) {
02011 char* ppools = getenv ("PURIFY_MEMPOOLS");
02012 if (ppools) {
02013 if (((ppools[0] == 'O') || (ppools[0] == 'o')) &&
02014 ((ppools[1] == 'N') || (ppools[1] == 'n'))) {
02015 purify_pools = TRUE;
02016 if ((ppools[2] == '-') &&
02017 ((ppools[3] == 'T') || (ppools[3] == 't')) &&
02018 ((ppools[4] == 'R') || (ppools[4] == 'r')) &&
02019 ((ppools[5] == 'A') || (ppools[5] == 'a')) &&
02020 ((ppools[6] == 'C') || (ppools[6] == 'c')) &&
02021 ((ppools[7] == 'E') || (ppools[7] == 'e'))) {
02022 purify_pools_trace = TRUE;
02023 if ((ppools[8] == '-') &&
02024 ((ppools[9] == 'X') || (ppools[9] == 'x'))) {
02025 purify_pools_trace_x = TRUE;
02026 if ((ppools[10] == '-') &&
02027 ((ppools[11] == 'O') || (ppools[11] == 'o')) &&
02028 ((ppools[12] == 'N') || (ppools[12] == 'n')) &&
02029 ((ppools[13] == 'L') || (ppools[13] == 'l')) &&
02030 ((ppools[14] == 'Y') || (ppools[14] == 'y'))) {
02031 purify_pools_trace = FALSE;
02032 DevWarn("Using purify memory pools, limited extended tracing ###");
02033 } else
02034 DevWarn ("Using purify memory pools, with extended tracing ###");
02035 }
02036 else
02037 DevWarn ("Using purify memory pools, with tracing ###");
02038 }
02039 else DevWarn ("Using purify memory pools ###");
02040 }
02041 else if (((ppools[0] == 'O') || (ppools[0] == 'o')) &&
02042 ((ppools[1] == 'F') || (ppools[1] == 'f')) &&
02043 ((ppools[2] == 'F') || (ppools[2] == 'f'))) {
02044 purify_pools = FALSE;
02045 }
02046 else DevWarn ("PURIFY_MEMPOOLS set to garbage, using regular pools");
02047 }
02048
02049 initialized = TRUE;
02050 }
02051 }
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063 void
02064 MEM_Initialize(void)
02065 {
02066 char* ppools = getenv ("PURIFY_MEMPOOLS");
02067 if (ppools) {
02068 if (((ppools[0] == 'O') || (ppools[0] == 'o')) &&
02069 ((ppools[1] == 'N') || (ppools[1] == 'n'))) {
02070 purify_pools = TRUE;
02071 if ((ppools[2] == '-') &&
02072 ((ppools[3] == 'T') || (ppools[3] == 't')) &&
02073 ((ppools[4] == 'R') || (ppools[4] == 'r')) &&
02074 ((ppools[5] == 'A') || (ppools[5] == 'a')) &&
02075 ((ppools[6] == 'C') || (ppools[6] == 'c')) &&
02076 ((ppools[7] == 'E') || (ppools[7] == 'e'))) {
02077 purify_pools_trace = TRUE;
02078 if ((ppools[8] == '-') &&
02079 ((ppools[9] == 'X') || (ppools[9] == 'x'))) {
02080 purify_pools_trace_x = TRUE;
02081 if ((ppools[10] == '-') &&
02082 ((ppools[11] == 'O') || (ppools[11] == 'o')) &&
02083 ((ppools[12] == 'N') || (ppools[12] == 'n')) &&
02084 ((ppools[13] == 'L') || (ppools[13] == 'l')) &&
02085 ((ppools[14] == 'Y') || (ppools[14] == 'y'))) {
02086 purify_pools_trace = FALSE;
02087 DevWarn("Using purify memory pools, limited extended tracing ###");
02088 } else
02089 DevWarn ("Using purify memory pools, with extended tracing ###");
02090 }
02091 else
02092 DevWarn ("Using purify memory pools, with tracing ###");
02093 }
02094 else DevWarn ("Using purify memory pools ###");
02095 }
02096 else if (((ppools[0] == 'O') || (ppools[0] == 'o')) &&
02097 ((ppools[1] == 'F') || (ppools[1] == 'f')) &&
02098 ((ppools[2] == 'F') || (ppools[2] == 'f'))) {
02099 purify_pools = FALSE;
02100 }
02101 else DevWarn ("PURIFY_MEMPOOLS set to garbage, using regular pools");
02102 }
02103
02104 MEM_POOL_Initialize(&MEM_local_pool,"Local",TRUE);
02105 MEM_POOL_Initialize(&MEM_src_pool,"Source",TRUE);
02106 MEM_POOL_Initialize(&MEM_pu_pool,"Program unit",TRUE);
02107 MEM_POOL_Initialize(&MEM_phase_pool,"Phase",TRUE);
02108
02109 MEM_POOL_Push(&MEM_local_pool);
02110 MEM_POOL_Push(&MEM_src_pool);
02111 MEM_POOL_Push(&MEM_pu_pool);
02112 MEM_POOL_Push(&MEM_phase_pool);
02113
02114 MEM_POOL_Initialize(&MEM_local_nz_pool,"Local (nz)",FALSE);
02115 MEM_POOL_Initialize(&MEM_src_nz_pool,"Source (nz)",FALSE);
02116 MEM_POOL_Initialize(&MEM_pu_nz_pool,"Program unit (nz)",FALSE);
02117 MEM_POOL_Initialize(&MEM_phase_nz_pool,"Phase (nz)",FALSE);
02118
02119 MEM_POOL_Push(&MEM_local_nz_pool);
02120 MEM_POOL_Push(&MEM_src_nz_pool);
02121 MEM_POOL_Push(&MEM_pu_nz_pool);
02122 MEM_POOL_Push(&MEM_phase_nz_pool);
02123
02124 }
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157 MEM_PTR
02158 Realloc_Clear ( MEM_PTR ptr, INT32 new_size, INT32 old_size )
02159 {
02160 MEM_PTR result = (MEM_PTR) realloc ( ptr, new_size );
02161 #ifdef KEY
02162 if (purify_pools_trace)
02163 if (result != ptr && ptr != 0)
02164 printf ("pool UNKNOWN, freed 0x%p (size %d)\n", ptr, old_size);
02165 #endif
02166
02167 if ( result == NULL )
02168 ErrMsg ( EC_No_Mem, "Realloc_Clear" );
02169
02170
02171 if ( new_size > old_size ) {
02172 MEM_PTR start_of_new = (MEM_PTR) ( ((char *) result) + old_size );
02173 INT32 num_added_bytes = new_size - old_size;
02174 BZERO ( start_of_new, num_added_bytes );
02175 }
02176
02177 return result;
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 MEM_PTR
02208 Re_Calloc ( MEM_PTR ptr, INT32 new_nelem, INT32 elsize, INT32 old_nelem )
02209 {
02210 return Realloc_Clear ( ptr, new_nelem * elsize, old_nelem * elsize );
02211 }