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