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