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