#At file:///home/inaam/w/page_hash_rw/ based on revid:jimmy.yang@stripped
3368 Inaam Rana 2010-12-08
WL5664 InnoDB: Use rw_locks for page_hash
Approved by: Marko rb://507
* Use rw_locks instead of mutexes to protect buffer pool page_hash.
* innodb_page_hash_mutexes is now changed to innodb_page_hash_locks
and the default value is 16 instead of 256
* introduce new UNIV_PERF_DEBUG. innodb_page_hash_locks is on settable
and visible when UNIV_PERF_DEBUG or UNIV_DEBUG is set
- hash table is now of three types based on the type of synchronization
.objects used for the access i.e.: NONE, MUTEX, LOCKS.
- New field ::type added to hash table struct
- ::n_mutexes replaced by ::n_sync_obj
- ::mutexes array is replaced by a union of mutex_t* and rw_lock_t*
- New functions added to hash table implementation
+# define hash_lock_s(t, f)
+# define hash_lock_x(t, f)
+# define hash_unlock_s(t, f)
+# define hash_unlock_x(t, f)
+# define hash_lock_x_all(t)
+# define hash_unlock_x_all(t)
+# define hash_unlock_x_all_but(t, l)
- Two new inline debug functions hash_assert_can_modify() and
hash_assert_can_search() to replace the macro ASSERT_HASH_MUTEX_OWN.
- buf_page_hash_get() and buf_block_hash_get() changed to
buf_page_hash_get_locked() and buf_block_hash_get_locked()
respectively:
- Both functions now return a pointer to the rw_lock that is held.
If NULL is passed then the lock is released just like mutex before.
- Both functions take a new parameter lock_mode to tell if the lock
is to be held in x or s mode.
- macros to access the above functions:
+#define buf_page_hash_get_s_locked(b, s, o, l) \
+ buf_page_hash_get_locked(b, s, o, l, RW_LOCK_SHARED)
+#define buf_page_hash_get_x_locked(b, s, o, l) \
+ buf_page_hash_get_locked(b, s, o, l, RW_LOCK_EX)
+#define buf_page_hash_get(b, s, o) \
+ buf_page_hash_get_locked(b, s, o, NULL, 0)
- innodb_page_hash_mutexees changed to innodb_page_hash_locks which is
only enabled when UNIV_DEBUG or a new macro UNIV_PERF_DEBUG is
enabled. Default value is set to 16.
- buf_pool_watch_occurred() get s-lock in place of hash_mutex.
- buf_page_get_gen() replace hash_mutex with following:
- get s-lock when the page is in the buffer pool. This is the most
typical case.
- get x-lock if a watch has to be set
- get x-lock if we need to decompress a compressed page
- for all other occurrences of hash_mutex replace them with x-lock
removed:
mysql-test/suite/sys_vars/r/innodb_page_hash_mutexes_basic.result
mysql-test/suite/sys_vars/t/innodb_page_hash_mutexes_basic.test
modified:
mysql-test/suite/sys_vars/r/all_vars.result
mysql-test/suite/sys_vars/t/all_vars.test
storage/innobase/btr/btr0sea.c
storage/innobase/buf/buf0buddy.c
storage/innobase/buf/buf0buf.c
storage/innobase/buf/buf0flu.c
storage/innobase/buf/buf0lru.c
storage/innobase/buf/buf0rea.c
storage/innobase/ha/ha0ha.c
storage/innobase/ha/hash0hash.c
storage/innobase/handler/ha_innodb.cc
storage/innobase/ibuf/ibuf0ibuf.c
storage/innobase/include/buf0buf.h
storage/innobase/include/buf0buf.ic
storage/innobase/include/ha0ha.h
storage/innobase/include/ha0ha.ic
storage/innobase/include/hash0hash.h
storage/innobase/include/hash0hash.ic
storage/innobase/include/srv0srv.h
storage/innobase/include/sync0sync.h
storage/innobase/include/univ.i
storage/innobase/srv/srv0srv.c
storage/innobase/sync/sync0sync.c
=== modified file 'mysql-test/suite/sys_vars/r/all_vars.result'
--- a/mysql-test/suite/sys_vars/r/all_vars.result revid:jimmy.yang@stripped
+++ b/mysql-test/suite/sys_vars/r/all_vars.result revid:inaam.rana@stripped
@@ -4,6 +4,7 @@ load data infile "MYSQLTEST_VARDIR/tmp/s
insert into t2 select variable_name from information_schema.global_variables;
insert into t2 select variable_name from information_schema.session_variables;
delete from t2 where variable_name='innodb_change_buffering_debug';
+delete from t2 where variable_name='innodb_page_hash_locks';
update t2 set variable_name= replace(variable_name, "PERFORMANCE_SCHEMA_", "PFS_");
select variable_name as `There should be *no* long test name listed below:` from t2
where length(variable_name) > 50;
=== removed file 'mysql-test/suite/sys_vars/r/innodb_page_hash_mutexes_basic.result'
--- a/mysql-test/suite/sys_vars/r/innodb_page_hash_mutexes_basic.result revid:jimmy.yang@stripped
+++ b/mysql-test/suite/sys_vars/r/innodb_page_hash_mutexes_basic.result 1970-01-01 00:00:00 +0000
@@ -1,21 +0,0 @@
-select @@global.innodb_page_hash_mutexes;
-@@global.innodb_page_hash_mutexes
-256
-select @@session.innodb_page_hash_mutexes;
-ERROR HY000: Variable 'innodb_page_hash_mutexes' is a GLOBAL variable
-show global variables like 'innodb_page_hash_mutexes';
-Variable_name Value
-innodb_page_hash_mutexes 256
-show session variables like 'innodb_page_hash_mutexes';
-Variable_name Value
-innodb_page_hash_mutexes 256
-select * from information_schema.global_variables where variable_name='innodb_page_hash_mutexes';
-VARIABLE_NAME VARIABLE_VALUE
-INNODB_PAGE_HASH_MUTEXES 256
-select * from information_schema.session_variables where variable_name='innodb_page_hash_mutexes';
-VARIABLE_NAME VARIABLE_VALUE
-INNODB_PAGE_HASH_MUTEXES 256
-set global innodb_page_hash_mutexes=1;
-ERROR HY000: Variable 'innodb_page_hash_mutexes' is a read only variable
-set session innodb_page_hash_mutexes=1;
-ERROR HY000: Variable 'innodb_page_hash_mutexes' is a read only variable
=== modified file 'mysql-test/suite/sys_vars/t/all_vars.test'
--- a/mysql-test/suite/sys_vars/t/all_vars.test revid:jimmy.yang@stripped
+++ b/mysql-test/suite/sys_vars/t/all_vars.test revid:inaam.rana@stripped
@@ -66,8 +66,9 @@ eval load data infile "$MYSQLTEST_VARDIR
insert into t2 select variable_name from information_schema.global_variables;
insert into t2 select variable_name from information_schema.session_variables;
-# This is only present in debug builds.
+# These are only present in debug builds.
delete from t2 where variable_name='innodb_change_buffering_debug';
+delete from t2 where variable_name='innodb_page_hash_locks';
# Performance schema variables are too long for files named
# 'mysql-test/suite/sys_vars/t/' ...
=== removed file 'mysql-test/suite/sys_vars/t/innodb_page_hash_mutexes_basic.test'
--- a/mysql-test/suite/sys_vars/t/innodb_page_hash_mutexes_basic.test revid:jimmy.yang@stripped
+++ b/mysql-test/suite/sys_vars/t/innodb_page_hash_mutexes_basic.test 1970-01-01 00:00:00 +0000
@@ -1,20 +0,0 @@
---source include/have_innodb.inc
-
-#
-# show the global and session values;
-#
-select @@global.innodb_page_hash_mutexes;
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
-select @@session.innodb_page_hash_mutexes;
-show global variables like 'innodb_page_hash_mutexes';
-show session variables like 'innodb_page_hash_mutexes';
-select * from information_schema.global_variables where variable_name='innodb_page_hash_mutexes';
-select * from information_schema.session_variables where variable_name='innodb_page_hash_mutexes';
-
-#
-# show that it's read-only
-#
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
-set global innodb_page_hash_mutexes=1;
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
-set session innodb_page_hash_mutexes=1;
=== modified file 'storage/innobase/btr/btr0sea.c'
--- a/storage/innobase/btr/btr0sea.c revid:jimmy.yang@stripped
+++ b/storage/innobase/btr/btr0sea.c revid:inaam.rana@stripped
@@ -1821,8 +1821,7 @@ btr_search_validate(void)
hash_block = buf_block_hash_get(
buf_pool,
buf_block_get_space(block),
- buf_block_get_page_no(block),
- NULL);
+ buf_block_get_page_no(block));
} else {
hash_block = NULL;
}
=== modified file 'storage/innobase/buf/buf0buddy.c'
--- a/storage/innobase/buf/buf0buddy.c revid:jimmy.yang@stripped
+++ b/storage/innobase/buf/buf0buddy.c revid:inaam.rana@stripped
@@ -356,7 +356,7 @@ buf_buddy_relocate_block(
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
ulint fold = buf_page_address_fold(bpage->space,
bpage->offset);
- mutex_t* hash_mutex = buf_page_hash_mutex_get(buf_pool, fold);
+ rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold);
ut_ad(buf_pool_mutex_own(buf_pool));
@@ -376,11 +376,11 @@ buf_buddy_relocate_block(
break;
}
- mutex_enter(hash_mutex);
+ rw_lock_x_lock(hash_lock);
mutex_enter(&buf_pool->zip_mutex);
if (!buf_page_can_relocate(bpage)) {
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
mutex_exit(&buf_pool->zip_mutex);
return(FALSE);
}
@@ -400,7 +400,7 @@ buf_buddy_relocate_block(
UNIV_MEM_INVALID(bpage, sizeof *bpage);
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
mutex_exit(&buf_pool->zip_mutex);
return(TRUE);
}
@@ -460,7 +460,7 @@ buf_buddy_relocate(
on uninitialized value. */
UNIV_MEM_VALID(&space, sizeof space);
UNIV_MEM_VALID(&page_no, sizeof page_no);
- bpage = buf_page_hash_get(buf_pool, space, page_no, NULL);
+ bpage = buf_page_hash_get(buf_pool, space, page_no);
if (!bpage || bpage->zip.data != src) {
/* The block has probably been freshly
=== modified file 'storage/innobase/buf/buf0buf.c'
--- a/storage/innobase/buf/buf0buf.c revid:jimmy.yang@stripped
+++ b/storage/innobase/buf/buf0buf.c revid:inaam.rana@stripped
@@ -1248,15 +1248,15 @@ buf_pool_init_instance(
buf_pool->curr_size = chunk->size;
buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
- /* Number of mutexes portecting page_hash must be a
+ /* Number of locks portecting page_hash must be a
power of two */
- srv_n_page_hash_mutexes =
- ut_2_power_up(srv_n_page_hash_mutexes);
- ut_a(srv_n_page_hash_mutexes != 0);
- ut_a(srv_n_page_hash_mutexes <= MAX_PAGE_HASH_MUTEXES);
+ srv_n_page_hash_locks =
+ ut_2_power_up(srv_n_page_hash_locks);
+ ut_a(srv_n_page_hash_locks != 0);
+ ut_a(srv_n_page_hash_locks <= MAX_PAGE_HASH_LOCKS);
buf_pool->page_hash = ha_create(2 * buf_pool->curr_size,
- srv_n_page_hash_mutexes,
+ srv_n_page_hash_locks,
MEM_HEAP_FOR_PAGE_HASH,
SYNC_BUF_PAGE_HASH);
@@ -1497,7 +1497,7 @@ buf_relocate(
fold = buf_page_address_fold(bpage->space, bpage->offset);
ut_ad(buf_pool_mutex_own(buf_pool));
- ut_ad(buf_page_hash_mutex_own(buf_pool, bpage));
+ ut_ad(buf_page_hash_lock_held_x(buf_pool, bpage));
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
ut_a(bpage->buf_fix_count == 0);
@@ -1760,25 +1760,25 @@ buf_pool_page_hash_rebuild_instance(
buf_pool_mutex_enter(buf_pool);
- hash_mutex_enter_all(buf_pool->page_hash);
+ hash_lock_x_all(buf_pool->page_hash);
/* Free, create, and populate the hash table. */
ha_clear(buf_pool->page_hash);
/*FIXME: This is broken. When we free the hash_table we
- free the mutex array as well. We either have to have a
+ free the sync_obj array as well. We either have to have a
mechanism where it is guaranteed that nobody will try to
- acquire any of the page_hash mutexes or think some other
+ acquire any of the page_hash locks or think some other
way to implement this. It doesn't matter as of now because
buffer pool resize code is not used currently. */
hash_table_free(buf_pool->page_hash);
- ut_a(srv_n_page_hash_mutexes != 0);
- ut_a(srv_n_page_hash_mutexes <= MAX_PAGE_HASH_MUTEXES);
+ ut_a(srv_n_page_hash_locks != 0);
+ ut_a(srv_n_page_hash_locks <= MAX_PAGE_HASH_LOCKS);
buf_pool->page_hash = page_hash
= ha_create(2 * buf_pool->curr_size,
- srv_n_page_hash_mutexes,
+ srv_n_page_hash_locks,
MEM_HEAP_FOR_PAGE_HASH,
SYNC_BUF_PAGE_HASH);
@@ -1858,7 +1858,7 @@ buf_pool_page_hash_rebuild_instance(
}
}
- hash_mutex_exit_all(buf_pool->page_hash);
+ hash_unlock_x_all(buf_pool->page_hash);
buf_flush_list_mutex_exit(buf_pool);
buf_pool_mutex_exit(buf_pool);
}
@@ -1873,13 +1873,8 @@ buf_pool_watch_is_sentinel(
buf_pool_t* buf_pool, /*!< buffer pool instance */
const buf_page_t* bpage) /*!< in: block */
{
-#ifdef UNIV_DEBUG
- /* We must also own the appropriate hash_bucket mutex. */
- ulint fold = buf_page_address_fold(bpage->space,
- bpage->offset);
- mutex_t* hash_mutex = buf_page_hash_mutex_get(buf_pool, fold);
- ut_ad(mutex_own(hash_mutex));
-#endif
+ /* We must also own the appropriate hash lock. */
+ ut_ad(buf_page_hash_lock_held_s_or_x(buf_pool, bpage));
ut_ad(buf_page_in_file(bpage));
if (bpage < &buf_pool->watch[0]
@@ -1901,8 +1896,8 @@ buf_pool_watch_is_sentinel(
/****************************************************************//**
Add watch for the given page to be read in. Caller must have
-appropriate hash_mutex for the bpage. This function may release the
-hash_mutex and reacquire it.
+appropriate hash_lock for the bpage. This function may release the
+hash_lock and reacquire it.
@return NULL if watch set, block if the page is in the buffer pool */
UNIV_INTERN
buf_page_t*
@@ -1915,11 +1910,13 @@ buf_pool_watch_set(
buf_page_t* bpage;
ulint i;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
- mutex_t* hash_mutex;
+ rw_lock_t* hash_lock;
- hash_mutex = buf_page_hash_mutex_get(buf_pool, fold);
+ hash_lock = buf_page_hash_lock_get(buf_pool, fold);
- ut_ad(mutex_own(hash_mutex));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(hash_lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
@@ -1936,29 +1933,29 @@ page_found:
/* From this point this function becomes fairly heavy in terms
of latching. We acquire the buf_pool mutex as well as all the
- hash_mutexes. buf_pool mutex is needed because any changes to
- the page_hash must be covered by it and hash_mutexes are needed
+ hash_locks. buf_pool mutex is needed because any changes to
+ the page_hash must be covered by it and hash_locks are needed
because we don't want to read any stale information in
buf_pool->watch[]. However, it is not in the critical code path
as this function will be called only by the purge thread. */
- /* To obey latching order first release the hash_mutex. */
- mutex_exit(hash_mutex);
+ /* To obey latching order first release the hash_lock. */
+ rw_lock_x_unlock(hash_lock);
buf_pool_mutex_enter(buf_pool);
- hash_mutex_enter_all(buf_pool->page_hash);
+ hash_lock_x_all(buf_pool->page_hash);
/* We have to recheck that the page
was not loaded or a watch set by some other
purge thread. This is because of the small
time window between when we release the
- hash_mutex to acquire buf_pool mutex above. */
+ hash_lock to acquire buf_pool mutex above. */
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
if (UNIV_LIKELY_NULL(bpage)) {
buf_pool_mutex_exit(buf_pool);
- hash_mutex_exit_all_but(buf_pool->page_hash, hash_mutex);
+ hash_unlock_x_all_but(buf_pool->page_hash, hash_lock);
goto page_found;
}
@@ -1992,10 +1989,10 @@ page_found:
buf_pool_mutex_exit(buf_pool);
/* Once the sentinel is in the page_hash we can
- safely release all mutexes except just the
- relevant hash_mutex */
- hash_mutex_exit_all_but(buf_pool->page_hash,
- hash_mutex);
+ safely release all locks except just the
+ relevant hash_lock */
+ hash_unlock_x_all_but(buf_pool->page_hash,
+ hash_lock);
return(NULL);
case BUF_BLOCK_ZIP_PAGE:
@@ -2148,11 +2145,11 @@ buf_pool_watch_remove(
space, offset) */
buf_page_t* watch) /*!< in/out: sentinel for watch */
{
-#ifdef UNIV_DEBUG
+#ifdef UNIV_SYNC_DEBUG
/* We must also own the appropriate hash_bucket mutex. */
- mutex_t* hash_mutex = buf_page_hash_mutex_get(buf_pool, fold);
- ut_ad(mutex_own(hash_mutex));
-#endif
+ rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold);
+ ut_ad(rw_lock_own(hash_lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(buf_pool_mutex_own(buf_pool));
@@ -2175,17 +2172,17 @@ buf_pool_watch_unset(
buf_page_t* bpage;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
ulint fold = buf_page_address_fold(space, offset);
- mutex_t* hash_mutex = buf_page_hash_mutex_get(buf_pool,
+ rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool,
fold);
/* We only need to have buf_pool mutex in case where we end
up calling buf_pool_watch_remove but to obey latching order
- we acquire it here before acquiring hash_mutex. This should
+ we acquire it here before acquiring hash_lock. This should
not cause too much grief as this function is only ever
called from the purge thread. */
buf_pool_mutex_enter(buf_pool);
- mutex_enter(hash_mutex);
+ rw_lock_x_lock(hash_lock);
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
/* The page must exist because buf_pool_watch_set()
@@ -2208,7 +2205,7 @@ buf_pool_watch_unset(
}
buf_pool_mutex_exit(buf_pool);
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
}
/****************************************************************//**
@@ -2227,17 +2224,17 @@ buf_pool_watch_occurred(
buf_page_t* bpage;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
ulint fold = buf_page_address_fold(space, offset);
- mutex_t* hash_mutex = buf_page_hash_mutex_get(buf_pool,
+ rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool,
fold);
- mutex_enter(hash_mutex);
+ rw_lock_s_lock(hash_lock);
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
/* The page must exist because buf_pool_watch_set()
increments buf_fix_count. */
ut_a(bpage);
ret = !buf_pool_watch_is_sentinel(buf_pool, bpage);
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
return(ret);
}
@@ -2307,9 +2304,10 @@ buf_reset_check_index_page_at_flush(
{
buf_block_t* block;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
- mutex_t* hash_mutex;
+ rw_lock_t* hash_lock;
- block = buf_block_hash_get(buf_pool, space, offset, &hash_mutex);
+ block = buf_block_hash_get_s_locked(buf_pool, space, offset,
+ &hash_lock);
if (block) {
if (buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
@@ -2318,7 +2316,7 @@ buf_reset_check_index_page_at_flush(
block->check_index_page_at_flush = FALSE;
}
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
}
}
@@ -2337,9 +2335,10 @@ buf_page_peek_if_search_hashed(
buf_block_t* block;
ibool is_hashed;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
- mutex_t* hash_mutex;
+ rw_lock_t* hash_lock;
- block = buf_block_hash_get(buf_pool, space, offset, &hash_mutex);
+ block = buf_block_hash_get_s_locked(buf_pool, space, offset,
+ &hash_lock);
if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
is_hashed = FALSE;
@@ -2349,7 +2348,7 @@ buf_page_peek_if_search_hashed(
}
if (block) {
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
}
return(is_hashed);
@@ -2371,14 +2370,15 @@ buf_page_set_file_page_was_freed(
{
buf_page_t* bpage;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
- mutex_t* hash_mutex;
+ rw_lock_t* hash_lock;
- bpage = buf_page_hash_get(buf_pool, space, offset, &hash_mutex);
+ bpage = buf_page_hash_get_s_locked(buf_pool, space, offset,
+ &hash_lock);
if (bpage) {
ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
bpage->file_page_was_freed = TRUE;
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
}
return(bpage);
@@ -2399,14 +2399,14 @@ buf_page_reset_file_page_was_freed(
{
buf_page_t* bpage;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
- mutex_t* hash_mutex;
-
- bpage = buf_page_hash_get(buf_pool, space, offset, &hash_mutex);
+ rw_lock_t* hash_lock;
+ bpage = buf_page_hash_get_s_locked(buf_pool, space, offset,
+ &hash_lock);
if (bpage) {
ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
bpage->file_page_was_freed = FALSE;
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
}
return(bpage);
@@ -2435,7 +2435,7 @@ buf_block_try_discard_uncompressed(
we need to check again if the block is still in page_hash. */
buf_pool_mutex_enter(buf_pool);
- bpage = buf_page_hash_get(buf_pool, space, offset, NULL);
+ bpage = buf_page_hash_get(buf_pool, space, offset);
if (bpage) {
buf_LRU_free_block(bpage, FALSE, NULL);
@@ -2463,7 +2463,7 @@ buf_page_get_zip(
{
buf_page_t* bpage;
mutex_t* block_mutex;
- mutex_t* hash_mutex;
+ rw_lock_t* hash_lock;
ibool discard_attempted = FALSE;
ibool must_read;
unsigned access_time;
@@ -2479,8 +2479,8 @@ lookup:
/* The following call will also grab the page_hash
mutex if the page is found. */
- bpage = buf_page_hash_get(buf_pool, space, offset,
- &hash_mutex);
+ bpage = buf_page_hash_get_s_locked(buf_pool, space,
+ offset, &hash_lock);
if (bpage) {
ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
break;
@@ -2488,7 +2488,7 @@ lookup:
/* Page not in buf_pool: needs to be read from file */
- ut_ad(!hash_mutex);
+ ut_ad(!hash_lock);
buf_read_page(space, zip_size, offset);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
@@ -2496,12 +2496,12 @@ lookup:
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
}
- ut_ad(buf_page_hash_mutex_own(buf_pool, bpage));
+ ut_ad(buf_page_hash_lock_held_s(buf_pool, bpage));
if (UNIV_UNLIKELY(!bpage->zip.data)) {
/* There is no compressed page. */
err_exit:
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
return(NULL);
}
@@ -2523,7 +2523,7 @@ err_exit:
case BUF_BLOCK_FILE_PAGE:
/* Discard the uncompressed page frame if possible. */
if (!discard_attempted) {
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
buf_block_try_discard_uncompressed(space,
offset);
discard_attempted = TRUE;
@@ -2544,7 +2544,7 @@ got_block:
must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
access_time = buf_page_is_accessed(bpage);
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
mutex_exit(block_mutex);
buf_page_set_accessed_make_young(bpage, access_time);
@@ -2885,7 +2885,7 @@ buf_page_get_gen(
unsigned access_time;
ulint fix_type;
ibool must_read;
- mutex_t* hash_mutex;
+ rw_lock_t* hash_lock;
mutex_t* block_mutex;
buf_page_t* hash_bpage;
ulint retries = 0;
@@ -2909,11 +2909,11 @@ buf_page_get_gen(
#endif
buf_pool->stat.n_page_gets++;
fold = buf_page_address_fold(space, offset);
- hash_mutex = buf_page_hash_mutex_get(buf_pool, fold);
+ hash_lock = buf_page_hash_lock_get(buf_pool, fold);
loop:
block = guess;
- mutex_enter(hash_mutex);
+ rw_lock_s_lock(hash_lock);
if (block) {
/* If the guess is a compressed page descriptor that
has been allocated by buf_buddy_alloc(), it may have
@@ -2944,7 +2944,7 @@ loop:
loop2:
if (!block || buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
block = NULL;
}
@@ -2952,22 +2952,31 @@ loop2:
/* Page not in buf_pool: needs to be read from file */
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
- mutex_enter(hash_mutex);
+ rw_lock_x_lock(hash_lock);
block = (buf_block_t*) buf_pool_watch_set(
space, offset, fold);
if (UNIV_LIKELY_NULL(block)) {
+ /* We can release hash_lock after we
+ acquire block_mutex to make sure that
+ no state change takes place. */
+ block_mutex = buf_page_get_mutex(&block->page);
+ mutex_enter(block_mutex);
- ut_ad(mutex_own(hash_mutex));
+ /* Now safe to release page_hash mutex */
+ rw_lock_x_unlock(hash_lock);
goto got_block;
}
- mutex_exit(hash_mutex);
+
+ rw_lock_x_unlock(hash_lock);
}
if (mode == BUF_GET_IF_IN_POOL
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
-
- ut_ad(!mutex_own(hash_mutex));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX));
+ ut_ad(!rw_lock_own(hash_lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
return(NULL);
}
@@ -3001,16 +3010,18 @@ loop2:
goto loop;
}
-got_block:
- /* We can release hash_mutex after we acquire block_mutex to
+
+ /* We can release hash_lock after we acquire block_mutex to
make sure that no state change takes place. */
block_mutex = buf_page_get_mutex(&block->page);
mutex_enter(block_mutex);
- ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
-
/* Now safe to release page_hash mutex */
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
+
+got_block:
+ ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
+ ut_ad(mutex_own(block_mutex));
must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
@@ -3056,13 +3067,13 @@ wait_until_unfixed:
buf_pool_mutex_enter(buf_pool);
- /* As we have released the page_hash mutex and the
+ /* As we have released the page_hash lock and the
block_mutex to allocate an uncompressed page it is
possible that page_hash might have changed. We do
- another lookup here while holding the hash_mutex
+ another lookup here while holding the hash_lock
to verify that bpage is indeed still a part of
page_hash. */
- mutex_enter(hash_mutex);
+ rw_lock_x_lock(hash_lock);
hash_bpage = buf_page_hash_get_low(buf_pool, space,
offset, fold);
@@ -3078,8 +3089,10 @@ wait_until_unfixed:
block = (buf_block_t*) hash_bpage;
+ rw_lock_x_unlock(hash_lock);
+ rw_lock_s_lock(hash_lock);
/* Note that we are still holding the
- hash_mutex which is fine as this is what
+ hash_lock which is fine as this is what
we expect when we move to loop2 above. */
goto loop2;
}
@@ -3088,7 +3101,7 @@ wait_until_unfixed:
(bpage->buf_fix_count
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
/* The block was buffer-fixed or I/O-fixed
while buf_pool->mutex was not held by this thread.
Free the block that was allocated and try again.
@@ -3138,7 +3151,7 @@ wait_until_unfixed:
UNIV_MEM_INVALID(bpage, sizeof *bpage);
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
mutex_exit(&block->mutex);
mutex_exit(&buf_pool->zip_mutex);
buf_pool->n_pend_unzip++;
@@ -3177,7 +3190,11 @@ wait_until_unfixed:
break;
}
- ut_ad(!mutex_own(hash_mutex));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX));
+ ut_ad(!rw_lock_own(hash_lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
+
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#if UNIV_WORD_SIZE == 4
@@ -3204,14 +3221,14 @@ wait_until_unfixed:
mutex_exit(&block->mutex);
/* Now we are only holding the buf_pool->mutex,
- not block->mutex or hash_mutex. Blocks cannot be
+ not block->mutex or hash_lock. Blocks cannot be
relocated or enter or exit the buf_pool while we
are holding the buf_pool->mutex. */
if (buf_LRU_free_block(&block->page, TRUE, NULL)
== BUF_LRU_FREED) {
buf_pool_mutex_exit(buf_pool);
- mutex_enter(hash_mutex);
+ rw_lock_x_lock(hash_lock);
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
/* Set the watch, as it would have
@@ -3228,10 +3245,13 @@ wait_until_unfixed:
/* The page entered the buffer
pool for some reason. Try to
evict it again. */
+ mutex_enter(block_mutex);
+ rw_lock_x_unlock(hash_lock);
+
goto got_block;
}
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
fprintf(stderr,
"innodb_change_buffering_debug evict %u %u\n",
(unsigned) space, (unsigned) offset);
@@ -3326,7 +3346,10 @@ wait_until_unfixed:
ut_a(ibuf_count_get(buf_block_get_space(block),
buf_block_get_page_no(block)) == 0);
#endif
- ut_ad(!mutex_own(hash_mutex));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX));
+ ut_ad(!rw_lock_own(hash_lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
return(block);
}
@@ -3569,16 +3592,17 @@ buf_page_try_get_func(
ibool success;
ulint fix_type;
buf_pool_t* buf_pool = buf_pool_get(space_id, page_no);
- mutex_t* hash_mutex;
+ rw_lock_t* hash_lock;
ut_ad(mtr);
ut_ad(mtr->state == MTR_ACTIVE);
- block = buf_block_hash_get(buf_pool, space_id, page_no, &hash_mutex);
+ block = buf_block_hash_get_s_locked(buf_pool, space_id,
+ page_no, &hash_lock);
if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
if (block) {
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
}
return(NULL);
}
@@ -3586,7 +3610,7 @@ buf_page_try_get_func(
ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
mutex_enter(&block->mutex);
- mutex_exit(hash_mutex);
+ rw_lock_s_unlock(hash_lock);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
@@ -3676,10 +3700,15 @@ buf_page_init(
buf_pool_t* buf_pool = buf_pool_get(space, offset);
ut_ad(buf_pool_mutex_own(buf_pool));
- ut_ad(mutex_own(buf_page_hash_mutex_get(buf_pool, fold)));
+
ut_ad(mutex_own(&(block->mutex)));
ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(buf_page_hash_lock_get(buf_pool, fold),
+ RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
/* Set the state of the block */
buf_block_set_file_page(block, space, offset);
@@ -3763,7 +3792,7 @@ buf_page_init_for_read(
buf_block_t* block;
buf_page_t* bpage = NULL;
buf_page_t* watch_page;
- mutex_t* hash_mutex;
+ rw_lock_t* hash_lock;
mtr_t mtr;
ulint fold;
ibool lru = FALSE;
@@ -3803,17 +3832,17 @@ buf_page_init_for_read(
}
fold = buf_page_address_fold(space, offset);
- hash_mutex = buf_page_hash_mutex_get(buf_pool, fold);
+ hash_lock = buf_page_hash_lock_get(buf_pool, fold);
buf_pool_mutex_enter(buf_pool);
- mutex_enter(hash_mutex);
+ rw_lock_x_lock(hash_lock);
watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
/* The page is already in the buffer pool. */
watch_page = NULL;
err_exit:
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
if (block) {
mutex_enter(&block->mutex);
buf_LRU_block_free_non_file_page(block);
@@ -3841,7 +3870,7 @@ err_exit:
ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
buf_page_init(space, offset, fold, block);
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
/* The block must be put to the LRU list, to the old blocks */
buf_LRU_add_block(bpage, TRUE/* to old blocks */);
@@ -3885,7 +3914,7 @@ err_exit:
mutex_exit(&block->mutex);
} else {
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
/* Defer buf_buddy_alloc() until after the block has
been found not to exist. The buf_buddy_alloc() and
buf_buddy_free() calls may be expensive because of
@@ -3901,7 +3930,7 @@ err_exit:
/* Initialize the buf_pool pointer. */
bpage->buf_pool_index = buf_pool_index(buf_pool);
- mutex_enter(hash_mutex);
+ rw_lock_x_lock(hash_lock);
/* If buf_buddy_alloc() allocated storage from the LRU list,
it released and reacquired buf_pool->mutex. Thus, we must
@@ -3916,7 +3945,7 @@ err_exit:
watch_page))) {
/* The block was added by some other thread. */
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
watch_page = NULL;
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
buf_buddy_free(buf_pool, data, zip_size);
@@ -3964,7 +3993,7 @@ err_exit:
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
bpage);
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
/* The block must be put to the LRU list, to the old blocks */
buf_LRU_add_block(bpage, TRUE/* to old blocks */);
@@ -3984,7 +4013,12 @@ func_exit:
mtr_commit(&mtr);
}
- ut_ad(!mutex_own(hash_mutex));
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX));
+ ut_ad(!rw_lock_own(hash_lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
+
ut_ad(!bpage || buf_page_in_file(bpage));
return(bpage);
}
@@ -4011,7 +4045,7 @@ buf_page_create(
buf_block_t* free_block = NULL;
ulint time_ms = ut_time_ms();
buf_pool_t* buf_pool = buf_pool_get(space, offset);
- mutex_t* hash_mutex;
+ rw_lock_t* hash_lock;
ut_ad(mtr);
ut_ad(mtr->state == MTR_ACTIVE);
@@ -4020,10 +4054,10 @@ buf_page_create(
free_block = buf_LRU_get_free_block(buf_pool, 0);
fold = buf_page_address_fold(space, offset);
- hash_mutex = buf_page_hash_mutex_get(buf_pool, fold);
+ hash_lock = buf_page_hash_lock_get(buf_pool, fold);
buf_pool_mutex_enter(buf_pool);
- mutex_enter(hash_mutex);
+ rw_lock_x_lock(hash_lock);
block = (buf_block_t*) buf_page_hash_get_low(
buf_pool, space, offset, fold);
@@ -4040,7 +4074,7 @@ buf_page_create(
/* Page can be found in buf_pool */
buf_pool_mutex_exit(buf_pool);
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
buf_block_free(free_block);
@@ -4063,7 +4097,7 @@ buf_page_create(
buf_page_init(space, offset, fold, block);
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
/* The block must be put to the LRU list */
buf_LRU_add_block(&block->page, FALSE);
@@ -4604,7 +4638,7 @@ buf_pool_validate_instance(
ut_ad(buf_pool);
buf_pool_mutex_enter(buf_pool);
- hash_mutex_enter_all(buf_pool->page_hash);
+ hash_lock_x_all(buf_pool->page_hash);
chunk = buf_pool->chunks;
@@ -4776,7 +4810,7 @@ buf_pool_validate_instance(
ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
- hash_mutex_exit_all(buf_pool->page_hash);
+ hash_unlock_x_all(buf_pool->page_hash);
buf_flush_list_mutex_exit(buf_pool);
mutex_exit(&buf_pool->zip_mutex);
=== modified file 'storage/innobase/buf/buf0flu.c'
--- a/storage/innobase/buf/buf0flu.c revid:jimmy.yang@stripped
+++ b/storage/innobase/buf/buf0flu.c revid:inaam.rana@stripped
@@ -1442,7 +1442,7 @@ buf_flush_try_neighbors(
buf_pool_mutex_enter(buf_pool);
/* We only want to flush pages from this buffer pool. */
- bpage = buf_page_hash_get(buf_pool, space, i, NULL);
+ bpage = buf_page_hash_get(buf_pool, space, i);
if (!bpage) {
=== modified file 'storage/innobase/buf/buf0lru.c'
--- a/storage/innobase/buf/buf0lru.c revid:jimmy.yang@stripped
+++ b/storage/innobase/buf/buf0lru.c revid:inaam.rana@stripped
@@ -124,8 +124,8 @@ If the block is compressed-only (BUF_BLO
the object will be freed.
The caller must hold buf_pool->mutex, the buf_page_get_mutex() mutex
-and the appropriate hash_mutex. This function will release the
-buf_page_get_mutex() and the hash_mutex.
+and the appropriate hash_lock. This function will release the
+buf_page_get_mutex() and the hash_lock.
If a compressed page or a compressed-only block descriptor is freed,
other compressed pages or compressed-only block descriptors may be
@@ -375,12 +375,12 @@ scan_again:
} else {
ulint fold = buf_page_address_fold(bpage->space,
bpage->offset);
- mutex_t* hash_mutex = buf_page_hash_mutex_get(buf_pool,
+ rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool,
fold);
mutex_t* block_mutex = buf_page_get_mutex(bpage);
- mutex_enter(hash_mutex);
+ rw_lock_x_lock(hash_lock);
mutex_enter(block_mutex);
if (bpage->buf_fix_count > 0) {
@@ -391,7 +391,7 @@ scan_again:
the modifications to the file */
all_freed = FALSE;
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
mutex_exit(block_mutex);
goto next_page;
}
@@ -446,7 +446,7 @@ scan_again:
zip_size = buf_page_get_zip_size(bpage);
page_no = buf_page_get_page_no(bpage);
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
mutex_exit(block_mutex);
/* Note that the following call will acquire
@@ -490,7 +490,10 @@ scan_again:
}
- ut_ad(!mutex_own(hash_mutex));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX)
+ && !rw_lock_own(hash_lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(!mutex_own(block_mutex));
}
next_page:
@@ -1471,7 +1474,7 @@ buf_LRU_free_block(
enum buf_lru_free_block_status ret;
const ulint fold = buf_page_address_fold(bpage->space,
bpage->offset);
- mutex_t* hash_mutex = buf_page_hash_mutex_get(buf_pool, fold);
+ rw_lock_t* hash_lock = buf_page_hash_lock_get(buf_pool, fold);
mutex_t* block_mutex = buf_page_get_mutex(bpage);
@@ -1479,7 +1482,7 @@ buf_LRU_free_block(
ut_ad(buf_page_in_file(bpage));
ut_ad(bpage->in_LRU_list);
- mutex_enter(hash_mutex);
+ rw_lock_x_lock(hash_lock);
mutex_enter(block_mutex);
#if UNIV_WORD_SIZE == 4
@@ -1537,7 +1540,7 @@ buf_LRU_free_block(
no_free_exit:
ret = BUF_LRU_NOT_FREED;
func_exit:
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
mutex_exit(block_mutex);
return(ret);
}
@@ -1568,7 +1571,9 @@ func_exit:
}
#endif /* UNIV_DEBUG */
- ut_ad(mutex_own(hash_mutex));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(hash_lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
ut_ad(buf_page_can_relocate(bpage));
if (buf_LRU_block_remove_hashed_page(bpage, zip)
@@ -1584,7 +1589,7 @@ func_exit:
if (b) {
buf_page_t* prev_b = UT_LIST_GET_PREV(LRU, b);
- mutex_enter(hash_mutex);
+ rw_lock_x_lock(hash_lock);
mutex_enter(block_mutex);
ut_a(!buf_page_hash_get_low(buf_pool,
@@ -1683,7 +1688,7 @@ func_exit:
b->buf_fix_count++;
b->io_fix = BUF_IO_READ;
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
mutex_exit(block_mutex);
}
@@ -1733,7 +1738,10 @@ func_exit:
buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
}
-
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX)
+ && !rw_lock_own(hash_lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
return(BUF_LRU_FREED);
}
@@ -1805,8 +1813,8 @@ If the block is compressed-only (BUF_BLO
the object will be freed.
The caller must hold buf_pool->mutex, the buf_page_get_mutex() mutex
-and the appropriate hash_mutex. This function will release the
-buf_page_get_mutex() and the hash_mutex.
+and the appropriate hash_lock. This function will release the
+buf_page_get_mutex() and the hash_lock.
If a compressed page or a compressed-only block descriptor is freed,
other compressed pages or compressed-only block descriptors may be
@@ -1826,15 +1834,17 @@ buf_LRU_block_remove_hashed_page(
ulint fold;
const buf_page_t* hashed_bpage;
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
- mutex_t* hash_mutex;
+ rw_lock_t* hash_lock;
ut_ad(bpage);
ut_ad(buf_pool_mutex_own(buf_pool));
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
fold = buf_page_address_fold(bpage->space, bpage->offset);
- hash_mutex = buf_page_hash_mutex_get(buf_pool, fold);
- ut_ad(mutex_own(hash_mutex));
+ hash_lock = buf_page_hash_lock_get(buf_pool, fold);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(hash_lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
ut_a(bpage->buf_fix_count == 0);
@@ -1940,7 +1950,7 @@ buf_LRU_block_remove_hashed_page(
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
mutex_exit(buf_page_get_mutex(bpage));
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
buf_pool_mutex_exit(buf_pool);
buf_print();
buf_LRU_print();
@@ -1965,7 +1975,7 @@ buf_LRU_block_remove_hashed_page(
UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
mutex_exit(&buf_pool->zip_mutex);
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
buf_pool_mutex_exit_forbid(buf_pool);
buf_buddy_free(
@@ -2006,7 +2016,7 @@ buf_LRU_block_remove_hashed_page(
and by the time we'll release it in the caller we'd
have inserted the compressed only descriptor in the
page_hash. */
- mutex_exit(hash_mutex);
+ rw_lock_x_unlock(hash_lock);
mutex_exit(&((buf_block_t*) bpage)->mutex);
if (zip && bpage->zip.data) {
=== modified file 'storage/innobase/buf/buf0rea.c'
--- a/storage/innobase/buf/buf0rea.c revid:jimmy.yang@stripped
+++ b/storage/innobase/buf/buf0rea.c revid:inaam.rana@stripped
@@ -331,7 +331,7 @@ buf_read_ahead_linear(
fail_count = 0;
for (i = low; i < high; i++) {
- bpage = buf_page_hash_get(buf_pool, space, i, NULL);
+ bpage = buf_page_hash_get(buf_pool, space, i);
if (bpage == NULL || !buf_page_is_accessed(bpage)) {
/* Not accessed */
@@ -369,7 +369,7 @@ buf_read_ahead_linear(
/* If we got this far, we know that enough pages in the area have
been accessed in the right order: linear read-ahead can be sensible */
- bpage = buf_page_hash_get(buf_pool, space, offset, NULL);
+ bpage = buf_page_hash_get(buf_pool, space, offset);
if (bpage == NULL) {
buf_pool_mutex_exit(buf_pool);
=== modified file 'storage/innobase/ha/ha0ha.c'
--- a/storage/innobase/ha/ha0ha.c revid:jimmy.yang@stripped
+++ b/storage/innobase/ha/ha0ha.c revid:inaam.rana@stripped
@@ -44,11 +44,13 @@ ha_create_func(
/*===========*/
ulint n, /*!< in: number of array cells */
#ifdef UNIV_SYNC_DEBUG
- ulint mutex_level, /*!< in: level of the mutexes in the latching
- order: this is used in the debug version */
+ ulint sync_level, /*!< in: level of the mutexes or rw_locks
+ in the latching order: this is used in the
+ debug version */
#endif /* UNIV_SYNC_DEBUG */
- ulint n_mutexes, /*!< in: number of mutexes to protect the
- hash table: must be a power of 2, or 0 */
+ ulint n_sync_obj, /*!< in: number of mutexes or rw_locks
+ to protect the hash table: must be a
+ power of 2, or 0 */
ulint type) /*!< in: type of datastructure for which
the memory heap is going to be used e.g.:
MEM_HEAP_FOR_BTR_SEARCH or
@@ -62,13 +64,13 @@ ha_create_func(
ut_a(type == MEM_HEAP_FOR_BTR_SEARCH
|| type == MEM_HEAP_FOR_PAGE_HASH);
- ut_ad(ut_is_2pow(n_mutexes));
+ ut_ad(ut_is_2pow(n_sync_obj));
table = hash_create(n);
/* Creating MEM_HEAP_BTR_SEARCH type heaps can potentially fail,
but in practise it never should in this case, hence the asserts. */
- if (n_mutexes == 0) {
+ if (n_sync_obj == 0) {
table->heap = mem_heap_create_typed(
ut_min(4096, MEM_MAX_ALLOC_IN_BUF), type);
ut_a(table->heap);
@@ -77,11 +79,19 @@ ha_create_func(
}
#ifndef UNIV_HOTBACKUP
- hash_create_mutexes(table, n_mutexes, mutex_level);
+ if (type == MEM_HEAP_FOR_PAGE_HASH) {
+ /* We create a hash table protected by rw_locks for
+ buf_pool->page_hash. */
+ hash_create_sync_obj(table, HASH_TABLE_SYNC_RW_LOCK,
+ n_sync_obj, sync_level);
+ } else {
+ hash_create_sync_obj(table, HASH_TABLE_SYNC_MUTEX,
+ n_sync_obj, sync_level);
+ }
- table->heaps = mem_alloc(n_mutexes * sizeof(void*));
+ table->heaps = mem_alloc(n_sync_obj * sizeof(void*));
- for (i = 0; i < n_mutexes; i++) {
+ for (i = 0; i < n_sync_obj; i++) {
table->heaps[i] = mem_heap_create_typed(4096, type);
ut_a(table->heaps[i]);
}
@@ -110,7 +120,7 @@ ha_clear(
#ifndef UNIV_HOTBACKUP
/* Free the memory heaps. */
- n = table->n_mutexes;
+ n = table->n_sync_obj;
for (i = 0; i < n; i++) {
mem_heap_free(table->heaps[i]);
@@ -120,10 +130,25 @@ ha_clear(
mem_free(table->heaps);
}
- if (table->mutexes) {
- mem_free(table->mutexes);
+ switch (table->type) {
+ case HASH_TABLE_SYNC_MUTEX:
+ mem_free(table->sync_obj.mutexes);
+ table->sync_obj.mutexes = NULL;
+ break;
+
+ case HASH_TABLE_SYNC_RW_LOCK:
+ mem_free(table->sync_obj.rw_locks);
+ table->sync_obj.rw_locks = NULL;
+ break;
+
+ case HASH_TABLE_SYNC_NONE:
+ /* do nothing */
+ break;
}
+ table->n_sync_obj = 0;
+ table->type = HASH_TABLE_SYNC_NONE;
+
#endif /* !UNIV_HOTBACKUP */
/* Clear the hash table. */
@@ -165,7 +190,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(block->frame == page_align(data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- ASSERT_HASH_MUTEX_OWN(table, fold);
+ hash_assert_can_modify(table, fold);
hash = hash_calc_hash(fold, table);
@@ -294,7 +319,7 @@ ha_search_and_update_if_found_func(
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ASSERT_HASH_MUTEX_OWN(table, fold);
+ hash_assert_can_modify(table, fold);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(new_block->frame == page_align(new_data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
@@ -333,7 +358,7 @@ ha_remove_all_nodes_to_page(
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ASSERT_HASH_MUTEX_OWN(table, fold);
+ hash_assert_can_modify(table, fold);
node = ha_chain_get_first(table, fold);
=== modified file 'storage/innobase/ha/hash0hash.c'
--- a/storage/innobase/ha/hash0hash.c revid:jimmy.yang@stripped
+++ b/storage/innobase/ha/hash0hash.c revid:inaam.rana@stripped
@@ -34,6 +34,7 @@ Created 5/20/1997 Heikki Tuuri
# ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t hash_table_mutex_key;
+UNIV_INTERN mysql_pfs_key_t hash_table_rw_lock_key;
# endif /* UNIV_PFS_MUTEX */
/************************************************************//**
@@ -45,6 +46,7 @@ hash_mutex_enter(
hash_table_t* table, /*!< in: hash table */
ulint fold) /*!< in: fold */
{
+ ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
mutex_enter(hash_get_mutex(table, fold));
}
@@ -57,6 +59,7 @@ hash_mutex_exit(
hash_table_t* table, /*!< in: hash table */
ulint fold) /*!< in: fold */
{
+ ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
mutex_exit(hash_get_mutex(table, fold));
}
@@ -70,9 +73,10 @@ hash_mutex_enter_all(
{
ulint i;
- for (i = 0; i < table->n_mutexes; i++) {
+ ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
+ for (i = 0; i < table->n_sync_obj; i++) {
- mutex_enter(table->mutexes + i);
+ mutex_enter(table->sync_obj.mutexes + i);
}
}
@@ -86,9 +90,10 @@ hash_mutex_exit_all(
{
ulint i;
- for (i = 0; i < table->n_mutexes; i++) {
+ ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
+ for (i = 0; i < table->n_sync_obj; i++) {
- mutex_exit(table->mutexes + i);
+ mutex_exit(table->sync_obj.mutexes + i);
}
}
@@ -103,9 +108,10 @@ hash_mutex_exit_all_but(
{
ulint i;
- for (i = 0; i < table->n_mutexes; i++) {
+ ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
+ for (i = 0; i < table->n_sync_obj; i++) {
- mutex_t* mutex = table->mutexes + i;
+ mutex_t* mutex = table->sync_obj.mutexes + i;
if (UNIV_LIKELY(keep_mutex != mutex)) {
mutex_exit(mutex);
}
@@ -113,6 +119,167 @@ hash_mutex_exit_all_but(
ut_ad(mutex_own(keep_mutex));
}
+
+/************************************************************//**
+s-lock a lock for a fold value in a hash table. */
+UNIV_INTERN
+void
+hash_lock_s(
+/*========*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold) /*!< in: fold */
+{
+
+ rw_lock_t* lock = hash_get_lock(table, fold);
+
+ ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
+ ut_ad(lock);
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
+ ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ rw_lock_s_lock(lock);
+}
+
+/************************************************************//**
+x-lock a lock for a fold value in a hash table. */
+UNIV_INTERN
+void
+hash_lock_x(
+/*========*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold) /*!< in: fold */
+{
+
+ rw_lock_t* lock = hash_get_lock(table, fold);
+
+ ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
+ ut_ad(lock);
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
+ ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ rw_lock_x_lock(lock);
+}
+
+/************************************************************//**
+unlock an s-lock for a fold value in a hash table. */
+UNIV_INTERN
+void
+hash_unlock_s(
+/*==========*/
+
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold) /*!< in: fold */
+{
+
+ rw_lock_t* lock = hash_get_lock(table, fold);
+
+ ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
+ ut_ad(lock);
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
+
+ rw_lock_s_unlock(lock);
+}
+
+/************************************************************//**
+unlock x-lock for a fold value in a hash table. */
+UNIV_INTERN
+void
+hash_unlock_x(
+/*==========*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold) /*!< in: fold */
+{
+ rw_lock_t* lock = hash_get_lock(table, fold);
+
+ ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
+ ut_ad(lock);
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ rw_lock_x_unlock(lock);
+}
+
+/************************************************************//**
+Reserves all the locks of a hash table, in an ascending order. */
+UNIV_INTERN
+void
+hash_lock_x_all(
+/*============*/
+ hash_table_t* table) /*!< in: hash table */
+{
+ ulint i;
+
+ ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
+ for (i = 0; i < table->n_sync_obj; i++) {
+
+ rw_lock_t* lock = table->sync_obj.rw_locks + i;
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
+ ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ rw_lock_x_lock(lock);
+ }
+}
+
+/************************************************************//**
+Releases all the locks of a hash table, in an ascending order. */
+UNIV_INTERN
+void
+hash_unlock_x_all(
+/*==============*/
+ hash_table_t* table) /*!< in: hash table */
+{
+ ulint i;
+
+ ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
+ for (i = 0; i < table->n_sync_obj; i++) {
+
+ rw_lock_t* lock = table->sync_obj.rw_locks + i;
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ rw_lock_x_unlock(lock);
+ }
+}
+
+/************************************************************//**
+Releases all but passed in lock of a hash table, */
+UNIV_INTERN
+void
+hash_unlock_x_all_but(
+/*==================*/
+ hash_table_t* table, /*!< in: hash table */
+ rw_lock_t* keep_lock) /*!< in: lock to keep */
+{
+ ulint i;
+
+ ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
+ for (i = 0; i < table->n_sync_obj; i++) {
+
+ rw_lock_t* lock = table->sync_obj.rw_locks + i;
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ if (UNIV_LIKELY(keep_lock != lock)) {
+ rw_lock_x_unlock(lock);
+ }
+ }
+}
+
#endif /* !UNIV_HOTBACKUP */
/*************************************************************//**
@@ -135,14 +302,17 @@ hash_create(
array = ut_malloc(sizeof(hash_cell_t) * prime);
+ /* The default type of hash_table is HASH_TABLE_SYNC_NONE i.e.:
+ the caller is responsible for access control to the table. */
+ table->type = HASH_TABLE_SYNC_NONE;
table->array = array;
table->n_cells = prime;
#ifndef UNIV_HOTBACKUP
# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
table->adaptive = FALSE;
# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- table->n_mutexes = 0;
- table->mutexes = NULL;
+ table->n_sync_obj = 0;
+ table->sync_obj.mutexes = NULL;
table->heaps = NULL;
#endif /* !UNIV_HOTBACKUP */
table->heap = NULL;
@@ -171,33 +341,60 @@ hash_table_free(
#ifndef UNIV_HOTBACKUP
/*************************************************************//**
-Creates a mutex array to protect a hash table. */
+Creates a sync object array array to protect a hash table.
+::sync_obj can be mutexes or rw_locks depening on the type of
+hash table. */
UNIV_INTERN
void
-hash_create_mutexes_func(
-/*=====================*/
- hash_table_t* table, /*!< in: hash table */
+hash_create_sync_obj_func(
+/*======================*/
+ hash_table_t* table, /*!< in: hash table */
+ enum hash_table_sync_t type, /*!< in: HASH_TABLE_SYNC_MUTEX
+ or HASH_TABLE_SYNC_RW_LOCK */
#ifdef UNIV_SYNC_DEBUG
- ulint sync_level, /*!< in: latching order level of the
- mutexes: used in the debug version */
+ ulint sync_level,/*!< in: latching order level
+ of the mutexes: used in the
+ debug version */
#endif /* UNIV_SYNC_DEBUG */
- ulint n_mutexes) /*!< in: number of mutexes, must be a
- power of 2 */
+ ulint n_sync_obj)/*!< in: number of sync objects,
+ must be a power of 2 */
{
ulint i;
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ut_a(n_mutexes > 0);
- ut_a(ut_is_2pow(n_mutexes));
+ ut_a(n_sync_obj > 0);
+ ut_a(ut_is_2pow(n_sync_obj));
+
+ table->type = type;
+
+ switch (type) {
+ case HASH_TABLE_SYNC_MUTEX:
+ table->sync_obj.mutexes = mem_alloc(n_sync_obj
+ * sizeof(mutex_t));
+
+ for (i = 0; i < n_sync_obj; i++) {
+ mutex_create(hash_table_mutex_key,
+ table->sync_obj.mutexes + i, sync_level);
+ }
+
+ break;
+
+ case HASH_TABLE_SYNC_RW_LOCK:
+ table->sync_obj.rw_locks = mem_alloc(n_sync_obj
+ * sizeof(rw_lock_t));
+
+ for (i = 0; i < n_sync_obj; i++) {
+ rw_lock_create(hash_table_rw_lock_key,
+ table->sync_obj.rw_locks + i, sync_level);
+ }
- table->mutexes = mem_alloc(n_mutexes * sizeof(mutex_t));
+ break;
- for (i = 0; i < n_mutexes; i++) {
- mutex_create(hash_table_mutex_key,
- table->mutexes + i, sync_level);
+ case HASH_TABLE_SYNC_NONE:
+ ut_error;
}
- table->n_mutexes = n_mutexes;
+ table->n_sync_obj = n_sync_obj;
}
#endif /* !UNIV_HOTBACKUP */
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc revid:jimmy.yang@stripped
+++ b/storage/innobase/handler/ha_innodb.cc revid:inaam.rana@stripped
@@ -12071,10 +12071,12 @@ static MYSQL_SYSVAR_LONGLONG(buffer_pool
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
NULL, NULL, 128*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 1024*1024L);
-static MYSQL_SYSVAR_ULONG(page_hash_mutexes, srv_n_page_hash_mutexes,
+#if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG
+static MYSQL_SYSVAR_ULONG(page_hash_locks, srv_n_page_hash_locks,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
- "Number of mutexes protecting buffer pool page_hash. Rounded up to the next power of 2",
- NULL, NULL, 256, 1, MAX_PAGE_HASH_MUTEXES, 0);
+ "Number of rw_locks protecting buffer pool page_hash. Rounded up to the next power of 2",
+ NULL, NULL, 16, 1, MAX_PAGE_HASH_LOCKS, 0);
+#endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */
static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
@@ -12314,7 +12316,9 @@ static struct st_mysql_sys_var* innobase
MYSQL_SYSVAR(reset_all_monitor_counter),
MYSQL_SYSVAR(purge_threads),
MYSQL_SYSVAR(purge_batch_size),
- MYSQL_SYSVAR(page_hash_mutexes),
+#if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG
+ MYSQL_SYSVAR(page_hash_locks),
+#endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */
NULL
};
=== modified file 'storage/innobase/ibuf/ibuf0ibuf.c'
--- a/storage/innobase/ibuf/ibuf0ibuf.c revid:jimmy.yang@stripped
+++ b/storage/innobase/ibuf/ibuf0ibuf.c revid:inaam.rana@stripped
@@ -3775,13 +3775,8 @@ check_watch:
{
buf_page_t* bpage;
- ulint fold = buf_page_address_fold(space, page_no);
buf_pool_t* buf_pool = buf_pool_get(space, page_no);
- mutex_t* hash_mutex = buf_page_hash_mutex_get(buf_pool, fold);
-
- mutex_enter(hash_mutex);
- bpage = buf_page_hash_get_low(buf_pool, space, page_no, fold);
- mutex_exit(hash_mutex);
+ bpage = buf_page_hash_get(buf_pool, space, page_no);
if (UNIV_LIKELY_NULL(bpage)) {
/* A buffer pool watch has been set or the
=== modified file 'storage/innobase/include/buf0buf.h'
--- a/storage/innobase/include/buf0buf.h revid:jimmy.yang@stripped
+++ b/storage/innobase/include/buf0buf.h revid:inaam.rana@stripped
@@ -69,8 +69,8 @@ Created 11/5/1995 Heikki Tuuri
#define BUF_POOL_WATCH_SIZE (srv_n_purge_threads + 1)
/*!< Maximum number of concurrent
buffer pool watches */
-#define MAX_PAGE_HASH_MUTEXES 1024 /*!< The maximum number of
- page_hash mutexes */
+#define MAX_PAGE_HASH_LOCKS 1024 /*!< The maximum number of
+ page_hash locks */
extern buf_pool_t* buf_pool_ptr; /*!< The buffer pools
of the database */
@@ -1161,49 +1161,77 @@ buf_page_hash_get_low(
ulint fold); /*!< in: buf_page_address_fold(space, offset) */
/******************************************************************//**
Returns the control block of a file page, NULL if not found.
-If the block is found and mutex is not NULL then the appropriate
-page_hash mutex is acquired. It is up to the caller to release the
-mutex. If the block is found and the mutex is NULL then the page_hash
-mutex is released by this function.
+If the block is found and lock is not NULL then the appropriate
+page_hash lock is acquired in the specified lock mode. Otherwise,
+mode value is ignored. It is up to the caller to release the
+lock. If the block is found and the lock is NULL then the page_hash
+lock is released by this function.
@return block, NULL if not found */
UNIV_INLINE
buf_page_t*
-buf_page_hash_get(
-/*==============*/
+buf_page_hash_get_locked(
+/*=====================*/
/*!< out: pointer to the bpage,
- or NULL; if NULL, hash_mutex
+ or NULL; if NULL, hash_lock
is also NULL. */
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint space, /*!< in: space id */
ulint offset, /*!< in: page number */
- mutex_t** mutex); /*!< in/out: mutex of the page
+ rw_lock_t** lock, /*!< in/out: lock of the page
hash acquired if bpage is
found. NULL otherwise. If NULL
- is passed then the hash_mutex
+ is passed then the hash_lock
is released by this function */
+ ulint lock_mode); /*!< in: RW_LOCK_EX or
+ RW_LOCK_SHARED. Ignored if
+ lock == NULL */
/******************************************************************//**
-Returns the control block of a file page, NULL if not found or an
-uncompressed page frame does not exist.
-If the block is found and mutex is not NULL then the appropriate
-page_hash mutex is acquired. It is upto the caller to release the
-mutex. If the block is found and the mutex is NULL then the page_hash
-mutex is released by this function.
+Returns the control block of a file page, NULL if not found.
+If the block is found and lock is not NULL then the appropriate
+page_hash lock is acquired in the specified lock mode. Otherwise,
+mode value is ignored. It is up to the caller to release the
+lock. If the block is found and the lock is NULL then the page_hash
+lock is released by this function.
@return block, NULL if not found */
UNIV_INLINE
buf_block_t*
-buf_block_hash_get(
-/*===============*/
+buf_block_hash_get_locked(
+/*=====================*/
/*!< out: pointer to the bpage,
- or NULL; if NULL, hash_mutex
+ or NULL; if NULL, hash_lock
is also NULL. */
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint space, /*!< in: space id */
ulint offset, /*!< in: page number */
- mutex_t** mutex); /*!< in/out: mutex of the page
+ rw_lock_t** lock, /*!< in/out: lock of the page
hash acquired if bpage is
found. NULL otherwise. If NULL
- is passed then the hash_mutex
+ is passed then the hash_lock
is released by this function */
+ ulint lock_mode); /*!< in: RW_LOCK_EX or
+ RW_LOCK_SHARED. Ignored if
+ lock == NULL */
+/* There are four different ways we can try to get a bpage or block
+from the page hash:
+1) Caller already holds the appropriate page hash lock: in the case call
+buf_page_hash_get_low() function.
+2) Caller wants to hold page hash lock in x-mode
+3) Caller wants to hold page hash lock in s-mode
+4) Caller doesn't want to hold page hash lock */
+#define buf_page_hash_get_s_locked(b, s, o, l) \
+ buf_page_hash_get_locked(b, s, o, l, RW_LOCK_SHARED)
+#define buf_page_hash_get_x_locked(b, s, o, l) \
+ buf_page_hash_get_locked(b, s, o, l, RW_LOCK_EX)
+#define buf_page_hash_get(b, s, o) \
+ buf_page_hash_get_locked(b, s, o, NULL, 0)
+
+#define buf_block_hash_get_s_locked(b, s, o, l) \
+ buf_block_hash_get_locked(b, s, o, l, RW_LOCK_SHARED)
+#define buf_block_hash_get_x_locked(b, s, o, l) \
+ buf_block_hash_get_locked(b, s, o, l, RW_LOCK_EX)
+#define buf_block_hash_get(b, s, o) \
+ buf_block_hash_get_locked(b, s, o, NULL, 0)
+
/*********************************************************************//**
Gets the current length of the free list of buffer blocks.
@return length of the free list */
@@ -1809,19 +1837,46 @@ Use these instead of accessing buf_pool-
-/** Get appropriate page_hash_mutex. */
-#define buf_page_hash_mutex_get(b, f) \
- hash_get_mutex(b->page_hash, f)
-
-/** Test if page_hash mutex is owned. */
-#define buf_page_hash_mutex_own(b, p) \
- mutex_own(buf_page_hash_mutex_get(b, \
+/** Get appropriate page_hash_lock. */
+# define buf_page_hash_lock_get(b, f) \
+ hash_get_lock(b->page_hash, f)
+
+#ifdef UNIV_SYNC_DEBUG
+/** Test if page_hash lock is held in s-mode. */
+# define buf_page_hash_lock_held_s(b, p) \
+ rw_lock_own(buf_page_hash_lock_get(b, \
+ buf_page_address_fold(p->space, \
+ p->offset)), \
+ RW_LOCK_SHARED)
+
+/** Test if page_hash lock is held in x-mode. */
+# define buf_page_hash_lock_held_x(b, p) \
+ rw_lock_own(buf_page_hash_lock_get(b, \
buf_page_address_fold(p->space, \
- p->offset)))
-#define buf_block_hash_mutex_own(b, p) \
- mutex_own(buf_page_hash_mutex_get(b, \
- buf_page_address_fold(p->page.space, \
- p->page.offset)))
+ p->offset)), \
+ RW_LOCK_EX)
+
+/** Test if page_hash lock is held in x or s-mode. */
+# define buf_page_hash_lock_held_s_or_x(b, p) \
+ (buf_page_hash_lock_held_s(b, p) \
+ || buf_page_hash_lock_held_x(b, p))
+
+# define buf_block_hash_lock_held_s(b, p) \
+ buf_page_hash_lock_held_s(b, &(p->page))
+
+# define buf_block_hash_lock_held_x(b, p) \
+ buf_page_hash_lock_held_x(b, &(p->page))
+
+# define buf_block_hash_lock_held_s_or_x(b, p) \
+ buf_page_hash_lock_held_s_or_x(b, &(p->page))
+#else /* UNIV_SYNC_DEBUG */
+# define buf_page_hash_lock_held_s(b, p) (TRUE)
+# define buf_page_hash_lock_held_x(b, p) (TRUE)
+# define buf_page_hash_lock_held_s_or_x(b, p) (TRUE)
+# define buf_block_hash_lock_held_s(b, p) (TRUE)
+# define buf_block_hash_lock_held_x(b, p) (TRUE)
+# define buf_block_hash_lock_held_s_or_x(b, p) (TRUE)
+#endif /* UNIV_SYNC_DEBUG */
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/** Forbid the release of the buffer pool mutex. */
=== modified file 'storage/innobase/include/buf0buf.ic'
--- a/storage/innobase/include/buf0buf.ic revid:jimmy.yang@stripped
+++ b/storage/innobase/include/buf0buf.ic revid:inaam.rana@stripped
@@ -975,18 +975,19 @@ buf_page_hash_get_low(
{
buf_page_t* bpage;
-#ifdef UNIV_DEBUG
- ulint hash_fold;
- mutex_t* hash_mutex;
-
ut_ad(buf_pool);
+#ifdef UNIV_SYNC_DEBUG
+ ulint hash_fold;
+ rw_lock_t* hash_lock;
+
hash_fold = buf_page_address_fold(space, offset);
ut_ad(hash_fold == fold);
- hash_mutex = hash_get_mutex(buf_pool->page_hash, fold);
- ut_ad(mutex_own(hash_mutex));
-#endif /* UNIV_DEBUG */
+ hash_lock = hash_get_lock(buf_pool->page_hash, fold);
+ ut_ad(rw_lock_own(hash_lock, RW_LOCK_EX)
+ || rw_lock_own(hash_lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
/* Look for the page in the hash table */
@@ -1011,105 +1012,144 @@ buf_page_hash_get_low(
/******************************************************************//**
Returns the control block of a file page, NULL if not found.
-If the block is found and mutex is not NULL then the appropriate
-page_hash mutex is acquired. It is up to the caller to release the
-mutex. If the block is found and the mutex is NULL then the page_hash
-mutex is released by this function.
+If the block is found and lock is not NULL then the appropriate
+page_hash lock is acquired in the specified lock mode. Otherwise,
+mode value is ignored. It is up to the caller to release the
+lock. If the block is found and the lock is NULL then the page_hash
+lock is released by this function.
@return block, NULL if not found */
UNIV_INLINE
buf_page_t*
-buf_page_hash_get(
-/*==============*/
+buf_page_hash_get_locked(
+/*=====================*/
/*!< out: pointer to the bpage,
- or NULL; if NULL, hash_mutex
+ or NULL; if NULL, hash_lock
is also NULL. */
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint space, /*!< in: space id */
ulint offset, /*!< in: page number */
- mutex_t** mutex) /*!< in/out: mutex of the page
+ rw_lock_t** lock, /*!< in/out: lock of the page
hash acquired if bpage is
found. NULL otherwise. If NULL
- is passed then the hash_mutex
+ is passed then the hash_lock
is released by this function */
+ ulint lock_mode) /*!< in: RW_LOCK_EX or
+ RW_LOCK_SHARED. Ignored if
+ lock == NULL */
{
- buf_page_t* bpage;
+ buf_page_t* bpage = NULL;
ulint fold;
- mutex_t* hash_mutex;
+ rw_lock_t* hash_lock;
+ ulint mode = RW_LOCK_SHARED;
- if (mutex != NULL) {
- *mutex = NULL;
+ if (lock != NULL) {
+ *lock = NULL;
+ ut_ad(lock_mode == RW_LOCK_EX
+ || lock_mode == RW_LOCK_SHARED);
+ mode = lock_mode;
}
fold = buf_page_address_fold(space, offset);
- hash_mutex = hash_get_mutex(buf_pool->page_hash, fold);
+ hash_lock = hash_get_lock(buf_pool->page_hash, fold);
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX)
+ && !rw_lock_own(hash_lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
+
+ if (mode == RW_LOCK_SHARED) {
+ rw_lock_s_lock(hash_lock);
+ } else {
+ rw_lock_x_lock(hash_lock);
+ }
- mutex_enter(hash_mutex);
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
if (!bpage || UNIV_UNLIKELY(buf_pool_watch_is_sentinel(buf_pool, bpage))) {
- mutex_exit(hash_mutex);
- return(NULL);
+ bpage = NULL;
+ goto unlock_and_exit;
}
ut_ad(buf_page_in_file(bpage));
ut_ad(offset == bpage->offset);
ut_ad(space == bpage->space);
- if (mutex == NULL) {
- /* The caller wants us to release the page_hash mutex */
- mutex_exit(hash_mutex);
+ if (lock == NULL) {
+ /* The caller wants us to release the page_hash lock */
+ goto unlock_and_exit;
} else {
/* To be released by the caller */
- *mutex = hash_mutex;
+ *lock = hash_lock;
+ goto exit;
}
+unlock_and_exit:
+ if (mode == RW_LOCK_SHARED) {
+ rw_lock_s_unlock(hash_lock);
+ } else {
+ rw_lock_x_unlock(hash_lock);
+ }
+exit:
return(bpage);
}
/******************************************************************//**
-Returns the control block of a file page, NULL if not found or an
-uncompressed page frame does not exist.
-If the block is found and mutex is not NULL then the appropriate
-page_hash mutex is acquired. It is upto the caller to release the
-mutex. If the block is found and the mutex is NULL then the page_hash
-mutex is released by this function.
+Returns the control block of a file page, NULL if not found.
+If the block is found and lock is not NULL then the appropriate
+page_hash lock is acquired in the specified lock mode. Otherwise,
+mode value is ignored. It is up to the caller to release the
+lock. If the block is found and the lock is NULL then the page_hash
+lock is released by this function.
@return block, NULL if not found */
UNIV_INLINE
buf_block_t*
-buf_block_hash_get(
-/*===============*/
+buf_block_hash_get_locked(
+/*=====================*/
/*!< out: pointer to the bpage,
- or NULL; if NULL, hash_mutex
+ or NULL; if NULL, hash_lock
is also NULL. */
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint space, /*!< in: space id */
ulint offset, /*!< in: page number */
- mutex_t** mutex) /*!< in/out: mutex of the page
+ rw_lock_t** lock, /*!< in/out: lock of the page
hash acquired if bpage is
found. NULL otherwise. If NULL
- is passed then the hash_mutex
+ is passed then the hash_lock
is released by this function */
+ ulint lock_mode) /*!< in: RW_LOCK_EX or
+ RW_LOCK_SHARED. Ignored if
+ lock == NULL */
{
- buf_page_t* bpage = buf_page_hash_get(buf_pool, space, offset, mutex);
+ buf_page_t* bpage = buf_page_hash_get_locked(buf_pool,
+ space,
+ offset,
+ lock,
+ lock_mode);
buf_block_t* block = buf_page_get_block(bpage);
if (block) {
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
- ut_ad(!mutex || mutex_own(*mutex));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!lock || rw_lock_own(*lock, lock_mode));
+#endif /* UNIV_SYNC_DEBUG */
return(block);
} else if (bpage) {
/* It is not a block. Just a bpage */
ut_ad(buf_page_in_file(bpage));
- if (mutex) {
- mutex_exit(*mutex);
+ if (lock) {
+ if (lock_mode == RW_LOCK_SHARED) {
+ rw_lock_s_unlock(*lock);
+ } else {
+ rw_lock_x_unlock(*lock);
+ }
}
- *mutex = NULL;
+ *lock = NULL;
return(NULL);
}
ut_ad(!bpage);
- ut_ad(mutex == NULL ||*mutex == NULL);
+ ut_ad(lock == NULL ||*lock == NULL);
return(NULL);
}
@@ -1129,7 +1169,7 @@ buf_page_peek(
{
buf_pool_t* buf_pool = buf_pool_get(space, offset);
- return(buf_page_hash_get(buf_pool, space, offset, NULL) != NULL);
+ return(buf_page_hash_get(buf_pool, space, offset) != NULL);
}
/********************************************************************//**
=== modified file 'storage/innobase/include/ha0ha.h'
--- a/storage/innobase/include/ha0ha.h revid:jimmy.yang@stripped
+++ b/storage/innobase/include/ha0ha.h revid:inaam.rana@stripped
@@ -225,20 +225,33 @@ struct ha_node_struct {
ulint fold; /*!< fold value for the data */
};
-#ifndef UNIV_HOTBACKUP
-/** Assert that the current thread is holding the mutex protecting a
-hash bucket corresponding to a fold value.
-@param table in: hash table
-@param fold in: fold value */
-# define ASSERT_HASH_MUTEX_OWN(table, fold) \
- ut_ad(!(table)->mutexes || mutex_own(hash_get_mutex(table, fold)))
-#else /* !UNIV_HOTBACKUP */
-/** Assert that the current thread is holding the mutex protecting a
-hash bucket corresponding to a fold value.
-@param table in: hash table
-@param fold in: fold value */
-# define ASSERT_HASH_MUTEX_OWN(table, fold) ((void) 0)
-#endif /* !UNIV_HOTBACKUP */
+#ifdef UNIV_DEBUG
+/********************************************************************//**
+Assert that the synchronization object in a hash operation involving
+possible change in the hash table is held.
+Note that in case of mutexes we assert that mutex is owned while in case
+of rw-locks we assert that it is held in exclusive mode. */
+UNIV_INLINE
+void
+hash_assert_can_modify(
+/*===================*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold); /*!< in: fold value */
+/********************************************************************//**
+Assert that the synchronization object in a hash search operation is held.
+Note that in case of mutexes we assert that mutex is owned while in case
+of rw-locks we assert that it is held either in x-mode or s-mode. */
+UNIV_INLINE
+void
+hash_assert_can_search(
+/*===================*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold); /*!< in: fold value */
+#else /* UNIV_DEBUG */
+#define hash_assert_can_modify(t, f)
+#define hash_assert_can_search(t, f)
+#endif /* UNIV_DEBUG */
+
#ifndef UNIV_NONINL
#include "ha0ha.ic"
=== modified file 'storage/innobase/include/ha0ha.ic'
--- a/storage/innobase/include/ha0ha.ic revid:jimmy.yang@stripped
+++ b/storage/innobase/include/ha0ha.ic revid:inaam.rana@stripped
@@ -105,6 +105,56 @@ ha_chain_get_first(
hash_get_nth_cell(table, hash_calc_hash(fold, table))->node);
}
+#ifdef UNIV_DEBUG
+/********************************************************************//**
+Assert that the synchronization object in a hash operation involving
+possible change in the hash table is held.
+Note that in case of mutexes we assert that mutex is owned while in case
+of rw-locks we assert that it is held in exclusive mode. */
+UNIV_INLINE
+void
+hash_assert_can_modify(
+/*===================*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold) /*!< in: fold value */
+{
+ if (table->type == HASH_TABLE_SYNC_MUTEX) {
+ ut_ad(mutex_own(hash_get_mutex(table, fold)));
+ } else if (table->type == HASH_TABLE_SYNC_RW_LOCK) {
+# ifdef UNIV_SYNC_DEBUG
+ rw_lock_t* lock = hash_get_lock(table, fold);
+ ut_ad(rw_lock_own(lock, RW_LOCK_EX));
+# endif
+ } else {
+ ut_ad(table->type == HASH_TABLE_SYNC_NONE);
+ }
+}
+
+/********************************************************************//**
+Assert that the synchronization object in a hash search operation is held.
+Note that in case of mutexes we assert that mutex is owned while in case
+of rw-locks we assert that it is held either in x-mode or s-mode. */
+UNIV_INLINE
+void
+hash_assert_can_search(
+/*===================*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold) /*!< in: fold value */
+{
+ if (table->type == HASH_TABLE_SYNC_MUTEX) {
+ ut_ad(mutex_own(hash_get_mutex(table, fold)));
+ } else if (table->type == HASH_TABLE_SYNC_RW_LOCK) {
+# ifdef UNIV_SYNC_DEBUG
+ rw_lock_t* lock = hash_get_lock(table, fold);
+ ut_ad(rw_lock_own(lock, RW_LOCK_EX)
+ || rw_lock_own(lock, RW_LOCK_SHARED));
+# endif
+ } else {
+ ut_ad(table->type == HASH_TABLE_SYNC_NONE);
+ }
+}
+#endif /* UNIV_DEBUG */
+
/*************************************************************//**
Looks for an element in a hash table.
@return pointer to the first hash table node in chain having the fold
@@ -118,7 +168,7 @@ ha_search(
{
ha_node_t* node;
- ASSERT_HASH_MUTEX_OWN(table, fold);
+ hash_assert_can_search(table, fold);
node = ha_chain_get_first(table, fold);
@@ -147,7 +197,7 @@ ha_search_and_get_data(
{
ha_node_t* node;
- ASSERT_HASH_MUTEX_OWN(table, fold);
+ hash_assert_can_search(table, fold);
node = ha_chain_get_first(table, fold);
@@ -176,7 +226,7 @@ ha_search_with_data(
{
ha_node_t* node;
- ASSERT_HASH_MUTEX_OWN(table, fold);
+ hash_assert_can_search(table, fold);
node = ha_chain_get_first(table, fold);
@@ -206,7 +256,7 @@ ha_search_and_delete_if_found(
{
ha_node_t* node;
- ASSERT_HASH_MUTEX_OWN(table, fold);
+ hash_assert_can_modify(table, fold);
node = ha_search_with_data(table, fold, data);
=== modified file 'storage/innobase/include/hash0hash.h'
--- a/storage/innobase/include/hash0hash.h revid:jimmy.yang@stripped
+++ b/storage/innobase/include/hash0hash.h revid:inaam.rana@stripped
@@ -30,6 +30,7 @@ Created 5/20/1997 Heikki Tuuri
#include "mem0mem.h"
#ifndef UNIV_HOTBACKUP
# include "sync0sync.h"
+# include "sync0rw.h"
#endif /* !UNIV_HOTBACKUP */
typedef struct hash_table_struct hash_table_t;
@@ -40,6 +41,18 @@ typedef void* hash_node_t;
/* Fix Bug #13859: symbol collision between imap/mysql */
#define hash_create hash0_create
+/* Differnt types of hash_table based on the synchronization
+method used for it. */
+enum hash_table_sync_t {
+ HASH_TABLE_SYNC_NONE = 0, /*!< Don't use any internal
+ synchronization objects for
+ this hash_table. */
+ HASH_TABLE_SYNC_MUTEX, /*!< Use mutexes to control
+ access to this hash_table. */
+ HASH_TABLE_SYNC_RW_LOCK, /*!< Use rw_locks to control
+ access to this hash_table. */
+};
+
/*************************************************************//**
Creates a hash table with >= n array cells. The actual number
of cells is chosen to be a prime number slightly bigger than n.
@@ -51,21 +64,29 @@ hash_create(
ulint n); /*!< in: number of array cells */
#ifndef UNIV_HOTBACKUP
/*************************************************************//**
-Creates a mutex array to protect a hash table. */
+Creates a sync object array array to protect a hash table.
+::sync_obj can be mutexes or rw_locks depening on the type of
+hash table. */
UNIV_INTERN
void
-hash_create_mutexes_func(
-/*=====================*/
- hash_table_t* table, /*!< in: hash table */
+hash_create_sync_obj_func(
+/*======================*/
+ hash_table_t* table, /*!< in: hash table */
+ enum hash_table_sync_t type, /*!< in: HASH_TABLE_SYNC_MUTEX
+ or HASH_TABLE_SYNC_RW_LOCK */
#ifdef UNIV_SYNC_DEBUG
- ulint sync_level, /*!< in: latching order level of the
- mutexes: used in the debug version */
+ ulint sync_level,/*!< in: latching order level
+ of the mutexes: used in the
+ debug version */
#endif /* UNIV_SYNC_DEBUG */
- ulint n_mutexes); /*!< in: number of mutexes */
+ ulint n_sync_obj);/*!< in: number of sync objects,
+ must be a power of 2 */
#ifdef UNIV_SYNC_DEBUG
-# define hash_create_mutexes(t,n,level) hash_create_mutexes_func(t,level,n)
+# define hash_create_sync_obj(t, s, n, level) \
+ hash_create_sync_obj_func(t, s, level, n)
#else /* UNIV_SYNC_DEBUG */
-# define hash_create_mutexes(t,n,level) hash_create_mutexes_func(t,n)
+# define hash_create_sync_obj(t, s, n, level) \
+ hash_create_sync_obj_func(t, s, n)
#endif /* UNIV_SYNC_DEBUG */
#endif /* !UNIV_HOTBACKUP */
@@ -87,11 +108,12 @@ hash_calc_hash(
hash_table_t* table); /*!< in: hash table */
#ifndef UNIV_HOTBACKUP
/********************************************************************//**
-Assert that the mutex for the table in a hash operation is owned. */
-# define HASH_ASSERT_OWNED(TABLE, FOLD) \
-ut_ad(!(TABLE)->mutexes || mutex_own(hash_get_mutex(TABLE, FOLD)));
+Assert that the mutex for the table is held */
+# define HASH_ASSERT_OWN(TABLE, FOLD) \
+ ut_ad((TABLE)->type != HASH_TABLE_SYNC_MUTEX \
+ || (mutex_own(hash_get_mutex((TABLE), FOLD))));
#else /* !UNIV_HOTBACKUP */
-# define HASH_ASSERT_OWNED(TABLE, FOLD)
+# define HASH_ASSERT_OWN(TABLE, FOLD)
#endif /* !UNIV_HOTBACKUP */
/*******************************************************************//**
@@ -102,7 +124,7 @@ do {\
hash_cell_t* cell3333;\
TYPE* struct3333;\
\
- HASH_ASSERT_OWNED(TABLE, FOLD)\
+ HASH_ASSERT_OWN(TABLE, FOLD)\
\
(DATA)->NAME = NULL;\
\
@@ -138,7 +160,7 @@ do {\
hash_cell_t* cell3333;\
TYPE* struct3333;\
\
- HASH_ASSERT_OWNED(TABLE, FOLD)\
+ HASH_ASSERT_OWN(TABLE, FOLD)\
\
cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\
\
@@ -175,7 +197,7 @@ Looks for a struct in a hash table. */
#define HASH_SEARCH(NAME, TABLE, FOLD, TYPE, DATA, ASSERTION, TEST)\
{\
\
- HASH_ASSERT_OWNED(TABLE, FOLD)\
+ HASH_ASSERT_OWN(TABLE, FOLD)\
\
(DATA) = (TYPE) HASH_GET_FIRST(TABLE, hash_calc_hash(FOLD, TABLE));\
HASH_ASSERT_VALID(DATA);\
@@ -329,12 +351,12 @@ do {\
} while (0)
/************************************************************//**
-Gets the mutex index for a fold value in a hash table.
-@return mutex number */
+Gets the sync object index for a fold value in a hash table.
+@return index */
UNIV_INLINE
ulint
-hash_get_mutex_no(
-/*==============*/
+hash_get_sync_obj_index(
+/*====================*/
hash_table_t* table, /*!< in: hash table */
ulint fold); /*!< in: fold */
/************************************************************//**
@@ -365,6 +387,15 @@ hash_get_nth_mutex(
hash_table_t* table, /*!< in: hash table */
ulint i); /*!< in: index of the mutex */
/************************************************************//**
+Gets the nth rw_lock in a hash table.
+@return rw_lock */
+UNIV_INLINE
+rw_lock_t*
+hash_get_nth_lock(
+/*==============*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint i); /*!< in: index of the rw_lock */
+/************************************************************//**
Gets the mutex for a fold value in a hash table.
@return mutex */
UNIV_INLINE
@@ -374,6 +405,15 @@ hash_get_mutex(
hash_table_t* table, /*!< in: hash table */
ulint fold); /*!< in: fold */
/************************************************************//**
+Gets the rw_lock for a fold value in a hash table.
+@return rw_lock */
+UNIV_INLINE
+rw_lock_t*
+hash_get_lock(
+/*==========*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold); /*!< in: fold */
+/************************************************************//**
Reserves the mutex for a fold value in a hash table. */
UNIV_INTERN
void
@@ -411,10 +451,76 @@ hash_mutex_exit_all_but(
/*====================*/
hash_table_t* table, /*!< in: hash table */
mutex_t* keep_mutex); /*!< in: mutex to keep */
+/************************************************************//**
+s-lock a lock for a fold value in a hash table. */
+UNIV_INTERN
+void
+hash_lock_s(
+/*========*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold); /*!< in: fold */
+/************************************************************//**
+x-lock a lock for a fold value in a hash table. */
+UNIV_INTERN
+void
+hash_lock_x(
+/*========*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold); /*!< in: fold */
+/************************************************************//**
+unlock an s-lock for a fold value in a hash table. */
+UNIV_INTERN
+void
+hash_unlock_s(
+/*==========*/
+
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold); /*!< in: fold */
+/************************************************************//**
+unlock x-lock for a fold value in a hash table. */
+UNIV_INTERN
+void
+hash_unlock_x(
+/*==========*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold); /*!< in: fold */
+/************************************************************//**
+Reserves all the locks of a hash table, in an ascending order. */
+UNIV_INTERN
+void
+hash_lock_x_all(
+/*============*/
+ hash_table_t* table); /*!< in: hash table */
+/************************************************************//**
+Releases all the locks of a hash table, in an ascending order. */
+UNIV_INTERN
+void
+hash_unlock_x_all(
+/*==============*/
+ hash_table_t* table); /*!< in: hash table */
+/************************************************************//**
+Releases all but passed in lock of a hash table, */
+UNIV_INTERN
+void
+hash_unlock_x_all_but(
+/*==================*/
+ hash_table_t* table, /*!< in: hash table */
+ rw_lock_t* keep_lock); /*!< in: lock to keep */
+
#else /* !UNIV_HOTBACKUP */
# define hash_get_heap(table, fold) ((table)->heap)
# define hash_mutex_enter(table, fold) ((void) 0)
# define hash_mutex_exit(table, fold) ((void) 0)
+# define hash_mutex_enter_all(table) ((void) 0)
+# define hash_mutex_exit_all(table) ((void) 0)
+# define hash_mutex_exit_all_but(t, m) ((void) 0)
+# define hash_lock_s(t, f) ((void) 0)
+# define hash_lock_x(t, f) ((void) 0)
+# define hash_unlock_s(t, f) ((void) 0)
+# define hash_unlock_x(t, f) ((void) 0)
+# define hash_lock_x_all(t) ((void) 0)
+# define hash_unlock_x_all(t) ((void) 0)
+# define hash_unlock_x_all_but(t, l) ((void) 0)
#endif /* !UNIV_HOTBACKUP */
struct hash_cell_struct{
@@ -423,27 +529,40 @@ struct hash_cell_struct{
/* The hash table structure */
struct hash_table_struct {
+ enum hash_table_sync_t type; /*<! type of hash_table. */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
# ifndef UNIV_HOTBACKUP
- ibool adaptive;/* TRUE if this is the hash table of the
- adaptive hash index */
+ ibool adaptive;/* TRUE if this is the hash
+ table of the adaptive hash
+ index */
# endif /* !UNIV_HOTBACKUP */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- ulint n_cells;/* number of cells in the hash table */
- hash_cell_t* array; /*!< pointer to cell array */
+ ulint n_cells;/* number of cells in the hash table */
+ hash_cell_t* array; /*!< pointer to cell array */
#ifndef UNIV_HOTBACKUP
- ulint n_mutexes;/* if mutexes != NULL, then the number of
- mutexes, must be a power of 2 */
- mutex_t* mutexes;/* NULL, or an array of mutexes used to
- protect segments of the hash table */
- mem_heap_t** heaps; /*!< if this is non-NULL, hash chain nodes for
- external chaining can be allocated from these
- memory heaps; there are then n_mutexes many of
- these heaps */
+ ulint n_sync_obj;/* if sync_objs != NULL, then
+ the number of either the number
+ of mutexes or the number of
+ rw_locks depending on the type.
+ Must be a power of 2 */
+ union {
+ mutex_t* mutexes;/* NULL, or an array of mutexes
+ used to protect segments of the
+ hash table */
+ rw_lock_t* rw_locks;/* NULL, or an array of rw_lcoks
+ used to protect segments of the
+ hash table */
+ } sync_obj;
+
+ mem_heap_t** heaps; /*!< if this is non-NULL, hash
+ chain nodes for external chaining
+ can be allocated from these memory
+ heaps; there are then n_mutexes
+ many of these heaps */
#endif /* !UNIV_HOTBACKUP */
- mem_heap_t* heap;
+ mem_heap_t* heap;
#ifdef UNIV_DEBUG
- ulint magic_n;
+ ulint magic_n;
# define HASH_TABLE_MAGIC_N 76561114
#endif /* UNIV_DEBUG */
};
=== modified file 'storage/innobase/include/hash0hash.ic'
--- a/storage/innobase/include/hash0hash.ic revid:jimmy.yang@stripped
+++ b/storage/innobase/include/hash0hash.ic revid:inaam.rana@stripped
@@ -87,20 +87,21 @@ hash_calc_hash(
#ifndef UNIV_HOTBACKUP
/************************************************************//**
-Gets the mutex index for a fold value in a hash table.
-@return mutex number */
+Gets the sync object index for a fold value in a hash table.
+@return index */
UNIV_INLINE
ulint
-hash_get_mutex_no(
-/*==============*/
+hash_get_sync_obj_index(
+/*====================*/
hash_table_t* table, /*!< in: hash table */
ulint fold) /*!< in: fold */
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ut_ad(ut_is_2pow(table->n_mutexes));
+ ut_ad(table->type != HASH_TABLE_SYNC_NONE);
+ ut_ad(ut_is_2pow(table->n_sync_obj));
return(ut_2pow_remainder(hash_calc_hash(fold, table),
- table->n_mutexes));
+ table->n_sync_obj));
}
/************************************************************//**
@@ -115,7 +116,8 @@ hash_get_nth_heap(
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ut_ad(i < table->n_mutexes);
+ ut_ad(table->type != HASH_TABLE_SYNC_NONE);
+ ut_ad(i < table->n_sync_obj);
return(table->heaps[i]);
}
@@ -139,7 +141,7 @@ hash_get_heap(
return(table->heap);
}
- i = hash_get_mutex_no(table, fold);
+ i = hash_get_sync_obj_index(table, fold);
return(hash_get_nth_heap(table, i));
}
@@ -156,9 +158,10 @@ hash_get_nth_mutex(
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ut_ad(i < table->n_mutexes);
+ ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
+ ut_ad(i < table->n_sync_obj);
- return(table->mutexes + i);
+ return(table->sync_obj.mutexes + i);
}
/************************************************************//**
@@ -176,8 +179,47 @@ hash_get_mutex(
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- i = hash_get_mutex_no(table, fold);
+ i = hash_get_sync_obj_index(table, fold);
return(hash_get_nth_mutex(table, i));
}
+
+/************************************************************//**
+Gets the nth rw_lock in a hash table.
+@return rw_lock */
+UNIV_INLINE
+rw_lock_t*
+hash_get_nth_lock(
+/*==============*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint i) /*!< in: index of the rw_lock */
+{
+ ut_ad(table);
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
+ ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
+ ut_ad(i < table->n_sync_obj);
+
+ return(table->sync_obj.rw_locks + i);
+}
+
+/************************************************************//**
+Gets the rw_lock for a fold value in a hash table.
+@return rw_lock */
+UNIV_INLINE
+rw_lock_t*
+hash_get_lock(
+/*==========*/
+ hash_table_t* table, /*!< in: hash table */
+ ulint fold) /*!< in: fold */
+{
+ ulint i;
+
+ ut_ad(table);
+ ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
+
+ i = hash_get_sync_obj_index(table, fold);
+
+ return(hash_get_nth_lock(table, i));
+}
#endif /* !UNIV_HOTBACKUP */
=== modified file 'storage/innobase/include/srv0srv.h'
--- a/storage/innobase/include/srv0srv.h revid:jimmy.yang@stripped
+++ b/storage/innobase/include/srv0srv.h revid:inaam.rana@stripped
@@ -155,7 +155,7 @@ extern ibool srv_use_sys_malloc;
#endif /* UNIV_HOTBACKUP */
extern ulint srv_buf_pool_size; /*!< requested size in bytes */
extern ulint srv_buf_pool_instances; /*!< requested number of buffer pool instances */
-extern ulong srv_n_page_hash_mutexes;/*!< number of mutexes to
+extern ulong srv_n_page_hash_locks; /*!< number of locks to
protect buf_pool->page_hash */
extern ulint srv_buf_pool_old_size; /*!< previously requested size */
extern ulint srv_buf_pool_curr_size; /*!< current size in bytes */
=== modified file 'storage/innobase/include/sync0sync.h'
--- a/storage/innobase/include/sync0sync.h revid:jimmy.yang@stripped
+++ b/storage/innobase/include/sync0sync.h revid:inaam.rana@stripped
@@ -696,7 +696,7 @@ or row lock! */
can call routines there! Otherwise
the level is SYNC_MEM_HASH. */
#define SYNC_BUF_POOL 150 /* Buffer pool mutex */
-#define SYNC_BUF_PAGE_HASH 149 /* buf_pool->page_hash mutex */
+#define SYNC_BUF_PAGE_HASH 149 /* buf_pool->page_hash rw_lock */
#define SYNC_BUF_BLOCK 146 /* Block mutex */
#define SYNC_BUF_FLUSH_LIST 145 /* Buffer flush list mutex */
#define SYNC_DOUBLEWRITE 140
=== modified file 'storage/innobase/include/univ.i'
--- a/storage/innobase/include/univ.i revid:jimmy.yang@stripped
+++ b/storage/innobase/include/univ.i revid:inaam.rana@stripped
@@ -203,6 +203,9 @@ debugging redo log application problems.
#define UNIV_IBUF_COUNT_DEBUG /* debug the insert buffer;
this limits the database to IBUF_COUNT_N_SPACES and IBUF_COUNT_N_PAGES,
and the insert buffer must be empty when the database is started */
+#define UNIV_PERF_DEBUG /* debug flag that enables
+ light weight performance
+ related stuff. */
#define UNIV_SYNC_DEBUG /* debug mutex and latch
operations (very slow); also UNIV_DEBUG must be defined */
#define UNIV_SEARCH_DEBUG /* debug B-tree comparisons */
=== modified file 'storage/innobase/srv/srv0srv.c'
--- a/storage/innobase/srv/srv0srv.c revid:jimmy.yang@stripped
+++ b/storage/innobase/srv/srv0srv.c revid:inaam.rana@stripped
@@ -192,8 +192,8 @@ UNIV_INTERN my_bool srv_use_sys_malloc =
UNIV_INTERN ulint srv_buf_pool_size = ULINT_MAX;
/* requested number of buffer pool instances */
UNIV_INTERN ulint srv_buf_pool_instances = 1;
-/* number of mutexes to protect buf_pool->page_hash */
-UNIV_INTERN ulong srv_n_page_hash_mutexes = 256;
+/* number of locks to protect buf_pool->page_hash */
+UNIV_INTERN ulong srv_n_page_hash_locks = 16;
/* previously requested size */
UNIV_INTERN ulint srv_buf_pool_old_size;
/* current size in kilobytes */
=== modified file 'storage/innobase/sync/sync0sync.c'
--- a/storage/innobase/sync/sync0sync.c revid:jimmy.yang@stripped
+++ b/storage/innobase/sync/sync0sync.c revid:inaam.rana@stripped
@@ -1212,7 +1212,7 @@ sync_thread_add_level(
case SYNC_BUF_PAGE_HASH:
- /* Multiple page_hash mutexes are only allowed during
+ /* Multiple page_hash locks are only allowed during
buf_validate and that is where buf_pool mutex is already
held. */
/* Fall through */
Attachment: [text/bzr-bundle] bzr/inaam.rana@oracle.com-20101208153001-lm0v0sedavr75jqe.bundle
| Thread |
|---|
| • bzr commit into mysql-trunk-innodb branch (inaam.rana:3368) | Inaam Rana | 8 Dec |