| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. |
| 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions |
| 8 | * are met: |
| 9 | * 1. Redistributions of source code must retain the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer. |
| 11 | * 2. Redistributions in binary form must reproduce the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer in the |
| 13 | * documentation and/or other materials provided with the distribution. |
| 14 | * 3. Berkeley Software Design Inc's name may not be used to endorse or |
| 15 | * promote products derived from this software without specific prior |
| 16 | * written permission. |
| 17 | * |
| 18 | * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND |
| 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 21 | * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE |
| 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 28 | * SUCH DAMAGE. |
| 29 | * |
| 30 | *	from BSDI Id: mutex.h,v 2.7.2.35 2000/04/27 03:10:26 cp |
| 31 | */ |
| 32 | |
| 33 | #ifndef _SYS_LOCK_H_ |
| 34 | #define _SYS_LOCK_H_ |
| 35 | |
| 36 | #include <sys/queue.h> |
| 37 | #include <sys/_lock.h> |
| 38 | #include <sys/ktr_class.h> |
| 39 | |
| 40 | struct lock_list_entry; |
| 41 | struct thread; |
| 42 | |
| 43 | /* |
| 44 | * Lock classes. Each lock has a class which describes characteristics |
| 45 | * common to all types of locks of a given class. |
| 46 | * |
| 47 | * Spin locks in general must always protect against preemption, as it is |
| 48 | * an error to perform any type of context switch while holding a spin lock. |
| 49 | * Also, for an individual lock to be recursable, its class must allow |
| 50 | * recursion and the lock itself must explicitly allow recursion. |
| 51 | * |
| 52 | * The 'lc_ddb_show' function pointer is used to dump class-specific |
| 53 | * data for the 'show lock' DDB command. The 'lc_lock' and |
| 54 | * 'lc_unlock' function pointers are used in sleep(9) and cv_wait(9) |
| 55 | * to lock and unlock locks while blocking on a sleep queue. The |
| 56 | * return value of 'lc_unlock' will be passed to 'lc_lock' on resume |
| 57 | * to allow communication of state between the two routines. |
| 58 | */ |
| 59 | |
| 60 | struct lock_class { |
| 61 | 	const		char *lc_name; |
| 62 | 	u_int		lc_flags; |
| 63 | 	void		(*lc_assert)(const struct lock_object *lock, int what); |
| 64 | 	void		(*lc_ddb_show)(const struct lock_object *lock); |
| 65 | 	void		(*lc_lock)(struct lock_object *lock, uintptr_t how); |
| 66 | 	int		(*lc_owner)(const struct lock_object *lock, |
| 67 | 			 struct thread **owner); |
| 68 | 	uintptr_t	(*lc_unlock)(struct lock_object *lock); |
| 69 | 	int		(*lc_trylock)(struct lock_object *lock, uintptr_t how); |
| 70 | }; |
| 71 | |
| 72 | #define	LC_SLEEPLOCK	0x00000001	/* Sleep lock. */ |
| 73 | #define	LC_SPINLOCK	0x00000002	/* Spin lock. */ |
| 74 | #define	LC_SLEEPABLE	0x00000004	/* Sleeping allowed with this lock. */ |
| 75 | #define	LC_RECURSABLE	0x00000008	/* Locks of this type may recurse. */ |
| 76 | #define	LC_UPGRADABLE	0x00000010	/* Upgrades and downgrades permitted. */ |
| 77 | |
| 78 | #define	LO_CLASSFLAGS	0x0000ffff	/* Class specific flags. */ |
| 79 | #define	LO_INITIALIZED	0x00010000	/* Lock has been initialized. */ |
| 80 | #define	LO_WITNESS	0x00020000	/* Should witness monitor this lock. */ |
| 81 | #define	LO_QUIET	0x00040000	/* Don't log locking operations. */ |
| 82 | #define	LO_RECURSABLE	0x00080000	/* Lock may recurse. */ |
| 83 | #define	LO_SLEEPABLE	0x00100000	/* Lock may be held while sleeping. */ |
| 84 | #define	LO_UPGRADABLE	0x00200000	/* Lock may be upgraded/downgraded. */ |
| 85 | #define	LO_DUPOK	0x00400000	/* Don't check for duplicate acquires */ |
| 86 | #define	LO_IS_VNODE	0x00800000	/* Tell WITNESS about a VNODE lock */ |
| 87 | #define	LO_CLASSMASK	0x0f000000	/* Class index bitmask. */ |
| 88 | #define LO_NOPROFILE 0x10000000 /* Don't profile this lock */ |
| 89 | #define	LO_NEW		0x20000000	/* Don't check for double-init */ |
| 90 | |
| 91 | /* |
| 92 | * Lock classes are statically assigned an index into the gobal lock_classes |
| 93 | * array. Debugging code looks up the lock class for a given lock object |
| 94 | * by indexing the array. |
| 95 | */ |
| 96 | #define	LO_CLASSSHIFT		24 |
| 97 | #define	LO_CLASSINDEX(lock)	((((lock)->lo_flags) & LO_CLASSMASK) >> LO_CLASSSHIFT) |
| 98 | #define	LOCK_CLASS(lock)	(lock_classes[LO_CLASSINDEX((lock))]) |
| 99 | #define	LOCK_CLASS_MAX		(LO_CLASSMASK >> LO_CLASSSHIFT) |
| 100 | |
| 101 | /* |
| 102 | * Option flags passed to lock operations that witness also needs to know |
| 103 | * about or that are generic across all locks. |
| 104 | */ |
| 105 | #define	LOP_NEWORDER	0x00000001	/* Define a new lock order. */ |
| 106 | #define	LOP_QUIET	0x00000002	/* Don't log locking operations. */ |
| 107 | #define	LOP_TRYLOCK	0x00000004	/* Don't check lock order. */ |
| 108 | #define	LOP_EXCLUSIVE	0x00000008	/* Exclusive lock. */ |
| 109 | #define	LOP_DUPOK	0x00000010	/* Don't check for duplicate acquires */ |
| 110 | #define	LOP_NOSLEEP	0x00000020	/* Non-sleepable despite LO_SLEEPABLE */ |
| 111 | |
| 112 | /* Flags passed to witness_assert. */ |
| 113 | #define	LA_MASKASSERT	0x000000ff	/* Mask for witness defined asserts. */ |
| 114 | #define	LA_UNLOCKED	0x00000000	/* Lock is unlocked. */ |
| 115 | #define	LA_LOCKED	0x00000001	/* Lock is at least share locked. */ |
| 116 | #define	LA_SLOCKED	0x00000002	/* Lock is exactly share locked. */ |
| 117 | #define	LA_XLOCKED	0x00000004	/* Lock is exclusively locked. */ |
| 118 | #define	LA_RECURSED	0x00000008	/* Lock is recursed. */ |
| 119 | #define	LA_NOTRECURSED	0x00000010	/* Lock is not recursed. */ |
| 120 | |
| 121 | #ifdef _KERNEL |
| 122 | /* |
| 123 | * Macros for KTR_LOCK tracing. |
| 124 | * |
| 125 | * opname - name of this operation (LOCK/UNLOCK/SLOCK, etc.) |
| 126 | * lo - struct lock_object * for this lock |
| 127 | * flags - flags passed to the lock operation |
| 128 | * recurse - this locks recursion level (or 0 if class is not recursable) |
| 129 | * result - result of a try lock operation |
| 130 | * file - file name |
| 131 | * line - line number |
| 132 | */ |
| 133 | #if LOCK_DEBUG > 0 |
| 134 | #define	LOCK_LOG_TEST(lo, flags)					\ |
| 135 | 	(((flags) & LOP_QUIET) == 0 && ((lo)->lo_flags & LO_QUIET) == 0) |
| 136 | #else |
| 137 | #define	LOCK_LOG_TEST(lo, flags)	0 |
| 138 | #endif |
| 139 | |
| 140 | #define	LOCK_LOG_LOCK(opname, lo, flags, recurse, file, line) do {	\ |
| 141 | 	if (LOCK_LOG_TEST((lo), (flags)))				\ |
| 142 | 		CTR6(KTR_LOCK, opname " (%s) %s %p r = %d at %s:%d",	\ |
| 143 | 		 LOCK_CLASS(lo)->lc_name, (lo)->lo_name,		\ |
| 144 | 		 (lo), (u_int)(recurse), (file), (line));		\ |
| 145 | } while (0) |
| 146 | |
| 147 | #define	LOCK_LOG_TRY(opname, lo, flags, result, file, line) do {	\ |
| 148 | 	if (LOCK_LOG_TEST((lo), (flags)))				\ |
| 149 | 		CTR6(KTR_LOCK, "TRY_" opname " (%s) %s %p result=%d at %s:%d",\ |
| 150 | 		 LOCK_CLASS(lo)->lc_name, (lo)->lo_name,		\ |
| 151 | 		 (lo), (u_int)(result), (file), (line));		\ |
| 152 | } while (0) |
| 153 | |
| 154 | #define	LOCK_LOG_INIT(lo, flags) do {					\ |
| 155 | 	if (LOCK_LOG_TEST((lo), (flags)))				\ |
| 156 | 		CTR4(KTR_LOCK, "%s: %p (%s) %s", __func__, (lo),	\ |
| 157 | 		 LOCK_CLASS(lo)->lc_name, (lo)->lo_name);		\ |
| 158 | } while (0) |
| 159 | |
| 160 | #define	LOCK_LOG_DESTROY(lo, flags)	LOCK_LOG_INIT(lo, flags) |
| 161 | |
| 162 | #define	lock_initialized(lo)	((lo)->lo_flags & LO_INITIALIZED) |
| 163 | |
| 164 | extern struct lock_class lock_class_mtx_sleep; |
| 165 | extern struct lock_class lock_class_mtx_spin; |
| 166 | extern struct lock_class lock_class_sx; |
| 167 | extern struct lock_class lock_class_rw; |
| 168 | extern struct lock_class lock_class_rm; |
| 169 | extern struct lock_class lock_class_rm_sleepable; |
| 170 | extern struct lock_class lock_class_lockmgr; |
| 171 | |
| 172 | extern struct lock_class *lock_classes[]; |
| 173 | |
| 174 | struct lock_delay_config { |
| 175 | 	u_short base; |
| 176 | 	u_short max; |
| 177 | }; |
| 178 | |
| 179 | extern struct lock_delay_config locks_delay; |
| 180 | extern u_short locks_delay_retries; |
| 181 | extern u_short locks_delay_loops; |
| 182 | |
| 183 | struct lock_delay_arg { |
| 184 | 	struct lock_delay_config *config; |
| 185 | 	u_int delay; |
| 186 | 	u_int spin_cnt; |
| 187 | }; |
| 188 | |
| 189 | static inline void |
| 190 | lock_delay_arg_init(struct lock_delay_arg *la, struct lock_delay_config *lc) |
| 191 | { |
| 192 | 	la->config = lc; |
| 193 | 	la->delay = lc->base; |
| 194 | 	la->spin_cnt = 0; |
| 195 | } |
| 196 | |
| 197 | static inline void |
| 198 | lock_delay_arg_init_noadapt(struct lock_delay_arg *la) |
| 199 | { |
| 200 | 	la->delay = 0; |
| 201 | 	la->spin_cnt = 0; |
| 202 | } |
| 203 | |
| 204 | #define lock_delay_spin(n)	do {	\ |
| 205 | 	u_int _i;			\ |
| 206 | 					\ |
| 207 | 	for (_i = (n); _i > 0; _i--)	\ |
| 208 | 		cpu_spinwait();		\ |
| 209 | } while (0) |
| 210 | |
| 211 | #define	LOCK_DELAY_SYSINIT(func) \ |
| 212 | 	SYSINIT(func##_ld, SI_SUB_LOCK, SI_ORDER_ANY, func, NULL) |
| 213 | |
| 214 | #define	LOCK_DELAY_SYSINIT_DEFAULT(lc) \ |
| 215 | 	SYSINIT(lock_delay_##lc##_ld, SI_SUB_LOCK, SI_ORDER_ANY, \ |
| 216 | 	 lock_delay_default_init, &lc) |
| 217 | |
| 218 | void	lock_init(struct lock_object *, struct lock_class *, |
| 219 | 	 const char *, const char *, int); |
| 220 | void	lock_destroy(struct lock_object *); |
| 221 | void	lock_delay(struct lock_delay_arg *); |
| 222 | void	lock_delay_default_init(struct lock_delay_config *); |
| 223 | void	spinlock_enter(void); |
| 224 | void	spinlock_exit(void); |
| 225 | void	witness_init(struct lock_object *, const char *); |
| 226 | void	witness_destroy(struct lock_object *); |
| 227 | int	witness_defineorder(struct lock_object *, struct lock_object *); |
| 228 | void	witness_checkorder(struct lock_object *, int, const char *, int, |
| 229 | 	 struct lock_object *); |
| 230 | void	witness_lock(struct lock_object *, int, const char *, int); |
| 231 | void	witness_upgrade(struct lock_object *, int, const char *, int); |
| 232 | void	witness_downgrade(struct lock_object *, int, const char *, int); |
| 233 | void	witness_unlock(struct lock_object *, int, const char *, int); |
| 234 | void	witness_save(struct lock_object *, const char **, int *); |
| 235 | void	witness_restore(struct lock_object *, const char *, int); |
| 236 | int	witness_list_locks(struct lock_list_entry **, |
| 237 | 	 int (*)(const char *, ...)); |
| 238 | int	witness_warn(int, struct lock_object *, const char *, ...); |
| 239 | void	witness_assert(const struct lock_object *, int, const char *, int); |
| 240 | int	witness_is_owned(const struct lock_object *lock); |
| 241 | void	witness_display_spinlock(struct lock_object *, struct thread *, |
| 242 | 	 int (*)(const char *, ...)); |
| 243 | int	witness_line(struct lock_object *); |
| 244 | void	witness_norelease(struct lock_object *); |
| 245 | void	witness_releaseok(struct lock_object *); |
| 246 | const char *witness_file(struct lock_object *); |
| 247 | void	witness_thread_exit(struct thread *); |
| 248 | |
| 249 | #ifdef	WITNESS |
| 250 | int	witness_startup_count(void); |
| 251 | void	witness_startup(void *); |
| 252 | |
| 253 | /* Flags for witness_warn(). */ |
| 254 | #define	WARN_GIANTOK	0x01	/* Giant is exempt from this check. */ |
| 255 | #define	WARN_PANIC	0x02	/* Panic if check fails. */ |
| 256 | #define	WARN_SLEEPOK	0x04	/* Sleepable locks are exempt from check. */ |
| 257 | |
| 258 | #define	WITNESS_INIT(lock, type)					\ |
| 259 | 	witness_init((lock), (type)) |
| 260 | |
| 261 | #define WITNESS_DESTROY(lock)						\ |
| 262 | 	witness_destroy(lock) |
| 263 | |
| 264 | #define	WITNESS_CHECKORDER(lock, flags, file, line, interlock)		\ |
| 265 | 	witness_checkorder((lock), (flags), (file), (line), (interlock)) |
| 266 | |
| 267 | #define	WITNESS_DEFINEORDER(lock1, lock2)				\ |
| 268 | 	witness_defineorder((struct lock_object *)(lock1),		\ |
| 269 | 	 (struct lock_object *)(lock2)) |
| 270 | |
| 271 | #define	WITNESS_LOCK(lock, flags, file, line)				\ |
| 272 | 	witness_lock((lock), (flags), (file), (line)) |
| 273 | |
| 274 | #define	WITNESS_UPGRADE(lock, flags, file, line)			\ |
| 275 | 	witness_upgrade((lock), (flags), (file), (line)) |
| 276 | |
| 277 | #define	WITNESS_DOWNGRADE(lock, flags, file, line)			\ |
| 278 | 	witness_downgrade((lock), (flags), (file), (line)) |
| 279 | |
| 280 | #define	WITNESS_UNLOCK(lock, flags, file, line)				\ |
| 281 | 	witness_unlock((lock), (flags), (file), (line)) |
| 282 | |
| 283 | #define	WITNESS_CHECK(flags, lock, fmt, ...)				\ |
| 284 | 	witness_warn((flags), (lock), (fmt), ## __VA_ARGS__) |
| 285 | |
| 286 | #define	WITNESS_WARN(flags, lock, fmt, ...)				\ |
| 287 | 	witness_warn((flags), (lock), (fmt), ## __VA_ARGS__) |
| 288 | |
| 289 | #define	WITNESS_SAVE_DECL(n)						\ |
| 290 | 	const char * __CONCAT(n, __wf);					\ |
| 291 | 	int __CONCAT(n, __wl) |
| 292 | |
| 293 | #define	WITNESS_SAVE(lock, n) 						\ |
| 294 | 	witness_save((lock), &__CONCAT(n, __wf), &__CONCAT(n, __wl)) |
| 295 | |
| 296 | #define	WITNESS_RESTORE(lock, n) 					\ |
| 297 | 	witness_restore((lock), __CONCAT(n, __wf), __CONCAT(n, __wl)) |
| 298 | |
| 299 | #define	WITNESS_NORELEASE(lock)						\ |
| 300 | 	witness_norelease(&(lock)->lock_object) |
| 301 | |
| 302 | #define	WITNESS_RELEASEOK(lock)						\ |
| 303 | 	witness_releaseok(&(lock)->lock_object) |
| 304 | |
| 305 | #define	WITNESS_FILE(lock) 						\ |
| 306 | 	witness_file(lock) |
| 307 | |
| 308 | #define	WITNESS_LINE(lock) 						\ |
| 309 | 	witness_line(lock) |
| 310 | |
| 311 | #else	/* WITNESS */ |
| 312 | #define	WITNESS_INIT(lock, type)				(void)0 |
| 313 | #define	WITNESS_DESTROY(lock)					(void)0 |
| 314 | #define	WITNESS_DEFINEORDER(lock1, lock2)	0 |
| 315 | #define	WITNESS_CHECKORDER(lock, flags, file, line, interlock)	(void)0 |
| 316 | #define	WITNESS_LOCK(lock, flags, file, line)			(void)0 |
| 317 | #define	WITNESS_UPGRADE(lock, flags, file, line)		(void)0 |
| 318 | #define	WITNESS_DOWNGRADE(lock, flags, file, line)		(void)0 |
| 319 | #define	WITNESS_UNLOCK(lock, flags, file, line)			(void)0 |
| 320 | #define	WITNESS_CHECK(flags, lock, fmt, ...)	0 |
| 321 | #define	WITNESS_WARN(flags, lock, fmt, ...)			(void)0 |
| 322 | #define	WITNESS_SAVE_DECL(n)					(void)0 |
| 323 | #define	WITNESS_SAVE(lock, n)					(void)0 |
| 324 | #define	WITNESS_RESTORE(lock, n)				(void)0 |
| 325 | #define	WITNESS_NORELEASE(lock)					(void)0 |
| 326 | #define	WITNESS_RELEASEOK(lock)					(void)0 |
| 327 | #define	WITNESS_FILE(lock) ("?") |
| 328 | #define	WITNESS_LINE(lock) (0) |
| 329 | #endif	/* WITNESS */ |
| 330 | |
| 331 | #endif	/* _KERNEL */ |
| 332 | #endif	/* _SYS_LOCK_H_ */ |