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.Dd January 9, 2023 35.Dt MI_SWITCH 9 36.Os 37.Sh NAME 38.Nm mi_switch , 39.Nm cpu_switch , 40.Nm cpu_throw 41.Nd switch to another thread context 42.Sh SYNOPSIS 43.In sys/param.h 44.In sys/proc.h 45.Ft void 46.Fn mi_switch "int flags" 47.Ft void 48.Fn cpu_switch "struct thread *oldtd" "struct thread *newtd" "struct mtx *lock" 49.Ft void 50.Fn cpu_throw "struct thread *oldtd" "struct thread *newtd" 51.Sh DESCRIPTION 52The 53.Fn mi_switch 54function implements the machine-independent prelude to a thread context 55switch. 56It is the single entry point for every context switch and is called from only 57a few distinguished places in the kernel. 58The context switch is, by necessity, always performed by the switched thread, 59even when the switch is initiated from elsewhere; e.g. preemption requested via 60Inter-Processor Interrupt (IPI). 61.Pp 62The various major uses of 63.Fn mi_switch 64can be enumerated as follows: 65.Bl -enum -offset indent 66.It 67From within a function such as 68.Xr sleepq_wait 9 69or 70.Fn turnstile_wait 71when the current thread 72voluntarily relinquishes the CPU to wait for some resource or lock to become 73available. 74.It 75Involuntary preemption due to arrival of a higher-priority thread. 76.It 77At the tail end of 78.Xr critical_exit 9 , 79if preemption was deferred due to the critical section. 80.It 81Within the TDA_SCHED AST handler, when rescheduling before the return to 82usermode was requested. 83There are several reasons for this, a notable one coming from 84.Fn sched_clock 85when the running thread has exceeded its time slice. 86.It 87In the signal handling code 88(see 89.Xr issignal 9 ) 90if a signal is delivered that causes a process to stop. 91.It 92In 93.Fn thread_suspend_check 94where a thread needs to stop execution due to the suspension state of 95the process as a whole. 96.It 97In 98.Xr kern_yield 9 99when a thread wants to voluntarily relinquish the processor. 100.El 101.Pp 102The 103.Va flags 104argument to 105.Fn mi_switch 106indicates the context switch type. 107One of the following must be passed: 108.Bl -tag -offset indent -width "SWT_REMOTEWAKEIDLE" 109.It Dv SWT_OWEPREEMPT 110Switch due to delayed preemption after exiting a critical section. 111.It Dv SWT_TURNSTILE 112Switch after propagating scheduling priority to the owner of a resource. 113.It Dv SWT_SLEEPQ 114Begin waiting on a 115.Xr sleepqueue 9 . 116.It Dv SWT_RELINQUISH 117Yield call. 118.It Dv SWT_NEEDRESCHED 119Rescheduling was requested. 120.It Dv SWT_IDLE 121Switch from the idle thread. 122.It Dv SWT_IWAIT 123A kernel thread which handles interrupts has finished work and must wait for 124interrupts to schedule additional work. 125.It Dv SWT_SUSPEND 126Thread suspended. 127.It Dv SWT_REMOTEPREEMPT 128Preemption by a higher-priority thread, initiated by a remote processor. 129.It Dv SWT_REMOTEWAKEIDLE 130Idle thread preempted, initiated by a remote processor. 131.It Dv SWT_BIND 132The running thread has been bound to another processor and must be switched 133out. 134.El 135.Pp 136In addition to the switch type, callers must specify the nature of the 137switch by performing a bitwise OR with one of the 138.Dv SW_VOL 139or 140.Dv SW_INVOL 141flags, but not both. 142Respectively, these flags denote whether the context switch is voluntary or 143involuntary on the part of the current thread. 144For an involuntary context switch in which the running thread is 145being preempted, the caller should also pass the 146.Dv SW_PREEMPT 147flag. 148.Pp 149Upon entry to 150.Fn mi_switch , 151the current thread must be holding its assigned thread lock. 152It may be unlocked as part of the context switch. 153After they have been rescheduled and execution resumes, threads will exit 154.Fn mi_switch 155with their thread lock unlocked. 156.Pp 157.Fn mi_switch 158records the amount of time the current thread has been running before handing 159control over to the scheduler, via 160.Fn sched_switch . 161After selecting a new thread to run, the scheduler will call 162.Fn cpu_switch 163to perform the low-level context switch. 164.Pp 165.Fn cpu_switch 166is the machine-dependent function that performs the actual switch from the 167running thread 168.Fa oldtd 169to the chosen thread 170.Fa newtd . 171First, it saves the context of 172.Fa oldtd 173to its Process Control Block 174.Po 175PCB, 176.Vt struct pcb 177.Pc , 178pointed at by 179.Va oldtd->td_pcb . 180The function then updates important per-CPU state such as the 181.Dv curthread 182variable, and activates 183.Fa newtd\&'s 184virtual address space using its associated 185.Xr pmap 9 186structure. 187Finally, it reads in the saved context from 188.Fa newtd\&'s 189PCB. 190CPU instruction flow continues in the new thread context, on 191.Fa newtd\&'s 192kernel stack. 193The return from 194.Fn cpu_switch 195can be understood as a completion of the function call initiated by 196.Fa newtd 197when it was previously switched out, at some point in the distant (relative to 198CPU time) past. 199.Pp 200The 201.Fa mtx 202argument to 203.Fn cpu_switch 204is used to pass the mutex which will be stored as 205.Fa oldtd\&'s 206thread lock at the moment that 207.Fa oldtd 208is completely switched out. 209This is an implementation detail of 210.Fn sched_switch . 211.Pp 212.Fn cpu_throw 213is similar to 214.Fn cpu_switch 215except that it does not save the context of the old thread. 216This function is useful when the kernel does not have an old thread 217context to save, such as when CPUs other than the boot CPU perform their 218first task switch, or when the kernel does not care about the state of the 219old thread, such as in 220.Xr thread_exit 9 221when the kernel terminates the current thread and switches into a new 222thread, 223.Fa newtd . 224The 225.Fa oldtd 226argument is unused. 227.Sh SEE ALSO 228.Xr critical_exit 9 , 229.Xr issignal 9 , 230.Xr kern_yield 9 , 231.Xr mutex 9 , 232.Xr pmap 9 , 233.Xr sleepqueue 9 , 234.Xr thread_exit 9 235