summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dist/filelist1
-rw-r--r--src/conn/conn_cache.c6
-rw-r--r--src/evict/evict_lru.c9
-rw-r--r--src/include/extern.h4
-rw-r--r--src/include/mutex.h7
-rw-r--r--src/support/cond_auto.c115
6 files changed, 135 insertions, 7 deletions
diff --git a/dist/filelist b/dist/filelist
index 4ed7d7e3beb..350e0c50087 100644
--- a/dist/filelist
+++ b/dist/filelist
@@ -153,6 +153,7 @@ src/session/session_compact.c
src/session/session_dhandle.c
src/session/session_salvage.c
src/support/cksum.c
+src/support/cond_auto.c
src/support/crypto.c
src/support/err.c
src/support/filename.c
diff --git a/src/conn/conn_cache.c b/src/conn/conn_cache.c
index 1831aad5895..0f370856881 100644
--- a/src/conn/conn_cache.c
+++ b/src/conn/conn_cache.c
@@ -147,8 +147,8 @@ __wt_cache_create(WT_SESSION_IMPL *session, const char *cfg[])
WT_ERR_MSG(session, EINVAL,
"eviction target must be lower than the eviction trigger");
- WT_ERR(__wt_cond_alloc(session,
- "cache eviction server", false, &cache->evict_cond));
+ WT_ERR(__wt_cond_auto_alloc(session, "cache eviction server",
+ false, 10000, WT_MILLION, &cache->evict_cond));
WT_ERR(__wt_cond_alloc(session,
"eviction waiters", false, &cache->evict_waiter_cond));
WT_ERR(__wt_spin_init(session, &cache->evict_lock, "cache eviction"));
@@ -246,7 +246,7 @@ __wt_cache_destroy(WT_SESSION_IMPL *session)
" bytes dirty and %" PRIu64 " pages dirty",
cache->bytes_dirty, cache->pages_dirty);
- WT_TRET(__wt_cond_destroy(session, &cache->evict_cond));
+ WT_TRET(__wt_cond_auto_destroy(session, &cache->evict_cond));
WT_TRET(__wt_cond_destroy(session, &cache->evict_waiter_cond));
__wt_spin_destroy(session, &cache->evict_lock);
__wt_spin_destroy(session, &cache->evict_walk_lock);
diff --git a/src/evict/evict_lru.c b/src/evict/evict_lru.c
index 884c08a02df..46a40dc124f 100644
--- a/src/evict/evict_lru.c
+++ b/src/evict/evict_lru.c
@@ -175,8 +175,8 @@ __evict_server(void *arg)
WT_SESSION_IMPL *session;
#ifdef HAVE_DIAGNOSTIC
struct timespec now, stuck_ts;
- uint64_t pages_evicted = 0;
#endif
+ uint64_t pages_evicted = 0;
u_int spins;
session = arg;
@@ -219,11 +219,11 @@ __evict_server(void *arg)
/* Next time we wake up, reverse the sweep direction. */
cache->flags ^= WT_CACHE_WALK_REVERSE;
-#ifdef HAVE_DIAGNOSTIC
pages_evicted = 0;
} else if (pages_evicted != cache->pages_evict) {
- WT_ERR(__wt_epoch(session, &stuck_ts));
pages_evicted = cache->pages_evict;
+#ifdef HAVE_DIAGNOSTIC
+ WT_ERR(__wt_epoch(session, &stuck_ts));
} else {
/* After being stuck for 5 minutes, give up. */
WT_ERR(__wt_epoch(session, &now));
@@ -238,7 +238,8 @@ __evict_server(void *arg)
WT_ERR(__wt_verbose(session, WT_VERB_EVICTSERVER, "sleeping"));
/* Don't rely on signals: check periodically. */
- WT_ERR(__wt_cond_wait(session, cache->evict_cond, 100000));
+ WT_ERR(__wt_cond_auto_wait(
+ session, cache->evict_cond, pages_evicted != 0));
WT_ERR(__wt_verbose(session, WT_VERB_EVICTSERVER, "waking"));
}
diff --git a/src/include/extern.h b/src/include/extern.h
index 55b0b8cd7ff..e52cf51779b 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -637,6 +637,10 @@ extern int __wt_session_lock_checkpoint(WT_SESSION_IMPL *session, const char *ch
extern int __wt_salvage(WT_SESSION_IMPL *session, const char *cfg[]);
extern uint32_t __wt_cksum(const void *chunk, size_t len);
extern void __wt_cksum_init(void);
+extern int __wt_cond_auto_alloc( WT_SESSION_IMPL *session, const char *name, bool is_signalled, uint64_t min, uint64_t max, WT_CONDVAR **condp);
+extern int __wt_cond_auto_wait_signal( WT_SESSION_IMPL *session, WT_CONDVAR *cond, bool progress, bool *signalled);
+extern int __wt_cond_auto_wait( WT_SESSION_IMPL *session, WT_CONDVAR *cond, bool progress);
+extern int __wt_cond_auto_destroy(WT_SESSION_IMPL *session, WT_CONDVAR **condp);
extern int __wt_decrypt(WT_SESSION_IMPL *session, WT_ENCRYPTOR *encryptor, size_t skip, WT_ITEM *in, WT_ITEM *out);
extern int __wt_encrypt(WT_SESSION_IMPL *session, WT_KEYED_ENCRYPTOR *kencryptor, size_t skip, WT_ITEM *in, WT_ITEM *out);
extern void __wt_encrypt_size(WT_SESSION_IMPL *session, WT_KEYED_ENCRYPTOR *kencryptor, size_t incoming_size, size_t *sizep);
diff --git a/src/include/mutex.h b/src/include/mutex.h
index f798bfb3ece..04679884930 100644
--- a/src/include/mutex.h
+++ b/src/include/mutex.h
@@ -20,6 +20,13 @@ struct __wt_condvar {
int waiters; /* Numbers of waiters, or
-1 if signalled with no waiters. */
+ /*
+ * The following fields are only used for automatically adjusting
+ * condition variables. They could be in a separate structure.
+ */
+ uint64_t min_wait; /* Minimum wait duration */
+ uint64_t max_wait; /* Maximum wait duration */
+ uint64_t prev_wait; /* Wait duration used last time */
};
/*
diff --git a/src/support/cond_auto.c b/src/support/cond_auto.c
new file mode 100644
index 00000000000..0c255bd1c98
--- /dev/null
+++ b/src/support/cond_auto.c
@@ -0,0 +1,115 @@
+/*-
+ * Public Domain 2014-2016 MongoDB, Inc.
+ * Public Domain 2008-2014 WiredTiger, Inc.
+ *
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "wt_internal.h"
+
+/*
+ * This is an implementation of condition variables that automatically adjust
+ * the wait time depending on whether the wake is resulting in useful work.
+ */
+
+/*
+ * __wt_cond_auto_alloc --
+ * Allocate and initialize an automatically adjusting condition variable.
+ */
+int
+__wt_cond_auto_alloc(
+ WT_SESSION_IMPL *session, const char *name,
+ bool is_signalled, uint64_t min, uint64_t max, WT_CONDVAR **condp)
+{
+ WT_CONDVAR *cond;
+
+ WT_RET(__wt_cond_alloc(session, name, is_signalled, condp));
+ cond = *condp;
+
+ cond->min_wait = min;
+ cond->max_wait = max;
+ cond->prev_wait = min;
+
+ return (0);
+}
+
+/*
+ * __wt_cond_auto_wait_signal --
+ * Wait on a mutex, optionally timing out. If we get it before the time
+ * out period expires, let the caller know.
+ * TODO: Can this version of the API be removed, now that we have the
+ * auto adjusting condition variables?
+ */
+int
+__wt_cond_auto_wait_signal(
+ WT_SESSION_IMPL *session, WT_CONDVAR *cond, bool progress, bool *signalled)
+{
+ uint64_t delta;
+
+ if (progress)
+ cond->prev_wait = cond->min_wait;
+ else {
+ delta = WT_MAX(1, (cond->max_wait - cond->min_wait) / 10);
+ cond->prev_wait = WT_MIN(
+ cond->max_wait, cond->prev_wait + delta);
+ }
+
+ WT_RET(__wt_cond_wait_signal(
+ session, cond, cond->prev_wait, signalled));
+
+ if (*signalled)
+ cond->prev_wait = cond->min_wait;
+
+ return (0);
+}
+
+/*
+ * __wt_cond_auto_wait --
+ * Wait on a mutex, optionally timing out. If we get it before the time
+ * out period expires, let the caller know.
+ */
+int
+__wt_cond_auto_wait(
+ WT_SESSION_IMPL *session, WT_CONDVAR *cond, bool progress)
+{
+ bool signalled;
+
+ /*
+ * Call the signal version so the wait period is reset if the
+ * condition is woken explicitly.
+ */
+ WT_RET(__wt_cond_auto_wait_signal(session, cond, progress, &signalled));
+
+ return (0);
+}
+
+/*
+ * __wt_cond_auto_destroy --
+ * Destroy a condition variable.
+ */
+int
+__wt_cond_auto_destroy(WT_SESSION_IMPL *session, WT_CONDVAR **condp)
+{
+ return (__wt_cond_destroy(session, condp));
+}