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
This commit is contained in:
Mitchell Horne 2023-02-09 11:40:29 -04:00
parent bff02948ed
commit 1029dab634
9 changed files with 31 additions and 35 deletions

View File

@ -141,8 +141,7 @@ bman_portal_setup(struct bman_softc *bsc)
} }
/* Not inititialized and "owned" by another thread */ /* Not inititialized and "owned" by another thread */
thread_lock(curthread); sched_relinquish(curthread);
mi_switch(SW_VOL);
} }
/* Map portal registers */ /* Map portal registers */

View File

@ -146,8 +146,7 @@ qman_portal_setup(struct qman_softc *qsc)
} }
/* Not inititialized and "owned" by another thread */ /* Not inititialized and "owned" by another thread */
thread_lock(curthread); sched_relinquish(curthread);
mi_switch(SW_VOL);
} }
/* Map portal registers */ /* Map portal registers */

View File

@ -565,8 +565,7 @@ poll_idle(void)
if (poll_in_idle_loop && poll_handlers > 0) { if (poll_in_idle_loop && poll_handlers > 0) {
idlepoll_sleeping = 0; idlepoll_sleeping = 0;
ether_poll(poll_each_burst); ether_poll(poll_each_burst);
thread_lock(td); sched_relinquish(td);
mi_switch(SW_VOL);
} else { } else {
idlepoll_sleeping = 1; idlepoll_sleeping = 1;
tsleep(&idlepoll_sleeping, 0, "pollid", hz * 3); tsleep(&idlepoll_sleeping, 0, "pollid", hz * 3);

View File

@ -83,20 +83,14 @@ SYSCTL_INT(_kern_sched, OID_AUTO, preemption, CTLFLAG_RD,
SYSCTL_NODE(_kern_sched, OID_AUTO, stats, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, SYSCTL_NODE(_kern_sched, OID_AUTO, stats, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
"switch stats"); "switch stats");
/* Switch reasons from mi_switch(). */ /* Switch reasons from mi_switch(9). */
DPCPU_DEFINE(long, sched_switch_stats[SWT_COUNT]); 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, SCHED_STAT_DEFINE_VAR(owepreempt,
&DPCPU_NAME(sched_switch_stats[SWT_OWEPREEMPT]), ""); &DPCPU_NAME(sched_switch_stats[SWT_OWEPREEMPT]), "");
SCHED_STAT_DEFINE_VAR(turnstile, SCHED_STAT_DEFINE_VAR(turnstile,
&DPCPU_NAME(sched_switch_stats[SWT_TURNSTILE]), ""); &DPCPU_NAME(sched_switch_stats[SWT_TURNSTILE]), "");
SCHED_STAT_DEFINE_VAR(sleepq, SCHED_STAT_DEFINE_VAR(sleepq,
&DPCPU_NAME(sched_switch_stats[SWT_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, SCHED_STAT_DEFINE_VAR(relinquish,
&DPCPU_NAME(sched_switch_stats[SWT_RELINQUISH]), ""); &DPCPU_NAME(sched_switch_stats[SWT_RELINQUISH]), "");
SCHED_STAT_DEFINE_VAR(needresched, SCHED_STAT_DEFINE_VAR(needresched,
@ -111,6 +105,8 @@ SCHED_STAT_DEFINE_VAR(remotepreempt,
&DPCPU_NAME(sched_switch_stats[SWT_REMOTEPREEMPT]), ""); &DPCPU_NAME(sched_switch_stats[SWT_REMOTEPREEMPT]), "");
SCHED_STAT_DEFINE_VAR(remotewakeidle, SCHED_STAT_DEFINE_VAR(remotewakeidle,
&DPCPU_NAME(sched_switch_stats[SWT_REMOTEWAKEIDLE]), ""); &DPCPU_NAME(sched_switch_stats[SWT_REMOTEWAKEIDLE]), "");
SCHED_STAT_DEFINE_VAR(bind,
&DPCPU_NAME(sched_switch_stats[SWT_BIND]), "");
static int static int
sysctl_stats_reset(SYSCTL_HANDLER_ARGS) sysctl_stats_reset(SYSCTL_HANDLER_ARGS)

View File

@ -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. * 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)) if (!TD_ON_LOCK(td) && !TD_IS_RUNNING(td))
mtx_assert(&Giant, MA_NOTOWNED); mtx_assert(&Giant, MA_NOTOWNED);
#endif #endif
/* thread_lock() performs spinlock_enter(). */
KASSERT(td->td_critnest == 1 || KERNEL_PANICKED(), 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, KASSERT((flags & (SW_INVOL | SW_VOL)) != 0,
("mi_switch: switch must be voluntary or involuntary")); ("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. * Don't perform context switches from the debugger.

View File

@ -1582,7 +1582,7 @@ sched_bind(struct thread *td, int cpu)
if (PCPU_GET(cpuid) == cpu) if (PCPU_GET(cpuid) == cpu)
return; return;
mi_switch(SW_VOL); mi_switch(SW_VOL | SWT_BIND);
thread_lock(td); thread_lock(td);
#endif #endif
} }

View File

@ -2922,7 +2922,7 @@ sched_bind(struct thread *td, int cpu)
return; return;
ts->ts_cpu = cpu; ts->ts_cpu = cpu;
/* When we return from mi_switch we'll be on the correct 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); thread_lock(td);
} }

View File

@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
#include <sys/refcount.h> #include <sys/refcount.h>
#include <sys/resourcevar.h> #include <sys/resourcevar.h>
#include <sys/rwlock.h> #include <sys/rwlock.h>
#include <sys/sched.h>
#include <sys/smp.h> #include <sys/smp.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/syscallsubr.h> #include <sys/syscallsubr.h>
@ -1425,8 +1426,7 @@ bufshutdown(int show_busybufs)
* threads to run. * threads to run.
*/ */
for (subiter = 0; subiter < 50 * iter; subiter++) { for (subiter = 0; subiter < 50 * iter; subiter++) {
thread_lock(curthread); sched_relinquish(curthread);
mi_switch(SW_VOL);
DELAY(1000); DELAY(1000);
} }
#endif #endif

View File

@ -904,22 +904,20 @@ struct proc {
#ifdef _KERNEL #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 SW_TYPE_MASK 0xff /* First 8 bits are switch type */
#define SWT_NONE 0 /* Unspecified switch. */ #define SWT_OWEPREEMPT 1 /* Switching due to owepreempt. */
#define SWT_PREEMPT 1 /* Switching due to preemption. */ #define SWT_TURNSTILE 2 /* Turnstile contention. */
#define SWT_OWEPREEMPT 2 /* Switching due to owepreempt. */ #define SWT_SLEEPQ 3 /* Sleepq wait. */
#define SWT_TURNSTILE 3 /* Turnstile contention. */ #define SWT_RELINQUISH 4 /* yield call. */
#define SWT_SLEEPQ 4 /* Sleepq wait. */ #define SWT_NEEDRESCHED 5 /* NEEDRESCHED was set. */
#define SWT_SLEEPQTIMO 5 /* Sleepq timeout wait. */ #define SWT_IDLE 6 /* Switching from the idle thread. */
#define SWT_RELINQUISH 6 /* yield call. */ #define SWT_IWAIT 7 /* Waiting for interrupts. */
#define SWT_NEEDRESCHED 7 /* NEEDRESCHED was set. */ #define SWT_SUSPEND 8 /* Thread suspended. */
#define SWT_IDLE 8 /* Switching from the idle thread. */ #define SWT_REMOTEPREEMPT 9 /* Remote processor preempted. */
#define SWT_IWAIT 9 /* Waiting for interrupts. */ #define SWT_REMOTEWAKEIDLE 10 /* Remote processor preempted idle. */
#define SWT_SUSPEND 10 /* Thread suspended. */ #define SWT_BIND 11 /* Thread bound to a new CPU. */
#define SWT_REMOTEPREEMPT 11 /* Remote processor preempted. */ #define SWT_COUNT 12 /* Number of switch types. */
#define SWT_REMOTEWAKEIDLE 12 /* Remote processor preempted idle. */
#define SWT_COUNT 13 /* Number of switch types. */
/* Flags */ /* Flags */
#define SW_VOL 0x0100 /* Voluntary switch. */ #define SW_VOL 0x0100 /* Voluntary switch. */
#define SW_INVOL 0x0200 /* Involuntary switch. */ #define SW_INVOL 0x0200 /* Involuntary switch. */