[master] 4d8aa0c ban lurker: When loosing the lock race to lookup, continue with other objects if possible
Nils Goroll
nils.goroll at uplex.de
Thu May 19 17:55:07 CEST 2016
commit 4d8aa0c306664ca93194d80de82ba108b712f36e
Author: Nils Goroll <nils.goroll at uplex.de>
Date: Tue May 3 16:13:14 2016 +0200
ban lurker: When loosing the lock race to lookup, continue with other objects if possible
diff --git a/bin/varnishd/cache/cache_ban_lurker.c b/bin/varnishd/cache/cache_ban_lurker.c
index 6b33465..2712ef3 100644
--- a/bin/varnishd/cache/cache_ban_lurker.c
+++ b/bin/varnishd/cache/cache_ban_lurker.c
@@ -36,7 +36,8 @@
#include "hash/hash_slinger.h"
#include "vtim.h"
-static struct objcore oc_marker = { .magic = OBJCORE_MAGIC, };
+static struct objcore oc_mark_cnt = { .magic = OBJCORE_MAGIC, };
+static struct objcore oc_mark_end = { .magic = OBJCORE_MAGIC, };
static unsigned ban_batch;
static unsigned ban_generation;
@@ -110,23 +111,56 @@ ban_cleantail(const struct ban *victim)
* makes most sense in HSH_Lookup(), but we come the other way.
* We optimistically try to get them the other way, and get out of
* the way if that fails, and retry again later.
+ *
+ * To avoid hammering on contested ocs, we first move those behind a marker
+ * once. When we only have contested ocs left, we stop moving them around and
+ * re-try them in order.
*/
static struct objcore *
ban_lurker_getfirst(struct vsl_log *vsl, struct ban *bt)
{
struct objhead *oh;
- struct objcore *oc;
+ struct objcore *oc, *noc;
+ int move_oc = 1;
+
+ Lck_Lock(&ban_mtx);
+ oc = VTAILQ_FIRST(&bt->objcore);
while (1) {
- Lck_Lock(&ban_mtx);
- oc = VTAILQ_FIRST(&bt->objcore);
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
- if (oc == &oc_marker) {
- VTAILQ_REMOVE(&bt->objcore, oc, ban_list);
+
+ if (oc == &oc_mark_cnt) {
+ if (VTAILQ_NEXT(oc, ban_list) == &oc_mark_end) {
+ /* done with this ban's oc list */
+ VTAILQ_REMOVE(&bt->objcore, &oc_mark_cnt,
+ ban_list);
+ VTAILQ_REMOVE(&bt->objcore, &oc_mark_end,
+ ban_list);
+ oc = NULL;
+ break;
+ }
+ oc = VTAILQ_NEXT(oc, ban_list);
+ CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
+ move_oc = 0;
+ } else if (oc == &oc_mark_end) {
+ assert(move_oc == 0);
+
+ /* hold off to give lookup a chance and reiterate */
Lck_Unlock(&ban_mtx);
- return (NULL);
+ VSC_C_main->bans_lurker_contention++;
+ VSL_Flush(vsl, 0);
+ VTIM_sleep(cache_param->ban_lurker_holdoff);
+ Lck_Lock(&ban_mtx);
+
+ oc = VTAILQ_FIRST(&bt->objcore);
+ assert(oc == &oc_mark_cnt);
+ continue;
}
+
+ assert(oc != &oc_mark_cnt);
+ assert(oc != &oc_mark_end);
+
oh = oc->objhead;
CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
if (!Lck_Trylock(&oh->mtx)) {
@@ -135,24 +169,28 @@ ban_lurker_getfirst(struct vsl_log *vsl, struct ban *bt)
} else {
/*
* We got the lock, and the oc is not being
- * dismantled under our feet.
+ * dismantled under our feet - grab a ref
*/
AZ(oc->flags & OC_F_BUSY);
oc->refcnt += 1;
VTAILQ_REMOVE(&bt->objcore, oc, ban_list);
VTAILQ_INSERT_TAIL(&bt->objcore, oc, ban_list);
Lck_Unlock(&oh->mtx);
- Lck_Unlock(&ban_mtx);
break;
}
}
- /* Try again, later */
- Lck_Unlock(&ban_mtx);
- VSC_C_main->bans_lurker_contention++;
- VSL_Flush(vsl, 0);
- VTIM_sleep(cache_param->ban_lurker_holdoff);
+ noc = VTAILQ_NEXT(oc, ban_list);
+
+ if (move_oc) {
+ /* contested ocs go between the two markers */
+ VTAILQ_REMOVE(&bt->objcore, oc, ban_list);
+ VTAILQ_INSERT_BEFORE(&oc_mark_end, oc, ban_list);
+ }
+
+ oc = noc;
}
+ Lck_Unlock(&ban_mtx);
return (oc);
}
@@ -166,12 +204,14 @@ ban_lurker_test_ban(struct worker *wrk, struct vsl_log *vsl, struct ban *bt,
int i;
/*
- * First see if there is anything to do, and if so, insert marker
+ * First see if there is anything to do, and if so, insert markers
*/
Lck_Lock(&ban_mtx);
oc = VTAILQ_FIRST(&bt->objcore);
- if (oc != NULL)
- VTAILQ_INSERT_TAIL(&bt->objcore, &oc_marker, ban_list);
+ if (oc != NULL) {
+ VTAILQ_INSERT_TAIL(&bt->objcore, &oc_mark_cnt, ban_list);
+ VTAILQ_INSERT_TAIL(&bt->objcore, &oc_mark_end, ban_list);
+ }
Lck_Unlock(&ban_mtx);
if (oc == NULL)
return;
More information about the varnish-commit
mailing list