Module Name:    src
Committed By:   ad
Date:           Thu Nov 21 20:51:05 UTC 2019

Modified Files:
        src/sys/kern: kern_synch.c

Log Message:
- Don't give up kpriority boost in preempt().  That's unfair and bad for
  interactive response.  It should only be dropped on final return to user.
- Clear l_dopreempt with atomics and add some comments around concurrency.
- Hold proc_lock over the lightning bolt and loadavg calc, no reason not to.
- cpu_did_preempt() is useless - don't call it.  Will remove soon.


To generate a diff of this commit:
cvs rdiff -u -r1.324 -r1.325 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_synch.c
diff -u src/sys/kern/kern_synch.c:1.324 src/sys/kern/kern_synch.c:1.325
--- src/sys/kern/kern_synch.c:1.324	Thu Oct  3 22:48:44 2019
+++ src/sys/kern/kern_synch.c	Thu Nov 21 20:51:05 2019
@@ -1,7 +1,7 @@
-/*	$NetBSD: kern_synch.c,v 1.324 2019/10/03 22:48:44 kamil Exp $	*/
+/*	$NetBSD: kern_synch.c,v 1.325 2019/11/21 20:51:05 ad Exp $	*/
 
 /*-
- * Copyright (c) 1999, 2000, 2004, 2006, 2007, 2008, 2009
+ * Copyright (c) 1999, 2000, 2004, 2006, 2007, 2008, 2009, 2019
  *    The NetBSD Foundation, Inc.
  * All rights reserved.
  *
@@ -69,7 +69,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.324 2019/10/03 22:48:44 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.325 2019/11/21 20:51:05 ad Exp $");
 
 #include "opt_kstack.h"
 #include "opt_dtrace.h"
@@ -272,6 +272,7 @@ yield(void)
 	lwp_lock(l);
 	KASSERT(lwp_locked(l, l->l_cpu->ci_schedstate.spc_lwplock));
 	KASSERT(l->l_stat == LSONPROC);
+	/* Voluntary - ditch kpriority boost. */
 	l->l_kpriority = false;
 	(void)mi_switch(l);
 	KERNEL_LOCK(l->l_biglocks, l);
@@ -290,7 +291,7 @@ preempt(void)
 	lwp_lock(l);
 	KASSERT(lwp_locked(l, l->l_cpu->ci_schedstate.spc_lwplock));
 	KASSERT(l->l_stat == LSONPROC);
-	l->l_kpriority = false;
+	/* Involuntary - keep kpriority boost. */
 	l->l_pflag |= LP_PREEMPTING;
 	(void)mi_switch(l);
 	KERNEL_LOCK(l->l_biglocks, l);
@@ -324,12 +325,12 @@ kpreempt(uintptr_t where)
 			 * been blocked", since we're going to
 			 * context switch.
 			 */
-			l->l_dopreempt = 0;
+			atomic_swap_uint(&l->l_dopreempt, 0);
 			return true;
 		}
 		if (__predict_false((l->l_flag & LW_IDLE) != 0)) {
 			/* Can't preempt idle loop, don't count as failure. */
-			l->l_dopreempt = 0;
+			atomic_swap_uint(&l->l_dopreempt, 0);
 			return true;
 		}
 		if (__predict_false(l->l_nopreempt != 0)) {
@@ -342,7 +343,7 @@ kpreempt(uintptr_t where)
 		}
 		if (__predict_false((l->l_pflag & LP_INTR) != 0)) {
 			/* Can't preempt soft interrupts yet. */
-			l->l_dopreempt = 0;
+			atomic_swap_uint(&l->l_dopreempt, 0);
 			failed = (uintptr_t)&is_softint;
 			break;
 		}
@@ -484,8 +485,11 @@ nextlwp(struct cpu_info *ci, struct sche
 	}
 
 	/*
-	 * Only clear want_resched if there are no pending (slow)
-	 * software interrupts.
+	 * Only clear want_resched if there are no pending (slow) software
+	 * interrupts.  We can do this without an atomic, because no new
+	 * LWPs can appear in the queue due to our hold on spc_mutex, and
+	 * the update to ci_want_resched will become globally visible before
+	 * the release of spc_mutex becomes globally visible.
 	 */
 	ci->ci_want_resched = ci->ci_data.cpu_softints;
 	spc->spc_flags &= ~SPCF_SWITCHCLEAR;
@@ -606,10 +610,11 @@ mi_switch(lwp_t *l)
 	}
 
 	/*
-	 * Preemption related tasks.  Must be done with the current
-	 * CPU locked.
+	 * Preemption related tasks.  Must be done holding spc_mutex.  Clear
+	 * l_dopreempt without an atomic - it's only ever set non-zero by
+	 * sched_resched_cpu() which also holds spc_mutex, and only ever
+	 * cleared by the LWP itself (us) with atomics when not under lock.
 	 */
-	cpu_did_resched(l);
 	l->l_dopreempt = 0;
 	if (__predict_false(l->l_pfailaddr != 0)) {
 		LOCKSTAT_FLAG(lsflag);
@@ -830,12 +835,6 @@ lwp_exit_switchaway(lwp_t *l)
 	 */
 	ci->ci_data.cpu_onproc = newl;
 
-	/*
-	 * Preemption related tasks.  Must be done with the current
-	 * CPU locked.
-	 */
-	cpu_did_resched(l);
-
 	/* Unlock the run queue. */
 	spc_unlock(ci);
 
@@ -1215,7 +1214,6 @@ sched_pstats(void)
 			psignal(p, sig);
 		}
 	}
-	mutex_exit(proc_lock);
 
 	/* Load average calculation. */
 	if (__predict_false(lavg_count == 0)) {
@@ -1229,4 +1227,6 @@ sched_pstats(void)
 
 	/* Lightning bolt. */
 	cv_broadcast(&lbolt);
+
+	mutex_exit(proc_lock);
 }

Reply via email to