summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsueloverso <sue@mongodb.com>2016-06-14 00:35:46 -0400
committerMichael Cahill <michael.cahill@mongodb.com>2016-06-14 14:35:46 +1000
commit66a13643f484caedf497c67572f3ab73fa603f64 (patch)
tree68a7e22fc292229b2850b56396ad6054b41f2fc3
parent398b1da2eabe604f0d9d3d4bb1a058b7d260af1e (diff)
downloadmongo-66a13643f484caedf497c67572f3ab73fa603f64.tar.gz
WT-2698 Change flag into atomically manipulated field to avoid deadlock. (#2796)
-rw-r--r--src/conn/conn_dhandle.c11
-rw-r--r--src/evict/evict_lru.c14
-rw-r--r--src/include/cache.h15
3 files changed, 24 insertions, 16 deletions
diff --git a/src/conn/conn_dhandle.c b/src/conn/conn_dhandle.c
index 9c376d1c320..08fb2b24468 100644
--- a/src/conn/conn_dhandle.c
+++ b/src/conn/conn_dhandle.c
@@ -544,6 +544,7 @@ __wt_conn_dhandle_discard_single(
WT_DATA_HANDLE *dhandle;
WT_DECL_RET;
int tret;
+ bool set_pass_intr;
dhandle = session->dhandle;
@@ -562,13 +563,17 @@ __wt_conn_dhandle_discard_single(
* Kludge: interrupt the eviction server in case it is holding the
* handle list lock.
*/
- if (!F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST))
- F_SET(S2C(session)->cache, WT_CACHE_PASS_INTERRUPT);
+ set_pass_intr = false;
+ if (!F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST)) {
+ set_pass_intr = true;
+ (void)__wt_atomic_add32(&S2C(session)->cache->pass_intr, 1);
+ }
/* Try to remove the handle, protected by the data handle lock. */
WT_WITH_HANDLE_LIST_LOCK(session,
tret = __conn_dhandle_remove(session, final));
- F_CLR(S2C(session)->cache, WT_CACHE_PASS_INTERRUPT);
+ if (set_pass_intr)
+ (void)__wt_atomic_sub32(&S2C(session)->cache->pass_intr, 1);
WT_TRET(tret);
/*
diff --git a/src/evict/evict_lru.c b/src/evict/evict_lru.c
index 382d6ee1653..b6a3d114380 100644
--- a/src/evict/evict_lru.c
+++ b/src/evict/evict_lru.c
@@ -273,7 +273,7 @@ __evict_server(WT_SESSION_IMPL *session, bool *did_work)
if (!F_ISSET(cache, WT_CACHE_STUCK)) {
for (spins = 0; (ret = __wt_spin_trylock(
session, &conn->dhandle_lock)) == EBUSY &&
- !F_ISSET(cache, WT_CACHE_PASS_INTERRUPT); spins++) {
+ cache->pass_intr == 0; spins++) {
if (spins < WT_THOUSAND)
__wt_yield();
else
@@ -610,7 +610,7 @@ __evict_pass(WT_SESSION_IMPL *session)
* If there is a request to clear eviction walks, do that now,
* before checking if the cache is full.
*/
- if (F_ISSET(cache, WT_CACHE_PASS_INTERRUPT))
+ if (cache->pass_intr != 0)
break;
/*
@@ -797,13 +797,13 @@ __wt_evict_file_exclusive_on(WT_SESSION_IMPL *session)
* this point.
*/
F_SET(btree, WT_BTREE_NO_EVICTION);
- F_SET(cache, WT_CACHE_PASS_INTERRUPT);
+ (void)__wt_atomic_add32(&cache->pass_intr, 1);
WT_FULL_BARRIER();
/* Clear any existing LRU eviction walk for the file. */
WT_WITH_PASS_LOCK(session, ret,
ret = __evict_clear_walk(session));
- F_CLR(cache, WT_CACHE_PASS_INTERRUPT);
+ (void)__wt_atomic_sub32(&cache->pass_intr, 1);
WT_ERR(ret);
/*
@@ -1087,7 +1087,7 @@ retry: while (slot < max_entries && ret == 0) {
* If another thread is waiting on the eviction server to clear
* the walk point in a tree, give up.
*/
- if (F_ISSET(cache, WT_CACHE_PASS_INTERRUPT))
+ if (cache->pass_intr != 0)
break;
/*
@@ -1097,7 +1097,7 @@ retry: while (slot < max_entries && ret == 0) {
if (!dhandle_locked) {
for (spins = 0; (ret = __wt_spin_trylock(
session, &conn->dhandle_lock)) == EBUSY &&
- !F_ISSET(cache, WT_CACHE_PASS_INTERRUPT);
+ cache->pass_intr == 0;
spins++) {
if (spins < WT_THOUSAND)
__wt_yield();
@@ -1223,7 +1223,7 @@ retry: while (slot < max_entries && ret == 0) {
* Try two passes through all the files, give up when we have some
* candidates and we aren't finding more.
*/
- if (!F_ISSET(cache, WT_CACHE_PASS_INTERRUPT) && ret == 0 &&
+ if (cache->pass_intr == 0 && ret == 0 &&
slot < max_entries && (retries < 2 ||
(retries < 10 &&
!FLD_ISSET(cache->state, WT_EVICT_PASS_WOULD_BLOCK) &&
diff --git a/src/include/cache.h b/src/include/cache.h
index 411aebacad7..24e12f5af63 100644
--- a/src/include/cache.h
+++ b/src/include/cache.h
@@ -149,16 +149,19 @@ struct __wt_cache {
#define WT_EVICT_PASS_DIRTY 0x04
#define WT_EVICT_PASS_WOULD_BLOCK 0x08
uint32_t state;
+ /*
+ * Pass interrupt counter.
+ */
+ uint32_t pass_intr; /* Interrupt eviction pass. */
/*
* Flags.
*/
-#define WT_CACHE_PASS_INTERRUPT 0x01 /* Stop eviction walks */
-#define WT_CACHE_POOL_MANAGER 0x02 /* The active cache pool manager */
-#define WT_CACHE_POOL_RUN 0x04 /* Cache pool thread running */
-#define WT_CACHE_STUCK 0x08 /* Eviction server is stuck */
-#define WT_CACHE_WALK_REVERSE 0x10 /* Scan backwards for candidates */
-#define WT_CACHE_WOULD_BLOCK 0x20 /* Pages that would block apps */
+#define WT_CACHE_POOL_MANAGER 0x01 /* The active cache pool manager */
+#define WT_CACHE_POOL_RUN 0x02 /* Cache pool thread running */
+#define WT_CACHE_STUCK 0x04 /* Eviction server is stuck */
+#define WT_CACHE_WALK_REVERSE 0x08 /* Scan backwards for candidates */
+#define WT_CACHE_WOULD_BLOCK 0x10 /* Pages that would block apps */
uint32_t flags;
};