git: 1029dab63457 - main - mi_switch(): clean up switch types and their usage

From: Mitchell Horne <mhorne_at_FreeBSD.org>
Date: Thu, 09 Feb 2023 16:02:46 UTC
The branch main has been updated by mhorne:

URL: https://cgit.FreeBSD.org/src/commit/?id=1029dab63457f23dace4dab3b698f1c177939b93

commit 1029dab63457f23dace4dab3b698f1c177939b93
Author:     Mitchell Horne <mhorne@FreeBSD.org>
AuthorDate: 2023-02-09 15:40:29 +0000
Commit:     Mitchell Horne <mhorne@FreeBSD.org>
CommitDate: 2023-02-09 16:01:32 +0000

    mi_switch(): clean up switch types and their usage
    
    Overall, this is a non-functional change, except for kernels built with
    SCHED_STATS. However, the switch types are useful for communicating the
    intent of the caller.
    
    1. Ensure that every caller provides a type. In most cases, we upgrade
       the basic yield to sched_relinquish() aka SWT_RELINQUISH.
    2. The case of sched_bind() is distinct, so add a new switch type SWT_BIND.
    3. Remove the two unused types, SWT_PREEMPT and SWT_SLEEPQTIMO.
    4. Remove SWT_NONE altogether and assert that callers always provide
       a type flag.
    5. Reference the mi_switch(9) man page in the comments, as these flags
       will be documented there.
    
    Reviewed by:    kib, markj
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D38184
---
 sys/dev/dpaa/bman_portals.c |  3 +--
 sys/dev/dpaa/qman_portals.c |  3 +--
 sys/kern/kern_poll.c        |  3 +--
 sys/kern/kern_switch.c      | 12 ++++--------
 sys/kern/kern_synch.c       |  9 +++++++--
 sys/kern/sched_4bsd.c       |  2 +-
 sys/kern/sched_ule.c        |  2 +-
 sys/kern/vfs_bio.c          |  4 ++--
 sys/sys/proc.h              | 28 +++++++++++++---------------
 9 files changed, 31 insertions(+), 35 deletions(-)

diff --git a/sys/dev/dpaa/bman_portals.c b/sys/dev/dpaa/bman_portals.c
index 9ef2bf7aa61c..d3c027bb29f8 100644
--- a/sys/dev/dpaa/bman_portals.c
+++ b/sys/dev/dpaa/bman_portals.c
@@ -141,8 +141,7 @@ bman_portal_setup(struct bman_softc *bsc)
 		}
 
 		/* Not inititialized and "owned" by another thread */
-		thread_lock(curthread);
-		mi_switch(SW_VOL);
+		sched_relinquish(curthread);
 	}
 
 	/* Map portal registers */
diff --git a/sys/dev/dpaa/qman_portals.c b/sys/dev/dpaa/qman_portals.c
index 92461665def2..37f9b4eec178 100644
--- a/sys/dev/dpaa/qman_portals.c
+++ b/sys/dev/dpaa/qman_portals.c
@@ -146,8 +146,7 @@ qman_portal_setup(struct qman_softc *qsc)
 		}
 
 		/* Not inititialized and "owned" by another thread */
-		thread_lock(curthread);
-		mi_switch(SW_VOL);
+		sched_relinquish(curthread);
 	}
 
 	/* Map portal registers */
