174912Sjhb/*- 274912Sjhb * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. 324269Speter * 424269Speter * Redistribution and use in source and binary forms, with or without 524269Speter * modification, are permitted provided that the following conditions 624269Speter * are met: 724269Speter * 1. Redistributions of source code must retain the above copyright 824269Speter * notice, this list of conditions and the following disclaimer. 924269Speter * 2. Redistributions in binary form must reproduce the above copyright 1024269Speter * notice, this list of conditions and the following disclaimer in the 1124269Speter * documentation and/or other materials provided with the distribution. 1274912Sjhb * 3. Berkeley Software Design Inc's name may not be used to endorse or 1374912Sjhb * promote products derived from this software without specific prior 1474912Sjhb * written permission. 1524269Speter * 1674912Sjhb * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND 1724269Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1824269Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1974912Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE 2024269Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2124269Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2224269Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2324269Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2424269Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2524269Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2624269Speter * SUCH DAMAGE. 2724269Speter * 28212408Sobrien * from BSDI Id: mutex.h,v 2.7.2.35 2000/04/27 03:10:26 cp 2950477Speter * $FreeBSD$ 3024269Speter */ 3124269Speter 3274912Sjhb#ifndef _SYS_LOCK_H_ 3374912Sjhb#define _SYS_LOCK_H_ 3424269Speter 3574912Sjhb#include <sys/queue.h> 3676166Smarkm#include <sys/_lock.h> 3774912Sjhb 38178165Sattiliostruct lock_list_entry; 39102506Sbdestruct thread; 40102506Sbde 4124269Speter/* 4274912Sjhb * Lock classes. Each lock has a class which describes characteristics 4374912Sjhb * common to all types of locks of a given class. 4424269Speter * 4574912Sjhb * Spin locks in general must always protect against preemption, as it is 4674912Sjhb * an error to perform any type of context switch while holding a spin lock. 4774912Sjhb * Also, for an individual lock to be recursable, its class must allow 4874912Sjhb * recursion and the lock itself must explicitly allow recursion. 49167368Sjhb * 50167368Sjhb * The 'lc_ddb_show' function pointer is used to dump class-specific 51167368Sjhb * data for the 'show lock' DDB command. The 'lc_lock' and 52167368Sjhb * 'lc_unlock' function pointers are used in sleep(9) and cv_wait(9) 53167368Sjhb * to lock and unlock locks while blocking on a sleep queue. The 54167368Sjhb * return value of 'lc_unlock' will be passed to 'lc_lock' on resume 55167368Sjhb * to allow communication of state between the two routines. 5624269Speter */ 5774912Sjhb 5883045Sobrienstruct lock_class { 59255745Sdavide const char *lc_name; 60255745Sdavide u_int lc_flags; 61255745Sdavide void (*lc_assert)(const struct lock_object *lock, int what); 62255745Sdavide void (*lc_ddb_show)(const struct lock_object *lock); 63255745Sdavide void (*lc_lock)(struct lock_object *lock, uintptr_t how); 64255745Sdavide int (*lc_owner)(const struct lock_object *lock, 65255745Sdavide struct thread **owner); 66255745Sdavide uintptr_t (*lc_unlock)(struct lock_object *lock); 6774912Sjhb}; 6874912Sjhb 6974912Sjhb#define LC_SLEEPLOCK 0x00000001 /* Sleep lock. */ 7074912Sjhb#define LC_SPINLOCK 0x00000002 /* Spin lock. */ 7174912Sjhb#define LC_SLEEPABLE 0x00000004 /* Sleeping allowed with this lock. */ 7274912Sjhb#define LC_RECURSABLE 0x00000008 /* Locks of this type may recurse. */ 7382244Sjhb#define LC_UPGRADABLE 0x00000010 /* Upgrades and downgrades permitted. */ 7474912Sjhb 7574912Sjhb#define LO_CLASSFLAGS 0x0000ffff /* Class specific flags. */ 7674912Sjhb#define LO_INITIALIZED 0x00010000 /* Lock has been initialized. */ 7774912Sjhb#define LO_WITNESS 0x00020000 /* Should witness monitor this lock. */ 7874912Sjhb#define LO_QUIET 0x00040000 /* Don't log locking operations. */ 7974912Sjhb#define LO_RECURSABLE 0x00080000 /* Lock may recurse. */ 8074912Sjhb#define LO_SLEEPABLE 0x00100000 /* Lock may be held while sleeping. */ 8182244Sjhb#define LO_UPGRADABLE 0x00200000 /* Lock may be upgraded/downgraded. */ 8293273Sjeff#define LO_DUPOK 0x00400000 /* Don't check for duplicate acquires */ 83250411Smarcel#define LO_IS_VNODE 0x00800000 /* Tell WITNESS about a VNODE lock */ 84154077Sjhb#define LO_CLASSMASK 0x0f000000 /* Class index bitmask. */ 85164159Skmacy#define LO_NOPROFILE 0x10000000 /* Don't profile this lock */ 8674912Sjhb 87154077Sjhb/* 88154077Sjhb * Lock classes are statically assigned an index into the gobal lock_classes 89154077Sjhb * array. Debugging code looks up the lock class for a given lock object 90154077Sjhb * by indexing the array. 91154077Sjhb */ 92154077Sjhb#define LO_CLASSSHIFT 24 93154077Sjhb#define LO_CLASSINDEX(lock) ((((lock)->lo_flags) & LO_CLASSMASK) >> LO_CLASSSHIFT) 94154077Sjhb#define LOCK_CLASS(lock) (lock_classes[LO_CLASSINDEX((lock))]) 95154484Sjhb#define LOCK_CLASS_MAX (LO_CLASSMASK >> LO_CLASSSHIFT) 96154077Sjhb 9724269Speter/* 9874912Sjhb * Option flags passed to lock operations that witness also needs to know 9974912Sjhb * about or that are generic across all locks. 10024269Speter */ 101125160Sjhb#define LOP_NEWORDER 0x00000001 /* Define a new lock order. */ 10274912Sjhb#define LOP_QUIET 0x00000002 /* Don't log locking operations. */ 10374912Sjhb#define LOP_TRYLOCK 0x00000004 /* Don't check lock order. */ 10476272Sjhb#define LOP_EXCLUSIVE 0x00000008 /* Exclusive lock. */ 105145421Sjeff#define LOP_DUPOK 0x00000010 /* Don't check for duplicate acquires */ 10624269Speter 10778871Sjhb/* Flags passed to witness_assert. */ 108176249Sattilio#define LA_MASKASSERT 0x000000ff /* Mask for witness defined asserts. */ 10978871Sjhb#define LA_UNLOCKED 0x00000000 /* Lock is unlocked. */ 11078871Sjhb#define LA_LOCKED 0x00000001 /* Lock is at least share locked. */ 11178871Sjhb#define LA_SLOCKED 0x00000002 /* Lock is exactly share locked. */ 11278871Sjhb#define LA_XLOCKED 0x00000004 /* Lock is exclusively locked. */ 11378871Sjhb#define LA_RECURSED 0x00000008 /* Lock is recursed. */ 11478871Sjhb#define LA_NOTRECURSED 0x00000010 /* Lock is not recursed. */ 11578871Sjhb 11674912Sjhb#ifdef _KERNEL 11724269Speter/* 11885186Sjhb * If any of WITNESS, INVARIANTS, or KTR_LOCK KTR tracing has been enabled, 11985186Sjhb * then turn on LOCK_DEBUG. When this option is on, extra debugging 12085186Sjhb * facilities such as tracking the file and line number of lock operations 12185186Sjhb * are enabled. Also, mutex locking operations are not inlined to avoid 12285186Sjhb * bloat from all the extra debugging code. We also have to turn on all the 12385186Sjhb * calling conventions for this debugging code in modules so that modules can 12485186Sjhb * work with both debug and non-debug kernels. 12585186Sjhb */ 126164159Skmacy#if defined(KLD_MODULE) || defined(WITNESS) || defined(INVARIANTS) || defined(INVARIANT_SUPPORT) || defined(KTR) || defined(LOCK_PROFILING) 12785186Sjhb#define LOCK_DEBUG 1 12885186Sjhb#else 12985186Sjhb#define LOCK_DEBUG 0 13085186Sjhb#endif 13185186Sjhb 13285186Sjhb/* 13383593Sjhb * In the LOCK_DEBUG case, use the filename and line numbers for debugging 13483593Sjhb * operations. Otherwise, use default values to avoid the unneeded bloat. 13583593Sjhb */ 13685186Sjhb#if LOCK_DEBUG > 0 13783593Sjhb#define LOCK_FILE __FILE__ 13883593Sjhb#define LOCK_LINE __LINE__ 13983593Sjhb#else 14083593Sjhb#define LOCK_FILE NULL 14183593Sjhb#define LOCK_LINE 0 14283593Sjhb#endif 14383593Sjhb 14483593Sjhb/* 14574912Sjhb * Macros for KTR_LOCK tracing. 14624269Speter * 14774912Sjhb * opname - name of this operation (LOCK/UNLOCK/SLOCK, etc.) 14874912Sjhb * lo - struct lock_object * for this lock 14974912Sjhb * flags - flags passed to the lock operation 15074912Sjhb * recurse - this locks recursion level (or 0 if class is not recursable) 15174912Sjhb * result - result of a try lock operation 15274912Sjhb * file - file name 15374912Sjhb * line - line number 15424269Speter */ 15574912Sjhb#define LOCK_LOG_TEST(lo, flags) \ 15674912Sjhb (((flags) & LOP_QUIET) == 0 && ((lo)->lo_flags & LO_QUIET) == 0) 15724269Speter 15874912Sjhb#define LOCK_LOG_LOCK(opname, lo, flags, recurse, file, line) do { \ 15974912Sjhb if (LOCK_LOG_TEST((lo), (flags))) \ 160196204Skib CTR6(KTR_LOCK, opname " (%s) %s %p r = %d at %s:%d", \ 161154077Sjhb LOCK_CLASS(lo)->lc_name, (lo)->lo_name, \ 162196204Skib (lo), (u_int)(recurse), (file), (line)); \ 16374912Sjhb} while (0) 16474912Sjhb 16574912Sjhb#define LOCK_LOG_TRY(opname, lo, flags, result, file, line) do { \ 16674912Sjhb if (LOCK_LOG_TEST((lo), (flags))) \ 167196204Skib CTR6(KTR_LOCK, "TRY_" opname " (%s) %s %p result=%d at %s:%d",\ 168154077Sjhb LOCK_CLASS(lo)->lc_name, (lo)->lo_name, \ 169196204Skib (lo), (u_int)(result), (file), (line)); \ 17074912Sjhb} while (0) 17174912Sjhb 17274912Sjhb#define LOCK_LOG_INIT(lo, flags) do { \ 17374912Sjhb if (LOCK_LOG_TEST((lo), (flags))) \ 17488661Sjake CTR4(KTR_LOCK, "%s: %p (%s) %s", __func__, (lo), \ 175154077Sjhb LOCK_CLASS(lo)->lc_name, (lo)->lo_name); \ 17674912Sjhb} while (0) 17774912Sjhb 17874912Sjhb#define LOCK_LOG_DESTROY(lo, flags) LOCK_LOG_INIT(lo, flags) 17974912Sjhb 180154484Sjhb#define lock_initalized(lo) ((lo)->lo_flags & LO_INITIALIZED) 181154484Sjhb 18224269Speter/* 18374912Sjhb * Helpful macros for quickly coming up with assertions with informative 18474912Sjhb * panic messages. 18524269Speter */ 18674912Sjhb#define MPASS(ex) MPASS4(ex, #ex, __FILE__, __LINE__) 18774912Sjhb#define MPASS2(ex, what) MPASS4(ex, what, __FILE__, __LINE__) 18874912Sjhb#define MPASS3(ex, file, line) MPASS4(ex, #ex, file, line) 18974912Sjhb#define MPASS4(ex, what, file, line) \ 19074912Sjhb KASSERT((ex), ("Assertion %s failed at %s:%d", what, file, line)) 19124269Speter 19274912Sjhbextern struct lock_class lock_class_mtx_sleep; 19374912Sjhbextern struct lock_class lock_class_mtx_spin; 19474912Sjhbextern struct lock_class lock_class_sx; 195154941Sjhbextern struct lock_class lock_class_rw; 196173444Supsextern struct lock_class lock_class_rm; 197252209Sjhbextern struct lock_class lock_class_rm_sleepable; 198164246Skmacyextern struct lock_class lock_class_lockmgr; 19970140Sjake 200154077Sjhbextern struct lock_class *lock_classes[]; 201154077Sjhb 202166455Sbmsvoid lock_init(struct lock_object *, struct lock_class *, 203207925Sattilio const char *, const char *, int); 204166455Sbmsvoid lock_destroy(struct lock_object *); 205144637Sjhbvoid spinlock_enter(void); 206144637Sjhbvoid spinlock_exit(void); 207179025Sattiliovoid witness_init(struct lock_object *, const char *); 20874912Sjhbvoid witness_destroy(struct lock_object *); 209125160Sjhbint witness_defineorder(struct lock_object *, struct lock_object *); 210182914Sjhbvoid witness_checkorder(struct lock_object *, int, const char *, int, 211207925Sattilio struct lock_object *); 21274912Sjhbvoid witness_lock(struct lock_object *, int, const char *, int); 21382244Sjhbvoid witness_upgrade(struct lock_object *, int, const char *, int); 21482244Sjhbvoid witness_downgrade(struct lock_object *, int, const char *, int); 21574912Sjhbvoid witness_unlock(struct lock_object *, int, const char *, int); 21674912Sjhbvoid witness_save(struct lock_object *, const char **, int *); 21774912Sjhbvoid witness_restore(struct lock_object *, const char *, int); 218207929Sattilioint witness_list_locks(struct lock_list_entry **, 219207929Sattilio int (*)(const char *, ...)); 220111881Sjhbint witness_warn(int, struct lock_object *, const char *, ...); 221227588Spjdvoid witness_assert(const struct lock_object *, int, const char *, int); 222207929Sattiliovoid witness_display_spinlock(struct lock_object *, struct thread *, 223207929Sattilio int (*)(const char *, ...)); 224102448Siedowseint witness_line(struct lock_object *); 225187511Sthompsavoid witness_norelease(struct lock_object *); 226187511Sthompsavoid witness_releaseok(struct lock_object *); 227102448Siedowseconst char *witness_file(struct lock_object *); 228181695Sattiliovoid witness_thread_exit(struct thread *); 22924269Speter 23074912Sjhb#ifdef WITNESS 231111881Sjhb 232111881Sjhb/* Flags for witness_warn(). */ 233111881Sjhb#define WARN_GIANTOK 0x01 /* Giant is exempt from this check. */ 234111881Sjhb#define WARN_PANIC 0x02 /* Panic if check fails. */ 235111881Sjhb#define WARN_SLEEPOK 0x04 /* Sleepable locks are exempt from check. */ 236111881Sjhb 237179025Sattilio#define WITNESS_INIT(lock, type) \ 238179025Sattilio witness_init((lock), (type)) 23966615Sjasone 24074912Sjhb#define WITNESS_DESTROY(lock) \ 24174912Sjhb witness_destroy(lock) 24224269Speter 243182914Sjhb#define WITNESS_CHECKORDER(lock, flags, file, line, interlock) \ 244182914Sjhb witness_checkorder((lock), (flags), (file), (line), (interlock)) 245125160Sjhb 246125160Sjhb#define WITNESS_DEFINEORDER(lock1, lock2) \ 247125160Sjhb witness_defineorder((struct lock_object *)(lock1), \ 248125160Sjhb (struct lock_object *)(lock2)) 249125160Sjhb 25074912Sjhb#define WITNESS_LOCK(lock, flags, file, line) \ 25174912Sjhb witness_lock((lock), (flags), (file), (line)) 25274912Sjhb 25382244Sjhb#define WITNESS_UPGRADE(lock, flags, file, line) \ 25482244Sjhb witness_upgrade((lock), (flags), (file), (line)) 25582244Sjhb 25682244Sjhb#define WITNESS_DOWNGRADE(lock, flags, file, line) \ 25782244Sjhb witness_downgrade((lock), (flags), (file), (line)) 25882244Sjhb 25974912Sjhb#define WITNESS_UNLOCK(lock, flags, file, line) \ 26074912Sjhb witness_unlock((lock), (flags), (file), (line)) 26174912Sjhb 262154934Sjhb#define WITNESS_CHECK(flags, lock, fmt, ...) \ 263154934Sjhb witness_warn((flags), (lock), (fmt), ## __VA_ARGS__) 264154934Sjhb 265111881Sjhb#define WITNESS_WARN(flags, lock, fmt, ...) \ 266111881Sjhb witness_warn((flags), (lock), (fmt), ## __VA_ARGS__) 26774912Sjhb 26874912Sjhb#define WITNESS_SAVE_DECL(n) \ 26974912Sjhb const char * __CONCAT(n, __wf); \ 27074912Sjhb int __CONCAT(n, __wl) 27174912Sjhb 27274912Sjhb#define WITNESS_SAVE(lock, n) \ 27374912Sjhb witness_save((lock), &__CONCAT(n, __wf), &__CONCAT(n, __wl)) 27474912Sjhb 27574912Sjhb#define WITNESS_RESTORE(lock, n) \ 27674912Sjhb witness_restore((lock), __CONCAT(n, __wf), __CONCAT(n, __wl)) 27774912Sjhb 278187511Sthompsa#define WITNESS_NORELEASE(lock) \ 279187511Sthompsa witness_norelease(&(lock)->lock_object) 280187511Sthompsa 281187511Sthompsa#define WITNESS_RELEASEOK(lock) \ 282187511Sthompsa witness_releaseok(&(lock)->lock_object) 283187511Sthompsa 284102448Siedowse#define WITNESS_FILE(lock) \ 285102448Siedowse witness_file(lock) 286102448Siedowse 287102448Siedowse#define WITNESS_LINE(lock) \ 288102448Siedowse witness_line(lock) 289102448Siedowse 29074912Sjhb#else /* WITNESS */ 291194578Srdivacky#define WITNESS_INIT(lock, type) (void)0 292194578Srdivacky#define WITNESS_DESTROY(lock) (void)0 293125160Sjhb#define WITNESS_DEFINEORDER(lock1, lock2) 0 294194578Srdivacky#define WITNESS_CHECKORDER(lock, flags, file, line, interlock) (void)0 295194578Srdivacky#define WITNESS_LOCK(lock, flags, file, line) (void)0 296194578Srdivacky#define WITNESS_UPGRADE(lock, flags, file, line) (void)0 297194578Srdivacky#define WITNESS_DOWNGRADE(lock, flags, file, line) (void)0 298194578Srdivacky#define WITNESS_UNLOCK(lock, flags, file, line) (void)0 299154934Sjhb#define WITNESS_CHECK(flags, lock, fmt, ...) 0 300194578Srdivacky#define WITNESS_WARN(flags, lock, fmt, ...) (void)0 301194578Srdivacky#define WITNESS_SAVE_DECL(n) (void)0 302194578Srdivacky#define WITNESS_SAVE(lock, n) (void)0 303194578Srdivacky#define WITNESS_RESTORE(lock, n) (void)0 304194578Srdivacky#define WITNESS_NORELEASE(lock) (void)0 305194578Srdivacky#define WITNESS_RELEASEOK(lock) (void)0 306102448Siedowse#define WITNESS_FILE(lock) ("?") 307102448Siedowse#define WITNESS_LINE(lock) (0) 30874912Sjhb#endif /* WITNESS */ 30974912Sjhb 31074912Sjhb#endif /* _KERNEL */ 31174912Sjhb#endif /* _SYS_LOCK_H_ */ 312