kern_lock.c revision 42408
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.20 1998/11/26 18:50:23 eivind 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
74static int acquire(struct lock *lkp, int extflags, int wanted);
75static int apause(struct lock *lkp, int flags);
76static int acquiredrain(struct lock *lkp, int extflags) ;
77
78static LOCK_INLINE void
79sharelock(struct lock *lkp, int incr) {
80	lkp->lk_flags |= LK_SHARE_NONZERO;
81	lkp->lk_sharecount += incr;
82}
83
84static LOCK_INLINE void
85shareunlock(struct lock *lkp, int decr) {
86	KASSERT(lkp->lk_sharecount >= decr, ("shareunlock: count < decr"));
87
88	if (lkp->lk_sharecount == decr) {
89		lkp->lk_flags &= ~LK_SHARE_NONZERO;
90		if (lkp->lk_flags & (LK_WANT_UPGRADE | LK_WANT_EXCL)) {
91			wakeup(lkp);
92		}
93		lkp->lk_sharecount = 0;
94	} else {
95		lkp->lk_sharecount -= decr;
96	}
97}
98
99/*
100 * This is the waitloop optimization, and note for this to work
101 * simple_lock and simple_unlock should be subroutines to avoid
102 * optimization troubles.
103 */
104static int
105apause(struct lock *lkp, int flags) {
106	int lock_wait;
107	lock_wait = LOCK_WAIT_TIME;
108	for (; lock_wait > 0; lock_wait--) {
109		int i;
110		if ((lkp->lk_flags & flags) == 0)
111			return 0;
112		simple_unlock(&lkp->lk_interlock);
113		for (i = LOCK_SAMPLE_WAIT; i > 0; i--) {
114			if ((lkp->lk_flags & flags) == 0) {
115				simple_lock(&lkp->lk_interlock);
116				if ((lkp->lk_flags & flags) == 0)
117					return 0;
118				break;
119			}
120		}
121	}
122	return 1;
123}
124
125static int
126acquire(struct lock *lkp, int extflags, int wanted) {
127	int s, error;
128
129	if ((extflags & LK_NOWAIT) && (lkp->lk_flags & wanted)) {
130		return EBUSY;
131	}
132
133	if (((lkp->lk_flags | extflags) & LK_NOPAUSE) == 0) {
134		error = apause(lkp, wanted);
135		if (error == 0)
136			return 0;
137	}
138
139	s = splhigh();
140	while ((lkp->lk_flags & wanted) != 0) {
141		lkp->lk_flags |= LK_WAIT_NONZERO;
142		lkp->lk_waitcount++;
143		simple_unlock(&lkp->lk_interlock);
144		error = tsleep(lkp, lkp->lk_prio, lkp->lk_wmesg, lkp->lk_timo);
145		simple_lock(&lkp->lk_interlock);
146		if (lkp->lk_waitcount == 1) {
147			lkp->lk_flags &= ~LK_WAIT_NONZERO;
148			lkp->lk_waitcount = 0;
149		} else {
150			lkp->lk_waitcount--;
151		}
152		if (error) {
153			splx(s);
154			return error;
155		}
156		if (extflags & LK_SLEEPFAIL) {
157			splx(s);
158			return ENOLCK;
159		}
160	}
161	splx(s);
162	return 0;
163}
164
165/*
166 * Set, change, or release a lock.
167 *
168 * Shared requests increment the shared count. Exclusive requests set the
169 * LK_WANT_EXCL flag (preventing further shared locks), and wait for already
170 * accepted shared locks and shared-to-exclusive upgrades to go away.
171 */
172int
173lockmgr(lkp, flags, interlkp, p)
174	struct lock *lkp;
175	u_int flags;
176	struct simplelock *interlkp;
177	struct proc *p;
178{
179	int error;
180	pid_t pid;
181	int extflags;
182
183	error = 0;
184	if (p == NULL)
185		pid = LK_KERNPROC;
186	else
187		pid = p->p_pid;
188
189	simple_lock(&lkp->lk_interlock);
190	if (flags & LK_INTERLOCK)
191		simple_unlock(interlkp);
192
193	extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
194
195	switch (flags & LK_TYPE_MASK) {
196
197	case LK_SHARED:
198		if (lkp->lk_lockholder != pid) {
199			error = acquire(lkp, extflags,
200				LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE);
201			if (error)
202				break;
203			sharelock(lkp, 1);
204			COUNT(p, 1);
205			break;
206		}
207		/*
208		 * We hold an exclusive lock, so downgrade it to shared.
209		 * An alternative would be to fail with EDEADLK.
210		 */
211		sharelock(lkp, 1);
212		COUNT(p, 1);
213		/* fall into downgrade */
214
215	case LK_DOWNGRADE:
216#if !defined(MAX_PERF)
217		if (lkp->lk_lockholder != pid || lkp->lk_exclusivecount == 0)
218			panic("lockmgr: not holding exclusive lock");
219#endif
220		sharelock(lkp, lkp->lk_exclusivecount);
221		lkp->lk_exclusivecount = 0;
222		lkp->lk_flags &= ~LK_HAVE_EXCL;
223		lkp->lk_lockholder = LK_NOPROC;
224		if (lkp->lk_waitcount)
225			wakeup((void *)lkp);
226		break;
227
228	case LK_EXCLUPGRADE:
229		/*
230		 * If another process is ahead of us to get an upgrade,
231		 * then we want to fail rather than have an intervening
232		 * exclusive access.
233		 */
234		if (lkp->lk_flags & LK_WANT_UPGRADE) {
235			shareunlock(lkp, 1);
236			COUNT(p, -1);
237			error = EBUSY;
238			break;
239		}
240		/* fall into normal upgrade */
241
242	case LK_UPGRADE:
243		/*
244		 * Upgrade a shared lock to an exclusive one. If another
245		 * shared lock has already requested an upgrade to an
246		 * exclusive lock, our shared lock is released and an
247		 * exclusive lock is requested (which will be granted
248		 * after the upgrade). If we return an error, the file
249		 * will always be unlocked.
250		 */
251#if !defined(MAX_PERF)
252		if ((lkp->lk_lockholder == pid) || (lkp->lk_sharecount <= 0))
253			panic("lockmgr: upgrade exclusive lock");
254#endif
255		shareunlock(lkp, 1);
256		COUNT(p, -1);
257		/*
258		 * If we are just polling, check to see if we will block.
259		 */
260		if ((extflags & LK_NOWAIT) &&
261		    ((lkp->lk_flags & LK_WANT_UPGRADE) ||
262		     lkp->lk_sharecount > 1)) {
263			error = EBUSY;
264			break;
265		}
266		if ((lkp->lk_flags & LK_WANT_UPGRADE) == 0) {
267			/*
268			 * We are first shared lock to request an upgrade, so
269			 * request upgrade and wait for the shared count to
270			 * drop to zero, then take exclusive lock.
271			 */
272			lkp->lk_flags |= LK_WANT_UPGRADE;
273			error = acquire(lkp, extflags, LK_SHARE_NONZERO);
274			lkp->lk_flags &= ~LK_WANT_UPGRADE;
275
276			if (error)
277				break;
278			lkp->lk_flags |= LK_HAVE_EXCL;
279			lkp->lk_lockholder = pid;
280#if !defined(MAX_PERF)
281			if (lkp->lk_exclusivecount != 0)
282				panic("lockmgr: non-zero exclusive count");
283#endif
284			lkp->lk_exclusivecount = 1;
285			COUNT(p, 1);
286			break;
287		}
288		/*
289		 * Someone else has requested upgrade. Release our shared
290		 * lock, awaken upgrade requestor if we are the last shared
291		 * lock, then request an exclusive lock.
292		 */
293		if ( (lkp->lk_flags & (LK_SHARE_NONZERO|LK_WAIT_NONZERO)) ==
294			LK_WAIT_NONZERO)
295			wakeup((void *)lkp);
296		/* fall into exclusive request */
297
298	case LK_EXCLUSIVE:
299		if (lkp->lk_lockholder == pid && pid != LK_KERNPROC) {
300			/*
301			 *	Recursive lock.
302			 */
303#if !defined(MAX_PERF)
304			if ((extflags & LK_CANRECURSE) == 0)
305				panic("lockmgr: locking against myself");
306#endif
307			lkp->lk_exclusivecount++;
308			COUNT(p, 1);
309			break;
310		}
311		/*
312		 * If we are just polling, check to see if we will sleep.
313		 */
314		if ((extflags & LK_NOWAIT) &&
315		    (lkp->lk_flags & (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | LK_SHARE_NONZERO))) {
316			error = EBUSY;
317			break;
318		}
319		/*
320		 * Try to acquire the want_exclusive flag.
321		 */
322		error = acquire(lkp, extflags, (LK_HAVE_EXCL | LK_WANT_EXCL));
323		if (error)
324			break;
325		lkp->lk_flags |= LK_WANT_EXCL;
326		/*
327		 * Wait for shared locks and upgrades to finish.
328		 */
329		error = acquire(lkp, extflags, LK_WANT_UPGRADE | LK_SHARE_NONZERO);
330		lkp->lk_flags &= ~LK_WANT_EXCL;
331		if (error)
332			break;
333		lkp->lk_flags |= LK_HAVE_EXCL;
334		lkp->lk_lockholder = pid;
335#if !defined(MAX_PERF)
336		if (lkp->lk_exclusivecount != 0)
337			panic("lockmgr: non-zero exclusive count");
338#endif
339		lkp->lk_exclusivecount = 1;
340		COUNT(p, 1);
341		break;
342
343	case LK_RELEASE:
344		if (lkp->lk_exclusivecount != 0) {
345#if !defined(MAX_PERF)
346			if (pid != lkp->lk_lockholder)
347				panic("lockmgr: pid %d, not %s %d unlocking",
348				    pid, "exclusive lock holder",
349				    lkp->lk_lockholder);
350#endif
351			COUNT(p, -1);
352			if (lkp->lk_exclusivecount == 1) {
353				lkp->lk_flags &= ~LK_HAVE_EXCL;
354				lkp->lk_lockholder = LK_NOPROC;
355				lkp->lk_exclusivecount = 0;
356			} else {
357				lkp->lk_exclusivecount--;
358			}
359		} else if (lkp->lk_flags & LK_SHARE_NONZERO) {
360			shareunlock(lkp, 1);
361			COUNT(p, -1);
362		}
363		if (lkp->lk_flags & LK_WAIT_NONZERO)
364			wakeup((void *)lkp);
365		break;
366
367	case LK_DRAIN:
368		/*
369		 * Check that we do not already hold the lock, as it can
370		 * never drain if we do. Unfortunately, we have no way to
371		 * check for holding a shared lock, but at least we can
372		 * check for an exclusive one.
373		 */
374#if !defined(MAX_PERF)
375		if (lkp->lk_lockholder == pid)
376			panic("lockmgr: draining against myself");
377#endif
378
379		error = acquiredrain(lkp, extflags);
380		if (error)
381			break;
382		lkp->lk_flags |= LK_DRAINING | LK_HAVE_EXCL;
383		lkp->lk_lockholder = pid;
384		lkp->lk_exclusivecount = 1;
385		COUNT(p, 1);
386		break;
387
388	default:
389#if !defined(MAX_PERF)
390		simple_unlock(&lkp->lk_interlock);
391		panic("lockmgr: unknown locktype request %d",
392		    flags & LK_TYPE_MASK);
393#endif
394		/* NOTREACHED */
395	}
396	if ((lkp->lk_flags & LK_WAITDRAIN) &&
397	    (lkp->lk_flags & (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE |
398		LK_SHARE_NONZERO | LK_WAIT_NONZERO)) == 0) {
399		lkp->lk_flags &= ~LK_WAITDRAIN;
400		wakeup((void *)&lkp->lk_flags);
401	}
402	simple_unlock(&lkp->lk_interlock);
403	return (error);
404}
405
406static int
407acquiredrain(struct lock *lkp, int extflags) {
408	int error;
409
410	if ((extflags & LK_NOWAIT) && (lkp->lk_flags & LK_ALL)) {
411		return EBUSY;
412	}
413
414	error = apause(lkp, LK_ALL);
415	if (error == 0)
416		return 0;
417
418	while (lkp->lk_flags & LK_ALL) {
419		lkp->lk_flags |= LK_WAITDRAIN;
420		simple_unlock(&lkp->lk_interlock);
421		error = tsleep(&lkp->lk_flags, lkp->lk_prio,
422			lkp->lk_wmesg, lkp->lk_timo);
423		simple_lock(&lkp->lk_interlock);
424		if (error)
425			return error;
426		if (extflags & LK_SLEEPFAIL) {
427			return ENOLCK;
428		}
429	}
430	return 0;
431}
432
433/*
434 * Initialize a lock; required before use.
435 */
436void
437lockinit(lkp, prio, wmesg, timo, flags)
438	struct lock *lkp;
439	int prio;
440	char *wmesg;
441	int timo;
442	int flags;
443{
444
445	simple_lock_init(&lkp->lk_interlock);
446	lkp->lk_flags = (flags & LK_EXTFLG_MASK);
447	lkp->lk_sharecount = 0;
448	lkp->lk_waitcount = 0;
449	lkp->lk_exclusivecount = 0;
450	lkp->lk_prio = prio;
451	lkp->lk_wmesg = wmesg;
452	lkp->lk_timo = timo;
453	lkp->lk_lockholder = LK_NOPROC;
454}
455
456/*
457 * Determine the status of a lock.
458 */
459int
460lockstatus(lkp)
461	struct lock *lkp;
462{
463	int lock_type = 0;
464
465	simple_lock(&lkp->lk_interlock);
466	if (lkp->lk_exclusivecount != 0)
467		lock_type = LK_EXCLUSIVE;
468	else if (lkp->lk_sharecount != 0)
469		lock_type = LK_SHARED;
470	simple_unlock(&lkp->lk_interlock);
471	return (lock_type);
472}
473
474/*
475 * Print out information about state of a lock. Used by VOP_PRINT
476 * routines to display status about contained locks.
477 */
478void
479lockmgr_printinfo(lkp)
480	struct lock *lkp;
481{
482
483	if (lkp->lk_sharecount)
484		printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg,
485		    lkp->lk_sharecount);
486	else if (lkp->lk_flags & LK_HAVE_EXCL)
487		printf(" lock type %s: EXCL (count %d) by pid %d",
488		    lkp->lk_wmesg, lkp->lk_exclusivecount, lkp->lk_lockholder);
489	if (lkp->lk_waitcount > 0)
490		printf(" with %d pending", lkp->lk_waitcount);
491}
492
493#if defined(SIMPLELOCK_DEBUG) && (NCPUS == 1 || defined(COMPILING_LINT))
494#include <sys/kernel.h>
495#include <sys/sysctl.h>
496
497static int lockpausetime = 0;
498SYSCTL_INT(_debug, OID_AUTO, lockpausetime, CTLFLAG_RW, &lockpausetime, 0, "");
499
500static int simplelockrecurse;
501
502/*
503 * Simple lock functions so that the debugger can see from whence
504 * they are being called.
505 */
506void
507simple_lock_init(alp)
508	struct simplelock *alp;
509{
510
511	alp->lock_data = 0;
512}
513
514void
515_simple_lock(alp, id, l)
516	struct simplelock *alp;
517	const char *id;
518	int l;
519{
520
521	if (simplelockrecurse)
522		return;
523	if (alp->lock_data == 1) {
524		if (lockpausetime == -1)
525			panic("%s:%d: simple_lock: lock held", id, l);
526		printf("%s:%d: simple_lock: lock held\n", id, l);
527		if (lockpausetime == 1) {
528			Debugger("simple_lock");
529			/*BACKTRACE(curproc); */
530		} else if (lockpausetime > 1) {
531			printf("%s:%d: simple_lock: lock held...", id, l);
532			tsleep(&lockpausetime, PCATCH | PPAUSE, "slock",
533			    lockpausetime * hz);
534			printf(" continuing\n");
535		}
536	}
537	alp->lock_data = 1;
538	if (curproc)
539		curproc->p_simple_locks++;
540}
541
542int
543_simple_lock_try(alp, id, l)
544	struct simplelock *alp;
545	const char *id;
546	int l;
547{
548
549	if (alp->lock_data)
550		return (0);
551	if (simplelockrecurse)
552		return (1);
553	alp->lock_data = 1;
554	if (curproc)
555		curproc->p_simple_locks++;
556	return (1);
557}
558
559void
560_simple_unlock(alp, id, l)
561	struct simplelock *alp;
562	const char *id;
563	int l;
564{
565
566	if (simplelockrecurse)
567		return;
568	if (alp->lock_data == 0) {
569		if (lockpausetime == -1)
570			panic("%s:%d: simple_unlock: lock not held", id, l);
571		printf("%s:%d: simple_unlock: lock not held\n", id, l);
572		if (lockpausetime == 1) {
573			Debugger("simple_unlock");
574			/* BACKTRACE(curproc); */
575		} else if (lockpausetime > 1) {
576			printf("%s:%d: simple_unlock: lock not held...", id, l);
577			tsleep(&lockpausetime, PCATCH | PPAUSE, "sunlock",
578			    lockpausetime * hz);
579			printf(" continuing\n");
580		}
581	}
582	alp->lock_data = 0;
583	if (curproc)
584		curproc->p_simple_locks--;
585}
586#elif defined(SIMPLELOCK_DEBUG)
587#error "SIMPLELOCK_DEBUG is not compatible with SMP!"
588#endif /* SIMPLELOCK_DEBUG && NCPUS == 1 */
589