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