Module Name: src Committed By: ad Date: Fri Jan 24 20:05:15 UTC 2020
Modified Files: src/sys/kern: kern_lock.c kern_synch.c Log Message: Carefully put kernel_lock back the way it was, and add a comment hinting that changing it is not a good idea, and hopefully nobody will ever try to change it ever again. To generate a diff of this commit: cvs rdiff -u -r1.166 -r1.167 src/sys/kern/kern_lock.c cvs rdiff -u -r1.337 -r1.338 src/sys/kern/kern_synch.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_lock.c diff -u src/sys/kern/kern_lock.c:1.166 src/sys/kern/kern_lock.c:1.167 --- src/sys/kern/kern_lock.c:1.166 Wed Jan 22 13:19:33 2020 +++ src/sys/kern/kern_lock.c Fri Jan 24 20:05:15 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_lock.c,v 1.166 2020/01/22 13:19:33 ad Exp $ */ +/* $NetBSD: kern_lock.c,v 1.167 2020/01/24 20:05:15 ad Exp $ */ /*- * Copyright (c) 2002, 2006, 2007, 2008, 2009, 2020 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_lock.c,v 1.166 2020/01/22 13:19:33 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_lock.c,v 1.167 2020/01/24 20:05:15 ad Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -156,6 +156,11 @@ _kernel_lock_dump(const volatile void *j /* * Acquire 'nlocks' holds on the kernel lock. + * + * Although it may not look it, this is one of the most central, intricate + * routines in the kernel, and tons of code elsewhere depends on its exact + * behaviour. If you change something in here, expect it to bite you in the + * rear. */ void _kernel_lock(int nlocks) @@ -164,7 +169,6 @@ _kernel_lock(int nlocks) LOCKSTAT_TIMER(spintime); LOCKSTAT_FLAG(lsflag); struct lwp *owant; - u_int count; #ifdef LOCKDEBUG u_int spins = 0; #endif @@ -210,16 +214,15 @@ _kernel_lock(int nlocks) */ membar_producer(); owant = ci->ci_biglock_wanted; + ci->ci_biglock_wanted = l; /* - * Stay pinned to the CPU and spin until we acquire the lock. Once - * we have it, record the time spent with lockstat. + * Spin until we acquire the lock. Once we have it, record the + * time spent with lockstat. */ - l->l_nopreempt++; LOCKSTAT_ENTER(lsflag); LOCKSTAT_START_TIMER(lsflag, spintime); - count = SPINLOCK_BACKOFF_MIN; do { splx(s); while (__SIMPLELOCK_LOCKED_P(kernel_lock)) { @@ -230,24 +233,12 @@ _kernel_lock(int nlocks) _KERNEL_LOCK_ABORT("spinout"); } #endif - SPINLOCK_BACKOFF(count); - if (count == SPINLOCK_BACKOFF_MAX) { - /* Ok, waiting for real. */ - ci->ci_biglock_wanted = l; - } } s = splvm(); } while (!__cpu_simple_lock_try(kernel_lock)); - /* - * Got it; not re-enable preemption, although we now can't do a - * preemption as kernel_lock is held! - */ - l->l_nopreempt--; ci->ci_biglock_count = nlocks; l->l_blcnt = nlocks; - splx(s); - LOCKSTAT_STOP_TIMER(lsflag, spintime); LOCKDEBUG_LOCKED(kernel_lock_dodebug, kernel_lock, NULL, RETURN_ADDRESS, 0); @@ -256,6 +247,7 @@ _kernel_lock(int nlocks) LB_KERNEL_LOCK | LB_SPIN, 1, spintime, RETURN_ADDRESS); } LOCKSTAT_EXIT(lsflag); + splx(s); /* * Now that we have kernel_lock, reset ci_biglock_wanted. This Index: src/sys/kern/kern_synch.c diff -u src/sys/kern/kern_synch.c:1.337 src/sys/kern/kern_synch.c:1.338 --- src/sys/kern/kern_synch.c:1.337 Wed Jan 22 13:19:33 2020 +++ src/sys/kern/kern_synch.c Fri Jan 24 20:05:15 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_synch.c,v 1.337 2020/01/22 13:19:33 ad Exp $ */ +/* $NetBSD: kern_synch.c,v 1.338 2020/01/24 20:05:15 ad Exp $ */ /*- * Copyright (c) 1999, 2000, 2004, 2006, 2007, 2008, 2009, 2019 @@ -69,7 +69,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.337 2020/01/22 13:19:33 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.338 2020/01/24 20:05:15 ad Exp $"); #include "opt_kstack.h" #include "opt_dtrace.h" @@ -353,7 +353,8 @@ kpreempt(uintptr_t where) break; } s = splsched(); - if (__predict_false(l->l_blcnt != 0)) { + if (__predict_false(l->l_blcnt != 0 || + curcpu()->ci_biglock_wanted != NULL)) { /* Hold or want kernel_lock, code is not MT safe. */ splx(s); if ((dop & DOPREEMPT_COUNTED) == 0) {