diff --git a/sys/kern/kern_poll.c b/sys/kern/kern_poll.c
index 8232f98f59ef..64deb7132710 100644
--- a/sys/kern/kern_poll.c
+++ b/sys/kern/kern_poll.c
@@ -565,8 +565,7 @@ poll_idle(void)
 		if (poll_in_idle_loop && poll_handlers > 0) {
 			idlepoll_sleeping = 0;
 			ether_poll(poll_each_burst);
-			thread_lock(td);
-			mi_switch(SW_VOL);
+			sched_relinquish(td);
 		} else {
 			idlepoll_sleeping = 1;
 			tsleep(&idlepoll_sleeping, 0, "pollid", hz * 3);
diff --git a/sys/kern/kern_switch.c b/sys/kern/kern_switch.c
index 9d48ab188e13..aee0c9cbd1ae 100644
--- a/sys/kern/kern_switch.c
+++ b/sys/kern/kern_switch.c
@@ -83,25 +83,19 @@ SYSCTL_INT(_kern_sched, OID_AUTO, preemption, CTLFLAG_RD,
 SYSCTL_NODE(_kern_sched, OID_AUTO, stats, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
     "switch stats");
 
-/* Switch reasons from mi_switch(). */
+/* Switch reasons from mi_switch(9). */
 DPCPU_DEFINE(long, sched_switch_stats[SWT_COUNT]);
-SCHED_STAT_DEFINE_VAR(uncategorized,
-    &DPCPU_NAME(sched_switch_stats[SWT_NONE]), "");
-SCHED_STAT_DEFINE_VAR(preempt,
-    &DPCPU_NAME(sched_switch_stats[SWT_PREEMPT]), "");
 SCHED_STAT_DEFINE_VAR(owepreempt,
     &DPCPU_NAME(sched_switch_stats[SWT_OWEPREEMPT]), "");
 SCHED_STAT_DEFINE_VAR(turnstile,
     &DPCPU_NAME(sched_switch_stats[SWT_TURNSTILE]), "");
 SCHED_STAT_DEFINE_VAR(sleepq,
     &DPCPU_NAME(sched_switch_stats[SWT_SLEEPQ]), "");
-SCHED_STAT_DEFINE_VAR(sleepqtimo,
-    &DPCPU_NAME(sched_switch_stats[SWT_SLEEPQTIMO]), "");
 SCHED_STAT_DEFINE_VAR(relinquish, 
     &DPCPU_NAME(sched_switch_stats[SWT_RELINQUISH]), "");
 SCHED_STAT_DEFINE_VAR(needresched,
     &DPCPU_NAME(sched_switch_stats[SWT_NEEDRESCHED]), "");
-SCHED_STAT_DEFINE_VAR(idle, 
+SCHED_STAT_DEFINE_VAR(idle,
     &DPCPU_NAME(sched_switch_stats[SWT_IDLE]), "");
 SCHED_STAT_DEFINE_VAR(iwait,
     &DPCPU_NAME(sched_switch_stats[SWT_IWAIT]), "");
@@ -111,6 +105,8 @@ SCHED_STAT_DEFINE_VAR(remotepreempt,
     &DPCPU_NAME(sched_switch_stats[SWT_REMOTEPREEMPT]), "");
 SCHED_STAT_DEFINE_VAR(remotewakeidle,
     &DPCPU_NAME(sched_switch_stats[SWT_REMOTEWAKEIDLE]), "");
+SCHED_STAT_DEFINE_VAR(bind,
+    &DPCPU_NAME(sched_switch_stats[SWT_BIND]), "");
 
 static int
 sysctl_stats_reset(SYSCTL_HANDLER_ARGS)
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index 7d0cb6178fc3..63a78353e9a5 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -483,7 +483,7 @@ kdb_switch(void)
 }
 
 /*
- * The machine independent parts of context switching.
+ * mi_switch(9): The machine-independent parts of context switching.
  *
  * The thread lock is required on entry and is no longer held on return.
  */
@@ -500,10 +500,15 @@ mi_switch(int flags)
 	if (!TD_ON_LOCK(td) && !TD_IS_RUNNING(td))
 		mtx_assert(&Giant, MA_NOTOWNED);
 #endif
+	/* thread_lock() performs spinlock_enter(). */
 	KASSERT(td->td_critnest == 1 || KERNEL_PANICKED(),
-		("mi_switch: switch in a critical section"));
+	    ("mi_switch: switch in a critical section"));
 	KASSERT((flags & (SW_INVOL | SW_VOL)) != 0,
 	    ("mi_switch: switch must be voluntary or involuntary"));
+	KASSERT((flags & SW_TYPE_MASK) != 0,
+	    ("mi_switch: a switch reason (type) must be specified"));
+	KASSERT((flags & SW_TYPE_MASK) < SWT_COUNT,
+	    ("mi_switch: invalid switch reason %d", (flags & SW_TYPE_MASK)));
 
 	/*
 	 * Don't perform context switches from the debugger.
diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c
index f0da4f8d8496..e81b0c9d46ec 100644
--- a/sys/kern/sched_4bsd.c
+++ b/sys/kern/sched_4bsd.c
@@ -1582,7 +1582,7 @@ sched_bind(struct thread *td, int cpu)
 	if (PCPU_GET(cpuid) == cpu)
 		return;
 
-	mi_switch(SW_VOL);
+	mi_switch(SW_VOL | SWT_BIND);
 	thread_lock(td);
 #endif
 }
diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index ba179caf5d34..881413ca5e73 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -2922,7 +2922,7 @@ sched_bind(struct thread *td, int cpu)
 		return;
 	ts->ts_cpu = cpu;
 	/* When we return from mi_switch we'll be on the correct cpu. */
-	mi_switch(SW_VOL);
+	mi_switch(SW_VOL | SWT_BIND);
 	thread_lock(td);
 }
 
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index cb94f3390d8a..3a5afec88a02 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/refcount.h>
 #include <sys/resourcevar.h>
 #include <sys/rwlock.h>
