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