mi_switch(9): update to current day

The function itself and much of the information in this page remains
relevant, but many details need to be fixed.
 - Update function signatures
 - Update the list of major uses of mi_switch() (it is not exhaustive)
 - Document 'flags' argument and its possible values
 - Document thread lock requirement for callers
 - Thread runtime limits are out of scope now, no need to describe them
 - Remove outdated information w.r.t. KSE, runqueue, non-preemptible
   kernel, etc
 - Update the description of cpu_switch() and its responsibilities

PR:		149574
Reviewed by:	kib
Discussed with:	markj
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D38185
This commit is contained in:
Mitchell Horne 2023-02-09 11:41:14 -04:00
parent 1029dab634
commit 175db7b582

View File

@ -2,10 +2,14 @@
.\" .\"
.\" Copyright (c) 1996 The NetBSD Foundation, Inc. .\" Copyright (c) 1996 The NetBSD Foundation, Inc.
.\" All rights reserved. .\" All rights reserved.
.\" Copyright (c) 2023 The FreeBSD Foundation
.\" .\"
.\" This code is derived from software contributed to The NetBSD Foundation .\" This code is derived from software contributed to The NetBSD Foundation
.\" by Paul Kranenburg. .\" by Paul Kranenburg.
.\" .\"
.\" Portions of this documentation were written by Mitchell Horne
.\" under sponsorship from the FreeBSD Foundation.
.\"
.\" Redistribution and use in source and binary forms, with or without .\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions .\" modification, are permitted provided that the following conditions
.\" are met: .\" are met:
@ -29,7 +33,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd November 24, 1996 .Dd January 9, 2023
.Dt MI_SWITCH 9 .Dt MI_SWITCH 9
.Os .Os
.Sh NAME .Sh NAME
@ -41,96 +45,171 @@
.In sys/param.h .In sys/param.h
.In sys/proc.h .In sys/proc.h
.Ft void .Ft void
.Fn mi_switch "void" .Fn mi_switch "int flags"
.Ft void .Ft void
.Fn cpu_switch "void" .Fn cpu_switch "struct thread *oldtd" "struct thread *newtd" "struct mtx *lock"
.Ft void .Ft void
.Fn cpu_throw "void" .Fn cpu_throw "struct thread *oldtd" "struct thread *newtd"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Fn mi_switch .Fn mi_switch
function implements the machine independent prelude to a thread context function implements the machine-independent prelude to a thread context
switch. switch.
It is called from only a few distinguished places in the kernel It is the single entry point for every context switch and is called from only
code as a result of the principle of non-preemptable kernel mode execution. a few distinguished places in the kernel.
The context switch is, by necessity, always performed by the switched thread,
even when the switch is initiated from elsewhere; e.g. preemption requested via
Inter-Processor Interrupt (IPI).
.Pp
The various major uses of The various major uses of
.Nm .Fn mi_switch
can be enumerated as follows: can be enumerated as follows:
.Bl -enum -offset indent .Bl -enum -offset indent
.It .It
From within a function such as From within a function such as
.Xr cv_wait 9 , .Xr sleepq_wait 9
.Xr mtx_lock 9 ,
or or
.Xr tsleep 9 .Fn turnstile_wait
when the current thread when the current thread
voluntarily relinquishes the CPU to wait for some resource or lock to become voluntarily relinquishes the CPU to wait for some resource or lock to become
available. available.
.It .It
After handling a trap Involuntary preemption due to arrival of a higher-priority thread.
(e.g.\& a system call, device interrupt) .It
when the kernel prepares a return to user-mode execution. At the tail end of
This case is .Xr critical_exit 9 ,
typically handled by machine dependent trap-handling code after detection if preemption was deferred due to the critical section.
of a change in the signal disposition of the current process, or when a .It
higher priority thread might be available to run. Within the TDA_SCHED AST handler, when rescheduling before the return to
The latter event is usermode was requested.
communicated by the machine independent scheduling routines by calling There are several reasons for this, a notable one coming from
the machine defined .Fn sched_clock
.Fn need_resched . when the running thread has exceeded its time slice.
.It .It
In the signal handling code In the signal handling code
(see (see
.Xr issignal 9 ) .Xr issignal 9 )
if a signal is delivered that causes a process to stop. if a signal is delivered that causes a process to stop.
.It .It
When a thread dies in
.Xr thread_exit 9
and control of the processor can be passed to the next runnable thread.
.It
In In
.Xr thread_suspend_check 9 .Fn thread_suspend_check
where a thread needs to stop execution due to the suspension state of where a thread needs to stop execution due to the suspension state of
the process as a whole. the process as a whole.
.It
In
.Xr kern_yield 9
when a thread wants to voluntarily relinquish the processor.
.El .El
.Pp .Pp
The
.Va flags
argument to
.Fn mi_switch .Fn mi_switch
records the amount of time the current thread has been running in the indicates the context switch type.
process structures and checks this value against the CPU time limits One of the following must be passed:
allocated to the process .Bl -tag -offset indent -width "SWT_REMOTEWAKEIDLE"
(see .It Dv SWT_OWEPREEMPT
.Xr getrlimit 2 ) . Switch due to delayed preemption after exiting a critical section.
Exceeding the soft limit results in a .It Dv SWT_TURNSTILE
.Dv SIGXCPU Switch after propagating scheduling priority to the owner of a resource.
signal to be posted to the process, while exceeding the hard limit will .It Dv SWT_SLEEPQ
cause a Begin waiting on a
.Dv SIGKILL . .Xr sleepqueue 9 .
.It Dv SWT_RELINQUISH
Yield call.
.It Dv SWT_NEEDRESCHED
Rescheduling was requested.
.It Dv SWT_IDLE
Switch from the idle thread.
.It Dv SWT_IWAIT
A kernel thread which handles interrupts has finished work and must wait for
interrupts to schedule additional work.
.It Dv SWT_SUSPEND
Thread suspended.
.It Dv SWT_REMOTEPREEMPT
Preemption by a higher-priority thread, initiated by a remote processor.
.It Dv SWT_REMOTEWAKEIDLE
Idle thread preempted, initiated by a remote processor.
.It Dv SWT_BIND
The running thread has been bound to another processor and must be switched
out.
.El
.Pp .Pp
If the thread is still in the In addition to the switch type, callers must specify the nature of the
.Dv TDS_RUNNING switch by performing a bitwise OR with one of the
state, .Dv SW_VOL
.Fn mi_switch or
will put it back onto the run queue, assuming that .Dv SW_INVOL
it will want to run again soon. flags, but not both.
If it is in one of the other Respectively, these flags denote whether the context switch is voluntary or
states and KSE threading is enabled, the associated involuntary on the part of the current thread.
.Em KSE For an involuntary context switch in which the running thread is
will be made available to any higher priority threads from the same being preempted, the caller should also pass the
group, to allow them to be scheduled next. .Dv SW_PREEMPT
flag.
.Pp .Pp
After these administrative tasks are done, Upon entry to
.Fn mi_switch ,
the current thread must be holding its assigned thread lock.
It may be unlocked as part of the context switch.
After they have been rescheduled and execution resumes, threads will exit
.Fn mi_switch .Fn mi_switch
hands over control to the machine dependent routine with their thread lock unlocked.
.Fn cpu_switch , .Pp
which will perform the actual thread context switch. .Fn mi_switch
records the amount of time the current thread has been running before handing
control over to the scheduler, via
.Fn sched_switch .
After selecting a new thread to run, the scheduler will call
.Fn cpu_switch
to perform the low-level context switch.
.Pp .Pp
.Fn cpu_switch .Fn cpu_switch
first saves the context of the current thread. is the machine-dependent function that performs the actual switch from the
Next, it calls running thread
.Fn choosethread .Fa oldtd
to determine which thread to run next. to the chosen thread
Finally, it reads in the saved context of the new thread and starts to .Fa newtd .
execute the new thread. First, it saves the context of
.Fa oldtd
to its Process Control Block,
.Po
PCB
.Vt struct pcb
.Pc ,
pointed at by
.Va oldtd->td_pcb .
The function then updates important per-CPU state such as the
.Dv curthread
variable, and activates
.Fa newtd\&'s
virtual address space using its associated
.Xr pmap 9
structure.
Finally, it reads in the saved context from
.Fa newtd\&'s
PCB.
CPU instruction flow continues in the new thread context, on
.Fa newtd\&'s
kernel stack.
The return from
.Fn cpu_switch
can be understood as a completion of the function call initiated by
.Fa newtd
when it was previously switched out, at some point in the distant (relative to
CPU time) past.
.Pp
The
.Fa mtx
argument to
.Fn cpu_switch
is used to pass the mutex which will be stored as
.Fa oldtd\&'s
thread lock at the moment that
.Fa oldtd
is completely switched out.
This is an implementation detail of
.Fn sched_switch .
.Pp .Pp
.Fn cpu_throw .Fn cpu_throw
is similar to is similar to
@ -140,19 +219,18 @@ This function is useful when the kernel does not have an old thread
context to save, such as when CPUs other than the boot CPU perform their context to save, such as when CPUs other than the boot CPU perform their
first task switch, or when the kernel does not care about the state of the first task switch, or when the kernel does not care about the state of the
old thread, such as in old thread, such as in
.Fn thread_exit .Xr thread_exit 9
when the kernel terminates the current thread and switches into a new when the kernel terminates the current thread and switches into a new
thread. thread,
.Pp .Fa newtd .
To protect the The
.Xr runqueue 9 , .Fa oldtd
all of these functions must be called with the argument is unused.
.Va sched_lock
mutex held.
.Sh SEE ALSO .Sh SEE ALSO
.Xr cv_wait 9 , .Xr critical_exit 9 ,
.Xr issignal 9 , .Xr issignal 9 ,
.Xr kern_yield 9 ,
.Xr mutex 9 , .Xr mutex 9 ,
.Xr runqueue 9 , .Xr pmap 9 ,
.Xr tsleep 9 , .Xr sleepqueue 9 ,
.Xr wakeup 9 .Xr thread_exit 9