lock.h revision 111881
150276Speter/*-
2166124Srafan * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
350276Speter *
450276Speter * Redistribution and use in source and binary forms, with or without
550276Speter * modification, are permitted provided that the following conditions
650276Speter * are met:
750276Speter * 1. Redistributions of source code must retain the above copyright
850276Speter *    notice, this list of conditions and the following disclaimer.
950276Speter * 2. Redistributions in binary form must reproduce the above copyright
1050276Speter *    notice, this list of conditions and the following disclaimer in the
1150276Speter *    documentation and/or other materials provided with the distribution.
1250276Speter * 3. Berkeley Software Design Inc's name may not be used to endorse or
1350276Speter *    promote products derived from this software without specific prior
1450276Speter *    written permission.
1550276Speter *
1650276Speter * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND
1750276Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1850276Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1950276Speter * ARE DISCLAIMED.  IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE
2050276Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2150276Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2250276Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2350276Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2450276Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2550276Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2650276Speter * SUCH DAMAGE.
2750276Speter *
2850276Speter *	from BSDI $Id: mutex.h,v 2.7.2.35 2000/04/27 03:10:26 cp Exp $
2950276Speter * $FreeBSD: head/sys/sys/lock.h 111881 2003-03-04 20:56:39Z jhb $
3050276Speter */
3150276Speter
32166124Srafan#ifndef _SYS_LOCK_H_
3350276Speter#define _SYS_LOCK_H_
3450276Speter
3550276Speter#include <sys/queue.h>
3650276Speter#include <sys/_lock.h>
3750276Speter
3850276Speterstruct thread;
39166124Srafan
40166124Srafan/*
41166124Srafan * Lock classes.  Each lock has a class which describes characteristics
4250276Speter * common to all types of locks of a given class.
4350276Speter *
4450276Speter * Spin locks in general must always protect against preemption, as it is
4597049Speter * an error to perform any type of context switch while holding a spin lock.
4697049Speter * Also, for an individual lock to be recursable, its class must allow
4756639Speter * recursion and the lock itself must explicitly allow recursion.
4897049Speter */
4997049Speter
5056639Speterstruct lock_class {
5156639Speter	const	char *lc_name;
5256639Speter	u_int	lc_flags;
5350276Speter};
5450276Speter
5550276Speter#define	LC_SLEEPLOCK	0x00000001	/* Sleep lock. */
5650276Speter#define	LC_SPINLOCK	0x00000002	/* Spin lock. */
5750276Speter#define	LC_SLEEPABLE	0x00000004	/* Sleeping allowed with this lock. */
5850276Speter#define	LC_RECURSABLE	0x00000008	/* Locks of this type may recurse. */
5950276Speter#define	LC_UPGRADABLE	0x00000010	/* Upgrades and downgrades permitted. */
6050276Speter
6150276Speter#define	LO_CLASSFLAGS	0x0000ffff	/* Class specific flags. */
6250276Speter#define	LO_INITIALIZED	0x00010000	/* Lock has been initialized. */
6350276Speter#define	LO_WITNESS	0x00020000	/* Should witness monitor this lock. */
6450276Speter#define	LO_QUIET	0x00040000	/* Don't log locking operations. */
6550276Speter#define	LO_RECURSABLE	0x00080000	/* Lock may recurse. */
6650276Speter#define	LO_SLEEPABLE	0x00100000	/* Lock may be held while sleeping. */
6750276Speter#define	LO_UPGRADABLE	0x00200000	/* Lock may be upgraded/downgraded. */
6850276Speter#define	LO_DUPOK	0x00400000	/* Don't check for duplicate acquires */
6950276Speter
7050276Speter#define	LI_RECURSEMASK	0x0000ffff	/* Recursion depth of lock instance. */
7150276Speter#define	LI_EXCLUSIVE	0x00010000	/* Exclusive lock instance. */
7250276Speter
7350276Speter/*
74166124Srafan * Option flags passed to lock operations that witness also needs to know
7550276Speter * about or that are generic across all locks.
7650276Speter */
77166124Srafan#define	LOP_QUIET	0x00000002	/* Don't log locking operations. */
7850276Speter#define	LOP_TRYLOCK	0x00000004	/* Don't check lock order. */
7950276Speter#define	LOP_EXCLUSIVE	0x00000008	/* Exclusive lock. */
8050276Speter
8150276Speter/* Flags passed to witness_assert. */
8250276Speter#define	LA_UNLOCKED	0x00000000	/* Lock is unlocked. */
8350276Speter#define	LA_LOCKED	0x00000001	/* Lock is at least share locked. */
8450276Speter#define	LA_SLOCKED	0x00000002	/* Lock is exactly share locked. */
8550276Speter#define	LA_XLOCKED	0x00000004	/* Lock is exclusively locked. */
8650276Speter#define	LA_RECURSED	0x00000008	/* Lock is recursed. */
8750276Speter#define	LA_NOTRECURSED	0x00000010	/* Lock is not recursed. */
8850276Speter
8950276Speter#ifdef _KERNEL
9062449Speter/*
9162449Speter * Lock instances.  A lock instance is the data associated with a lock while
92166124Srafan * it is held by witness.  For example, a lock instance will hold the
93166124Srafan * recursion count of a lock.  Lock instances are held in lists.  Spin locks
94166124Srafan * are held in a per-cpu list while sleep locks are held in per-process list.
9550276Speter */
9650276Speterstruct lock_instance {
9750276Speter	struct	lock_object *li_lock;
9850276Speter	const	char *li_file;		/* File and line of last acquire. */
9950276Speter	int	li_line;
10050276Speter	u_int	li_flags;		/* Recursion count and LI_* flags. */
10150276Speter};
102166124Srafan
10350276Speter/*
10497049Speter * A simple list type used to build the list of locks held by a process
10562449Speter * or CPU.  We can't simply embed the list in struct lock_object since a
10662449Speter * lock may be held by more than one process if it is a shared lock.  Locks
10797049Speter * are added to the head of the list, so we fill up each list entry from
10862449Speter * "the back" logically.  To ease some of the arithmetic, we actually fill
10950276Speter * in each list entry the normal way (childer[0] then children[1], etc.) but
11050276Speter * when we traverse the list we read children[count-1] as the first entry
11150276Speter * down to children[0] as the final entry.
11250276Speter */
11350276Speter#define	LOCK_NCHILDREN	3
11450276Speter
11550276Speterstruct lock_list_entry {
11650276Speter	struct	lock_list_entry *ll_next;
11762449Speter	struct	lock_instance ll_children[LOCK_NCHILDREN];
11862449Speter	u_int	ll_count;
11950276Speter};
12050276Speter
12162449Speter/*
12266963Speter * If any of WITNESS, INVARIANTS, or KTR_LOCK KTR tracing has been enabled,
12350276Speter * then turn on LOCK_DEBUG.  When this option is on, extra debugging
12450276Speter * facilities such as tracking the file and line number of lock operations
12556639Speter * are enabled.  Also, mutex locking operations are not inlined to avoid
12650276Speter * bloat from all the extra debugging code.  We also have to turn on all the
12750276Speter * calling conventions for this debugging code in modules so that modules can
12866963Speter * work with both debug and non-debug kernels.
12950276Speter */
13062449Speter#if defined(KLD_MODULE) || defined(WITNESS) || defined(INVARIANTS) || defined(INVARIANT_SUPPORT) || defined(KTR)
13156639Speter#define	LOCK_DEBUG	1
13266963Speter#else
13366963Speter#define	LOCK_DEBUG	0
13466963Speter#endif
13566963Speter
13666963Speter/*
13766963Speter * In the LOCK_DEBUG case, use the filename and line numbers for debugging
13866963Speter * operations.  Otherwise, use default values to avoid the unneeded bloat.
13966963Speter */
14050276Speter#if LOCK_DEBUG > 0
14150276Speter#define	LOCK_FILE	__FILE__
14250276Speter#define	LOCK_LINE	__LINE__
14356639Speter#else
14450276Speter#define	LOCK_FILE	NULL
14556639Speter#define	LOCK_LINE	0
14656639Speter#endif
14756639Speter
14856639Speter/*
14956639Speter * Macros for KTR_LOCK tracing.
15056639Speter *
15156639Speter * opname  - name of this operation (LOCK/UNLOCK/SLOCK, etc.)
15266963Speter * lo      - struct lock_object * for this lock
15356639Speter * flags   - flags passed to the lock operation
15466963Speter * recurse - this locks recursion level (or 0 if class is not recursable)
15556639Speter * result  - result of a try lock operation
15656639Speter * file    - file name
15756639Speter * line    - line number
15856639Speter */
15950276Speter#define	LOCK_LOG_TEST(lo, flags)					\
16056639Speter	(((flags) & LOP_QUIET) == 0 && ((lo)->lo_flags & LO_QUIET) == 0)
16162449Speter
16250276Speter#define	LOCK_LOG_LOCK(opname, lo, flags, recurse, file, line) do {	\
16350276Speter	if (LOCK_LOG_TEST((lo), (flags)))				\
16450276Speter		CTR5(KTR_LOCK, opname " (%s) %s r = %d at %s:%d",	\
16550276Speter		    (lo)->lo_class->lc_name, (lo)->lo_name,		\
16650276Speter		    (u_int)(recurse), (file), (line));			\
16750276Speter} while (0)
16850276Speter
16950276Speter#define	LOCK_LOG_TRY(opname, lo, flags, result, file, line) do {	\
170166124Srafan	if (LOCK_LOG_TEST((lo), (flags)))				\
17162449Speter		CTR5(KTR_LOCK, "TRY_" opname " (%s) %s result=%d at %s:%d",\
17250276Speter		    (lo)->lo_class->lc_name, (lo)->lo_name,		\
17362449Speter		    (u_int)(result), (file), (line));			\
17466963Speter} while (0)
17550276Speter
17662449Speter#define	LOCK_LOG_INIT(lo, flags) do {					\
17750276Speter	if (LOCK_LOG_TEST((lo), (flags)))				\
17862449Speter		CTR4(KTR_LOCK, "%s: %p (%s) %s", __func__, (lo),	\
17962449Speter 		    (lo)->lo_class->lc_name, (lo)->lo_name);		\
18050276Speter} while (0)
18150276Speter
182166124Srafan#define	LOCK_LOG_DESTROY(lo, flags)	LOCK_LOG_INIT(lo, flags)
18397049Speter
18450276Speter/*
185166124Srafan * Helpful macros for quickly coming up with assertions with informative
186166124Srafan * panic messages.
18797049Speter */
18897049Speter#define MPASS(ex)		MPASS4(ex, #ex, __FILE__, __LINE__)
189166124Srafan#define MPASS2(ex, what)	MPASS4(ex, what, __FILE__, __LINE__)
19050276Speter#define MPASS3(ex, file, line)	MPASS4(ex, #ex, file, line)
191166124Srafan#define MPASS4(ex, what, file, line)					\
192166124Srafan	KASSERT((ex), ("Assertion %s failed at %s:%d", what, file, line))
193166124Srafan
194166124Srafanextern struct lock_class lock_class_mtx_sleep;
195166124Srafanextern struct lock_class lock_class_mtx_spin;
196166124Srafanextern struct lock_class lock_class_sx;
197166124Srafan
198166124Srafanvoid	witness_init(struct lock_object *);
199166124Srafanvoid	witness_destroy(struct lock_object *);
200166124Srafanvoid	witness_lock(struct lock_object *, int, const char *, int);
201166124Srafanvoid	witness_upgrade(struct lock_object *, int, const char *, int);
202166124Srafanvoid	witness_downgrade(struct lock_object *, int, const char *, int);
203166124Srafanvoid	witness_unlock(struct lock_object *, int, const char *, int);
204166124Srafanvoid	witness_save(struct lock_object *, const char **, int *);
205166124Srafanvoid	witness_restore(struct lock_object *, const char *, int);
206166124Srafanint	witness_list_locks(struct lock_list_entry **);
207166124Srafanint	witness_warn(int, struct lock_object *, const char *, ...);
208166124Srafanvoid	witness_assert(struct lock_object *, int, const char *, int);
209166124Srafanint	witness_line(struct lock_object *);
210166124Srafanconst char *witness_file(struct lock_object *);
211166124Srafan
212166124Srafan#ifdef	WITNESS
213166124Srafan
214166124Srafan/* Flags for witness_warn(). */
215166124Srafan#define	WARN_GIANTOK	0x01	/* Giant is exempt from this check. */
216166124Srafan#define	WARN_PANIC	0x02	/* Panic if check fails. */
217166124Srafan#define	WARN_SLEEPOK	0x04	/* Sleepable locks are exempt from check. */
218166124Srafan
219166124Srafan#define	WITNESS_INIT(lock)						\
220166124Srafan	witness_init((lock))
221166124Srafan
222166124Srafan#define WITNESS_DESTROY(lock)						\
223166124Srafan	witness_destroy(lock)
224166124Srafan
225166124Srafan#define	WITNESS_LOCK(lock, flags, file, line)				\
226166124Srafan	witness_lock((lock), (flags), (file), (line))
227166124Srafan
228166124Srafan#define	WITNESS_UPGRADE(lock, flags, file, line)			\
229166124Srafan	witness_upgrade((lock), (flags), (file), (line))
230166124Srafan
231166124Srafan#define	WITNESS_DOWNGRADE(lock, flags, file, line)			\
232166124Srafan	witness_downgrade((lock), (flags), (file), (line))
233166124Srafan
234166124Srafan#define	WITNESS_UNLOCK(lock, flags, file, line)				\
235166124Srafan	witness_unlock((lock), (flags), (file), (line))
236166124Srafan
237166124Srafan#define	WITNESS_WARN(flags, lock, fmt, ...)				\
238166124Srafan	witness_warn((flags), (lock), (fmt), ## __VA_ARGS__)
239166124Srafan
240166124Srafan#define	WITNESS_SAVE_DECL(n)						\
241166124Srafan	const char * __CONCAT(n, __wf);					\
242166124Srafan	int __CONCAT(n, __wl)
243166124Srafan
244166124Srafan#define	WITNESS_SAVE(lock, n) 						\
245166124Srafan	witness_save((lock), &__CONCAT(n, __wf), &__CONCAT(n, __wl))
246166124Srafan
247166124Srafan#define	WITNESS_RESTORE(lock, n) 					\
248166124Srafan	witness_restore((lock), __CONCAT(n, __wf), __CONCAT(n, __wl))
249166124Srafan
250166124Srafan#define	WITNESS_FILE(lock) 						\
251166124Srafan	witness_file(lock)
252166124Srafan
253166124Srafan#define	WITNESS_LINE(lock) 						\
254166124Srafan	witness_line(lock)
255166124Srafan
256166124Srafan#else	/* WITNESS */
257166124Srafan#define	WITNESS_INIT(lock)	((lock)->lo_flags |= LO_INITIALIZED)
258166124Srafan#define	WITNESS_DESTROY(lock)	((lock)->lo_flags &= ~LO_INITIALIZED)
259166124Srafan#define	WITNESS_LOCK(lock, flags, file, line)
260166124Srafan#define	WITNESS_UPGRADE(lock, flags, file, line)
261166124Srafan#define	WITNESS_DOWNGRADE(lock, flags, file, line)
262166124Srafan#define	WITNESS_UNLOCK(lock, flags, file, line)
263166124Srafan#define	WITNESS_WARN(flags, lock, fmt, ...)
264166124Srafan#define	WITNESS_SAVE_DECL(n)
265166124Srafan#define	WITNESS_SAVE(lock, n)
266166124Srafan#define	WITNESS_RESTORE(lock, n)
267166124Srafan#define	WITNESS_FILE(lock) ("?")
268166124Srafan#define	WITNESS_LINE(lock) (0)
269166124Srafan#endif	/* WITNESS */
270166124Srafan
271166124Srafan#endif	/* _KERNEL */
272166124Srafan#endif	/* _SYS_LOCK_H_ */
273166124Srafan