📄 mem0pool.c
字号:
ibool ret; n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE)); mutex_enter(&(pool->mutex)); mem_n_threads_inside++; ut_a(mem_n_threads_inside == 1); area = UT_LIST_GET_FIRST(pool->free_list[n]); if (area == NULL) { ret = mem_pool_fill_free_list(n, pool); if (ret == FALSE) { /* Out of memory in memory pool: we try to allocate from the operating system with the regular malloc: */ mem_n_threads_inside--; mutex_exit(&(pool->mutex)); return(ut_malloc(size)); } area = UT_LIST_GET_FIRST(pool->free_list[n]); } if (!mem_area_get_free(area)) { fprintf(stderr,"InnoDB: Error: Removing element from mem pool free list %lu though the\n""InnoDB: element is not marked free!\n", (ulong) n); mem_analyze_corruption((byte*)area); /* Try to analyze a strange assertion failure reported at mysql@lists.mysql.com where the free bit IS 1 in the hex dump above */ if (mem_area_get_free(area)) { fprintf(stderr,"InnoDB: Probably a race condition because now the area is marked free!\n"); } ut_error; } if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) { fprintf(stderr,"InnoDB: Error: Removing element from mem pool free list %lu\n""InnoDB: though the list length is 0!\n", (ulong) n); mem_analyze_corruption((byte*)area); ut_error; } ut_ad(mem_area_get_size(area) == ut_2_exp(n)); mem_area_set_free(area, FALSE); UT_LIST_REMOVE(free_list, pool->free_list[n], area); pool->reserved += mem_area_get_size(area); mem_n_threads_inside--; mutex_exit(&(pool->mutex)); ut_ad(mem_pool_validate(pool)); return((void*)(MEM_AREA_EXTRA_SIZE + ((byte*)area))); }/************************************************************************Gets the buddy of an area, if it exists in pool. */UNIV_INLINEmem_area_t*mem_area_get_buddy(/*===============*/ /* out: the buddy, NULL if no buddy in pool */ mem_area_t* area, /* in: memory area */ ulint size, /* in: memory area size */ mem_pool_t* pool) /* in: memory pool */{ mem_area_t* buddy; ut_ad(size != 0); if (((((byte*)area) - pool->buf) % (2 * size)) == 0) { /* The buddy is in a higher address */ buddy = (mem_area_t*)(((byte*)area) + size); if ((((byte*)buddy) - pool->buf) + size > pool->size) { /* The buddy is not wholly contained in the pool: there is no buddy */ buddy = NULL; } } else { /* The buddy is in a lower address; NOTE that area cannot be at the pool lower end, because then we would end up to the upper branch in this if-clause: the remainder would be 0 */ buddy = (mem_area_t*)(((byte*)area) - size); } return(buddy);}/************************************************************************Frees memory to a pool. */voidmem_area_free(/*==========*/ void* ptr, /* in, own: pointer to allocated memory buffer */ mem_pool_t* pool) /* in: memory pool */{ mem_area_t* area; mem_area_t* buddy; void* new_ptr; ulint size; ulint n; /* It may be that the area was really allocated from the OS with regular malloc: check if ptr points within our memory pool */ if ((byte*)ptr < pool->buf || (byte*)ptr >= pool->buf + pool->size) { ut_free(ptr); return; } area = (mem_area_t*) (((byte*)ptr) - MEM_AREA_EXTRA_SIZE); if (mem_area_get_free(area)) { fprintf(stderr,"InnoDB: Error: Freeing element to mem pool free list though the\n""InnoDB: element is marked free!\n"); mem_analyze_corruption((byte*)area); ut_error; } size = mem_area_get_size(area); if (size == 0) { fprintf(stderr,"InnoDB: Error: Mem area size is 0. Possibly a memory overrun of the\n""InnoDB: previous allocated area!\n"); mem_analyze_corruption((byte*)area); ut_error; }#ifdef UNIV_LIGHT_MEM_DEBUG if (((byte*)area) + size < pool->buf + pool->size) { ulint next_size; next_size = mem_area_get_size( (mem_area_t*)(((byte*)area) + size)); if (ut_2_power_up(next_size) != next_size) { fprintf(stderr,"InnoDB: Error: Memory area size %lu, next area size %lu not a power of 2!\n""InnoDB: Possibly a memory overrun of the buffer being freed here.\n", (ulong) size, (ulong) next_size); mem_analyze_corruption((byte*)area); ut_error; } }#endif buddy = mem_area_get_buddy(area, size, pool); n = ut_2_log(size); mutex_enter(&(pool->mutex)); mem_n_threads_inside++; ut_a(mem_n_threads_inside == 1); if (buddy && mem_area_get_free(buddy) && (size == mem_area_get_size(buddy))) { /* The buddy is in a free list */ if ((byte*)buddy < (byte*)area) { new_ptr = ((byte*)buddy) + MEM_AREA_EXTRA_SIZE; mem_area_set_size(buddy, 2 * size); mem_area_set_free(buddy, FALSE); } else { new_ptr = ptr; mem_area_set_size(area, 2 * size); } /* Remove the buddy from its free list and merge it to area */ UT_LIST_REMOVE(free_list, pool->free_list[n], buddy); pool->reserved += ut_2_exp(n); mem_n_threads_inside--; mutex_exit(&(pool->mutex)); mem_area_free(new_ptr, pool); return; } else { UT_LIST_ADD_FIRST(free_list, pool->free_list[n], area); mem_area_set_free(area, TRUE); ut_ad(pool->reserved >= size); pool->reserved -= size; } mem_n_threads_inside--; mutex_exit(&(pool->mutex)); ut_ad(mem_pool_validate(pool));}/************************************************************************Validates a memory pool. */iboolmem_pool_validate(/*==============*/ /* out: TRUE if ok */ mem_pool_t* pool) /* in: memory pool */{ mem_area_t* area; mem_area_t* buddy; ulint free; ulint i; mutex_enter(&(pool->mutex)); free = 0; for (i = 0; i < 64; i++) { UT_LIST_VALIDATE(free_list, mem_area_t, pool->free_list[i]); area = UT_LIST_GET_FIRST(pool->free_list[i]); while (area != NULL) { ut_a(mem_area_get_free(area)); ut_a(mem_area_get_size(area) == ut_2_exp(i)); buddy = mem_area_get_buddy(area, ut_2_exp(i), pool); ut_a(!buddy || !mem_area_get_free(buddy) || (ut_2_exp(i) != mem_area_get_size(buddy))); area = UT_LIST_GET_NEXT(free_list, area); free += ut_2_exp(i); } } ut_a(free + pool->reserved == pool->size); mutex_exit(&(pool->mutex)); return(TRUE);}/************************************************************************Prints info of a memory pool. */voidmem_pool_print_info(/*================*/ FILE* outfile,/* in: output file to write to */ mem_pool_t* pool) /* in: memory pool */{ ulint i; mem_pool_validate(pool); fprintf(outfile, "INFO OF A MEMORY POOL\n"); mutex_enter(&(pool->mutex)); for (i = 0; i < 64; i++) { if (UT_LIST_GET_LEN(pool->free_list[i]) > 0) { fprintf(outfile, "Free list length %lu for blocks of size %lu\n", (ulong) UT_LIST_GET_LEN(pool->free_list[i]), (ulong) ut_2_exp(i)); } } fprintf(outfile, "Pool size %lu, reserved %lu.\n", (ulong) pool->size, (ulong) pool->reserved); mutex_exit(&(pool->mutex));}/************************************************************************Returns the amount of reserved memory. */ulintmem_pool_get_reserved(/*==================*/ /* out: reserved memory in bytes */ mem_pool_t* pool) /* in: memory pool */{ ulint reserved; mutex_enter(&(pool->mutex)); reserved = pool->reserved; mutex_exit(&(pool->mutex)); return(reserved);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -