diff options
Diffstat (limited to 'storage/xtradb/buf/buf0buddy.c')
-rw-r--r-- | storage/xtradb/buf/buf0buddy.c | 163 |
1 files changed, 84 insertions, 79 deletions
diff --git a/storage/xtradb/buf/buf0buddy.c b/storage/xtradb/buf/buf0buddy.c index 494db91d159..6ee7a71a2e5 100644 --- a/storage/xtradb/buf/buf0buddy.c +++ b/storage/xtradb/buf/buf0buddy.c @@ -16,7 +16,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ -/****************************************************** +/**************************************************//** +@file buf/buf0buddy.c Binary buddy allocator for compressed pages Created December 2006 by Marko Makela @@ -44,15 +45,15 @@ static ulint buf_buddy_n_frames; Protected by buf_pool_mutex. */ UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1]; -/************************************************************************** -Get the offset of the buddy of a compressed page frame. */ +/**********************************************************************//** +Get the offset of the buddy of a compressed page frame. +@return the buddy relative of page */ UNIV_INLINE byte* buf_buddy_get( /*==========*/ - /* out: the buddy relative of page */ - byte* page, /* in: compressed page */ - ulint size) /* in: page size in bytes */ + byte* page, /*!< in: compressed page */ + ulint size) /*!< in: page size in bytes */ { ut_ad(ut_is_2pow(size)); ut_ad(size >= BUF_BUDDY_LOW); @@ -66,14 +67,14 @@ buf_buddy_get( } } -/************************************************************************** +/**********************************************************************//** Add a block to the head of the appropriate buddy free list. */ UNIV_INLINE void buf_buddy_add_to_free( /*==================*/ - buf_page_t* bpage, /* in,own: block to be freed */ - ulint i) /* in: index of buf_pool->zip_free[] */ + buf_page_t* bpage, /*!< in,own: block to be freed */ + ulint i) /*!< in: index of buf_pool->zip_free[] */ { #ifdef UNIV_DEBUG_VALGRIND buf_page_t* b = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); @@ -81,6 +82,9 @@ buf_buddy_add_to_free( if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i); #endif /* UNIV_DEBUG_VALGRIND */ + //ut_ad(buf_pool_mutex_own()); + ut_ad(mutex_own(&zip_free_mutex)); + ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE); ut_ad(buf_pool->zip_free[i].start != bpage); UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_free[i], bpage); @@ -90,14 +94,14 @@ buf_buddy_add_to_free( #endif /* UNIV_DEBUG_VALGRIND */ } -/************************************************************************** +/**********************************************************************//** Remove a block from the appropriate buddy free list. */ UNIV_INLINE void buf_buddy_remove_from_free( /*=======================*/ - buf_page_t* bpage, /* in: block to be removed */ - ulint i) /* in: index of buf_pool->zip_free[] */ + buf_page_t* bpage, /*!< in: block to be removed */ + ulint i) /*!< in: index of buf_pool->zip_free[] */ { #ifdef UNIV_DEBUG_VALGRIND buf_page_t* prev = UT_LIST_GET_PREV(zip_list, bpage); @@ -110,6 +114,8 @@ buf_buddy_remove_from_free( ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE); #endif /* UNIV_DEBUG_VALGRIND */ + //ut_ad(buf_pool_mutex_own()); + ut_ad(mutex_own(&zip_free_mutex)); ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE); UT_LIST_REMOVE(zip_list, buf_pool->zip_free[i], bpage); @@ -119,15 +125,14 @@ buf_buddy_remove_from_free( #endif /* UNIV_DEBUG_VALGRIND */ } -/************************************************************************** -Try to allocate a block from buf_pool->zip_free[]. */ +/**********************************************************************//** +Try to allocate a block from buf_pool->zip_free[]. +@return allocated block, or NULL if buf_pool->zip_free[] was empty */ static void* buf_buddy_alloc_zip( /*================*/ - /* out: allocated block, or NULL - if buf_pool->zip_free[] was empty */ - ulint i) /* in: index of buf_pool->zip_free[] */ + ulint i) /*!< in: index of buf_pool->zip_free[] */ { buf_page_t* bpage; @@ -135,10 +140,12 @@ buf_buddy_alloc_zip( ut_ad(mutex_own(&zip_free_mutex)); ut_a(i < BUF_BUDDY_SIZES); -#if defined UNIV_DEBUG && !defined UNIV_DEBUG_VALGRIND +#ifndef UNIV_DEBUG_VALGRIND /* Valgrind would complain about accessing free memory. */ - UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i]); -#endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */ + ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i], + ut_ad(buf_page_get_state(ut_list_node_313) + == BUF_BLOCK_ZIP_FREE))); +#endif /* !UNIV_DEBUG_VALGRIND */ bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]); if (bpage) { @@ -172,13 +179,13 @@ buf_buddy_alloc_zip( return(bpage); } -/************************************************************************** +/**********************************************************************//** Deallocate a buffer frame of UNIV_PAGE_SIZE. */ static void buf_buddy_block_free( /*=================*/ - void* buf, /* in: buffer frame to deallocate */ + void* buf, /*!< in: buffer frame to deallocate */ ibool have_page_hash_mutex) { const ulint fold = BUF_POOL_ZIP_FOLD_PTR(buf); @@ -216,17 +223,18 @@ buf_buddy_block_free( ut_d(buf_buddy_n_frames--); } -/************************************************************************** +/**********************************************************************//** Allocate a buffer block to the buddy allocator. */ static void buf_buddy_block_register( /*=====================*/ - buf_block_t* block) /* in: buffer frame to allocate */ + buf_block_t* block) /*!< in: buffer frame to allocate */ { const ulint fold = BUF_POOL_ZIP_FOLD(block); //ut_ad(buf_pool_mutex_own()); ut_ad(!mutex_own(&buf_pool_zip_mutex)); + ut_ad(buf_block_get_state(block) == BUF_BLOCK_READY_FOR_USE); buf_block_set_state(block, BUF_BLOCK_MEMORY); @@ -244,16 +252,16 @@ buf_buddy_block_register( ut_d(buf_buddy_n_frames++); } -/************************************************************************** -Allocate a block from a bigger object. */ +/**********************************************************************//** +Allocate a block from a bigger object. +@return allocated block */ static void* buf_buddy_alloc_from( /*=================*/ - /* out: allocated block */ - void* buf, /* in: a block that is free to use */ - ulint i, /* in: index of buf_pool->zip_free[] */ - ulint j) /* in: size of buf as an index + void* buf, /*!< in: a block that is free to use */ + ulint i, /*!< in: index of buf_pool->zip_free[] */ + ulint j) /*!< in: size of buf as an index of buf_pool->zip_free[] */ { ulint offs = BUF_BUDDY_LOW << j; @@ -271,29 +279,31 @@ buf_buddy_alloc_from( bpage = (buf_page_t*) ((byte*) buf + offs); ut_d(memset(bpage, j, BUF_BUDDY_LOW << j)); bpage->state = BUF_BLOCK_ZIP_FREE; -#if defined UNIV_DEBUG && !defined UNIV_DEBUG_VALGRIND +#ifndef UNIV_DEBUG_VALGRIND /* Valgrind would complain about accessing free memory. */ - UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[j]); -#endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */ + ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i], + ut_ad(buf_page_get_state( + ut_list_node_313) + == BUF_BLOCK_ZIP_FREE))); +#endif /* !UNIV_DEBUG_VALGRIND */ buf_buddy_add_to_free(bpage, j); } return(buf); } -/************************************************************************** +/**********************************************************************//** Allocate a block. The thread calling this function must hold buf_pool_mutex and must not hold buf_pool_zip_mutex or any block->mutex. -The buf_pool_mutex may only be released and reacquired if lru != NULL. */ +The buf_pool_mutex may only be released and reacquired if lru != NULL. +@return allocated block, possibly NULL if lru==NULL */ UNIV_INTERN void* buf_buddy_alloc_low( /*================*/ - /* out: allocated block, - possibly NULL if lru==NULL */ - ulint i, /* in: index of buf_pool->zip_free[], + ulint i, /*!< in: index of buf_pool->zip_free[], or BUF_BUDDY_SIZES */ - ibool* lru, /* in: pointer to a variable that will be assigned + ibool* lru, /*!< in: pointer to a variable that will be assigned TRUE if storage was allocated from the LRU list and buf_pool_mutex was temporarily released, or NULL if the LRU list should not be used */ @@ -357,15 +367,15 @@ func_exit: return(block); } -/************************************************************************** -Try to relocate the control block of a compressed page. */ +/**********************************************************************//** +Try to relocate the control block of a compressed page. +@return TRUE if relocated */ static ibool buf_buddy_relocate_block( /*=====================*/ - /* out: TRUE if relocated */ - buf_page_t* bpage, /* in: block to relocate */ - buf_page_t* dpage) /* in: free block to relocate to */ + buf_page_t* bpage, /*!< in: block to relocate */ + buf_page_t* dpage) /*!< in: free block to relocate to */ { buf_page_t* b; @@ -425,16 +435,16 @@ buf_buddy_relocate_block( return(TRUE); } -/************************************************************************** -Try to relocate a block. */ +/**********************************************************************//** +Try to relocate a block. +@return TRUE if relocated */ static ibool buf_buddy_relocate( /*===============*/ - /* out: TRUE if relocated */ - void* src, /* in: block to relocate */ - void* dst, /* in: free block to relocate to */ - ulint i, /* in: index of buf_pool->zip_free[] */ + void* src, /*!< in: block to relocate */ + void* dst, /*!< in: free block to relocate to */ + ulint i, /*!< in: index of buf_pool->zip_free[] */ ibool have_page_hash_mutex) { buf_page_t* bpage; @@ -461,16 +471,15 @@ buf_buddy_relocate( actually is a properly initialized buf_page_t object. */ if (size >= PAGE_ZIP_MIN_SIZE) { - mutex_t* mutex; - if (!have_page_hash_mutex) - mutex_exit(&zip_free_mutex); - /* This is a compressed page. */ + mutex_t* mutex; if (!have_page_hash_mutex) { + mutex_exit(&zip_free_mutex); mutex_enter(&LRU_list_mutex); rw_lock_x_lock(&page_hash_latch); } + /* The src block may be split into smaller blocks, some of which may be free. Thus, the mach_read_from_4() calls below may attempt to read @@ -521,15 +530,9 @@ buf_buddy_relocate( contain uninitialized data. */ UNIV_MEM_ASSERT_W(src, size); - mutex = buf_page_get_mutex(bpage); + mutex = buf_page_get_mutex_enter(bpage); + ut_a(mutex); -retry_lock: - mutex_enter(mutex); - if (mutex != buf_page_get_mutex(bpage)) { - mutex_exit(mutex); - mutex = buf_page_get_mutex(bpage); - goto retry_lock; - } mutex_enter(&zip_free_mutex); if (buf_page_can_relocate(bpage)) { @@ -594,15 +597,16 @@ success: return(FALSE); } -/************************************************************************** +/**********************************************************************//** Deallocate a block. */ UNIV_INTERN void buf_buddy_free_low( /*===============*/ - void* buf, /* in: block to be freed, must not be + void* buf, /*!< in: block to be freed, must not be pointed to by the buffer pool */ - ulint i, /* in: index of buf_pool->zip_free[] */ + ulint i, /*!< in: index of buf_pool->zip_free[], + or BUF_BUDDY_SIZES */ ibool have_page_hash_mutex) { buf_page_t* bpage; @@ -676,7 +680,9 @@ buddy_free2: #ifndef UNIV_DEBUG_VALGRIND buddy_nonfree: /* Valgrind would complain about accessing free memory. */ - ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i])); + ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i], + ut_ad(buf_page_get_state(ut_list_node_313) + == BUF_BLOCK_ZIP_FREE))); #endif /* UNIV_DEBUG_VALGRIND */ /* The buddy is not free. Is there a free block of this size? */ @@ -702,21 +708,20 @@ buddy_nonfree: buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage), BUF_BUDDY_LOW << i); -#if defined UNIV_DEBUG && !defined UNIV_DEBUG_VALGRIND - { - const buf_page_t* b; +#ifndef UNIV_DEBUG_VALGRIND + /* Valgrind would complain about accessing free memory. */ - /* The buddy must not be (completely) free, because - we always recombine adjacent free blocks. - (Parts of the buddy can be free in - buf_pool->zip_free[j] with j < i.)*/ - for (b = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); - b; b = UT_LIST_GET_NEXT(zip_list, b)) { + /* The buddy must not be (completely) free, because we + always recombine adjacent free blocks. - ut_a(b != buddy); - } - } -#endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */ + (Parts of the buddy can be free in + buf_pool->zip_free[j] with j < i.) */ + ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i], + ut_ad(buf_page_get_state( + ut_list_node_313) + == BUF_BLOCK_ZIP_FREE + && ut_list_node_313 != buddy))); +#endif /* !UNIV_DEBUG_VALGRIND */ if (buf_buddy_relocate(buddy, buf, i, have_page_hash_mutex)) { |