aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/subr_lock.c
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2016-08-01 21:48:37 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2016-08-01 21:48:37 +0000
commit1ada904147c50b3aad694c25fd46409324e79f36 (patch)
treeb028139badd977a970d22c6915536a75e4786fcf /sys/kern/subr_lock.c
parente72a746a6edb54194f8c97ff967c6ea489e26dc8 (diff)
Implement trivial backoff for locking primitives.
All current spinning loops retry an atomic op the first chance they get, which leads to performance degradation under load. One classic solution to the problem consists of delaying the test to an extent. This implementation has a trivial linear increment and a random factor for each attempt. For simplicity, this first thouch implementation only modifies spinning loops where the lock owner is running. spin mutexes and thread lock were not modified. Current parameters are autotuned on boot based on mp_cpus. Autotune factors are very conservative and are subject to change later. Reviewed by: kib, jhb Tested by: pho MFC after: 1 week
Notes
Notes: svn path=/head/; revision=303643
Diffstat (limited to 'sys/kern/subr_lock.c')
-rw-r--r--sys/kern/subr_lock.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/sys/kern/subr_lock.c b/sys/kern/subr_lock.c
index e78d5a9a4b18..bfe189d4363e 100644
--- a/sys/kern/subr_lock.c
+++ b/sys/kern/subr_lock.c
@@ -103,6 +103,34 @@ lock_destroy(struct lock_object *lock)
lock->lo_flags &= ~LO_INITIALIZED;
}
+void
+lock_delay(struct lock_delay_arg *la)
+{
+ u_int i, delay, backoff, min, max;
+ struct lock_delay_config *lc = la->config;
+
+ delay = la->delay;
+
+ if (delay == 0)
+ delay = lc->initial;
+ else {
+ delay += lc->step;
+ max = lc->max;
+ if (delay > max)
+ delay = max;
+ }
+
+ backoff = cpu_ticks() % delay;
+ min = lc->min;
+ if (backoff < min)
+ backoff = min;
+ for (i = 0; i < backoff; i++)
+ cpu_spinwait();
+
+ la->delay = delay;
+ la->spin_cnt += backoff;
+}
+
#ifdef DDB
DB_SHOW_COMMAND(lock, db_show_lock)
{