1.\" $NetBSD: ctxsw.9,v 1.2 1996/12/02 00:11:31 tls Exp $ 2.\" 3.\" Copyright (c) 1996 The NetBSD Foundation, Inc. 4.\" All rights reserved. 5.\" Copyright (c) 2023 The FreeBSD Foundation 6.\" 7.\" This code is derived from software contributed to The NetBSD Foundation 8.\" by Paul Kranenburg. 9.\" 10.\" Portions of this documentation were written by Mitchell Horne 11.\" under sponsorship from the FreeBSD Foundation. 12.\" 13.\" Redistribution and use in source and binary forms, with or without 14.\" modification, are permitted provided that the following conditions 15.\" are met: 16.\" 1. Redistributions of source code must retain the above copyright 17.\" notice, this list of conditions and the following disclaimer. 18.\" 2. Redistributions in binary form must reproduce the above copyright 19.\" notice, this list of conditions and the following disclaimer in the 20.\" documentation and/or other materials provided with the distribution. 21.\" 22.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 26.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32.\" POSSIBILITY OF SUCH DAMAGE. 33.\" 34.\" $FreeBSD$ 35.\" 36.Dd January 9, 2023 37.Dt MI_SWITCH 9 38.Os 39.Sh NAME 40.Nm mi_switch , 41.Nm cpu_switch , 42.Nm cpu_throw 43.Nd switch to another thread context 44.Sh SYNOPSIS 45.In sys/param.h 46.In sys/proc.h 47.Ft void 48.Fn mi_switch "int flags" 49.Ft void 50.Fn cpu_switch "struct thread *oldtd" "struct thread *newtd" "struct mtx *lock" 51.Ft void 52.Fn cpu_throw "struct thread *oldtd" "struct thread *newtd" 53.Sh DESCRIPTION 54The 55.Fn mi_switch 56function implements the machine-independent prelude to a thread context 57switch. 58It is the single entry point for every context switch and is called from only 59a few distinguished places in the kernel. 60The context switch is, by necessity, always performed by the switched thread, 61even when the switch is initiated from elsewhere; e.g. preemption requested via 62Inter-Processor Interrupt (IPI). 63.Pp 64The various major uses of 65.Fn mi_switch 66can be enumerated as follows: 67.Bl -enum -offset indent 68.It 69From within a function such as 70.Xr sleepq_wait 9 71or 72.Fn turnstile_wait 73when the current thread 74voluntarily relinquishes the CPU to wait for some resource or lock to become 75available. 76.It 77Involuntary preemption due to arrival of a higher-priority thread. 78.It 79At the tail end of 80.Xr critical_exit 9 , 81if preemption was deferred due to the critical section. 82.It 83Within the TDA_SCHED AST handler, when rescheduling before the return to 84usermode was requested. 85There are several reasons for this, a notable one coming from 86.Fn sched_clock 87when the running thread has exceeded its time slice. 88.It 89In the signal handling code 90(see 91.Xr issignal 9 ) 92if a signal is delivered that causes a process to stop. 93.It 94In 95.Fn thread_suspend_check 96where a thread needs to stop execution due to the suspension state of 97the process as a whole. 98.It 99In 100.Xr kern_yield 9 101when a thread wants to voluntarily relinquish the processor. 102.El 103.Pp 104The 105.Va flags 106argument to 107.Fn mi_switch 108indicates the context switch type. 109One of the following must be passed: 110.Bl -tag -offset indent -width "SWT_REMOTEWAKEIDLE" 111.It Dv SWT_OWEPREEMPT 112Switch due to delayed preemption after exiting a critical section. 113.It Dv SWT_TURNSTILE 114Switch after propagating scheduling priority to the owner of a resource. 115.It Dv SWT_SLEEPQ 116Begin waiting on a 117.Xr sleepqueue 9 . 118.It Dv SWT_RELINQUISH 119Yield call. 120.It Dv SWT_NEEDRESCHED 121Rescheduling was requested. 122.It Dv SWT_IDLE 123Switch from the idle thread. 124.It Dv SWT_IWAIT 125A kernel thread which handles interrupts has finished work and must wait for 126interrupts to schedule additional work. 127.It Dv SWT_SUSPEND 128Thread suspended. 129.It Dv SWT_REMOTEPREEMPT 130Preemption by a higher-priority thread, initiated by a remote processor. 131.It Dv SWT_REMOTEWAKEIDLE 132Idle thread preempted, initiated by a remote processor. 133.It Dv SWT_BIND 134The running thread has been bound to another processor and must be switched 135out. 136.El 137.Pp 138In addition to the switch type, callers must specify the nature of the 139switch by performing a bitwise OR with one of the 140.Dv SW_VOL 141or 142.Dv SW_INVOL 143flags, but not both. 144Respectively, these flags denote whether the context switch is voluntary or 145involuntary on the part of the current thread. 146For an involuntary context switch in which the running thread is 147being preempted, the caller should also pass the 148.Dv SW_PREEMPT 149flag. 150.Pp 151Upon entry to 152.Fn mi_switch , 153the current thread must be holding its assigned thread lock. 154It may be unlocked as part of the context switch. 155After they have been rescheduled and execution resumes, threads will exit 156.Fn mi_switch 157with their thread lock unlocked. 158.Pp 159.Fn mi_switch 160records the amount of time the current thread has been running before handing 161control over to the scheduler, via 162.Fn sched_switch . 163After selecting a new thread to run, the scheduler will call 164.Fn cpu_switch 165to perform the low-level context switch. 166.Pp 167.Fn cpu_switch 168is the machine-dependent function that performs the actual switch from the 169running thread 170.Fa oldtd 171to the chosen thread 172.Fa newtd . 173First, it saves the context of 174.Fa oldtd 175to its Process Control Block, 176.Po 177PCB 178.Vt struct pcb 179.Pc , 180pointed at by 181.Va oldtd->td_pcb . 182The function then updates important per-CPU state such as the 183.Dv curthread 184variable, and activates 185.Fa newtd\&'s 186virtual address space using its associated 187.Xr pmap 9 188structure. 189Finally, it reads in the saved context from 190.Fa newtd\&'s 191PCB. 192CPU instruction flow continues in the new thread context, on 193.Fa newtd\&'s 194kernel stack. 195The return from 196.Fn cpu_switch 197can be understood as a completion of the function call initiated by 198.Fa newtd 199when it was previously switched out, at some point in the distant (relative to 200CPU time) past. 201.Pp 202The 203.Fa mtx 204argument to 205.Fn cpu_switch 206is used to pass the mutex which will be stored as 207.Fa oldtd\&'s 208thread lock at the moment that 209.Fa oldtd 210is completely switched out. 211This is an implementation detail of 212.Fn sched_switch . 213.Pp 214.Fn cpu_throw 215is similar to 216.Fn cpu_switch 217except that it does not save the context of the old thread. 218This function is useful when the kernel does not have an old thread 219context to save, such as when CPUs other than the boot CPU perform their 220first task switch, or when the kernel does not care about the state of the 221old thread, such as in 222.Xr thread_exit 9 223when the kernel terminates the current thread and switches into a new 224thread, 225.Fa newtd . 226The 227.Fa oldtd 228argument is unused. 229.Sh SEE ALSO 230.Xr critical_exit 9 , 231.Xr issignal 9 , 232.Xr kern_yield 9 , 233.Xr mutex 9 , 234.Xr pmap 9 , 235.Xr sleepqueue 9 , 236.Xr thread_exit 9 237