#include "univ.i"#include "os0file.h"#include "ut0lst.h"Include dependency graph for mem0pool.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
Classes | |
| struct | mem_area_struct |
Defines | |
| #define | MEM_AREA_EXTRA_SIZE |
Typedefs | |
| typedef mem_area_struct | mem_area_t |
| typedef mem_pool_struct | mem_pool_t |
Functions | |
| mem_pool_t * | mem_pool_create (ulint size) |
| void * | mem_area_alloc (ulint size, mem_pool_t *pool) |
| void | mem_area_free (void *ptr, mem_pool_t *pool) |
| ulint | mem_pool_get_reserved (mem_pool_t *pool) |
| void | mem_pool_mutex_enter (void) |
| void | mem_pool_mutex_exit (void) |
| ibool | mem_pool_validate (mem_pool_t *pool) |
| void | mem_pool_print_info (FILE *outfile, mem_pool_t *pool) |
Variables | |
| mem_pool_t * | mem_comm_pool |
| #define MEM_AREA_EXTRA_SIZE |
Value:
(ut_calc_align(sizeof(struct mem_area_struct),\ UNIV_MEM_ALIGNMENT))
Definition at line 34 of file mem0pool.h.
Referenced by mem_area_alloc(), and mem_area_free().
| typedef struct mem_area_struct mem_area_t |
Definition at line 16 of file mem0pool.h.
| typedef struct mem_pool_struct mem_pool_t |
Definition at line 17 of file mem0pool.h.
| void* mem_area_alloc | ( | ulint | size, | |
| mem_pool_t * | pool | |||
| ) |
Definition at line 322 of file mem0pool.c.
References FALSE, mem_pool_struct::free_list, mem_analyze_corruption(), MEM_AREA_EXTRA_SIZE, mem_area_get_free(), mem_area_get_size(), MEM_AREA_MIN_SIZE, mem_area_set_free(), mem_n_threads_inside, mem_pool_fill_free_list(), mem_pool_validate(), mem_pool_struct::mutex, mutex_enter, mutex_exit(), n, NULL, mem_pool_struct::reserved, ut_2_exp(), ut_2_log(), ut_a, ut_ad, ut_error, UT_LIST_GET_FIRST, UT_LIST_GET_LEN, UT_LIST_REMOVE, ut_malloc(), and ut_max().
Referenced by mem_heap_create_block().
00324 : allocated memory buffer */ 00325 ulint size, /* in: allocated size in bytes; for optimum 00326 space usage, the size should be a power of 2 00327 minus MEM_AREA_EXTRA_SIZE */ 00328 mem_pool_t* pool) /* in: memory pool */ 00329 { 00330 mem_area_t* area; 00331 ulint n; 00332 ibool ret; 00333 00334 n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE)); 00335 00336 mutex_enter(&(pool->mutex)); 00337 mem_n_threads_inside++; 00338 00339 ut_a(mem_n_threads_inside == 1); 00340 00341 area = UT_LIST_GET_FIRST(pool->free_list[n]); 00342 00343 if (area == NULL) { 00344 ret = mem_pool_fill_free_list(n, pool); 00345 00346 if (ret == FALSE) { 00347 /* Out of memory in memory pool: we try to allocate 00348 from the operating system with the regular malloc: */ 00349 00350 mem_n_threads_inside--; 00351 mutex_exit(&(pool->mutex)); 00352 00353 return(ut_malloc(size)); 00354 } 00355 00356 area = UT_LIST_GET_FIRST(pool->free_list[n]); 00357 } 00358 00359 if (!mem_area_get_free(area)) { 00360 fprintf(stderr, 00361 "InnoDB: Error: Removing element from mem pool free list %lu though the\n" 00362 "InnoDB: element is not marked free!\n", 00363 (ulong) n); 00364 00365 mem_analyze_corruption(area); 00366 00367 /* Try to analyze a strange assertion failure reported at 00368 mysql@lists.mysql.com where the free bit IS 1 in the 00369 hex dump above */ 00370 00371 if (mem_area_get_free(area)) { 00372 fprintf(stderr, 00373 "InnoDB: Probably a race condition because now the area is marked free!\n"); 00374 } 00375 00376 ut_error; 00377 } 00378 00379 if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) { 00380 fprintf(stderr, 00381 "InnoDB: Error: Removing element from mem pool free list %lu\n" 00382 "InnoDB: though the list length is 0!\n", 00383 (ulong) n); 00384 mem_analyze_corruption(area); 00385 00386 ut_error; 00387 } 00388 00389 ut_ad(mem_area_get_size(area) == ut_2_exp(n)); 00390 00391 mem_area_set_free(area, FALSE); 00392 00393 UT_LIST_REMOVE(free_list, pool->free_list[n], area); 00394 00395 pool->reserved += mem_area_get_size(area); 00396 00397 mem_n_threads_inside--; 00398 mutex_exit(&(pool->mutex)); 00399 00400 ut_ad(mem_pool_validate(pool)); 00401 00402 return((void*)(MEM_AREA_EXTRA_SIZE + ((byte*)area))); 00403 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void mem_area_free | ( | void * | ptr, | |
| mem_pool_t * | pool | |||
| ) |
Definition at line 449 of file mem0pool.c.
References mem_pool_struct::buf, FALSE, mem_pool_struct::free_list, mem_analyze_corruption(), MEM_AREA_EXTRA_SIZE, mem_area_free(), mem_area_get_buddy(), mem_area_get_free(), mem_area_get_size(), mem_area_set_free(), mem_area_set_size(), mem_n_threads_inside, mem_pool_validate(), mem_pool_struct::mutex, mutex_enter, mutex_exit(), n, mem_pool_struct::reserved, mem_pool_struct::size, TRUE, ut_2_exp(), ut_2_log(), ut_2_power_up(), ut_a, ut_ad, ut_error, ut_free(), UT_LIST_ADD_FIRST, and UT_LIST_REMOVE.
Referenced by mem_area_free(), and mem_heap_block_free().
00451 : pointer to allocated memory 00452 buffer */ 00453 mem_pool_t* pool) /* in: memory pool */ 00454 { 00455 mem_area_t* area; 00456 mem_area_t* buddy; 00457 void* new_ptr; 00458 ulint size; 00459 ulint n; 00460 00461 /* It may be that the area was really allocated from the OS with 00462 regular malloc: check if ptr points within our memory pool */ 00463 00464 if ((byte*)ptr < pool->buf || (byte*)ptr >= pool->buf + pool->size) { 00465 ut_free(ptr); 00466 00467 return; 00468 } 00469 00470 area = (mem_area_t*) (((byte*)ptr) - MEM_AREA_EXTRA_SIZE); 00471 00472 if (mem_area_get_free(area)) { 00473 fprintf(stderr, 00474 "InnoDB: Error: Freeing element to mem pool free list though the\n" 00475 "InnoDB: element is marked free!\n"); 00476 00477 mem_analyze_corruption(area); 00478 ut_error; 00479 } 00480 00481 size = mem_area_get_size(area); 00482 00483 if (size == 0) { 00484 fprintf(stderr, 00485 "InnoDB: Error: Mem area size is 0. Possibly a memory overrun of the\n" 00486 "InnoDB: previous allocated area!\n"); 00487 00488 mem_analyze_corruption(area); 00489 ut_error; 00490 } 00491 00492 #ifdef UNIV_LIGHT_MEM_DEBUG 00493 if (((byte*)area) + size < pool->buf + pool->size) { 00494 00495 ulint next_size; 00496 00497 next_size = mem_area_get_size( 00498 (mem_area_t*)(((byte*)area) + size)); 00499 if (ut_2_power_up(next_size) != next_size) { 00500 fprintf(stderr, 00501 "InnoDB: Error: Memory area size %lu, next area size %lu not a power of 2!\n" 00502 "InnoDB: Possibly a memory overrun of the buffer being freed here.\n", 00503 (ulong) size, (ulong) next_size); 00504 mem_analyze_corruption(area); 00505 00506 ut_error; 00507 } 00508 } 00509 #endif 00510 buddy = mem_area_get_buddy(area, size, pool); 00511 00512 n = ut_2_log(size); 00513 00514 mutex_enter(&(pool->mutex)); 00515 mem_n_threads_inside++; 00516 00517 ut_a(mem_n_threads_inside == 1); 00518 00519 if (buddy && mem_area_get_free(buddy) 00520 && (size == mem_area_get_size(buddy))) { 00521 00522 /* The buddy is in a free list */ 00523 00524 if ((byte*)buddy < (byte*)area) { 00525 new_ptr = ((byte*)buddy) + MEM_AREA_EXTRA_SIZE; 00526 00527 mem_area_set_size(buddy, 2 * size); 00528 mem_area_set_free(buddy, FALSE); 00529 } else { 00530 new_ptr = ptr; 00531 00532 mem_area_set_size(area, 2 * size); 00533 } 00534 00535 /* Remove the buddy from its free list and merge it to area */ 00536 00537 UT_LIST_REMOVE(free_list, pool->free_list[n], buddy); 00538 00539 pool->reserved += ut_2_exp(n); 00540 00541 mem_n_threads_inside--; 00542 mutex_exit(&(pool->mutex)); 00543 00544 mem_area_free(new_ptr, pool); 00545 00546 return; 00547 } else { 00548 UT_LIST_ADD_FIRST(free_list, pool->free_list[n], area); 00549 00550 mem_area_set_free(area, TRUE); 00551 00552 ut_ad(pool->reserved >= size); 00553 00554 pool->reserved -= size; 00555 } 00556 00557 mem_n_threads_inside--; 00558 mutex_exit(&(pool->mutex)); 00559 00560 ut_ad(mem_pool_validate(pool)); 00561 }
Here is the call graph for this function:

Here is the caller graph for this function:

| mem_pool_t* mem_pool_create | ( | ulint | size | ) |
Definition at line 186 of file mem0pool.c.
References mem_pool_struct::buf, FALSE, mem_pool_struct::free_list, MEM_AREA_MIN_SIZE, mem_area_set_free(), mem_area_set_size(), mem_pool_struct::mutex, mutex_create, mem_pool_struct::reserved, mem_pool_struct::size, SYNC_MEM_POOL, TRUE, ut_2_exp(), ut_2_log(), ut_a, ut_ad, UT_LIST_ADD_FIRST, UT_LIST_INIT, ut_malloc(), and ut_malloc_low().
Referenced by mem_init().
00188 : memory pool */ 00189 ulint size) /* in: pool size in bytes */ 00190 { 00191 mem_pool_t* pool; 00192 mem_area_t* area; 00193 ulint i; 00194 ulint used; 00195 00196 ut_a(size > 10000); 00197 00198 pool = ut_malloc(sizeof(mem_pool_t)); 00199 00200 /* We do not set the memory to zero (FALSE) in the pool, 00201 but only when allocated at a higher level in mem0mem.c. 00202 This is to avoid masking useful Purify warnings. */ 00203 00204 pool->buf = ut_malloc_low(size, FALSE, TRUE); 00205 pool->size = size; 00206 00207 mutex_create(&pool->mutex, SYNC_MEM_POOL); 00208 00209 /* Initialize the free lists */ 00210 00211 for (i = 0; i < 64; i++) { 00212 00213 UT_LIST_INIT(pool->free_list[i]); 00214 } 00215 00216 used = 0; 00217 00218 while (size - used >= MEM_AREA_MIN_SIZE) { 00219 00220 i = ut_2_log(size - used); 00221 00222 if (ut_2_exp(i) > size - used) { 00223 00224 /* ut_2_log rounds upward */ 00225 00226 i--; 00227 } 00228 00229 area = (mem_area_t*)(pool->buf + used); 00230 00231 mem_area_set_size(area, ut_2_exp(i)); 00232 mem_area_set_free(area, TRUE); 00233 00234 UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area); 00235 00236 used = used + ut_2_exp(i); 00237 } 00238 00239 ut_ad(size >= used); 00240 00241 pool->reserved = 0; 00242 00243 return(pool); 00244 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint mem_pool_get_reserved | ( | mem_pool_t * | pool | ) |
Definition at line 645 of file mem0pool.c.
References mem_pool_struct::mutex, mutex_enter, mutex_exit(), and mem_pool_struct::reserved.
Referenced by srv_printf_innodb_monitor().
00647 : reserved memory in bytes */ 00648 mem_pool_t* pool) /* in: memory pool */ 00649 { 00650 ulint reserved; 00651 00652 mutex_enter(&(pool->mutex)); 00653 00654 reserved = pool->reserved; 00655 00656 mutex_exit(&(pool->mutex)); 00657 00658 return(reserved); 00659 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void mem_pool_mutex_enter | ( | void | ) |
Definition at line 110 of file mem0pool.c.
References mem_comm_pool, mem_pool_struct::mutex, and mutex_enter.
Referenced by mem_heap_block_free(), and mem_heap_create_block().
00112 { 00113 mutex_enter(&(mem_comm_pool->mutex)); 00114 }
Here is the caller graph for this function:

| void mem_pool_mutex_exit | ( | void | ) |
Definition at line 120 of file mem0pool.c.
References mem_comm_pool, mem_pool_struct::mutex, and mutex_exit().
Referenced by mem_heap_block_free(), and mem_heap_create_block().
00122 { 00123 mutex_exit(&(mem_comm_pool->mutex)); 00124 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void mem_pool_print_info | ( | FILE * | outfile, | |
| mem_pool_t * | pool | |||
| ) |
Definition at line 613 of file mem0pool.c.
References mem_pool_struct::free_list, mem_pool_validate(), mem_pool_struct::mutex, mutex_enter, ut_2_exp(), and UT_LIST_GET_LEN.
Referenced by mem_print_info_low().
00615 : output file to write to */ 00616 mem_pool_t* pool) /* in: memory pool */ 00617 { 00618 ulint i; 00619 00620 mem_pool_validate(pool); 00621 00622 fprintf(outfile, "INFO OF A MEMORY POOL\n"); 00623 00624 mutex_enter(&(pool->mutex)); 00625 00626 for (i = 0; i < 64; i++) { 00627 if (UT_LIST_GET_LEN(pool->free_list[i]) > 0) { 00628 00629 fprintf(outfile, 00630 "Free list length %lu for blocks of size %lu\n", 00631 (ulong) UT_LIST_GET_LEN(pool->free_list[i]), 00632 (ulong) ut_2_exp(i)); 00633 } 00634 } 00635 00636 fprintf(outfile, "Pool size %lu, reserved %lu.\n", (ulong) pool->size, 00637 (ulong) pool->reserved); 00638 mutex_exit(&(pool->mutex)); 00639 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool mem_pool_validate | ( | mem_pool_t * | pool | ) |
Definition at line 567 of file mem0pool.c.
References free, mem_pool_struct::free_list, mem_area_get_buddy(), mem_area_get_free(), mem_area_get_size(), mem_pool_struct::mutex, mutex_enter, mutex_exit(), NULL, mem_pool_struct::reserved, mem_pool_struct::size, TRUE, ut_2_exp(), ut_a, UT_LIST_GET_FIRST, UT_LIST_GET_NEXT, and UT_LIST_VALIDATE.
Referenced by mem_area_alloc(), mem_area_free(), and mem_pool_print_info().
00569 : TRUE if ok */ 00570 mem_pool_t* pool) /* in: memory pool */ 00571 { 00572 mem_area_t* area; 00573 mem_area_t* buddy; 00574 ulint free; 00575 ulint i; 00576 00577 mutex_enter(&(pool->mutex)); 00578 00579 free = 0; 00580 00581 for (i = 0; i < 64; i++) { 00582 00583 UT_LIST_VALIDATE(free_list, mem_area_t, pool->free_list[i]); 00584 00585 area = UT_LIST_GET_FIRST(pool->free_list[i]); 00586 00587 while (area != NULL) { 00588 ut_a(mem_area_get_free(area)); 00589 ut_a(mem_area_get_size(area) == ut_2_exp(i)); 00590 00591 buddy = mem_area_get_buddy(area, ut_2_exp(i), pool); 00592 00593 ut_a(!buddy || !mem_area_get_free(buddy) 00594 || (ut_2_exp(i) != mem_area_get_size(buddy))); 00595 00596 area = UT_LIST_GET_NEXT(free_list, area); 00597 00598 free += ut_2_exp(i); 00599 } 00600 } 00601 00602 ut_a(free + pool->reserved == pool->size); 00603 00604 mutex_exit(&(pool->mutex)); 00605 00606 return(TRUE); 00607 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 98 of file mem0pool.c.
Referenced by mem_heap_block_free(), mem_heap_create_block(), mem_init(), mem_pool_mutex_enter(), mem_pool_mutex_exit(), mem_print_info_low(), and srv_printf_innodb_monitor().
1.4.7

