xref: /netbsd-src/share/man/man9/KERNEL_LOCK.9 (revision b5684b14a5eaa9ef44b86ac7f87934cb86083c5b)
1.\"	$NetBSD: KERNEL_LOCK.9,v 1.2 2022/02/15 22:58:25 wiz Exp $
2.\"
3.\" Copyright (c) 2022 The NetBSD Foundation, Inc.
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\"    notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\"    notice, this list of conditions and the following disclaimer in the
13.\"    documentation and/or other materials provided with the distribution.
14.\"
15.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25.\" POSSIBILITY OF SUCH DAMAGE.
26.\"
27.Dd February 13, 2022
28.Dt KERNEL_LOCK 9
29.Os
30.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
31.Sh NAME
32.Nm KERNEL_LOCK
33.Nd compatibility with legacy uniprocessor code
34.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
35.Sh SYNOPSIS
36.In sys/systm.h
37.\"
38.Ft void
39.Fn KERNEL_LOCK "int nlocks" "struct lwp *l"
40.Ft void
41.Fn KERNEL_UNLOCK_ONE "struct lwp *l"
42.Ft void
43.Fn KERNEL_UNLOCK_ALL "struct lwp *l" "int *nlocksp"
44.Ft void
45.Fn KERNEL_UNLOCK_LAST "struct lwp *l"
46.Ft bool
47.Fn KERNEL_LOCKED_P
48.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
49.Sh DESCRIPTION
50The
51.Nm
52facility serves to gradually transition software from the kernel's
53legacy uniprocessor execution model, where the kernel runs on only a
54single CPU and never in parallel on multiple CPUs, to a multiprocessor
55system.
56.Pp
57.Sy New code should not use Nm .
58.Nm
59is meant only for gradual transition of
60.Nx
61to natively MP-safe code, which uses
62.Xr mutex 9
63or other
64.Xr locking 9
65facilities to synchronize between threads and interrupt handlers.
66Use of
67.Nm
68hurts system performance and responsiveness.
69This man page exists only to document the legacy API in order to make
70it easier to transition away from.
71.Pp
72The kernel lock, sometimes also known as
73.Sq giant lock
74or
75.Sq big lock ,
76is a recursive exclusive spin-lock that can be held by a CPU at any
77interrupt priority level and is dropped while sleeping.
78This means:
79.Bl -tag -width "held by a CPU"
80.It recursive
81If a CPU already holds the kernel lock, it can be acquired again and
82again, as long as it is released an equal number of times.
83.It exclusive
84Only one CPU at a time can hold the kernel lock.
85.It spin-lock
86When one CPU holds the kernel lock and another CPU wants to hold it,
87the second CPU
88.Sq spins ,
89i.e., repeatedly executes instructions to see if the kernel lock is
90available yet, until the first CPU releases it.
91During this time, no other threads can run on the spinning CPU.
92.Pp
93This means holding the kernel lock for long periods of time, such as
94nontrivial computation, must be avoided.
95Under
96.Dv LOCKDEBUG
97kernels, holding the kernel lock for too long can lead to
98.Sq spinout
99crashes.
100.It held by a CPU
101The kernel lock is held by a CPU, not by a process, kthread, LWP, or
102interrupt handler.
103It may be shared by a kthread LWP and several softint LWPs at the same
104time, for example, if the softints interrupted the thread on a CPU.
105.It any interrupt priority level
106The kernel lock
107.Em does not
108block interrupts; subsystems running with the kernel lock use
109.Xr spl 9
110to synchronize with interrupt handlers.
111.Pp
112Interrupt handlers that are not marked MP-safe are always run with the
113kernel lock.
114If the interrupt arrives on a CPU where the kernel lock is already
115held, it is simply taken again recursively on interrupt entry and
116released to its original recursion depth on interrupt exit.
117.It dropped while sleeping
118Any time the kernel sleeps to let other threads run, for any reason
119including
120.Xr tsleep 9
121or
122.Xr condvar 9
123or even adaptive
124.Xr mutex 9
125locks, it releases the kernel lock before going to sleep and then
126reacquires it afterward.
127.Pp
128This means, for instance, that although data structures accessed only
129under the kernel lock won't be changed before the sleep, they may be
130changed by another thread during the sleep.
131For example, the following program may crash on an assertion failure
132because the sleep in
133.Xr mutex_enter 9
134can allow another CPU to run and change the global variable
135.Dv x :
136.Bd -literal
137	KERNEL_LOCK(1, NULL);
138	x = 42;
139	mutex_enter(...);
140	...
141	mutex_exit(...);
142	KASSERT(x == 42);
143	KERNEL_UNLOCK_ONE(NULL);
144.Ed
145.Pp
146This means simply introducing calls to
147.Xr mutex_enter 9
148and
149.Xr mutex_exit 9
150can break kernel-locked assumptions.
151Subsystems need to be consistently converted from
152.Nm
153and
154.Xr spl 9
155to
156.Xr mutex 9 ,
157.Xr condvar 9 ,
158etc.; mixing
159.Xr mutex 9
160and
161.Nm
162usually doesn't work.
163.El
164.Pp
165Holding the kernel lock
166.Em does not
167prevent other code from running on other CPUs at the same time.
168It only prevents other
169.Em kernel-locked
170code from running on other CPUs at the same time.
171.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
172.Sh FUNCTIONS
173.Bl -tag -width abcd
174.It Fn KERNEL_LOCK nlocks l
175Acquire
176.Fa nlocks
177recursive levels of kernel lock.
178.Pp
179If the kernel lock is already held by another CPU, spins until it can
180be acquired by this one.
181If the kernel lock is already held by this CPU, records the kernel
182lock recursion depth and returns immediately.
183.Pp
184Most of the time
185.Fa nlocks
186is 1, but code that deliberately releases all of the kernel locks held
187by the current CPU in order to sleep and later reacquire the same
188number of kernel locks will pass a value of
189.Fa nlocks
190obtained from
191.Fn KERNEL_UNLOCK_ALL .
192.It Fn KERNEL_UNLOCK_ONE l
193Release one level of the kernel lock.
194Equivalent to
195.Fo KERNEL_UNLOCK
196.Li 1 ,
197.Fa l ,
198.Dv NULL
199.Fc .
200.It Fn KERNEL_UNLOCK_ALL l nlocksp
201Store the kernel lock recursion depth at
202.Fa nlocksp
203and release all recursive levels of the kernel lock.
204.Pp
205This is often used inside logic implementing sleep, around a call to
206.Xr mi_switch 9 ,
207so that the same number of recursive kernel locks can be reacquired
208afterward once the thread is reawoken:
209.Bd -literal
210	int nlocks;
211
212	KERNEL_UNLOCK_ALL(l, &nlocks);
213	... mi_switch(l) ...
214	KERNEL_LOCK(nlocks, l);
215.Ed
216.It Fn KERNEL_UNLOCK_LAST l
217Release the kernel lock, which must be held at exactly one level.
218.Pp
219This is normally used at the end of a non-MP-safe thread, which was
220known to have started with exactly one level of the kernel lock, and is
221now about to exit.
222.It Fn KERNEL_LOCKED_P
223True if the kernel lock is held.
224.Pp
225To be used only in diagnostic assertions with
226.Xr KASSERT 9 .
227.El
228.Pp
229The legacy argument
230.Fa l
231must be
232.Dv NULL
233or
234.Dv curlwp ,
235which mean the same thing.
236.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
237.Sh NOTES
238Some
239.Nx
240kernel abstractions execute caller-specified functions with the kernel
241lock held by default, for compatibility with legacy code, but can be
242explicitly instructed
243.Em not
244to hold the kernel lock by passing an MP-safe flag:
245.Bl -bullet
246.It
247.Xr callout 9 ,
248.Dv CALLOUT_MPSAFE
249.It
250.Xr kfilter_register 9
251and
252.Xr knote 9 ,
253.Dv FILTEROPS_MPSAFE
254.It
255.Xr kthread 9 ,
256.Dv KTHREAD_MPSAFE
257.It
258.Xr pci_intr 9 ,
259.Dv PCI_INTR_MPSAFE
260.It
261.Xr scsipi 9 ,
262.Dv SCSIPI_ADAPT_MPSAFE
263.It
264.Xr softint 9 ,
265.Dv SOFTINT_MPSAFE
266.It
267.Xr usbdi 9
268pipes,
269.Dv USBD_MPSAFE
270.It
271.Xr usbdi 9
272tasks,
273.Dv USB_TASKQ_MPSAFE
274.It
275.Xr vnode 9 ,
276.Dv VV_MPSAFE
277.It
278.Xr workqueue 9 ,
279.Dv WQ_MPSAFE
280.El
281.Pp
282The following
283.Nx
284subsystems are still kernel-locked and need re-engineering to take
285advantage of parallelism on multiprocessor systems:
286.Bl -bullet
287.It
288.Xr ata 4 ,
289.Xr atapi 4 ,
290.Xr wd 4
291.It
292.Xr video 4
293.It
294.Xr autoconf 9
295.It
296most of the network stack by default, unless the option
297.Dv NET_MPSAFE
298is enabled
299.It
300.No ...
301.El
302.Pp
303All interrupt handlers at
304.Dv IPL_VM ,
305or lower
306.Pq Xr spl 9
307run with the kernel lock on most ports.
308.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
309.Sh SEE ALSO
310.Xr locking 9 ,
311.Xr mutex 9 ,
312.Xr spl 9
313