svn commit: r305671 - head/sys/kern
Mateusz Guzik
mjg at FreeBSD.org
Fri Sep 9 19:13:04 UTC 2016
Author: mjg
Date: Fri Sep 9 19:13:02 2016
New Revision: 305671
URL: https://svnweb.freebsd.org/changeset/base/305671
Log:
locks: add backoff for spin mutexes and thread lock
Reviewed by: jhb
Modified:
head/sys/kern/kern_mutex.c
Modified: head/sys/kern/kern_mutex.c
==============================================================================
--- head/sys/kern/kern_mutex.c Fri Sep 9 18:49:45 2016 (r305670)
+++ head/sys/kern/kern_mutex.c Fri Sep 9 19:13:02 2016 (r305671)
@@ -170,6 +170,36 @@ mtx_delay_sysinit(void *dummy)
LOCK_DELAY_SYSINIT(mtx_delay_sysinit);
#endif
+static SYSCTL_NODE(_debug, OID_AUTO, mtx_spin, CTLFLAG_RD, NULL,
+ "mtx spin debugging");
+
+static struct lock_delay_config mtx_spin_delay = {
+ .initial = 1000,
+ .step = 500,
+ .min = 100,
+ .max = 5000,
+};
+
+SYSCTL_INT(_debug_mtx_spin, OID_AUTO, delay_initial, CTLFLAG_RW,
+ &mtx_spin_delay.initial, 0, "");
+SYSCTL_INT(_debug_mtx_spin, OID_AUTO, delay_step, CTLFLAG_RW, &mtx_spin_delay.step,
+ 0, "");
+SYSCTL_INT(_debug_mtx_spin, OID_AUTO, delay_min, CTLFLAG_RW, &mtx_spin_delay.min,
+ 0, "");
+SYSCTL_INT(_debug_mtx_spin, OID_AUTO, delay_max, CTLFLAG_RW, &mtx_spin_delay.max,
+ 0, "");
+
+static void
+mtx_spin_delay_sysinit(void *dummy)
+{
+
+ mtx_spin_delay.initial = mp_ncpus * 25;
+ mtx_spin_delay.step = (mp_ncpus * 25) / 2;
+ mtx_spin_delay.min = mp_ncpus * 5;
+ mtx_spin_delay.max = mp_ncpus * 25 * 10;
+}
+LOCK_DELAY_SYSINIT(mtx_spin_delay_sysinit);
+
/*
* System-wide mutexes
*/
@@ -641,7 +671,7 @@ _mtx_lock_spin_cookie(volatile uintptr_t
const char *file, int line)
{
struct mtx *m;
- int i = 0;
+ struct lock_delay_arg lda;
#ifdef LOCK_PROFILING
int contested = 0;
uint64_t waittime = 0;
@@ -653,6 +683,7 @@ _mtx_lock_spin_cookie(volatile uintptr_t
if (SCHEDULER_STOPPED())
return;
+ lock_delay_arg_init(&lda, &mtx_spin_delay);
m = mtxlock2mtx(c);
if (LOCK_LOG_TEST(&m->lock_object, opts))
@@ -673,11 +704,13 @@ _mtx_lock_spin_cookie(volatile uintptr_t
/* Give interrupts a chance while we spin. */
spinlock_exit();
while (m->mtx_lock != MTX_UNOWNED) {
- if (i++ < 10000000) {
- cpu_spinwait();
+ if (lda.spin_cnt < 10000000) {
+ lock_delay(&lda);
continue;
}
- if (i < 60000000 || kdb_active || panicstr != NULL)
+ lda.spin_cnt++;
+ if (lda.spin_cnt < 60000000 || kdb_active ||
+ panicstr != NULL)
DELAY(1);
else
_mtx_lock_spin_failed(m);
@@ -708,7 +741,7 @@ thread_lock_flags_(struct thread *td, in
{
struct mtx *m;
uintptr_t tid;
- int i;
+ struct lock_delay_arg lda;
#ifdef LOCK_PROFILING
int contested = 0;
uint64_t waittime = 0;
@@ -717,7 +750,6 @@ thread_lock_flags_(struct thread *td, in
int64_t spin_time = 0;
#endif
- i = 0;
tid = (uintptr_t)curthread;
if (SCHEDULER_STOPPED()) {
@@ -730,6 +762,8 @@ thread_lock_flags_(struct thread *td, in
return;
}
+ lock_delay_arg_init(&lda, &mtx_spin_delay);
+
#ifdef KDTRACE_HOOKS
spin_time -= lockstat_nsecs(&td->td_lock->lock_object);
#endif
@@ -763,14 +797,17 @@ retry:
/* Give interrupts a chance while we spin. */
spinlock_exit();
while (m->mtx_lock != MTX_UNOWNED) {
- if (i++ < 10000000)
+ if (lda.spin_cnt < 10000000) {
+ lock_delay(&lda);
+ } else {
+ lda.spin_cnt++;
+ if (lda.spin_cnt < 60000000 ||
+ kdb_active || panicstr != NULL)
+ DELAY(1);
+ else
+ _mtx_lock_spin_failed(m);
cpu_spinwait();
- else if (i < 60000000 ||
- kdb_active || panicstr != NULL)
- DELAY(1);
- else
- _mtx_lock_spin_failed(m);
- cpu_spinwait();
+ }
if (m != td->td_lock)
goto retry;
}
More information about the svn-src-head
mailing list