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 */
thread_lock(curthread);
mi_switch(SW_VOL);
sched_relinquish(curthread);
}
/* Map portal registers */

View File

@ -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 */

View File

@ -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);

View File

@ -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)

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.
*/
@ -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.

View File

@ -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
}

View File

@ -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);
}

View File

@ -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

View File

@ -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. */