kern_lock.c revision 1.2 1 /* $NetBSD: kern_lock.c,v 1.2 1997/07/06 12:35:33 fvdl Exp $ */
2
3 /*
4 * Copyright (c) 1995
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code contains ideas from software contributed to Berkeley by
8 * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating
9 * System project at Carnegie-Mellon University.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * @(#)kern_lock.c 8.18 (Berkeley) 5/21/95
40 */
41
42 #include <sys/param.h>
43 #include <sys/proc.h>
44 #include <sys/lock.h>
45 #include <sys/systm.h>
46 #include <machine/cpu.h>
47
48 /*
49 * Locking primitives implementation.
50 * Locks provide shared/exclusive sychronization.
51 */
52
53 #ifdef DEBUG
54 #define COUNT(p, x) if (p) (p)->p_locks += (x)
55 #else
56 #define COUNT(p, x)
57 #endif
58
59 #if NCPUS > 1
60
61 /*
62 * For multiprocessor system, try spin lock first.
63 *
64 * This should be inline expanded below, but we cannot have #if
65 * inside a multiline define.
66 */
67 int lock_wait_time = 100;
68 #define PAUSE(lkp, wanted) \
69 if (lock_wait_time > 0) { \
70 int i; \
71 \
72 simple_unlock(&lkp->lk_interlock); \
73 for (i = lock_wait_time; i > 0; i--) \
74 if (!(wanted)) \
75 break; \
76 simple_lock(&lkp->lk_interlock); \
77 } \
78 if (!(wanted)) \
79 break;
80
81 #else /* NCPUS == 1 */
82
83 /*
84 * It is an error to spin on a uniprocessor as nothing will ever cause
85 * the simple lock to clear while we are executing.
86 */
87 #define PAUSE(lkp, wanted)
88
89 #endif /* NCPUS == 1 */
90
91 /*
92 * Acquire a resource.
93 */
94 #define ACQUIRE(lkp, error, extflags, wanted) \
95 PAUSE(lkp, wanted); \
96 for (error = 0; wanted; ) { \
97 (lkp)->lk_waitcount++; \
98 simple_unlock(&(lkp)->lk_interlock); \
99 error = tsleep((void *)lkp, (lkp)->lk_prio, \
100 (lkp)->lk_wmesg, (lkp)->lk_timo); \
101 simple_lock(&(lkp)->lk_interlock); \
102 (lkp)->lk_waitcount--; \
103 if (error) \
104 break; \
105 if ((extflags) & LK_SLEEPFAIL) { \
106 error = ENOLCK; \
107 break; \
108 } \
109 }
110
111 /*
112 * Initialize a lock; required before use.
113 */
114 void
115 lockinit(lkp, prio, wmesg, timo, flags)
116 struct lock *lkp;
117 int prio;
118 char *wmesg;
119 int timo;
120 int flags;
121 {
122
123 bzero(lkp, sizeof(struct lock));
124 simple_lock_init(&lkp->lk_interlock);
125 lkp->lk_flags = flags & LK_EXTFLG_MASK;
126 lkp->lk_prio = prio;
127 lkp->lk_timo = timo;
128 lkp->lk_wmesg = wmesg;
129 lkp->lk_lockholder = LK_NOPROC;
130 }
131
132 /*
133 * Determine the status of a lock.
134 */
135 int
136 lockstatus(lkp)
137 struct lock *lkp;
138 {
139 int lock_type = 0;
140
141 simple_lock(&lkp->lk_interlock);
142 if (lkp->lk_exclusivecount != 0)
143 lock_type = LK_EXCLUSIVE;
144 else if (lkp->lk_sharecount != 0)
145 lock_type = LK_SHARED;
146 simple_unlock(&lkp->lk_interlock);
147 return (lock_type);
148 }
149
150 /*
151 * Set, change, or release a lock.
152 *
153 * Shared requests increment the shared count. Exclusive requests set the
154 * LK_WANT_EXCL flag (preventing further shared locks), and wait for already
155 * accepted shared locks and shared-to-exclusive upgrades to go away.
156 */
157 int
158 lockmgr(lkp, flags, interlkp, p)
159 __volatile struct lock *lkp;
160 u_int flags;
161 struct simplelock *interlkp;
162 struct proc *p;
163 {
164 int error;
165 pid_t pid;
166 int extflags;
167
168 error = 0;
169 if (p)
170 pid = p->p_pid;
171 else
172 pid = LK_KERNPROC;
173 simple_lock(&lkp->lk_interlock);
174 if (flags & LK_INTERLOCK)
175 simple_unlock(interlkp);
176 extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
177 #ifdef DIAGNOSTIC
178 /*
179 * Once a lock has drained, the LK_DRAINING flag is set and an
180 * exclusive lock is returned. The only valid operation thereafter
181 * is a single release of that exclusive lock. This final release
182 * clears the LK_DRAINING flag and sets the LK_DRAINED flag. Any
183 * further requests of any sort will result in a panic. The bits
184 * selected for these two flags are chosen so that they will be set
185 * in memory that is freed (freed memory is filled with 0xdeadbeef).
186 * The final release is permitted to give a new lease on life to
187 * the lock by specifying LK_REENABLE.
188 */
189 if (lkp->lk_flags & (LK_DRAINING|LK_DRAINED)) {
190 if (lkp->lk_flags & LK_DRAINED)
191 panic("lockmgr: using decommissioned lock");
192 if ((flags & LK_TYPE_MASK) != LK_RELEASE ||
193 lkp->lk_lockholder != pid)
194 panic("lockmgr: non-release on draining lock: %d\n",
195 flags & LK_TYPE_MASK);
196 lkp->lk_flags &= ~LK_DRAINING;
197 if ((flags & LK_REENABLE) == 0)
198 lkp->lk_flags |= LK_DRAINED;
199 }
200 #endif DIAGNOSTIC
201
202 switch (flags & LK_TYPE_MASK) {
203
204 case LK_SHARED:
205 if (lkp->lk_lockholder != pid) {
206 /*
207 * If just polling, check to see if we will block.
208 */
209 if ((extflags & LK_NOWAIT) && (lkp->lk_flags &
210 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE))) {
211 error = EBUSY;
212 break;
213 }
214 /*
215 * Wait for exclusive locks and upgrades to clear.
216 */
217 ACQUIRE(lkp, error, extflags, lkp->lk_flags &
218 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE));
219 if (error)
220 break;
221 lkp->lk_sharecount++;
222 COUNT(p, 1);
223 break;
224 }
225 /*
226 * We hold an exclusive lock, so downgrade it to shared.
227 * An alternative would be to fail with EDEADLK.
228 */
229 lkp->lk_sharecount++;
230 COUNT(p, 1);
231 /* fall into downgrade */
232
233 case LK_DOWNGRADE:
234 if (lkp->lk_lockholder != pid || lkp->lk_exclusivecount == 0)
235 panic("lockmgr: not holding exclusive lock");
236 lkp->lk_sharecount += lkp->lk_exclusivecount;
237 lkp->lk_exclusivecount = 0;
238 lkp->lk_flags &= ~LK_HAVE_EXCL;
239 lkp->lk_lockholder = LK_NOPROC;
240 if (lkp->lk_waitcount)
241 wakeup((void *)lkp);
242 break;
243
244 case LK_EXCLUPGRADE:
245 /*
246 * If another process is ahead of us to get an upgrade,
247 * then we want to fail rather than have an intervening
248 * exclusive access.
249 */
250 if (lkp->lk_flags & LK_WANT_UPGRADE) {
251 lkp->lk_sharecount--;
252 COUNT(p, -1);
253 error = EBUSY;
254 break;
255 }
256 /* fall into normal upgrade */
257
258 case LK_UPGRADE:
259 /*
260 * Upgrade a shared lock to an exclusive one. If another
261 * shared lock has already requested an upgrade to an
262 * exclusive lock, our shared lock is released and an
263 * exclusive lock is requested (which will be granted
264 * after the upgrade). If we return an error, the file
265 * will always be unlocked.
266 */
267 if (lkp->lk_lockholder == pid || lkp->lk_sharecount <= 0)
268 panic("lockmgr: upgrade exclusive lock");
269 lkp->lk_sharecount--;
270 COUNT(p, -1);
271 /*
272 * If we are just polling, check to see if we will block.
273 */
274 if ((extflags & LK_NOWAIT) &&
275 ((lkp->lk_flags & LK_WANT_UPGRADE) ||
276 lkp->lk_sharecount > 1)) {
277 error = EBUSY;
278 break;
279 }
280 if ((lkp->lk_flags & LK_WANT_UPGRADE) == 0) {
281 /*
282 * We are first shared lock to request an upgrade, so
283 * request upgrade and wait for the shared count to
284 * drop to zero, then take exclusive lock.
285 */
286 lkp->lk_flags |= LK_WANT_UPGRADE;
287 ACQUIRE(lkp, error, extflags, lkp->lk_sharecount);
288 lkp->lk_flags &= ~LK_WANT_UPGRADE;
289 if (error)
290 break;
291 lkp->lk_flags |= LK_HAVE_EXCL;
292 lkp->lk_lockholder = pid;
293 if (lkp->lk_exclusivecount != 0)
294 panic("lockmgr: non-zero exclusive count");
295 lkp->lk_exclusivecount = 1;
296 COUNT(p, 1);
297 break;
298 }
299 /*
300 * Someone else has requested upgrade. Release our shared
301 * lock, awaken upgrade requestor if we are the last shared
302 * lock, then request an exclusive lock.
303 */
304 if (lkp->lk_sharecount == 0 && lkp->lk_waitcount)
305 wakeup((void *)lkp);
306 /* fall into exclusive request */
307
308 case LK_EXCLUSIVE:
309 if (lkp->lk_lockholder == pid && pid != LK_KERNPROC) {
310 /*
311 * Recursive lock.
312 */
313 if ((extflags & LK_CANRECURSE) == 0)
314 panic("lockmgr: locking against myself");
315 lkp->lk_exclusivecount++;
316 COUNT(p, 1);
317 break;
318 }
319 /*
320 * If we are just polling, check to see if we will sleep.
321 */
322 if ((extflags & LK_NOWAIT) && ((lkp->lk_flags &
323 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE)) ||
324 lkp->lk_sharecount != 0)) {
325 error = EBUSY;
326 break;
327 }
328 /*
329 * Try to acquire the want_exclusive flag.
330 */
331 ACQUIRE(lkp, error, extflags, lkp->lk_flags &
332 (LK_HAVE_EXCL | LK_WANT_EXCL));
333 if (error)
334 break;
335 lkp->lk_flags |= LK_WANT_EXCL;
336 /*
337 * Wait for shared locks and upgrades to finish.
338 */
339 ACQUIRE(lkp, error, extflags, lkp->lk_sharecount != 0 ||
340 (lkp->lk_flags & LK_WANT_UPGRADE));
341 lkp->lk_flags &= ~LK_WANT_EXCL;
342 if (error)
343 break;
344 lkp->lk_flags |= LK_HAVE_EXCL;
345 lkp->lk_lockholder = pid;
346 if (lkp->lk_exclusivecount != 0)
347 panic("lockmgr: non-zero exclusive count");
348 lkp->lk_exclusivecount = 1;
349 COUNT(p, 1);
350 break;
351
352 case LK_RELEASE:
353 if (lkp->lk_exclusivecount != 0) {
354 if (pid != lkp->lk_lockholder)
355 panic("lockmgr: pid %d, not %s %d unlocking",
356 pid, "exclusive lock holder",
357 lkp->lk_lockholder);
358 lkp->lk_exclusivecount--;
359 COUNT(p, -1);
360 if (lkp->lk_exclusivecount == 0) {
361 lkp->lk_flags &= ~LK_HAVE_EXCL;
362 lkp->lk_lockholder = LK_NOPROC;
363 }
364 } else if (lkp->lk_sharecount != 0) {
365 lkp->lk_sharecount--;
366 COUNT(p, -1);
367 }
368 if (lkp->lk_waitcount)
369 wakeup((void *)lkp);
370 break;
371
372 case LK_DRAIN:
373 /*
374 * Check that we do not already hold the lock, as it can
375 * never drain if we do. Unfortunately, we have no way to
376 * check for holding a shared lock, but at least we can
377 * check for an exclusive one.
378 */
379 if (lkp->lk_lockholder == pid)
380 panic("lockmgr: draining against myself");
381 /*
382 * If we are just polling, check to see if we will sleep.
383 */
384 if ((extflags & LK_NOWAIT) && ((lkp->lk_flags &
385 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE)) ||
386 lkp->lk_sharecount != 0 || lkp->lk_waitcount != 0)) {
387 error = EBUSY;
388 break;
389 }
390 PAUSE(lkp, ((lkp->lk_flags &
391 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE)) ||
392 lkp->lk_sharecount != 0 || lkp->lk_waitcount != 0));
393 for (error = 0; ((lkp->lk_flags &
394 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE)) ||
395 lkp->lk_sharecount != 0 || lkp->lk_waitcount != 0); ) {
396 lkp->lk_flags |= LK_WAITDRAIN;
397 simple_unlock(&lkp->lk_interlock);
398 if ((error = tsleep((void *)&lkp->lk_flags,
399 lkp->lk_prio, lkp->lk_wmesg, lkp->lk_timo)))
400 return (error);
401 if ((extflags) & LK_SLEEPFAIL)
402 return (ENOLCK);
403 simple_lock(&lkp->lk_interlock);
404 }
405 lkp->lk_flags |= LK_DRAINING | LK_HAVE_EXCL;
406 lkp->lk_lockholder = pid;
407 lkp->lk_exclusivecount = 1;
408 COUNT(p, 1);
409 break;
410
411 default:
412 simple_unlock(&lkp->lk_interlock);
413 panic("lockmgr: unknown locktype request %d",
414 flags & LK_TYPE_MASK);
415 /* NOTREACHED */
416 }
417 if ((lkp->lk_flags & LK_WAITDRAIN) && ((lkp->lk_flags &
418 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE)) == 0 &&
419 lkp->lk_sharecount == 0 && lkp->lk_waitcount == 0)) {
420 lkp->lk_flags &= ~LK_WAITDRAIN;
421 wakeup((void *)&lkp->lk_flags);
422 }
423 simple_unlock(&lkp->lk_interlock);
424 return (error);
425 }
426
427 /*
428 * Print out information about state of a lock. Used by VOP_PRINT
429 * routines to display ststus about contained locks.
430 */
431 void
432 lockmgr_printinfo(lkp)
433 struct lock *lkp;
434 {
435
436 if (lkp->lk_sharecount)
437 printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg,
438 lkp->lk_sharecount);
439 else if (lkp->lk_flags & LK_HAVE_EXCL)
440 printf(" lock type %s: EXCL (count %d) by pid %d",
441 lkp->lk_wmesg, lkp->lk_exclusivecount, lkp->lk_lockholder);
442 if (lkp->lk_waitcount > 0)
443 printf(" with %d pending", lkp->lk_waitcount);
444 }
445
446 #if defined(DEBUG) && NCPUS == 1
447 #include <sys/kernel.h>
448 #include <vm/vm.h>
449 #include <sys/sysctl.h>
450 int lockpausetime = 0;
451 struct ctldebug debug2 = { "lockpausetime", &lockpausetime };
452 int simplelockrecurse;
453 /*
454 * Simple lock functions so that the debugger can see from whence
455 * they are being called.
456 */
457 void
458 simple_lock_init(alp)
459 struct simplelock *alp;
460 {
461
462 alp->lock_data = 0;
463 }
464
465 void
466 _simple_lock(alp, id, l)
467 __volatile struct simplelock *alp;
468 const char *id;
469 int l;
470 {
471
472 if (simplelockrecurse)
473 return;
474 if (alp->lock_data == 1) {
475 if (lockpausetime == -1)
476 panic("%s:%d: simple_lock: lock held", id, l);
477 printf("%s:%d: simple_lock: lock held\n", id, l);
478 if (lockpausetime == 1) {
479 #ifdef BACKTRACE
480 BACKTRACE(curproc);
481 #endif
482 } else if (lockpausetime > 1) {
483 printf("%s:%d: simple_lock: lock held...", id, l);
484 tsleep(&lockpausetime, PCATCH | PPAUSE, "slock",
485 lockpausetime * hz);
486 printf(" continuing\n");
487 }
488 }
489 alp->lock_data = 1;
490 if (curproc)
491 curproc->p_simple_locks++;
492 }
493
494 int
495 _simple_lock_try(alp, id, l)
496 __volatile struct simplelock *alp;
497 const char *id;
498 int l;
499 {
500
501 if (alp->lock_data)
502 return (0);
503 if (simplelockrecurse)
504 return (1);
505 alp->lock_data = 1;
506 if (curproc)
507 curproc->p_simple_locks++;
508 return (1);
509 }
510
511 void
512 _simple_unlock(alp, id, l)
513 __volatile struct simplelock *alp;
514 const char *id;
515 int l;
516 {
517
518 if (simplelockrecurse)
519 return;
520 if (alp->lock_data == 0) {
521 if (lockpausetime == -1)
522 panic("%s:%d: simple_unlock: lock not held", id, l);
523 printf("%s:%d: simple_unlock: lock not held\n", id, l);
524 if (lockpausetime == 1) {
525 #ifdef BACKTRACE
526 BACKTRACE(curproc);
527 #endif
528 } else if (lockpausetime > 1) {
529 printf("%s:%d: simple_unlock: lock not held...", id, l);
530 tsleep(&lockpausetime, PCATCH | PPAUSE, "sunlock",
531 lockpausetime * hz);
532 printf(" continuing\n");
533 }
534 }
535 alp->lock_data = 0;
536 if (curproc)
537 curproc->p_simple_locks--;
538 }
539 #endif /* DEBUG && NCPUS == 1 */
540