FreeBSD/Linux Kernel Cross Reference
sys/sys/lock.h
1 /* $NetBSD: lock.h,v 1.52.2.1 2004/07/02 18:18:27 he Exp $ */
2
3 /*-
4 * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * This code is derived from software contributed to The NetBSD Foundation
12 * by Ross Harvey.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by the NetBSD
25 * Foundation, Inc. and its contributors.
26 * 4. Neither the name of The NetBSD Foundation nor the names of its
27 * contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
31 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
32 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
34 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 * POSSIBILITY OF SUCH DAMAGE.
41 */
42
43 /*
44 * Copyright (c) 1995
45 * The Regents of the University of California. All rights reserved.
46 *
47 * This code contains ideas from software contributed to Berkeley by
48 * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating
49 * System project at Carnegie-Mellon University.
50 *
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
53 * are met:
54 * 1. Redistributions of source code must retain the above copyright
55 * notice, this list of conditions and the following disclaimer.
56 * 2. Redistributions in binary form must reproduce the above copyright
57 * notice, this list of conditions and the following disclaimer in the
58 * documentation and/or other materials provided with the distribution.
59 * 3. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 * @(#)lock.h 8.12 (Berkeley) 5/19/95
76 */
77
78 #ifndef _SYS_LOCK_H_
79 #define _SYS_LOCK_H_
80
81 #if defined(_KERNEL_OPT)
82 #include "opt_lockdebug.h"
83 #include "opt_multiprocessor.h"
84 #endif
85
86 #include <sys/queue.h>
87 #include <machine/lock.h>
88
89 /*
90 * The simple lock. Provides a simple spinning mutex. Note the
91 * member which is used in atomic operations must be aligned in
92 * order for it to work on the widest range of processor types.
93 */
94 struct simplelock {
95 __cpu_simple_lock_t lock_data;
96 #ifdef LOCKDEBUG
97 const char *lock_file;
98 const char *unlock_file;
99 short lock_line;
100 short unlock_line;
101 TAILQ_ENTRY(simplelock) list;
102 cpuid_t lock_holder; /* CPU ID */
103 #endif
104 };
105
106 #ifdef LOCKDEBUG
107 #define SIMPLELOCK_INITIALIZER { __SIMPLELOCK_UNLOCKED, NULL, NULL, 0, \
108 0, { NULL, NULL }, LK_NOCPU }
109 #else
110 #define SIMPLELOCK_INITIALIZER { __SIMPLELOCK_UNLOCKED }
111 #endif
112
113 /*
114 * The general lock structure. Provides for multiple shared locks,
115 * upgrading from shared to exclusive, and sleeping/spinning until the
116 * lock can be gained.
117 */
118 struct lock {
119 struct simplelock lk_interlock; /* lock on remaining fields */
120 u_int lk_flags; /* see below */
121 int lk_sharecount; /* # of accepted shared locks */
122 short lk_exclusivecount; /* # of recursive exclusive locks */
123 short lk_recurselevel; /* lvl above which recursion ok */
124 int lk_waitcount; /* # of sleepers/spinners */
125
126 /*
127 * This is the sleep message for sleep locks, and a simple name
128 * for spin locks.
129 */
130 const char *lk_wmesg;
131
132 union {
133 struct {
134 /* pid of exclusive lock holder */
135 pid_t lk_sleep_lockholder;
136 lwpid_t lk_sleep_locklwp;
137
138 /* priority at which to sleep */
139 int lk_sleep_prio;
140
141 /* maximum sleep time (for tsleep) */
142 int lk_sleep_timo;
143 } lk_un_sleep;
144 struct {
145 /* CPU ID of exclusive lock holder */
146 cpuid_t lk_spin_cpu;
147 #if defined(LOCKDEBUG)
148 TAILQ_ENTRY(lock) lk_spin_list;
149 #endif
150 } lk_un_spin;
151 } lk_un;
152
153 #define lk_lockholder lk_un.lk_un_sleep.lk_sleep_lockholder
154 #define lk_locklwp lk_un.lk_un_sleep.lk_sleep_locklwp
155 #define lk_prio lk_un.lk_un_sleep.lk_sleep_prio
156 #define lk_timo lk_un.lk_un_sleep.lk_sleep_timo
157
158 #define lk_cpu lk_un.lk_un_spin.lk_spin_cpu
159 #if defined(LOCKDEBUG)
160 #define lk_list lk_un.lk_un_spin.lk_spin_list
161 #endif
162
163 #if defined(LOCKDEBUG)
164 const char *lk_lock_file;
165 const char *lk_unlock_file;
166 int lk_lock_line;
167 int lk_unlock_line;
168 #endif
169 };
170
171 #define LOCK_INITIALIZER(prio, wmesg, timo, flags) \
172 { SIMPLELOCK_INITIALIZER, \
173 (flags), \
174 0, \
175 0, \
176 0, \
177 0, \
178 (wmesg), \
179 { .lk_un_sleep = { 0, 0, (prio), (timo) } } \
180 }
181
182 /*
183 * Lock request types:
184 * LK_SHARED - get one of many possible shared locks. If a process
185 * holding an exclusive lock requests a shared lock, the exclusive
186 * lock(s) will be downgraded to shared locks.
187 * LK_EXCLUSIVE - stop further shared locks, when they are cleared,
188 * grant a pending upgrade if it exists, then grant an exclusive
189 * lock. Only one exclusive lock may exist at a time, except that
190 * a process holding an exclusive lock may get additional exclusive
191 * locks if it explicitly sets the LK_CANRECURSE flag in the lock
192 * request, or if the LK_CANRECUSE flag was set when the lock was
193 * initialized.
194 * LK_UPGRADE - the process must hold a shared lock that it wants to
195 * have upgraded to an exclusive lock. Other processes may get
196 * exclusive access to the resource between the time that the upgrade
197 * is requested and the time that it is granted.
198 * LK_EXCLUPGRADE - the process must hold a shared lock that it wants to
199 * have upgraded to an exclusive lock. If the request succeeds, no
200 * other processes will have gotten exclusive access to the resource
201 * between the time that the upgrade is requested and the time that
202 * it is granted. However, if another process has already requested
203 * an upgrade, the request will fail (see error returns below).
204 * LK_DOWNGRADE - the process must hold an exclusive lock that it wants
205 * to have downgraded to a shared lock. If the process holds multiple
206 * (recursive) exclusive locks, they will all be downgraded to shared
207 * locks.
208 * LK_RELEASE - release one instance of a lock.
209 * LK_DRAIN - wait for all activity on the lock to end, then mark it
210 * decommissioned. This feature is used before freeing a lock that
211 * is part of a piece of memory that is about to be freed.
212 *
213 * These are flags that are passed to the lockmgr routine.
214 */
215 #define LK_TYPE_MASK 0x0000000f /* type of lock sought */
216 #define LK_SHARED 0x00000001 /* shared lock */
217 #define LK_EXCLUSIVE 0x00000002 /* exclusive lock */
218 #define LK_UPGRADE 0x00000003 /* shared-to-exclusive upgrade */
219 #define LK_EXCLUPGRADE 0x00000004 /* first shared-to-exclusive upgrade */
220 #define LK_DOWNGRADE 0x00000005 /* exclusive-to-shared downgrade */
221 #define LK_RELEASE 0x00000006 /* release any type of lock */
222 #define LK_DRAIN 0x00000007 /* wait for all lock activity to end */
223 /*
224 * External lock flags.
225 *
226 * The first three flags may be set in lock_init to set their mode permanently,
227 * or passed in as arguments to the lock manager. The LK_REENABLE flag may be
228 * set only at the release of a lock obtained by drain.
229 */
230 #define LK_EXTFLG_MASK 0x00700070 /* mask of external flags */
231 #define LK_NOWAIT 0x00000010 /* do not sleep to await lock */
232 #define LK_SLEEPFAIL 0x00000020 /* sleep, then return failure */
233 #define LK_CANRECURSE 0x00000040 /* this may be recursive lock attempt */
234 #define LK_REENABLE 0x00000080 /* lock is be reenabled after drain */
235 #define LK_SETRECURSE 0x00100000 /* other locks while we have it OK */
236 #define LK_RECURSEFAIL 0x00200000 /* attempt at recursive lock fails */
237 #define LK_SPIN 0x00400000 /* lock spins instead of sleeps */
238 /*
239 * Internal lock flags.
240 *
241 * These flags are used internally to the lock manager.
242 */
243 #define LK_WANT_UPGRADE 0x00000100 /* waiting for share-to-excl upgrade */
244 #define LK_WANT_EXCL 0x00000200 /* exclusive lock sought */
245 #define LK_HAVE_EXCL 0x00000400 /* exclusive lock obtained */
246 #define LK_WAITDRAIN 0x00000800 /* process waiting for lock to drain */
247 #define LK_DRAINING 0x00004000 /* lock is being drained */
248 #define LK_DRAINED 0x00008000 /* lock has been decommissioned */
249 /*
250 * Internal state flags corresponding to lk_sharecount, and lk_waitcount
251 */
252 #define LK_SHARE_NONZERO 0x00040000 /* lk_sharecount != 0 */
253 #define LK_WAIT_NONZERO 0x00080000 /* lk_waitcount != 0 */
254 /*
255 * Control flags
256 *
257 * Non-persistent external flags.
258 */
259 #define LK_INTERLOCK 0x00010000 /* unlock passed simple lock after
260 getting lk_interlock */
261 #define LK_RETRY 0x00020000 /* vn_lock: retry until locked */
262
263 /*
264 * Lock return status.
265 *
266 * Successfully obtained locks return 0. Locks will always succeed
267 * unless one of the following is true:
268 * LK_FORCEUPGRADE is requested and some other process has already
269 * requested a lock upgrade (returns EBUSY).
270 * LK_WAIT is set and a sleep would be required (returns EBUSY).
271 * LK_SLEEPFAIL is set and a sleep was done (returns ENOLCK).
272 * PCATCH is set in lock priority and a signal arrives (returns
273 * either EINTR or ERESTART if system calls is to be restarted).
274 * Non-null lock timeout and timeout expires (returns EWOULDBLOCK).
275 * A failed lock attempt always returns a non-zero error value. No lock
276 * is held after an error return (in particular, a failed LK_UPGRADE
277 * or LK_FORCEUPGRADE will have released its shared access lock).
278 */
279
280 /*
281 * Indicator that no process/cpu holds exclusive lock
282 */
283 #define LK_KERNPROC ((pid_t) -2)
284 #define LK_NOPROC ((pid_t) -1)
285 #define LK_NOCPU ((cpuid_t) -1)
286
287 #ifdef _KERNEL
288
289 struct proc;
290
291 void lockinit(struct lock *, int, const char *, int, int);
292 #if defined(LOCKDEBUG)
293 int _lockmgr(__volatile struct lock *, u_int, struct simplelock *,
294 const char *, int);
295 #define lockmgr(l, f, i) _lockmgr((l), (f), (i), __FILE__, __LINE__)
296 #else
297 int lockmgr(__volatile struct lock *, u_int flags, struct simplelock *);
298 #endif /* LOCKDEBUG */
299 int lockstatus(struct lock *);
300 void lockmgr_printinfo(__volatile struct lock *);
301
302 #if defined(LOCKDEBUG) || defined(DIAGNOSTIC)
303 void spinlock_switchcheck(void);
304 #endif
305
306 #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
307 #define spinlockinit(lkp, name, flags) \
308 lockinit((lkp), 0, (name), 0, (flags) | LK_SPIN)
309 #define spinlockmgr(lkp, flags, intrlk) \
310 lockmgr((lkp), (flags) | LK_SPIN, (intrlk))
311 #else
312 #define spinlockinit(lkp, name, flags) (void)(lkp)
313 #define spinlockmgr(lkp, flags, intrlk) (0)
314 #endif
315
316 #if defined(LOCKDEBUG)
317 int _spinlock_release_all(__volatile struct lock *, const char *, int);
318 void _spinlock_acquire_count(__volatile struct lock *, int, const char *,
319 int);
320
321 #define spinlock_release_all(l) _spinlock_release_all((l), __FILE__, __LINE__)
322 #define spinlock_acquire_count(l, c) _spinlock_acquire_count((l), (c), \
323 __FILE__, __LINE__)
324 #else
325 int spinlock_release_all(__volatile struct lock *);
326 void spinlock_acquire_count(__volatile struct lock *, int);
327 #endif
328
329 #if defined(LOCKDEBUG)
330 void _simple_lock(__volatile struct simplelock *, const char *, int);
331 int _simple_lock_try(__volatile struct simplelock *, const char *, int);
332 void _simple_unlock(__volatile struct simplelock *, const char *, int);
333 int _simple_lock_held(__volatile struct simplelock *);
334 void simple_lock_only_held(__volatile struct simplelock *, const char *);
335
336 #define simple_lock(alp) _simple_lock((alp), __FILE__, __LINE__)
337 #define simple_lock_try(alp) _simple_lock_try((alp), __FILE__, __LINE__)
338 #define simple_unlock(alp) _simple_unlock((alp), __FILE__, __LINE__)
339 #define simple_lock_held(alp) _simple_lock_held((alp))
340
341 #define LOCK_ASSERT(x) KASSERT(x)
342
343 void simple_lock_init(struct simplelock *);
344 void simple_lock_dump(void);
345 void simple_lock_freecheck(void *, void *);
346 void simple_lock_switchcheck(void);
347 #elif defined(MULTIPROCESSOR)
348 #define simple_lock_init(alp) __cpu_simple_lock_init(&(alp)->lock_data)
349 #define simple_lock(alp) __cpu_simple_lock(&(alp)->lock_data)
350 #define simple_lock_try(alp) __cpu_simple_lock_try(&(alp)->lock_data)
351 #define simple_unlock(alp) __cpu_simple_unlock(&(alp)->lock_data)
352 #define LOCK_ASSERT(x) /* nothing */
353 #define simple_lock_only_held(x,y) /* nothing */
354 #else
355 #define simple_lock_try(alp) (1)
356 #ifndef __lint__
357 #define simple_lock_init(alp) (void)(alp)
358 #define simple_lock(alp) (void)(alp)
359 #define simple_unlock(alp) (void)(alp)
360 #else /* __lint__ */
361 #define simple_lock_init(alp) /* nothing */
362 #define simple_lock(alp) /* nothing */
363 #define simple_unlock(alp) /* nothing */
364 #define simple_lock_only_held(x,y) /* nothing */
365 #endif /* __lint__ */
366 #define LOCK_ASSERT(x) /* nothing */
367 #endif
368
369 #if defined(MULTIPROCESSOR)
370 extern struct lock kernel_lock;
371 #endif
372
373 #endif /* _KERNEL */
374
375 #endif /* _SYS_LOCK_H_ */
Cache object: fc194d9f928785a33f498b0b25159854
|