00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00027 #ifdef UNIV_MEM_DEBUG
00028 # ifndef UNIV_HOTBACKUP
00029
00030
00031
00032 UNIV_INTERN mutex_t mem_hash_mutex;
00033
00034 #ifdef UNIV_PFS_MUTEX
00035
00036 UNIV_INTERN mysql_pfs_key_t mem_hash_mutex_key;
00037 #endif
00038
00039 # endif
00040
00041
00042
00043
00044
00045 static ulint mem_n_created_heaps = 0;
00046 static ulint mem_n_allocations = 0;
00047 static ulint mem_total_allocated_memory = 0;
00048 UNIV_INTERN ulint mem_current_allocated_memory = 0;
00049 static ulint mem_max_allocated_memory = 0;
00050 # ifndef UNIV_HOTBACKUP
00051 static ulint mem_last_print_info = 0;
00052 static ibool mem_hash_initialized = FALSE;
00053 # endif
00054
00055
00056 #define MEM_HASH_SIZE 997
00057
00058
00059
00060 typedef struct mem_hash_node_struct mem_hash_node_t;
00061 struct mem_hash_node_struct {
00062 UT_LIST_NODE_T(mem_hash_node_t)
00063 list;
00064 mem_heap_t* heap;
00065 const char* file_name;
00066 ulint line;
00067 ulint nth_heap;
00068 UT_LIST_NODE_T(mem_hash_node_t)
00069 all_list;
00070 };
00071
00072 typedef UT_LIST_BASE_NODE_T(mem_hash_node_t) mem_hash_cell_t;
00073
00074
00075 static mem_hash_cell_t mem_hash_table[MEM_HASH_SIZE];
00076
00077
00078 static mem_hash_cell_t mem_all_list_base;
00079
00080
00081
00082 UNIV_INLINE
00083 mem_hash_cell_t*
00084 mem_hash_get_nth_cell(ulint i);
00085
00086
00087
00088 UNIV_INLINE
00089 mem_hash_cell_t*
00090 mem_hash_get_nth_cell(ulint i)
00091 {
00092 ut_a(i < MEM_HASH_SIZE);
00093
00094 return(&(mem_hash_table[i]));
00095 }
00096
00097
00098 UNIV_INTERN
00099 void
00100 mem_field_header_set_len(byte* field, ulint len)
00101 {
00102 mach_write_to_4(field - 2 * sizeof(ulint), len);
00103 }
00104
00105 UNIV_INTERN
00106 ulint
00107 mem_field_header_get_len(byte* field)
00108 {
00109 return(mach_read_from_4(field - 2 * sizeof(ulint)));
00110 }
00111
00112 UNIV_INTERN
00113 void
00114 mem_field_header_set_check(byte* field, ulint check)
00115 {
00116 mach_write_to_4(field - sizeof(ulint), check);
00117 }
00118
00119 UNIV_INTERN
00120 ulint
00121 mem_field_header_get_check(byte* field)
00122 {
00123 return(mach_read_from_4(field - sizeof(ulint)));
00124 }
00125
00126 UNIV_INTERN
00127 void
00128 mem_field_trailer_set_check(byte* field, ulint check)
00129 {
00130 mach_write_to_4(field + mem_field_header_get_len(field), check);
00131 }
00132
00133 UNIV_INTERN
00134 ulint
00135 mem_field_trailer_get_check(byte* field)
00136 {
00137 return(mach_read_from_4(field
00138 + mem_field_header_get_len(field)));
00139 }
00140 #endif
00141
00142 #ifndef UNIV_HOTBACKUP
00143
00145 UNIV_INTERN
00146 void
00147 mem_init(
00148
00149 ulint size)
00150 {
00151 #ifdef UNIV_MEM_DEBUG
00152
00153 ulint i;
00154
00155
00156 ut_a(FALSE == mem_hash_initialized);
00157
00158 mutex_create(mem_hash_mutex_key, &mem_hash_mutex, SYNC_MEM_HASH);
00159
00160 for (i = 0; i < MEM_HASH_SIZE; i++) {
00161 UT_LIST_INIT(*mem_hash_get_nth_cell(i));
00162 }
00163
00164 UT_LIST_INIT(mem_all_list_base);
00165
00166 mem_hash_initialized = TRUE;
00167 #endif
00168
00169 if (UNIV_LIKELY(srv_use_sys_malloc)) {
00170
00171
00172
00173
00174 size = 1;
00175 }
00176
00177 mem_comm_pool = mem_pool_create(size);
00178 }
00179
00180
00182 UNIV_INTERN
00183 void
00184 mem_close(void)
00185
00186 {
00187 mem_pool_free(mem_comm_pool);
00188 mem_comm_pool = NULL;
00189 #ifdef UNIV_MEM_DEBUG
00190 mutex_free(&mem_hash_mutex);
00191 mem_hash_initialized = FALSE;
00192 #endif
00193 }
00194 #endif
00195
00196 #ifdef UNIV_MEM_DEBUG
00197
00199 UNIV_INTERN
00200 void
00201 mem_field_init(
00202
00203 byte* buf,
00204 ulint n)
00205 {
00206 ulint rnd;
00207 byte* usr_buf;
00208
00209 usr_buf = buf + MEM_FIELD_HEADER_SIZE;
00210
00211
00212
00213
00214
00215
00216
00217 mem_field_header_set_len(usr_buf, n);
00218
00219 rnd = ut_rnd_gen_ulint();
00220
00221 mem_field_header_set_check(usr_buf, rnd);
00222 mem_field_trailer_set_check(usr_buf, rnd);
00223
00224
00225
00226 mutex_enter(&mem_hash_mutex);
00227
00228 mem_total_allocated_memory += n;
00229 mem_current_allocated_memory += n;
00230 mem_n_allocations++;
00231
00232 if (mem_current_allocated_memory > mem_max_allocated_memory) {
00233 mem_max_allocated_memory = mem_current_allocated_memory;
00234 }
00235
00236 mutex_exit(&mem_hash_mutex);
00237
00238
00239
00240
00241 mem_init_buf(usr_buf, n);
00242 }
00243
00244
00246 UNIV_INTERN
00247 void
00248 mem_field_erase(
00249
00250 byte* buf,
00251 ulint )
00253 {
00254 byte* usr_buf;
00255
00256 usr_buf = buf + MEM_FIELD_HEADER_SIZE;
00257
00258 mutex_enter(&mem_hash_mutex);
00259 mem_current_allocated_memory -= n;
00260 mutex_exit(&mem_hash_mutex);
00261
00262
00263 ut_ad(n == (ulint)mem_field_header_get_len(usr_buf));
00264
00265
00266
00267
00268 mem_erase_buf(buf, MEM_SPACE_NEEDED(n));
00269 }
00270
00271
00274 UNIV_INTERN
00275 void
00276 mem_init_buf(
00277
00278 byte* buf,
00279 ulint n)
00280 {
00281 byte* ptr;
00282
00283 UNIV_MEM_ASSERT_W(buf, n);
00284
00285 for (ptr = buf; ptr < buf + n; ptr++) {
00286
00287 if (ut_rnd_gen_ibool()) {
00288 *ptr = 0xBA;
00289 } else {
00290 *ptr = 0xBE;
00291 }
00292 }
00293
00294 UNIV_MEM_INVALID(buf, n);
00295 }
00296
00297
00300 UNIV_INTERN
00301 void
00302 mem_erase_buf(
00303
00304 byte* buf,
00305 ulint n)
00306 {
00307 byte* ptr;
00308
00309 UNIV_MEM_ASSERT_W(buf, n);
00310
00311 for (ptr = buf; ptr < buf + n; ptr++) {
00312 if (ut_rnd_gen_ibool()) {
00313 *ptr = 0xDE;
00314 } else {
00315 *ptr = 0xAD;
00316 }
00317 }
00318
00319 UNIV_MEM_FREE(buf, n);
00320 }
00321
00322
00325 UNIV_INTERN
00326 void
00327 mem_hash_insert(
00328
00329 mem_heap_t* heap,
00330 const char* file_name,
00331 ulint line)
00332 {
00333 mem_hash_node_t* new_node;
00334 ulint cell_no ;
00335
00336 ut_ad(mem_heap_check(heap));
00337
00338 mutex_enter(&mem_hash_mutex);
00339
00340 cell_no = ut_hash_ulint((ulint)heap, MEM_HASH_SIZE);
00341
00342
00343 new_node = ut_malloc(sizeof(mem_hash_node_t));
00344
00345 new_node->heap = heap;
00346 new_node->file_name = file_name;
00347 new_node->line = line;
00348 new_node->nth_heap = mem_n_created_heaps;
00349
00350
00351 UT_LIST_ADD_FIRST(list, *mem_hash_get_nth_cell(cell_no), new_node);
00352
00353 UT_LIST_ADD_LAST(all_list, mem_all_list_base, new_node);
00354
00355 mem_n_created_heaps++;
00356
00357 mutex_exit(&mem_hash_mutex);
00358 }
00359
00360
00368 UNIV_INTERN
00369 void
00370 mem_hash_remove(
00371
00372 mem_heap_t* heap,
00373 const char* file_name,
00374 ulint line)
00375 {
00376 mem_hash_node_t* node;
00377 ulint cell_no;
00378 ibool error;
00379 ulint size;
00380
00381 ut_ad(mem_heap_check(heap));
00382
00383 mutex_enter(&mem_hash_mutex);
00384
00385 cell_no = ut_hash_ulint((ulint)heap, MEM_HASH_SIZE);
00386
00387
00388 node = UT_LIST_GET_FIRST(*mem_hash_get_nth_cell(cell_no));
00389
00390 while (node != NULL) {
00391 if (node->heap == heap) {
00392
00393 break;
00394 }
00395
00396 node = UT_LIST_GET_NEXT(list, node);
00397 }
00398
00399 if (node == NULL) {
00400 fprintf(stderr,
00401 "Memory heap or buffer freed in %s line %lu"
00402 " did not exist.\n",
00403 file_name, (ulong) line);
00404 ut_error;
00405 }
00406
00407
00408 UT_LIST_REMOVE(list, *mem_hash_get_nth_cell(cell_no), node);
00409
00410 UT_LIST_REMOVE(all_list, mem_all_list_base, node);
00411
00412
00413 mem_heap_validate_or_print(node->heap, NULL, FALSE, &error, &size,
00414 NULL, NULL);
00415 if (error) {
00416 fprintf(stderr,
00417 "Inconsistency in memory heap or"
00418 " buffer n:o %lu created\n"
00419 "in %s line %lu and tried to free in %s line %lu.\n"
00420 "Hex dump of 400 bytes around memory heap"
00421 " first block start:\n",
00422 node->nth_heap, node->file_name, (ulong) node->line,
00423 file_name, (ulong) line);
00424 ut_print_buf(stderr, (byte*)node->heap - 200, 400);
00425 fputs("\nDump of the mem heap:\n", stderr);
00426 mem_heap_validate_or_print(node->heap, NULL, TRUE, &error,
00427 &size, NULL, NULL);
00428 ut_error;
00429 }
00430
00431
00432 ut_free(node);
00433
00434 mem_current_allocated_memory -= size;
00435
00436 mutex_exit(&mem_hash_mutex);
00437 }
00438 #endif
00439
00440 #if defined UNIV_MEM_DEBUG || defined UNIV_DEBUG
00441
00447 UNIV_INTERN
00448 void
00449 mem_heap_validate_or_print(
00450
00451 mem_heap_t* heap,
00452 byte* ,
00456 ibool print,
00459 ibool* error,
00460 ulint* us_size,
00465 ulint* ph_size,
00468 ulint* n_blocks)
00471 {
00472 mem_block_t* block;
00473 ulint total_len = 0;
00474 ulint block_count = 0;
00475 ulint phys_len = 0;
00476 #ifdef UNIV_MEM_DEBUG
00477 ulint len;
00478 byte* field;
00479 byte* user_field;
00480 ulint check_field;
00481 #endif
00482
00483
00484 if (us_size != NULL) {
00485 *us_size = 0;
00486 }
00487 if (ph_size != NULL) {
00488 *ph_size = 0;
00489 }
00490 if (n_blocks != NULL) {
00491 *n_blocks = 0;
00492 }
00493 *error = TRUE;
00494
00495 block = heap;
00496
00497 if (block->magic_n != MEM_BLOCK_MAGIC_N) {
00498 return;
00499 }
00500
00501 if (print) {
00502 fputs("Memory heap:", stderr);
00503 }
00504
00505 while (block != NULL) {
00506 phys_len += mem_block_get_len(block);
00507
00508 if ((block->type == MEM_HEAP_BUFFER)
00509 && (mem_block_get_len(block) > UNIV_PAGE_SIZE)) {
00510
00511 fprintf(stderr,
00512 "InnoDB: Error: mem block %p"
00513 " length %lu > UNIV_PAGE_SIZE\n",
00514 (void*) block,
00515 (ulong) mem_block_get_len(block));
00516
00517
00518 return;
00519 }
00520
00521 #ifdef UNIV_MEM_DEBUG
00522
00523
00524 if (print) {
00525 fprintf(stderr, " Block %ld:", block_count);
00526 }
00527
00528 field = (byte*)block + mem_block_get_start(block);
00529
00530 if (top && (field == top)) {
00531
00532 goto completed;
00533 }
00534
00535 while (field < (byte*)block + mem_block_get_free(block)) {
00536
00537
00538
00539
00540 user_field = field + MEM_FIELD_HEADER_SIZE;
00541
00542 len = mem_field_header_get_len(user_field);
00543
00544 if (print) {
00545 ut_print_buf(stderr, user_field, len);
00546 putc('\n', stderr);
00547 }
00548
00549 total_len += len;
00550 check_field = mem_field_header_get_check(user_field);
00551
00552 if (check_field
00553 != mem_field_trailer_get_check(user_field)) {
00554
00555
00556 fprintf(stderr,
00557 "InnoDB: Error: block %lx mem"
00558 " field %lx len %lu\n"
00559 "InnoDB: header check field is"
00560 " %lx but trailer %lx\n",
00561 (ulint)block,
00562 (ulint)field, len, check_field,
00563 mem_field_trailer_get_check(
00564 user_field));
00565
00566 return;
00567 }
00568
00569
00570 field = field + MEM_SPACE_NEEDED(len);
00571
00572 if (top && (field == top)) {
00573
00574 goto completed;
00575 }
00576
00577 }
00578
00579
00580
00581
00582 if (field != (byte*)block + mem_block_get_free(block)) {
00583
00584
00585 fprintf(stderr,
00586 "InnoDB: Error: block %lx end of"
00587 " mem fields %lx\n"
00588 "InnoDB: but block free at %lx\n",
00589 (ulint)block, (ulint)field,
00590 (ulint)((byte*)block
00591 + mem_block_get_free(block)));
00592
00593 return;
00594 }
00595
00596 #endif
00597
00598 block = UT_LIST_GET_NEXT(list, block);
00599 block_count++;
00600 }
00601 #ifdef UNIV_MEM_DEBUG
00602 completed:
00603 #endif
00604 if (us_size != NULL) {
00605 *us_size = total_len;
00606 }
00607 if (ph_size != NULL) {
00608 *ph_size = phys_len;
00609 }
00610 if (n_blocks != NULL) {
00611 *n_blocks = block_count;
00612 }
00613 *error = FALSE;
00614 }
00615
00616
00618 static
00619 void
00620 mem_heap_print(
00621
00622 mem_heap_t* heap)
00623 {
00624 ibool error;
00625 ulint us_size;
00626 ulint phys_size;
00627 ulint n_blocks;
00628
00629 ut_ad(mem_heap_check(heap));
00630
00631 mem_heap_validate_or_print(heap, NULL, TRUE, &error,
00632 &us_size, &phys_size, &n_blocks);
00633 fprintf(stderr,
00634 "\nheap type: %lu; size: user size %lu;"
00635 " physical size %lu; blocks %lu.\n",
00636 (ulong) heap->type, (ulong) us_size,
00637 (ulong) phys_size, (ulong) n_blocks);
00638 ut_a(!error);
00639 }
00640
00641
00644 UNIV_INTERN
00645 ibool
00646 mem_heap_validate(
00647
00648 mem_heap_t* heap)
00649 {
00650 ibool error;
00651 ulint us_size;
00652 ulint phys_size;
00653 ulint n_blocks;
00654
00655 ut_ad(mem_heap_check(heap));
00656
00657 mem_heap_validate_or_print(heap, NULL, FALSE, &error, &us_size,
00658 &phys_size, &n_blocks);
00659 if (error) {
00660 mem_heap_print(heap);
00661 }
00662
00663 ut_a(!error);
00664
00665 return(TRUE);
00666 }
00667 #endif
00668
00669 #ifdef UNIV_DEBUG
00670
00673 UNIV_INTERN
00674 ibool
00675 mem_heap_check(
00676
00677 mem_heap_t* heap)
00678 {
00679 ut_a(heap->magic_n == MEM_BLOCK_MAGIC_N);
00680
00681 return(TRUE);
00682 }
00683 #endif
00684
00685 #ifdef UNIV_MEM_DEBUG
00686
00689 UNIV_INTERN
00690 ibool
00691 mem_all_freed(void)
00692
00693 {
00694 mem_hash_node_t* node;
00695 ulint heap_count = 0;
00696 ulint i;
00697
00698 mem_validate();
00699
00700 mutex_enter(&mem_hash_mutex);
00701
00702 for (i = 0; i < MEM_HASH_SIZE; i++) {
00703
00704 node = UT_LIST_GET_FIRST(*mem_hash_get_nth_cell(i));
00705 while (node != NULL) {
00706 heap_count++;
00707 node = UT_LIST_GET_NEXT(list, node);
00708 }
00709 }
00710
00711 mutex_exit(&mem_hash_mutex);
00712
00713 if (heap_count == 0) {
00714 # ifndef UNIV_HOTBACKUP
00715 ut_a(mem_pool_get_reserved(mem_comm_pool) == 0);
00716 # endif
00717
00718 return(TRUE);
00719 } else {
00720 return(FALSE);
00721 }
00722 }
00723
00724
00727 UNIV_INTERN
00728 ibool
00729 mem_validate_no_assert(void)
00730
00731 {
00732 mem_hash_node_t* node;
00733 ulint n_heaps = 0;
00734 ulint allocated_mem;
00735 ulint ph_size;
00736 ulint total_allocated_mem = 0;
00737 ibool error = FALSE;
00738 ulint n_blocks;
00739 ulint i;
00740
00741 # ifndef UNIV_HOTBACKUP
00742 mem_pool_validate(mem_comm_pool);
00743 # endif
00744
00745 mutex_enter(&mem_hash_mutex);
00746
00747 for (i = 0; i < MEM_HASH_SIZE; i++) {
00748
00749 node = UT_LIST_GET_FIRST(*mem_hash_get_nth_cell(i));
00750
00751 while (node != NULL) {
00752 n_heaps++;
00753
00754 mem_heap_validate_or_print(node->heap, NULL,
00755 FALSE, &error,
00756 &allocated_mem,
00757 &ph_size, &n_blocks);
00758
00759 if (error) {
00760 fprintf(stderr,
00761 "\nERROR!!!!!!!!!!!!!!!!!!!"
00762 "!!!!!!!!!!!!!!!!!!!!!!!\n\n"
00763 "Inconsistency in memory heap"
00764 " or buffer created\n"
00765 "in %s line %lu.\n",
00766 node->file_name, node->line);
00767
00768 mutex_exit(&mem_hash_mutex);
00769
00770 return(TRUE);
00771 }
00772
00773 total_allocated_mem += allocated_mem;
00774 node = UT_LIST_GET_NEXT(list, node);
00775 }
00776 }
00777
00778 if ((n_heaps == 0) && (mem_current_allocated_memory != 0)) {
00779 error = TRUE;
00780 }
00781
00782 if (mem_total_allocated_memory < mem_current_allocated_memory) {
00783 error = TRUE;
00784 }
00785
00786 if (mem_max_allocated_memory > mem_total_allocated_memory) {
00787 error = TRUE;
00788 }
00789
00790 if (mem_n_created_heaps < n_heaps) {
00791 error = TRUE;
00792 }
00793
00794 mutex_exit(&mem_hash_mutex);
00795
00796 return(error);
00797 }
00798
00799
00802 UNIV_INTERN
00803 ibool
00804 mem_validate(void)
00805
00806 {
00807 ut_a(!mem_validate_no_assert());
00808
00809 return(TRUE);
00810 }
00811 #endif
00812
00813
00816 UNIV_INTERN
00817 void
00818 mem_analyze_corruption(
00819
00820 void* ptr)
00821 {
00822 byte* p;
00823 ulint i;
00824 ulint dist;
00825
00826 fputs("InnoDB: Apparent memory corruption: mem dump ", stderr);
00827 ut_print_buf(stderr, (byte*)ptr - 250, 500);
00828
00829 fputs("\nInnoDB: Scanning backward trying to find"
00830 " previous allocated mem blocks\n", stderr);
00831
00832 p = (byte*)ptr;
00833 dist = 0;
00834
00835 for (i = 0; i < 10; i++) {
00836 for (;;) {
00837 if (((ulint)p) % 4 == 0) {
00838
00839 if (*((ulint*)p) == MEM_BLOCK_MAGIC_N) {
00840 fprintf(stderr,
00841 "Mem block at - %lu,"
00842 " file %s, line %lu\n",
00843 (ulong) dist,
00844 (p + sizeof(ulint)),
00845 (ulong)
00846 (*(ulint*)(p + 8
00847 + sizeof(ulint))));
00848
00849 break;
00850 }
00851
00852 if (*((ulint*)p) == MEM_FREED_BLOCK_MAGIC_N) {
00853 fprintf(stderr,
00854 "Freed mem block at - %lu,"
00855 " file %s, line %lu\n",
00856 (ulong) dist,
00857 (p + sizeof(ulint)),
00858 (ulong)
00859 (*(ulint*)(p + 8
00860 + sizeof(ulint))));
00861
00862 break;
00863 }
00864 }
00865
00866 p--;
00867 dist++;
00868 }
00869
00870 p--;
00871 dist++;
00872 }
00873
00874 fprintf(stderr,
00875 "InnoDB: Scanning forward trying to find next"
00876 " allocated mem blocks\n");
00877
00878 p = (byte*)ptr;
00879 dist = 0;
00880
00881 for (i = 0; i < 10; i++) {
00882 for (;;) {
00883 if (((ulint)p) % 4 == 0) {
00884
00885 if (*((ulint*)p) == MEM_BLOCK_MAGIC_N) {
00886 fprintf(stderr,
00887 "Mem block at + %lu, file %s,"
00888 " line %lu\n",
00889 (ulong) dist,
00890 (p + sizeof(ulint)),
00891 (ulong)
00892 (*(ulint*)(p + 8
00893 + sizeof(ulint))));
00894
00895 break;
00896 }
00897
00898 if (*((ulint*)p) == MEM_FREED_BLOCK_MAGIC_N) {
00899 fprintf(stderr,
00900 "Freed mem block at + %lu,"
00901 " file %s, line %lu\n",
00902 (ulong) dist,
00903 (p + sizeof(ulint)),
00904 (ulong)
00905 (*(ulint*)(p + 8
00906 + sizeof(ulint))));
00907
00908 break;
00909 }
00910 }
00911
00912 p++;
00913 dist++;
00914 }
00915
00916 p++;
00917 dist++;
00918 }
00919 }
00920
00921 #ifndef UNIV_HOTBACKUP
00922
00925 static
00926 void
00927 mem_print_info_low(
00928
00929 ibool print_all)
00932 {
00933 #ifdef UNIV_MEM_DEBUG
00934 mem_hash_node_t* node;
00935 ulint n_heaps = 0;
00936 ulint allocated_mem;
00937 ulint ph_size;
00938 ulint total_allocated_mem = 0;
00939 ibool error;
00940 ulint n_blocks;
00941 #endif
00942 FILE* outfile;
00943
00944
00945
00946 outfile = stdout;
00947
00948 fprintf(outfile, "\n");
00949 fprintf(outfile,
00950 "________________________________________________________\n");
00951 fprintf(outfile, "MEMORY ALLOCATION INFORMATION\n\n");
00952
00953 #ifndef UNIV_MEM_DEBUG
00954
00955 UT_NOT_USED(print_all);
00956
00957 mem_pool_print_info(outfile, mem_comm_pool);
00958
00959 fprintf(outfile,
00960 "Sorry, non-debug version cannot give more memory info\n");
00961
00962
00963
00964 return;
00965 #else
00966 mutex_enter(&mem_hash_mutex);
00967
00968 fprintf(outfile, "LIST OF CREATED HEAPS AND ALLOCATED BUFFERS: \n\n");
00969
00970 if (!print_all) {
00971 fprintf(outfile, "AFTER THE LAST PRINT INFO\n");
00972 }
00973
00974 node = UT_LIST_GET_FIRST(mem_all_list_base);
00975
00976 while (node != NULL) {
00977 n_heaps++;
00978
00979 if (!print_all && node->nth_heap < mem_last_print_info) {
00980
00981 goto next_heap;
00982 }
00983
00984 mem_heap_validate_or_print(node->heap, NULL,
00985 FALSE, &error, &allocated_mem,
00986 &ph_size, &n_blocks);
00987 total_allocated_mem += allocated_mem;
00988
00989 fprintf(outfile,
00990 "%lu: file %s line %lu of size %lu phys.size %lu"
00991 " with %lu blocks, type %lu\n",
00992 node->nth_heap, node->file_name, node->line,
00993 allocated_mem, ph_size, n_blocks,
00994 (node->heap)->type);
00995 next_heap:
00996 node = UT_LIST_GET_NEXT(all_list, node);
00997 }
00998
00999 fprintf(outfile, "\n");
01000
01001 fprintf(outfile, "Current allocated memory : %lu\n",
01002 mem_current_allocated_memory);
01003 fprintf(outfile, "Current allocated heaps and buffers : %lu\n",
01004 n_heaps);
01005 fprintf(outfile, "Cumulative allocated memory : %lu\n",
01006 mem_total_allocated_memory);
01007 fprintf(outfile, "Maximum allocated memory : %lu\n",
01008 mem_max_allocated_memory);
01009 fprintf(outfile, "Cumulative created heaps and buffers : %lu\n",
01010 mem_n_created_heaps);
01011 fprintf(outfile, "Cumulative number of allocations : %lu\n",
01012 mem_n_allocations);
01013
01014 mem_last_print_info = mem_n_created_heaps;
01015
01016 mutex_exit(&mem_hash_mutex);
01017
01018 mem_pool_print_info(outfile, mem_comm_pool);
01019
01020
01021
01022
01023 #endif
01024 }
01025
01026
01029 UNIV_INTERN
01030 void
01031 mem_print_info(void)
01032
01033 {
01034 mem_print_info_low(TRUE);
01035 }
01036
01037
01040 UNIV_INTERN
01041 void
01042 mem_print_new_info(void)
01043
01044 {
01045 mem_print_info_low(FALSE);
01046 }
01047 #endif