#include "mem0pool.h"#include "sync0sync.h"#include "ut0mem.h"#include "ut0lst.h"#include "ut0byte.h"#include "mem0mem.h"Include dependency graph for mem0pool.c:

Go to the source code of this file.
Classes | |
| struct | mem_pool_struct |
Defines | |
| #define | MEM_AREA_FREE 1 |
| #define | MEM_AREA_MIN_SIZE (2 * MEM_AREA_EXTRA_SIZE) |
Functions | |
| void | mem_pool_mutex_enter (void) |
| void | mem_pool_mutex_exit (void) |
| UNIV_INLINE ulint | mem_area_get_size (mem_area_t *area) |
| UNIV_INLINE void | mem_area_set_size (mem_area_t *area, ulint size) |
| UNIV_INLINE ibool | mem_area_get_free (mem_area_t *area) |
| UNIV_INLINE void | mem_area_set_free (mem_area_t *area, ibool free) |
| mem_pool_t * | mem_pool_create (ulint size) |
| static ibool | mem_pool_fill_free_list (ulint i, mem_pool_t *pool) |
| void * | mem_area_alloc (ulint size, mem_pool_t *pool) |
| UNIV_INLINE mem_area_t * | mem_area_get_buddy (mem_area_t *area, ulint size, mem_pool_t *pool) |
| void | mem_area_free (void *ptr, mem_pool_t *pool) |
| ibool | mem_pool_validate (mem_pool_t *pool) |
| void | mem_pool_print_info (FILE *outfile, mem_pool_t *pool) |
| ulint | mem_pool_get_reserved (mem_pool_t *pool) |
Variables | |
| mem_pool_t * | mem_comm_pool = NULL |
| ulint | mem_n_threads_inside = 0 |
| #define MEM_AREA_FREE 1 |
Definition at line 77 of file mem0pool.c.
Referenced by mem_area_get_free(), mem_area_get_size(), mem_area_set_free(), and mem_area_set_size().
| #define MEM_AREA_MIN_SIZE (2 * MEM_AREA_EXTRA_SIZE) |
| 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:

| UNIV_INLINE mem_area_t* mem_area_get_buddy | ( | mem_area_t * | area, | |
| ulint | size, | |||
| mem_pool_t * | pool | |||
| ) |
Definition at line 409 of file mem0pool.c.
References mem_pool_struct::buf, NULL, mem_pool_struct::size, and ut_ad.
Referenced by mem_area_free(), and mem_pool_validate().
00411 : the buddy, NULL if no buddy in pool */ 00412 mem_area_t* area, /* in: memory area */ 00413 ulint size, /* in: memory area size */ 00414 mem_pool_t* pool) /* in: memory pool */ 00415 { 00416 mem_area_t* buddy; 00417 00418 ut_ad(size != 0); 00419 00420 if (((((byte*)area) - pool->buf) % (2 * size)) == 0) { 00421 00422 /* The buddy is in a higher address */ 00423 00424 buddy = (mem_area_t*)(((byte*)area) + size); 00425 00426 if ((((byte*)buddy) - pool->buf) + size > pool->size) { 00427 00428 /* The buddy is not wholly contained in the pool: 00429 there is no buddy */ 00430 00431 buddy = NULL; 00432 } 00433 } else { 00434 /* The buddy is in a lower address; NOTE that area cannot 00435 be at the pool lower end, because then we would end up to 00436 the upper branch in this if-clause: the remainder would be 00437 0 */ 00438 00439 buddy = (mem_area_t*)(((byte*)area) - size); 00440 } 00441 00442 return(buddy); 00443 }
Here is the caller graph for this function:

| UNIV_INLINE ibool mem_area_get_free | ( | mem_area_t * | area | ) |
Definition at line 155 of file mem0pool.c.
References MEM_AREA_FREE, and mem_area_struct::size_and_free.
Referenced by mem_area_alloc(), mem_area_free(), and mem_pool_validate().
00157 : TRUE if free */ 00158 mem_area_t* area) /* in: area */ 00159 { 00160 #if TRUE != MEM_AREA_FREE 00161 # error "TRUE != MEM_AREA_FREE" 00162 #endif 00163 return(area->size_and_free & MEM_AREA_FREE); 00164 }
Here is the caller graph for this function:

| UNIV_INLINE ulint mem_area_get_size | ( | mem_area_t * | area | ) |
Definition at line 130 of file mem0pool.c.
References MEM_AREA_FREE, and mem_area_struct::size_and_free.
Referenced by mem_area_alloc(), mem_area_free(), and mem_pool_validate().
00132 : size */ 00133 mem_area_t* area) /* in: area */ 00134 { 00135 return(area->size_and_free & ~MEM_AREA_FREE); 00136 }
Here is the caller graph for this function:

