1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
|
.\" $OpenBSD: lock.9,v 1.7 2003/03/18 09:57:53 avsm Exp $
.\" $NetBSD: lock.9,v 1.12 2001/11/01 01:13:43 wiz Exp $
.\"
.\" Copyright (c) 2000 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd June 23, 2000
.Dt LOCK 9
.Os
.Sh NAME
.Nm lock ,
.Nm simple_lock_init ,
.Nm simple_lock ,
.Nm simple_lock_try ,
.Nm simple_unlock ,
.Nm lockinit ,
.Nm lockmgr ,
.Nm lockstatus ,
.Nm lockmgr_printinfo ,
.Nd kernel lock functions
.Sh SYNOPSIS
.Fd #include \*[Lt]sys/lock.h\*[Gt]
.Ft void
.Fn simple_lock_init "struct simplelock *slock"
.Ft void
.Fn simple_lock "struct simplelock *slock"
.Ft int
.Fn simple_lock_try "struct simplelock *slock"
.Ft void
.Fn simple_unlock "struct simplelock *slock"
.Ft void
.Fn lockinit "struct lock *lock" "int prio" "const char *wmesg" \
"int timo" "int flags"
.Ft int
.Fn lockmgr "struct lock *lock" "u_int flags" "struct simplelock *slock" \
"struct proc *p"
.Ft int
.Fn lockstatus "struct lock *lock"
.Ft void
.Fn lockmgr_printinfo "struct lock *lock"
.Sh DESCRIPTION
The
.Nm
functions provide synchronisation in the kernel by preventing multiple
processes from simultaneously executing critical sections of code
accessing shared data.
A number of different locks are available:
.Pp
.Bl -tag -width compact
.It struct simplelock
Provides a simple spinning mutex.
A processor will busy-wait while trying to acquire a simplelock.
The simplelock operations are
implemented with machine-dependent locking primitives.
.Pp
Simplelocks are usually used only by the high-level lock manager and
to protect short, critical sections of code.
Simplelocks are the only
locks that can be used inside an interrupt handler.
For a simplelock to be used in an interrupt handler, care must be taken to
disable the interrupt, acquire the lock, do any processing, release
the simplelock and re-enable the interrupt.
This procedure is necessary to avoid deadlock between the interrupt handler
and other processes executing on the same processor.
.It struct lock
Provides a high-level lock supporting sleeping/spinning until the lock
can be acquired.
The lock manager supplies both exclusive-access and
shared-access locks, with recursive exclusive-access locks within a
single process.
It also allows upgrading a shared-access lock to an
exclusive-access lock, as well as downgrading an exclusive-access lock
to a shared-access lock.
.El
.Pp
If the kernel option LOCKDEBUG is enabled, additional facilities
are provided to record additional lock information.
These facilities are provided to assist in determining deadlock occurrences.
.Sh FUNCTIONS
The functions which operate on simplelocks are:
.Pp
.Bl -tag -width compact
.It Fn simple_lock_init "slock"
The simplelock
.Fa slock
is initialised to the unlocked state.
A statically allocated simplelock also can be initialised with the macro
SIMPLELOCK_INITIALIZER.
The effect is the same as the dynamic initialisation by a call to
simple_lock_init.
For example,
.Pp
struct simplelock slock = SIMPLELOCK_INITIALIZER;
.It Fn simple_lock "slock"
The simplelock
.Fa slock
is locked.
If the simplelock is held then execution will
spin until the simplelock is acquired.
Care must be taken that the calling process does not already hold
the simplelock.
In this case, the simplelock can never be acquired.
If kernel option LOCKDEBUG is enabled, a "locking against myself" panic
will occur.
.It Fn simple_lock_try "slock"
Try to acquire the simplelock
.Fa slock
without spinning.
If the simplelock is held by another process then the return value is 0.
If the simplelock was acquired successfully then the return value is 1.
.It Fn simple_unlock "slock"
The simplelock
.Fa slock
is unlocked.
The simplelock must be locked and the calling process must
be the one that last acquired the simplelock.
If the calling process does not hold the simplelock, the simplelock
will be released but the kernel behaviour is undefined.
.El
.Pp
The functions which operate on locks are:
.Pp
.Bl -tag -width compact
.It Fn lockinit "lock" "prio" "wmesg" "timo" "flags"
The lock
.Fa lock
is initialised according to the parameters provided.
Arguments are as follows:
.Bl -tag -width compact
.It Fa lock
The lock.
.It Fa prio
The process priority when it is woken up after sleeping on the lock.
.It Fa wmesg
A sleep message used when a process goes to sleep waiting for the lock, so
that the exact reason it is sleeping can easily be identified.
.It Fa timo
The maximum sleep time.
Used by
.Xr tsleep 9 .
.It Fa flags
Flags to specify the lock behaviour permanently over the lifetime of
the lock.
Valid lock flags are:
.Bl -tag -width compact
.It LK_NOWAIT
Processes should not sleep when attempting to acquire the lock.
.It LK_SLEEPFAIL
Processes should sleep, then return failure when acquiring the lock.
.It LK_CANRECURSE
Processes can acquire the lock recursively.
.El
.El
.It Fn lockmgr "lock" "flags" "slock" "p"
Set, change or release a lock according to the parameters provided.
Arguments are as follows:
.Bl -tag -width compact
.It Fa lock
The lock.
.It Fa flags
Flags to specify the lock request type.
In addition to the flags specified above, the following flags are valid:
.Bl -tag -width compact
.It LK_SHARED
Get one of many possible shared-access locks.
If a process holding an exclusive-access lock requests a shared-access lock,
the exclusive-access lock is downgraded to a shared-access lock.
.It LK_EXCLUSIVE
Stop further shared-access locks, when they are cleared, grant a
pending upgrade if it exists, then grant an exclusive-access lock.
Only one exclusive-access lock may exist at a time, except that a
process holding an exclusive-access lock may get additional
exclusive-access locks if it explicitly sets the LK_CANRECURSE flag in
the lock request, or if the LK_CANRECURSE flag was set when the lock
was initialised.
.It LK_UPGRADE
The process must hold a shared-access lock that it wants to have
upgraded to an exclusive-access lock.
Other processes may get exclusive
access to the protected resource between the time that the upgrade is
requested and the time that it is granted.
.It LK_EXCLUPGRADE
The process must hold a shared-access lock that it wants to have
upgraded to an exclusive-access lock.
If the request succeeds, no
other processes will have acquired exclusive access to the protected
resource between the time that the upgrade is requested and the time
that it is granted.
However, if another process has already requested
an upgrade, the request will fail.
.It LK_DOWNGRADE
The process must hold an exclusive-access lock that it wants to have
downgraded to a shared-access lock.
If the process holds multiple
(recursive) exclusive-access locks, they will all be downgraded to
shared-access locks.
.It LK_RELEASE
Release one instance of a lock.
.It LK_DRAIN
Wait for all activity on the lock to end, then mark it decommissioned.
This feature is used before freeing a lock that is part of a piece of
memory that is about to be freed.
.It LK_REENABLE
Lock is to be re-enabled after drain.
The LK_REENABLE flag may be set
only at the release of a lock obtained by a drain.
.It LK_SETRECURSE
Other locks while we have it OK.
.It LK_RECURSEFAIL
Attempt at recursive lock fails.
.It LK_SPIN
Lock spins instead of sleeping.
.It LK_INTERLOCK
Unlock the simplelock
.Fa slock
when the lock is acquired.
.El
.It Fa slock
Simplelock interlock.
If the flag LK_INTERLOCK is set in
.Fa flags ,
.Fa slock
is a simplelock held by the caller.
When the lock
.Fa lock
is acquired, the simplelock is released.
If the flag LK_INTERLOCK is not set,
.Fa slock
is ignored.
.It Fa p
Should always point to the current process
.Va curproc .
.El
.It Fn lockstatus "lock"
Determine the status of lock
.Fa lock .
Returns LK_EXCLUSIVE or LK_SHARED for exclusive-access and
shared-access locks respectively.
.It Fn lockmgr_printinfo "lock"
Print out information about state of lock
.Fa lock .
.El
.Sh RETURN VALUES
Successfully acquired locks return 0.
A failed lock attempt always returns a non-zero error value.
No lock is held after an error return (in particular, a failed LK_UPGRADE or
LK_FORCEUPGRADE will have released its shared-access lock).
Locks will always succeed unless one of the following is true:
.Bl -tag -width Er
.It Bq Er EBUSY
LK_FORCEUPGRADE is requested and some other process has already
requested a lock upgrade or LK_NOWAIT is set and a sleep would
be required.
.It Bq Er ENOLCK
LK_SLEEPFAIL is set and a sleep was done.
.It Bq Er EINTR
PCATCH is set in lock priority and a signal arrives to interrupt
a system call.
.It Bq Er ERESTART
PCATCH is set in lock priority and a signal arrives so that
the system call is restarted.
.It Bq Er EWOULDBLOCK
Non-null lock timeout and timeout expires.
.El
.Sh CODE REFERENCES
This section describes places within the
.Ox
source tree where actual code implementing or utilising the locking
framework can be found.
All pathnames are relative to
.Pa /usr/src .
.Pp
The locking framework itself is implemented within the file
.Pa sys/kern/kern_lock.c .
Data structures and function prototypes for the framework are located
in
.Pa sys/sys/lock.h .
Machine-dependent simplelock primitives are implemented within the
file
.Pa sys/arch/\*[Lt]arch\*[Gt]/include/lock.h .
.Sh SEE ALSO
.Xr pmap 9 ,
.Xr spl 9 ,
.Xr tsleep 9 ,
.Xr uvm 9
.Sh HISTORY
The kernel locking API first appeared in
.Bx 4.4 -lite2 .
|