Loading innobase/buf/buf0buf.c +115 −56 Original line number Diff line number Diff line Loading @@ -221,6 +221,9 @@ in the free list to the frames. 5) When we have AWE enabled, we disable adaptive hash indexes. */ /* Value in microseconds */ static const int WAIT_FOR_READ = 20000; buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */ ulint buf_dbg_counter = 0; /* This is used to insert validation Loading Loading @@ -466,6 +469,9 @@ buf_block_init( block->n_pointers = 0; mutex_create(&block->mutex); mutex_set_level(&block->mutex, SYNC_BUF_BLOCK); rw_lock_create(&(block->lock)); ut_ad(rw_lock_validate(&(block->lock))); Loading Loading @@ -734,8 +740,15 @@ buf_awe_map_page_to_frame( bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped); while (bck) { if (bck->state == BUF_BLOCK_FILE_PAGE && (bck->buf_fix_count != 0 || bck->io_fix != 0)) { ibool skip; mutex_enter(&bck->mutex); skip = (bck->state == BUF_BLOCK_FILE_PAGE && (bck->buf_fix_count != 0 || bck->io_fix != 0)); if (skip) { mutex_exit(&bck->mutex); /* We have to skip this */ bck = UT_LIST_GET_PREV(awe_LRU_free_mapped, bck); Loading Loading @@ -768,6 +781,8 @@ buf_awe_map_page_to_frame( buf_pool->n_pages_awe_remapped++; mutex_exit(&bck->mutex); return; } } Loading Loading @@ -806,13 +821,22 @@ buf_block_make_young( /*=================*/ buf_block_t* block) /* in: block to make younger */ { #ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&(buf_pool->mutex))); #endif /* UNIV_SYNC_DEBUG */ /* Note that we read freed_page_clock's without holding any mutex: this is allowed since the result is used only in heuristics */ if (buf_pool->freed_page_clock >= block->freed_page_clock + 1 + (buf_pool->curr_size / 1024)) { + 1 + (buf_pool->curr_size / 4)) { mutex_enter(&buf_pool->mutex); /* There has been freeing activity in the LRU list: best to move to the head of the LRU list */ buf_LRU_make_block_young(block); mutex_exit(&buf_pool->mutex); } } Loading Loading @@ -847,12 +871,16 @@ buf_block_free( /*===========*/ buf_block_t* block) /* in, own: block to be freed */ { ut_a(block->state != BUF_BLOCK_FILE_PAGE); mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); ut_a(block->state != BUF_BLOCK_FILE_PAGE); buf_LRU_block_free_non_file_page(block); mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); } Loading Loading @@ -1071,9 +1099,8 @@ buf_page_get_gen( #endif buf_pool->n_page_gets++; loop: mutex_enter_fast(&(buf_pool->mutex)); block = NULL; mutex_enter_fast(&(buf_pool->mutex)); if (guess) { block = buf_block_align(guess); Loading Loading @@ -1111,6 +1138,8 @@ buf_page_get_gen( goto loop; } mutex_enter(&block->mutex); ut_a(block->state == BUF_BLOCK_FILE_PAGE); must_read = FALSE; Loading @@ -1120,9 +1149,9 @@ buf_page_get_gen( must_read = TRUE; if (mode == BUF_GET_IF_IN_POOL) { /* The page is only being read to buffer */ mutex_exit(&(buf_pool->mutex)); mutex_exit(&buf_pool->mutex); mutex_exit(&block->mutex); return(NULL); } Loading @@ -1146,7 +1175,7 @@ buf_page_get_gen( #else buf_block_buf_fix_inc(block); #endif buf_block_make_young(block); mutex_exit(&buf_pool->mutex); /* Check if this is the first access to the page */ Loading @@ -1154,10 +1183,13 @@ buf_page_get_gen( block->accessed = TRUE; mutex_exit(&block->mutex); buf_block_make_young(block); #ifdef UNIV_DEBUG_FILE_ACCESSES ut_a(block->file_page_was_freed == FALSE); #endif mutex_exit(&(buf_pool->mutex)); #ifdef UNIV_DEBUG buf_dbg_counter++; Loading @@ -1182,13 +1214,14 @@ buf_page_get_gen( } if (!success) { mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); block->buf_fix_count--; mutex_exit(&block->mutex); #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif mutex_exit(&(buf_pool->mutex)); return(NULL); } Loading @@ -1199,18 +1232,16 @@ buf_page_get_gen( completes */ for (;;) { mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); if (block->io_fix == BUF_IO_READ) { mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); /* Sleep 20 milliseconds */ os_thread_sleep(20000); os_thread_sleep(WAIT_FOR_READ); } else { mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); break; } Loading Loading @@ -1269,13 +1300,13 @@ buf_page_optimistic_get_func( ut_ad(mtr && block); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); mutex_enter(&(buf_pool->mutex)); /* If AWE is used, block may have a different frame now, e.g., NULL */ mutex_enter(&block->mutex); if (block->state != BUF_BLOCK_FILE_PAGE || block->frame != guess) { mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); return(FALSE); } Loading @@ -1285,15 +1316,14 @@ buf_page_optimistic_get_func( #else buf_block_buf_fix_inc(block); #endif buf_block_make_young(block); /* Check if this is the first access to the page */ accessed = block->accessed; block->accessed = TRUE; mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); buf_block_make_young(block); /* Check if this is the first access to the page */ ut_ad(!ibuf_inside() || ibuf_page(block->space, block->offset)); Loading @@ -1308,14 +1338,15 @@ buf_page_optimistic_get_func( } if (!success) { mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); block->buf_fix_count--; mutex_exit(&block->mutex); #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif mutex_exit(&(buf_pool->mutex)); return(FALSE); } Loading @@ -1329,14 +1360,15 @@ buf_page_optimistic_get_func( rw_lock_x_unlock(&(block->lock)); } mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); block->buf_fix_count--; mutex_exit(&block->mutex); #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif mutex_exit(&(buf_pool->mutex)); return(FALSE); } Loading Loading @@ -1394,10 +1426,10 @@ buf_page_get_known_nowait( ut_ad(mtr); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); mutex_enter(&(buf_pool->mutex)); block = buf_block_align(guess); mutex_enter(&block->mutex); if (block->state == BUF_BLOCK_REMOVE_HASH) { /* Another thread is just freeing the block from the LRU list of the buffer pool: do not try to access this page; this Loading @@ -1406,7 +1438,7 @@ buf_page_get_known_nowait( we have already removed it from the page address hash table of the buffer pool. */ mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); return(FALSE); } Loading @@ -1418,12 +1450,12 @@ buf_page_get_known_nowait( #else buf_block_buf_fix_inc(block); #endif mutex_exit(&block->mutex); if (mode == BUF_MAKE_YOUNG) { buf_block_make_young(block); } mutex_exit(&(buf_pool->mutex)); ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD)); if (rw_latch == RW_S_LATCH) { Loading @@ -1437,13 +1469,15 @@ buf_page_get_known_nowait( } if (!success) { mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); block->buf_fix_count--; mutex_exit(&block->mutex); #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif mutex_exit(&(buf_pool->mutex)); return(FALSE); } Loading Loading @@ -1491,7 +1525,6 @@ buf_page_init_for_backup_restore( block->offset = offset; block->lock_hash_val = 0; block->lock_mutex = NULL; block->freed_page_clock = 0; Loading Loading @@ -1524,6 +1557,7 @@ buf_page_init( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(block->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_a(block->state != BUF_BLOCK_FILE_PAGE); Loading @@ -1537,7 +1571,6 @@ buf_page_init( block->check_index_page_at_flush = FALSE; block->lock_hash_val = lock_rec_hash(space, offset); block->lock_mutex = NULL; /* Insert into the hash table of file pages */ Loading Loading @@ -1630,6 +1663,7 @@ buf_page_init_for_read( ut_a(block); mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); if (fil_tablespace_deleted_or_being_deleted_in_mem(space, tablespace_version)) { Loading @@ -1642,7 +1676,9 @@ buf_page_init_for_read( /* The page belongs to a space which has been deleted or is being deleted, or the page is already in buf_pool, return */ mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); buf_block_free(block); if (mode == BUF_READ_IBUF_PAGES_ONLY) { Loading @@ -1662,6 +1698,7 @@ buf_page_init_for_read( buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */ block->io_fix = BUF_IO_READ; buf_pool->n_pend_reads++; /* We set a pass-type x-lock on the frame because then the same Loading @@ -1673,6 +1710,7 @@ buf_page_init_for_read( rw_lock_x_lock_gen(&(block->lock), BUF_IO_READ); mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); if (mode == BUF_READ_IBUF_PAGES_ONLY) { Loading Loading @@ -1735,6 +1773,8 @@ buf_page_create( block = free_block; mutex_enter(&block->mutex); buf_page_init(space, offset, block); /* The block must be put to the LRU list */ Loading @@ -1745,13 +1785,15 @@ buf_page_create( #else buf_block_buf_fix_inc(block); #endif buf_pool->n_pages_created++; mutex_exit(&(buf_pool->mutex)); mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX); block->accessed = TRUE; buf_pool->n_pages_created++; mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); /* Delete possible entries for the page from the insert buffer: such can exist if the page belonged to an index which was dropped */ Loading Loading @@ -1800,6 +1842,12 @@ buf_page_io_complete( ut_a(block->state == BUF_BLOCK_FILE_PAGE); /* We do not need protect block->io_fix here by block->mutex to read it because this is the only function where we can change the value from BUF_IO_READ or BUF_IO_WRITE to some other value, and our code ensures that this is the only thread that handles the i/o for this block. */ io_type = block->io_fix; if (io_type == BUF_IO_READ) { Loading Loading @@ -1868,11 +1916,12 @@ buf_page_io_complete( } } mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); #ifdef UNIV_IBUF_DEBUG ut_a(ibuf_count_get(block->space, block->offset) == 0); #endif mutex_enter(&(buf_pool->mutex)); /* Because this thread which does the unlocking is not the same that did the locking, we use a pass value != 0 in unlock, which simply removes the newest lock debug record, without checking the thread Loading Loading @@ -1911,6 +1960,7 @@ buf_page_io_complete( } } mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); if (buf_debug_prints) { Loading Loading @@ -1970,6 +2020,8 @@ buf_validate(void) block = buf_pool_get_nth_block(buf_pool, i); mutex_enter(&block->mutex); if (block->state == BUF_BLOCK_FILE_PAGE) { ut_a(buf_page_hash_get(block->space, Loading Loading @@ -2013,6 +2065,8 @@ buf_validate(void) } else if (block->state == BUF_BLOCK_NOT_USED) { n_free++; } mutex_exit(&block->mutex); } if (n_lru + n_free > buf_pool->curr_size) { Loading Loading @@ -2303,16 +2357,21 @@ buf_all_freed(void) block = buf_pool_get_nth_block(buf_pool, i); mutex_enter(&block->mutex); if (block->state == BUF_BLOCK_FILE_PAGE) { if (!buf_flush_ready_for_replace(block)) { fprintf(stderr, "Page %lu %lu still fixed or dirty\n", (ulong) block->space, (ulong) block->offset); (ulong) block->space, (ulong) block->offset); ut_error; } } mutex_exit(&block->mutex); } mutex_exit(&(buf_pool->mutex)); Loading innobase/buf/buf0flu.c +65 −27 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ buf_flush_ready_for_replace( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ if (block->state != BUF_BLOCK_FILE_PAGE) { ut_print_timestamp(stderr); Loading Loading @@ -148,6 +149,7 @@ buf_flush_ready_for_flush( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(block->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_a(block->state == BUF_BLOCK_FILE_PAGE); Loading Loading @@ -533,8 +535,15 @@ buf_flush_try_page( ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); if (!block) { mutex_exit(&(buf_pool->mutex)); return(0); } mutex_enter(&block->mutex); if (flush_type == BUF_FLUSH_LIST && block && buf_flush_ready_for_flush(block, flush_type)) { && buf_flush_ready_for_flush(block, flush_type)) { block->io_fix = BUF_IO_WRITE; Loading Loading @@ -572,6 +581,7 @@ buf_flush_try_page( locked = TRUE; } mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); if (!locked) { Loading @@ -590,7 +600,7 @@ buf_flush_try_page( return(1); } else if (flush_type == BUF_FLUSH_LRU && block } else if (flush_type == BUF_FLUSH_LRU && buf_flush_ready_for_flush(block, flush_type)) { /* VERY IMPORTANT: Loading Loading @@ -631,13 +641,14 @@ buf_flush_try_page( buf_pool mutex: this ensures that the latch is acquired immediately. */ mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); buf_flush_write_block_low(block); return(1); } else if (flush_type == BUF_FLUSH_SINGLE_PAGE && block } else if (flush_type == BUF_FLUSH_SINGLE_PAGE && buf_flush_ready_for_flush(block, flush_type)) { block->io_fix = BUF_IO_WRITE; Loading @@ -664,6 +675,7 @@ buf_flush_try_page( (buf_pool->n_flush[flush_type])++; mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE); Loading @@ -678,12 +690,13 @@ buf_flush_try_page( buf_flush_write_block_low(block); return(1); } else { } mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); return(0); } } /*************************************************************** Flushes to disk all flushable pages within the flush area. */ Loading Loading @@ -727,34 +740,48 @@ buf_flush_try_neighbors( block = buf_page_hash_get(space, i); ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); if (block && flush_type == BUF_FLUSH_LRU && i != offset if (!block) { continue; } else if (flush_type == BUF_FLUSH_LRU && i != offset && !block->old) { /* We avoid flushing 'non-old' blocks in an LRU flush, because the flushed blocks are soon freed */ continue; } } else { mutex_enter(&block->mutex); if (block && buf_flush_ready_for_flush(block, flush_type) if (buf_flush_ready_for_flush(block, flush_type) && (i == offset || block->buf_fix_count == 0)) { /* We only try to flush those neighbors != offset where the buf fix count is zero, as we then know that we probably can latch the page without a semaphore wait. Semaphore waits are expensive because we must /* We only try to flush those neighbors != offset where the buf fix count is zero, as we then know that we probably can latch the page without a semaphore wait. Semaphore waits are expensive because we must flush the doublewrite buffer before we start waiting. */ mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); /* Note: as we release the buf_pool mutex above, in buf_flush_try_page we cannot be sure the page is still in a flushable state: therefore we check it again inside that function. */ /* Note: as we release the buf_pool mutex above, in buf_flush_try_page we cannot be sure the page is still in a flushable state: therefore we check it again inside that function. */ count += buf_flush_try_page(space, i, flush_type); count += buf_flush_try_page(space, i, flush_type); mutex_enter(&(buf_pool->mutex)); } else { mutex_exit(&block->mutex); } } } Loading Loading @@ -848,12 +875,15 @@ buf_flush_batch( while ((block != NULL) && !found) { ut_a(block->state == BUF_BLOCK_FILE_PAGE); mutex_enter(&block->mutex); if (buf_flush_ready_for_flush(block, flush_type)) { found = TRUE; space = block->space; offset = block->offset; mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); old_page_count = page_count; Loading @@ -871,10 +901,14 @@ buf_flush_batch( } else if (flush_type == BUF_FLUSH_LRU) { mutex_exit(&block->mutex); block = UT_LIST_GET_PREV(LRU, block); } else { ut_ad(flush_type == BUF_FLUSH_LIST); mutex_exit(&block->mutex); block = UT_LIST_GET_PREV(flush_list, block); } } Loading Loading @@ -951,10 +985,14 @@ buf_flush_LRU_recommendation(void) + BUF_FLUSH_EXTRA_MARGIN) && (distance < BUF_LRU_FREE_SEARCH_LEN)) { mutex_enter(&block->mutex); if (buf_flush_ready_for_replace(block)) { n_replaceable++; } mutex_exit(&block->mutex); distance++; block = UT_LIST_GET_PREV(LRU, block); Loading innobase/buf/buf0lru.c +24 −1 Original line number Diff line number Diff line Loading @@ -86,6 +86,9 @@ buf_LRU_invalidate_tablespace( block = UT_LIST_GET_LAST(buf_pool->LRU); while (block != NULL) { mutex_enter(&block->mutex); ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (block->space == id Loading @@ -112,6 +115,8 @@ buf_LRU_invalidate_tablespace( if (block->is_hashed) { page_no = block->offset; mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); /* Note that the following call will acquire Loading @@ -138,6 +143,7 @@ buf_LRU_invalidate_tablespace( buf_LRU_block_free_hashed_page(block); } next_page: mutex_exit(&block->mutex); block = UT_LIST_GET_PREV(LRU, block); } Loading Loading @@ -211,6 +217,9 @@ buf_LRU_search_and_free_block( while (block != NULL) { ut_a(block->in_LRU_list); mutex_enter(&block->mutex); if (buf_flush_ready_for_replace(block)) { if (buf_debug_prints) { Loading @@ -223,6 +232,7 @@ buf_LRU_search_and_free_block( buf_LRU_block_remove_hashed_page(block); mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); /* Remove possible adaptive hash index built on the page; in the case of AWE the block may not have a Loading @@ -231,15 +241,21 @@ buf_LRU_search_and_free_block( if (block->frame) { btr_search_drop_page_hash_index(block->frame); } mutex_enter(&(buf_pool->mutex)); ut_a(block->buf_fix_count == 0); mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); buf_LRU_block_free_hashed_page(block); freed = TRUE; mutex_exit(&block->mutex); break; } mutex_exit(&block->mutex); block = UT_LIST_GET_PREV(LRU, block); distance++; Loading Loading @@ -413,8 +429,12 @@ buf_LRU_get_free_block(void) } } mutex_enter(&block->mutex); block->state = BUF_BLOCK_READY_FOR_USE; mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); if (started_monitor) { Loading Loading @@ -815,6 +835,7 @@ buf_LRU_block_free_non_file_page( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad(block); Loading Loading @@ -854,6 +875,7 @@ buf_LRU_block_remove_hashed_page( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad(block); Loading Loading @@ -911,6 +933,7 @@ buf_LRU_block_free_hashed_page( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_a(block->state == BUF_BLOCK_REMOVE_HASH); Loading innobase/include/buf0buf.h +28 −12 Original line number Diff line number Diff line Loading @@ -455,8 +455,8 @@ Gets the mutex number protecting the page record lock hash chain in the lock table. */ UNIV_INLINE mutex_t* buf_frame_get_lock_mutex( /*=====================*/ buf_frame_get_mutex( /*================*/ /* out: mutex */ byte* ptr); /* in: pointer to within a buffer frame */ /*********************************************************************** Loading Loading @@ -699,7 +699,10 @@ struct buf_block_struct{ ulint magic_n; /* magic number to check */ ulint state; /* state of the control block: BUF_BLOCK_NOT_USED, ... */ BUF_BLOCK_NOT_USED, ...; changing this is only allowed when a thread has BOTH the buffer pool mutex AND block->mutex locked */ byte* frame; /* pointer to buffer frame which is of size UNIV_PAGE_SIZE, and aligned to an address divisible by Loading @@ -717,8 +720,12 @@ struct buf_block_struct{ ulint offset; /* page number within the space */ ulint lock_hash_val; /* hashed value of the page address in the record lock hash table */ mutex_t* lock_mutex; /* mutex protecting the chain in the record lock hash table */ mutex_t mutex; /* mutex protecting this block: state (also protected by the buffer pool mutex), io_fix, buf_fix_count, and accessed; we introduce this new mutex in InnoDB-5.1 to relieve contention on the buffer pool mutex */ rw_lock_t lock; /* read-write lock of the buffer frame */ buf_block_t* hash; /* node used in chaining to the page Loading Loading @@ -774,20 +781,27 @@ struct buf_block_struct{ in heuristic algorithms, because of the possibility of a wrap-around! */ ulint freed_page_clock;/* the value of freed_page_clock buffer pool when this block was last time put to the head of the LRU list */ of the buffer pool when this block was the last time put to the head of the LRU list; a thread is allowed to read this for heuristic purposes without holding any mutex or latch */ ibool old; /* TRUE if the block is in the old blocks in the LRU list */ ibool accessed; /* TRUE if the page has been accessed while in the buffer pool: read-ahead may read in pages which have not been accessed yet */ accessed yet; this is protected by block->mutex; a thread is allowed to read this for heuristic purposes without holding any mutex or latch */ ulint buf_fix_count; /* count of how manyfold this block is currently bufferfixed */ is currently bufferfixed; this is protected by block->mutex */ ulint io_fix; /* if a read is pending to the frame, io_fix is BUF_IO_READ, in the case of a write BUF_IO_WRITE, otherwise 0 */ of a write BUF_IO_WRITE, otherwise 0; this is protected by block->mutex */ /* 4. Optimistic search field */ dulint modify_clock; /* this clock is incremented every Loading Loading @@ -940,7 +954,9 @@ struct buf_pool_struct{ number of buffer blocks removed from the end of the LRU list; NOTE that this counter may wrap around at 4 billion! */ billion! A thread is allowed to read this for heuristic purposes without holding any mutex or latch */ ulint LRU_flush_ended;/* when an LRU flush ends for a page, this is incremented by one; this is set to zero when a buffer block is Loading innobase/include/buf0buf.ic +12 −7 Original line number Diff line number Diff line Loading @@ -333,8 +333,8 @@ Gets the mutex number protecting the page record lock hash chain in the lock table. */ UNIV_INLINE mutex_t* buf_frame_get_lock_mutex( /*=====================*/ buf_frame_get_mutex( /*================*/ /* out: mutex */ byte* ptr) /* in: pointer to within a buffer frame */ { Loading @@ -342,7 +342,7 @@ buf_frame_get_lock_mutex( block = buf_block_align(ptr); return(block->lock_mutex); return(&block->mutex); } /************************************************************************* Loading Loading @@ -521,6 +521,7 @@ buf_block_buf_fix_inc_debug( ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line); ut_ad(ret == TRUE); ut_ad(mutex_own(&block->mutex)); #endif block->buf_fix_count++; } Loading @@ -533,6 +534,9 @@ buf_block_buf_fix_inc( /*==================*/ buf_block_t* block) /* in: block to bufferfix */ { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&block->mutex)); #endif block->buf_fix_count++; } #endif /* UNIV_SYNC_DEBUG */ Loading Loading @@ -627,23 +631,24 @@ buf_page_release( ut_ad(block); mutex_enter_fast(&(buf_pool->mutex)); ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->buf_fix_count > 0); if (rw_latch == RW_X_LATCH && mtr->modifications) { mutex_enter(&buf_pool->mutex); buf_flush_note_modification(block, mtr); mutex_exit(&buf_pool->mutex); } mutex_enter(&block->mutex); #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif buf_fix_count = block->buf_fix_count; block->buf_fix_count = buf_fix_count - 1; mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); if (rw_latch == RW_S_LATCH) { rw_lock_s_unlock(&(block->lock)); Loading Loading
innobase/buf/buf0buf.c +115 −56 Original line number Diff line number Diff line Loading @@ -221,6 +221,9 @@ in the free list to the frames. 5) When we have AWE enabled, we disable adaptive hash indexes. */ /* Value in microseconds */ static const int WAIT_FOR_READ = 20000; buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */ ulint buf_dbg_counter = 0; /* This is used to insert validation Loading Loading @@ -466,6 +469,9 @@ buf_block_init( block->n_pointers = 0; mutex_create(&block->mutex); mutex_set_level(&block->mutex, SYNC_BUF_BLOCK); rw_lock_create(&(block->lock)); ut_ad(rw_lock_validate(&(block->lock))); Loading Loading @@ -734,8 +740,15 @@ buf_awe_map_page_to_frame( bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped); while (bck) { if (bck->state == BUF_BLOCK_FILE_PAGE && (bck->buf_fix_count != 0 || bck->io_fix != 0)) { ibool skip; mutex_enter(&bck->mutex); skip = (bck->state == BUF_BLOCK_FILE_PAGE && (bck->buf_fix_count != 0 || bck->io_fix != 0)); if (skip) { mutex_exit(&bck->mutex); /* We have to skip this */ bck = UT_LIST_GET_PREV(awe_LRU_free_mapped, bck); Loading Loading @@ -768,6 +781,8 @@ buf_awe_map_page_to_frame( buf_pool->n_pages_awe_remapped++; mutex_exit(&bck->mutex); return; } } Loading Loading @@ -806,13 +821,22 @@ buf_block_make_young( /*=================*/ buf_block_t* block) /* in: block to make younger */ { #ifdef UNIV_SYNC_DEBUG ut_ad(!mutex_own(&(buf_pool->mutex))); #endif /* UNIV_SYNC_DEBUG */ /* Note that we read freed_page_clock's without holding any mutex: this is allowed since the result is used only in heuristics */ if (buf_pool->freed_page_clock >= block->freed_page_clock + 1 + (buf_pool->curr_size / 1024)) { + 1 + (buf_pool->curr_size / 4)) { mutex_enter(&buf_pool->mutex); /* There has been freeing activity in the LRU list: best to move to the head of the LRU list */ buf_LRU_make_block_young(block); mutex_exit(&buf_pool->mutex); } } Loading Loading @@ -847,12 +871,16 @@ buf_block_free( /*===========*/ buf_block_t* block) /* in, own: block to be freed */ { ut_a(block->state != BUF_BLOCK_FILE_PAGE); mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); ut_a(block->state != BUF_BLOCK_FILE_PAGE); buf_LRU_block_free_non_file_page(block); mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); } Loading Loading @@ -1071,9 +1099,8 @@ buf_page_get_gen( #endif buf_pool->n_page_gets++; loop: mutex_enter_fast(&(buf_pool->mutex)); block = NULL; mutex_enter_fast(&(buf_pool->mutex)); if (guess) { block = buf_block_align(guess); Loading Loading @@ -1111,6 +1138,8 @@ buf_page_get_gen( goto loop; } mutex_enter(&block->mutex); ut_a(block->state == BUF_BLOCK_FILE_PAGE); must_read = FALSE; Loading @@ -1120,9 +1149,9 @@ buf_page_get_gen( must_read = TRUE; if (mode == BUF_GET_IF_IN_POOL) { /* The page is only being read to buffer */ mutex_exit(&(buf_pool->mutex)); mutex_exit(&buf_pool->mutex); mutex_exit(&block->mutex); return(NULL); } Loading @@ -1146,7 +1175,7 @@ buf_page_get_gen( #else buf_block_buf_fix_inc(block); #endif buf_block_make_young(block); mutex_exit(&buf_pool->mutex); /* Check if this is the first access to the page */ Loading @@ -1154,10 +1183,13 @@ buf_page_get_gen( block->accessed = TRUE; mutex_exit(&block->mutex); buf_block_make_young(block); #ifdef UNIV_DEBUG_FILE_ACCESSES ut_a(block->file_page_was_freed == FALSE); #endif mutex_exit(&(buf_pool->mutex)); #ifdef UNIV_DEBUG buf_dbg_counter++; Loading @@ -1182,13 +1214,14 @@ buf_page_get_gen( } if (!success) { mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); block->buf_fix_count--; mutex_exit(&block->mutex); #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif mutex_exit(&(buf_pool->mutex)); return(NULL); } Loading @@ -1199,18 +1232,16 @@ buf_page_get_gen( completes */ for (;;) { mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); if (block->io_fix == BUF_IO_READ) { mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); /* Sleep 20 milliseconds */ os_thread_sleep(20000); os_thread_sleep(WAIT_FOR_READ); } else { mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); break; } Loading Loading @@ -1269,13 +1300,13 @@ buf_page_optimistic_get_func( ut_ad(mtr && block); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); mutex_enter(&(buf_pool->mutex)); /* If AWE is used, block may have a different frame now, e.g., NULL */ mutex_enter(&block->mutex); if (block->state != BUF_BLOCK_FILE_PAGE || block->frame != guess) { mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); return(FALSE); } Loading @@ -1285,15 +1316,14 @@ buf_page_optimistic_get_func( #else buf_block_buf_fix_inc(block); #endif buf_block_make_young(block); /* Check if this is the first access to the page */ accessed = block->accessed; block->accessed = TRUE; mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); buf_block_make_young(block); /* Check if this is the first access to the page */ ut_ad(!ibuf_inside() || ibuf_page(block->space, block->offset)); Loading @@ -1308,14 +1338,15 @@ buf_page_optimistic_get_func( } if (!success) { mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); block->buf_fix_count--; mutex_exit(&block->mutex); #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif mutex_exit(&(buf_pool->mutex)); return(FALSE); } Loading @@ -1329,14 +1360,15 @@ buf_page_optimistic_get_func( rw_lock_x_unlock(&(block->lock)); } mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); block->buf_fix_count--; mutex_exit(&block->mutex); #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif mutex_exit(&(buf_pool->mutex)); return(FALSE); } Loading Loading @@ -1394,10 +1426,10 @@ buf_page_get_known_nowait( ut_ad(mtr); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); mutex_enter(&(buf_pool->mutex)); block = buf_block_align(guess); mutex_enter(&block->mutex); if (block->state == BUF_BLOCK_REMOVE_HASH) { /* Another thread is just freeing the block from the LRU list of the buffer pool: do not try to access this page; this Loading @@ -1406,7 +1438,7 @@ buf_page_get_known_nowait( we have already removed it from the page address hash table of the buffer pool. */ mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); return(FALSE); } Loading @@ -1418,12 +1450,12 @@ buf_page_get_known_nowait( #else buf_block_buf_fix_inc(block); #endif mutex_exit(&block->mutex); if (mode == BUF_MAKE_YOUNG) { buf_block_make_young(block); } mutex_exit(&(buf_pool->mutex)); ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD)); if (rw_latch == RW_S_LATCH) { Loading @@ -1437,13 +1469,15 @@ buf_page_get_known_nowait( } if (!success) { mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); block->buf_fix_count--; mutex_exit(&block->mutex); #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif mutex_exit(&(buf_pool->mutex)); return(FALSE); } Loading Loading @@ -1491,7 +1525,6 @@ buf_page_init_for_backup_restore( block->offset = offset; block->lock_hash_val = 0; block->lock_mutex = NULL; block->freed_page_clock = 0; Loading Loading @@ -1524,6 +1557,7 @@ buf_page_init( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(block->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_a(block->state != BUF_BLOCK_FILE_PAGE); Loading @@ -1537,7 +1571,6 @@ buf_page_init( block->check_index_page_at_flush = FALSE; block->lock_hash_val = lock_rec_hash(space, offset); block->lock_mutex = NULL; /* Insert into the hash table of file pages */ Loading Loading @@ -1630,6 +1663,7 @@ buf_page_init_for_read( ut_a(block); mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); if (fil_tablespace_deleted_or_being_deleted_in_mem(space, tablespace_version)) { Loading @@ -1642,7 +1676,9 @@ buf_page_init_for_read( /* The page belongs to a space which has been deleted or is being deleted, or the page is already in buf_pool, return */ mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); buf_block_free(block); if (mode == BUF_READ_IBUF_PAGES_ONLY) { Loading @@ -1662,6 +1698,7 @@ buf_page_init_for_read( buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */ block->io_fix = BUF_IO_READ; buf_pool->n_pend_reads++; /* We set a pass-type x-lock on the frame because then the same Loading @@ -1673,6 +1710,7 @@ buf_page_init_for_read( rw_lock_x_lock_gen(&(block->lock), BUF_IO_READ); mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); if (mode == BUF_READ_IBUF_PAGES_ONLY) { Loading Loading @@ -1735,6 +1773,8 @@ buf_page_create( block = free_block; mutex_enter(&block->mutex); buf_page_init(space, offset, block); /* The block must be put to the LRU list */ Loading @@ -1745,13 +1785,15 @@ buf_page_create( #else buf_block_buf_fix_inc(block); #endif buf_pool->n_pages_created++; mutex_exit(&(buf_pool->mutex)); mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX); block->accessed = TRUE; buf_pool->n_pages_created++; mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); /* Delete possible entries for the page from the insert buffer: such can exist if the page belonged to an index which was dropped */ Loading Loading @@ -1800,6 +1842,12 @@ buf_page_io_complete( ut_a(block->state == BUF_BLOCK_FILE_PAGE); /* We do not need protect block->io_fix here by block->mutex to read it because this is the only function where we can change the value from BUF_IO_READ or BUF_IO_WRITE to some other value, and our code ensures that this is the only thread that handles the i/o for this block. */ io_type = block->io_fix; if (io_type == BUF_IO_READ) { Loading Loading @@ -1868,11 +1916,12 @@ buf_page_io_complete( } } mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); #ifdef UNIV_IBUF_DEBUG ut_a(ibuf_count_get(block->space, block->offset) == 0); #endif mutex_enter(&(buf_pool->mutex)); /* Because this thread which does the unlocking is not the same that did the locking, we use a pass value != 0 in unlock, which simply removes the newest lock debug record, without checking the thread Loading Loading @@ -1911,6 +1960,7 @@ buf_page_io_complete( } } mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); if (buf_debug_prints) { Loading Loading @@ -1970,6 +2020,8 @@ buf_validate(void) block = buf_pool_get_nth_block(buf_pool, i); mutex_enter(&block->mutex); if (block->state == BUF_BLOCK_FILE_PAGE) { ut_a(buf_page_hash_get(block->space, Loading Loading @@ -2013,6 +2065,8 @@ buf_validate(void) } else if (block->state == BUF_BLOCK_NOT_USED) { n_free++; } mutex_exit(&block->mutex); } if (n_lru + n_free > buf_pool->curr_size) { Loading Loading @@ -2303,16 +2357,21 @@ buf_all_freed(void) block = buf_pool_get_nth_block(buf_pool, i); mutex_enter(&block->mutex); if (block->state == BUF_BLOCK_FILE_PAGE) { if (!buf_flush_ready_for_replace(block)) { fprintf(stderr, "Page %lu %lu still fixed or dirty\n", (ulong) block->space, (ulong) block->offset); (ulong) block->space, (ulong) block->offset); ut_error; } } mutex_exit(&block->mutex); } mutex_exit(&(buf_pool->mutex)); Loading
innobase/buf/buf0flu.c +65 −27 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ buf_flush_ready_for_replace( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ if (block->state != BUF_BLOCK_FILE_PAGE) { ut_print_timestamp(stderr); Loading Loading @@ -148,6 +149,7 @@ buf_flush_ready_for_flush( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(block->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_a(block->state == BUF_BLOCK_FILE_PAGE); Loading Loading @@ -533,8 +535,15 @@ buf_flush_try_page( ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); if (!block) { mutex_exit(&(buf_pool->mutex)); return(0); } mutex_enter(&block->mutex); if (flush_type == BUF_FLUSH_LIST && block && buf_flush_ready_for_flush(block, flush_type)) { && buf_flush_ready_for_flush(block, flush_type)) { block->io_fix = BUF_IO_WRITE; Loading Loading @@ -572,6 +581,7 @@ buf_flush_try_page( locked = TRUE; } mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); if (!locked) { Loading @@ -590,7 +600,7 @@ buf_flush_try_page( return(1); } else if (flush_type == BUF_FLUSH_LRU && block } else if (flush_type == BUF_FLUSH_LRU && buf_flush_ready_for_flush(block, flush_type)) { /* VERY IMPORTANT: Loading Loading @@ -631,13 +641,14 @@ buf_flush_try_page( buf_pool mutex: this ensures that the latch is acquired immediately. */ mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); buf_flush_write_block_low(block); return(1); } else if (flush_type == BUF_FLUSH_SINGLE_PAGE && block } else if (flush_type == BUF_FLUSH_SINGLE_PAGE && buf_flush_ready_for_flush(block, flush_type)) { block->io_fix = BUF_IO_WRITE; Loading @@ -664,6 +675,7 @@ buf_flush_try_page( (buf_pool->n_flush[flush_type])++; mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE); Loading @@ -678,12 +690,13 @@ buf_flush_try_page( buf_flush_write_block_low(block); return(1); } else { } mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); return(0); } } /*************************************************************** Flushes to disk all flushable pages within the flush area. */ Loading Loading @@ -727,34 +740,48 @@ buf_flush_try_neighbors( block = buf_page_hash_get(space, i); ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); if (block && flush_type == BUF_FLUSH_LRU && i != offset if (!block) { continue; } else if (flush_type == BUF_FLUSH_LRU && i != offset && !block->old) { /* We avoid flushing 'non-old' blocks in an LRU flush, because the flushed blocks are soon freed */ continue; } } else { mutex_enter(&block->mutex); if (block && buf_flush_ready_for_flush(block, flush_type) if (buf_flush_ready_for_flush(block, flush_type) && (i == offset || block->buf_fix_count == 0)) { /* We only try to flush those neighbors != offset where the buf fix count is zero, as we then know that we probably can latch the page without a semaphore wait. Semaphore waits are expensive because we must /* We only try to flush those neighbors != offset where the buf fix count is zero, as we then know that we probably can latch the page without a semaphore wait. Semaphore waits are expensive because we must flush the doublewrite buffer before we start waiting. */ mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); /* Note: as we release the buf_pool mutex above, in buf_flush_try_page we cannot be sure the page is still in a flushable state: therefore we check it again inside that function. */ /* Note: as we release the buf_pool mutex above, in buf_flush_try_page we cannot be sure the page is still in a flushable state: therefore we check it again inside that function. */ count += buf_flush_try_page(space, i, flush_type); count += buf_flush_try_page(space, i, flush_type); mutex_enter(&(buf_pool->mutex)); } else { mutex_exit(&block->mutex); } } } Loading Loading @@ -848,12 +875,15 @@ buf_flush_batch( while ((block != NULL) && !found) { ut_a(block->state == BUF_BLOCK_FILE_PAGE); mutex_enter(&block->mutex); if (buf_flush_ready_for_flush(block, flush_type)) { found = TRUE; space = block->space; offset = block->offset; mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); old_page_count = page_count; Loading @@ -871,10 +901,14 @@ buf_flush_batch( } else if (flush_type == BUF_FLUSH_LRU) { mutex_exit(&block->mutex); block = UT_LIST_GET_PREV(LRU, block); } else { ut_ad(flush_type == BUF_FLUSH_LIST); mutex_exit(&block->mutex); block = UT_LIST_GET_PREV(flush_list, block); } } Loading Loading @@ -951,10 +985,14 @@ buf_flush_LRU_recommendation(void) + BUF_FLUSH_EXTRA_MARGIN) && (distance < BUF_LRU_FREE_SEARCH_LEN)) { mutex_enter(&block->mutex); if (buf_flush_ready_for_replace(block)) { n_replaceable++; } mutex_exit(&block->mutex); distance++; block = UT_LIST_GET_PREV(LRU, block); Loading
innobase/buf/buf0lru.c +24 −1 Original line number Diff line number Diff line Loading @@ -86,6 +86,9 @@ buf_LRU_invalidate_tablespace( block = UT_LIST_GET_LAST(buf_pool->LRU); while (block != NULL) { mutex_enter(&block->mutex); ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (block->space == id Loading @@ -112,6 +115,8 @@ buf_LRU_invalidate_tablespace( if (block->is_hashed) { page_no = block->offset; mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); /* Note that the following call will acquire Loading @@ -138,6 +143,7 @@ buf_LRU_invalidate_tablespace( buf_LRU_block_free_hashed_page(block); } next_page: mutex_exit(&block->mutex); block = UT_LIST_GET_PREV(LRU, block); } Loading Loading @@ -211,6 +217,9 @@ buf_LRU_search_and_free_block( while (block != NULL) { ut_a(block->in_LRU_list); mutex_enter(&block->mutex); if (buf_flush_ready_for_replace(block)) { if (buf_debug_prints) { Loading @@ -223,6 +232,7 @@ buf_LRU_search_and_free_block( buf_LRU_block_remove_hashed_page(block); mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); /* Remove possible adaptive hash index built on the page; in the case of AWE the block may not have a Loading @@ -231,15 +241,21 @@ buf_LRU_search_and_free_block( if (block->frame) { btr_search_drop_page_hash_index(block->frame); } mutex_enter(&(buf_pool->mutex)); ut_a(block->buf_fix_count == 0); mutex_enter(&(buf_pool->mutex)); mutex_enter(&block->mutex); buf_LRU_block_free_hashed_page(block); freed = TRUE; mutex_exit(&block->mutex); break; } mutex_exit(&block->mutex); block = UT_LIST_GET_PREV(LRU, block); distance++; Loading Loading @@ -413,8 +429,12 @@ buf_LRU_get_free_block(void) } } mutex_enter(&block->mutex); block->state = BUF_BLOCK_READY_FOR_USE; mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); if (started_monitor) { Loading Loading @@ -815,6 +835,7 @@ buf_LRU_block_free_non_file_page( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad(block); Loading Loading @@ -854,6 +875,7 @@ buf_LRU_block_remove_hashed_page( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad(block); Loading Loading @@ -911,6 +933,7 @@ buf_LRU_block_free_hashed_page( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_a(block->state == BUF_BLOCK_REMOVE_HASH); Loading
innobase/include/buf0buf.h +28 −12 Original line number Diff line number Diff line Loading @@ -455,8 +455,8 @@ Gets the mutex number protecting the page record lock hash chain in the lock table. */ UNIV_INLINE mutex_t* buf_frame_get_lock_mutex( /*=====================*/ buf_frame_get_mutex( /*================*/ /* out: mutex */ byte* ptr); /* in: pointer to within a buffer frame */ /*********************************************************************** Loading Loading @@ -699,7 +699,10 @@ struct buf_block_struct{ ulint magic_n; /* magic number to check */ ulint state; /* state of the control block: BUF_BLOCK_NOT_USED, ... */ BUF_BLOCK_NOT_USED, ...; changing this is only allowed when a thread has BOTH the buffer pool mutex AND block->mutex locked */ byte* frame; /* pointer to buffer frame which is of size UNIV_PAGE_SIZE, and aligned to an address divisible by Loading @@ -717,8 +720,12 @@ struct buf_block_struct{ ulint offset; /* page number within the space */ ulint lock_hash_val; /* hashed value of the page address in the record lock hash table */ mutex_t* lock_mutex; /* mutex protecting the chain in the record lock hash table */ mutex_t mutex; /* mutex protecting this block: state (also protected by the buffer pool mutex), io_fix, buf_fix_count, and accessed; we introduce this new mutex in InnoDB-5.1 to relieve contention on the buffer pool mutex */ rw_lock_t lock; /* read-write lock of the buffer frame */ buf_block_t* hash; /* node used in chaining to the page Loading Loading @@ -774,20 +781,27 @@ struct buf_block_struct{ in heuristic algorithms, because of the possibility of a wrap-around! */ ulint freed_page_clock;/* the value of freed_page_clock buffer pool when this block was last time put to the head of the LRU list */ of the buffer pool when this block was the last time put to the head of the LRU list; a thread is allowed to read this for heuristic purposes without holding any mutex or latch */ ibool old; /* TRUE if the block is in the old blocks in the LRU list */ ibool accessed; /* TRUE if the page has been accessed while in the buffer pool: read-ahead may read in pages which have not been accessed yet */ accessed yet; this is protected by block->mutex; a thread is allowed to read this for heuristic purposes without holding any mutex or latch */ ulint buf_fix_count; /* count of how manyfold this block is currently bufferfixed */ is currently bufferfixed; this is protected by block->mutex */ ulint io_fix; /* if a read is pending to the frame, io_fix is BUF_IO_READ, in the case of a write BUF_IO_WRITE, otherwise 0 */ of a write BUF_IO_WRITE, otherwise 0; this is protected by block->mutex */ /* 4. Optimistic search field */ dulint modify_clock; /* this clock is incremented every Loading Loading @@ -940,7 +954,9 @@ struct buf_pool_struct{ number of buffer blocks removed from the end of the LRU list; NOTE that this counter may wrap around at 4 billion! */ billion! A thread is allowed to read this for heuristic purposes without holding any mutex or latch */ ulint LRU_flush_ended;/* when an LRU flush ends for a page, this is incremented by one; this is set to zero when a buffer block is Loading
innobase/include/buf0buf.ic +12 −7 Original line number Diff line number Diff line Loading @@ -333,8 +333,8 @@ Gets the mutex number protecting the page record lock hash chain in the lock table. */ UNIV_INLINE mutex_t* buf_frame_get_lock_mutex( /*=====================*/ buf_frame_get_mutex( /*================*/ /* out: mutex */ byte* ptr) /* in: pointer to within a buffer frame */ { Loading @@ -342,7 +342,7 @@ buf_frame_get_lock_mutex( block = buf_block_align(ptr); return(block->lock_mutex); return(&block->mutex); } /************************************************************************* Loading Loading @@ -521,6 +521,7 @@ buf_block_buf_fix_inc_debug( ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line); ut_ad(ret == TRUE); ut_ad(mutex_own(&block->mutex)); #endif block->buf_fix_count++; } Loading @@ -533,6 +534,9 @@ buf_block_buf_fix_inc( /*==================*/ buf_block_t* block) /* in: block to bufferfix */ { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&block->mutex)); #endif block->buf_fix_count++; } #endif /* UNIV_SYNC_DEBUG */ Loading Loading @@ -627,23 +631,24 @@ buf_page_release( ut_ad(block); mutex_enter_fast(&(buf_pool->mutex)); ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->buf_fix_count > 0); if (rw_latch == RW_X_LATCH && mtr->modifications) { mutex_enter(&buf_pool->mutex); buf_flush_note_modification(block, mtr); mutex_exit(&buf_pool->mutex); } mutex_enter(&block->mutex); #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif buf_fix_count = block->buf_fix_count; block->buf_fix_count = buf_fix_count - 1; mutex_exit(&(buf_pool->mutex)); mutex_exit(&block->mutex); if (rw_latch == RW_S_LATCH) { rw_lock_s_unlock(&(block->lock)); Loading