| UNIV_INLINE void mem_area_set_free | ( | mem_area_t * | area, | |
| ibool | free | |||
| ) |
Definition at line 170 of file mem0pool.c.
References MEM_AREA_FREE, and mem_area_struct::size_and_free.
Referenced by mem_area_alloc(), mem_area_free(), mem_pool_create(), and mem_pool_fill_free_list().
00172 : area */ 00173 ibool free) /* in: free bit value */ 00174 { 00175 #if TRUE != MEM_AREA_FREE 00176 # error "TRUE != MEM_AREA_FREE" 00177 #endif 00178 area->size_and_free = (area->size_and_free & ~MEM_AREA_FREE) 00179 | free; 00180 }
Here is the caller graph for this function:

| UNIV_INLINE void mem_area_set_size | ( | mem_area_t * | area, | |
| ulint | size | |||
| ) |
Definition at line 142 of file mem0pool.c.
References MEM_AREA_FREE, and mem_area_struct::size_and_free.
Referenced by mem_area_free(), mem_pool_create(), and mem_pool_fill_free_list().
00144 : area */ 00145 ulint size) /* in: size */ 00146 { 00147 area->size_and_free = (area->size_and_free & MEM_AREA_FREE) 00148 | size; 00149 }
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:

| static ibool mem_pool_fill_free_list | ( | ulint | i, | |
| mem_pool_t * | pool | |||
| ) | [static] |
Definition at line 250 of file mem0pool.c.
References FALSE, mem_pool_struct::free_list, mem_analyze_corruption(), mem_area_set_free(), mem_area_set_size(), mem_pool_struct::mutex, NULL, TRUE, ut_2_exp(), ut_ad, ut_error, UT_LIST_ADD_FIRST, UT_LIST_GET_FIRST, UT_LIST_GET_LEN, UT_LIST_REMOVE, and ut_print_timestamp().
Referenced by mem_area_alloc().
00252 : TRUE if we were able to insert a 00253 block to the free list */ 00254 ulint i, /* in: free list index */ 00255 mem_pool_t* pool) /* in: memory pool */ 00256 { 00257 mem_area_t* area; 00258 mem_area_t* area2; 00259 ibool ret; 00260 00261 #ifdef UNIV_SYNC_DEBUG 00262 ut_ad(mutex_own(&(pool->mutex))); 00263 #endif /* UNIV_SYNC_DEBUG */ 00264 00265 if (i >= 63) { 00266 /* We come here when we have run out of space in the 00267 memory pool: */ 00268 00269 return(FALSE); 00270 } 00271 00272 area = UT_LIST_GET_FIRST(pool->free_list[i + 1]); 00273 00274 if (area == NULL) { 00275 if (UT_LIST_GET_LEN(pool->free_list[i + 1]) > 0) { 00276 ut_print_timestamp(stderr); 00277 00278 fprintf(stderr, 00279 " InnoDB: Error: mem pool free list %lu length is %lu\n" 00280 "InnoDB: though the list is empty!\n", 00281 (ulong) i + 1, 00282 (ulong) UT_LIST_GET_LEN(pool->free_list[i + 1])); 00283 } 00284 00285 ret = mem_pool_fill_free_list(i + 1, pool); 00286 00287 if (ret == FALSE) { 00288 00289 return(FALSE); 00290 } 00291 00292 area = UT_LIST_GET_FIRST(pool->free_list[i + 1]); 00293 } 00294 00295 if (UT_LIST_GET_LEN(pool->free_list[i + 1]) == 0) { 00296 mem_analyze_corruption(area); 00297 00298 ut_error; 00299 } 00300 00301 UT_LIST_REMOVE(free_list, pool->free_list[i + 1], area); 00302 00303 area2 = (mem_area_t*)(((byte*)area) + ut_2_exp(i)); 00304 00305 mem_area_set_size(area2, ut_2_exp(i)); 00306 mem_area_set_free(area2, TRUE); 00307 00308 UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area2); 00309 00310 mem_area_set_size(area, ut_2_exp(i)); 00311 00312 UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area); 00313 00314 return(TRUE); 00315 }
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:

| mem_pool_t* mem_comm_pool = NULL |
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