+#include <sys/sched.h>
 #include <sys/smp.h>
 #include <sys/sysctl.h>
 #include <sys/syscallsubr.h>
@@ -1425,8 +1426,7 @@ bufshutdown(int show_busybufs)
 		 * threads to run.
 		 */
 		for (subiter = 0; subiter < 50 * iter; subiter++) {
-			thread_lock(curthread);
-			mi_switch(SW_VOL);
+			sched_relinquish(curthread);
 			DELAY(1000);
 		}
 #endif
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index d031c2a73ce6..c6670bdc96f8 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -904,22 +904,20 @@ struct proc {
 
 #ifdef _KERNEL
 
-/* Types and flags for mi_switch(). */
+/* Types and flags for mi_switch(9). */
 #define	SW_TYPE_MASK		0xff	/* First 8 bits are switch type */
-#define	SWT_NONE		0	/* Unspecified switch. */
-#define	SWT_PREEMPT		1	/* Switching due to preemption. */
-#define	SWT_OWEPREEMPT		2	/* Switching due to owepreempt. */
-#define	SWT_TURNSTILE		3	/* Turnstile contention. */
-#define	SWT_SLEEPQ		4	/* Sleepq wait. */
-#define	SWT_SLEEPQTIMO		5	/* Sleepq timeout wait. */
-#define	SWT_RELINQUISH		6	/* yield call. */
-#define	SWT_NEEDRESCHED		7	/* NEEDRESCHED was set. */
-#define	SWT_IDLE		8	/* Switching from the idle thread. */
-#define	SWT_IWAIT		9	/* Waiting for interrupts. */
-#define	SWT_SUSPEND		10	/* Thread suspended. */
-#define	SWT_REMOTEPREEMPT	11	/* Remote processor preempted. */
-#define	SWT_REMOTEWAKEIDLE	12	/* Remote processor preempted idle. */
-#define	SWT_COUNT		13	/* Number of switch types. */
+#define	SWT_OWEPREEMPT		1	/* Switching due to owepreempt. */
+#define	SWT_TURNSTILE		2	/* Turnstile contention. */
+#define	SWT_SLEEPQ		3	/* Sleepq wait. */
+#define	SWT_RELINQUISH		4	/* yield call. */
+#define	SWT_NEEDRESCHED		5	/* NEEDRESCHED was set. */
+#define	SWT_IDLE		6	/* Switching from the idle thread. */
+#define	SWT_IWAIT		7	/* Waiting for interrupts. */
+#define	SWT_SUSPEND		8	/* Thread suspended. */
+#define	SWT_REMOTEPREEMPT	9	/* Remote processor preempted. */
+#define	SWT_REMOTEWAKEIDLE	10	/* Remote processor preempted idle. */
+#define	SWT_BIND		11	/* Thread bound to a new CPU. */
+#define	SWT_COUNT		12	/* Number of switch types. */
 /* Flags */
 #define	SW_VOL		0x0100		/* Voluntary switch. */
 #define	SW_INVOL	0x0200		/* Involuntary switch. */