diff options
author | jhb <jhb@FreeBSD.org> | 2003-03-24 21:03:53 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2003-03-24 21:03:53 +0000 |
commit | 966c72c3455be2bc91181aa09b807b58a8b4deb9 (patch) | |
tree | b9dfa84319d09ada516aa5ba270aaf4d10054b02 /sys/kern | |
parent | fd221086efb2f2aa47c70b46fea051fd850215e6 (diff) | |
download | FreeBSD-src-966c72c3455be2bc91181aa09b807b58a8b4deb9.zip FreeBSD-src-966c72c3455be2bc91181aa09b807b58a8b4deb9.tar.gz |
- Remove witness_dead and just use witness_watch instead. If witness_watch
is set to 0, it now has the same affect as setting witness_dead used to
have.
- Added a sysctl handler that allows root to change witness_watch from a
non-zero value to zero to disable witness at runtime. Note that you
can't turn witness back on once it is off. You can only turn it off as
a one-way switch.
- Added a comment describing the possible values of witness_watch.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/subr_witness.c | 72 |
1 files changed, 51 insertions, 21 deletions
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c index d22d964..94c9390 100644 --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -166,6 +166,7 @@ static int rebalancetree(struct witness_list *list); static void removechild(struct witness *parent, struct witness *child); static int reparentchildren(struct witness *newparent, struct witness *oldparent); +static int sysctl_debug_witness_watch(SYSCTL_HANDLER_ARGS); static void witness_displaydescendants(void(*)(const char *fmt, ...), struct witness *, int indent); static const char *fixup_filename(const char *file); @@ -189,9 +190,19 @@ static void witness_display(void(*)(const char *fmt, ...)); MALLOC_DEFINE(M_WITNESS, "witness", "witness structure"); +/* + * If set to 0, witness is disabled. If set to 1, witness performs full lock + * order checking for all locks. If set to 2 or higher, then witness skips + * the full lock order check if the lock being acquired is at a higher level + * (i.e. farther down in the tree) than the current lock. This last mode is + * somewhat experimental and not considered fully safe. At runtime, this + * value may be set to 0 to turn off witness. witness is not allowed be + * turned on once it is turned off, however. + */ static int witness_watch = 1; TUNABLE_INT("debug.witness_watch", &witness_watch); -SYSCTL_INT(_debug, OID_AUTO, witness_watch, CTLFLAG_RD, &witness_watch, 0, ""); +SYSCTL_PROC(_debug, OID_AUTO, witness_watch, CTLFLAG_RW | CTLTYPE_INT, NULL, 0, + sysctl_debug_witness_watch, "I", "witness is watching lock operations"); #ifdef DDB /* @@ -235,7 +246,6 @@ static struct witness_list w_spin = STAILQ_HEAD_INITIALIZER(w_spin); static struct witness_list w_sleep = STAILQ_HEAD_INITIALIZER(w_sleep); static struct witness_child_list_entry *w_child_free = NULL; static struct lock_list_entry *w_lock_list_free = NULL; -static int witness_dead; /* fatal error, probably no memory */ static struct witness w_data[WITNESS_COUNT]; static struct witness_child_list_entry w_childdata[WITNESS_CHILDCOUNT]; @@ -406,6 +416,26 @@ witness_initialize(void *dummy __unused) } SYSINIT(witness_init, SI_SUB_WITNESS, SI_ORDER_FIRST, witness_initialize, NULL) +static int +sysctl_debug_witness_watch(SYSCTL_HANDLER_ARGS) +{ + int error, value; + + value = witness_watch; + error = sysctl_handle_int(oidp, &value, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + error = suser(req->td); + if (error != 0) + return (error); + if (value == witness_watch) + return (0); + if (value != 0) + return (EINVAL); + witness_watch = 0; + return (0); +} + void witness_init(struct lock_object *lock) { @@ -435,7 +465,7 @@ witness_init(struct lock_object *lock) if (lock_cur_cnt > lock_max_cnt) lock_max_cnt = lock_cur_cnt; mtx_unlock(&all_mtx); - if (!witness_cold && !witness_dead && panicstr == NULL && + if (!witness_cold && witness_watch != 0 && panicstr == NULL && (lock->lo_flags & LO_WITNESS) != 0) lock->lo_witness = enroll(lock->lo_type, class); else @@ -556,7 +586,7 @@ witness_lock(struct lock_object *lock, int flags, const char *file, int line) int go_into_ddb = 0; #endif - if (witness_cold || witness_dead || lock->lo_witness == NULL || + if (witness_cold || witness_watch == 0 || lock->lo_witness == NULL || panicstr != NULL) return; w = lock->lo_witness; @@ -834,7 +864,7 @@ witness_upgrade(struct lock_object *lock, int flags, const char *file, int line) struct lock_class *class; KASSERT(!witness_cold, ("%s: witness_cold", __func__)); - if (lock->lo_witness == NULL || witness_dead || panicstr != NULL) + if (lock->lo_witness == NULL || witness_watch == 0 || panicstr != NULL) return; class = lock->lo_class; file = fixup_filename(file); @@ -869,7 +899,7 @@ witness_downgrade(struct lock_object *lock, int flags, const char *file, struct lock_class *class; KASSERT(!witness_cold, ("%s: witness_cold", __func__)); - if (lock->lo_witness == NULL || witness_dead || panicstr != NULL) + if (lock->lo_witness == NULL || witness_watch == 0 || panicstr != NULL) return; class = lock->lo_class; file = fixup_filename(file); @@ -903,7 +933,7 @@ witness_unlock(struct lock_object *lock, int flags, const char *file, int line) register_t s; int i, j; - if (witness_cold || witness_dead || lock->lo_witness == NULL || + if (witness_cold || witness_watch == 0 || lock->lo_witness == NULL || panicstr != NULL) return; td = curthread; @@ -993,7 +1023,7 @@ witness_warn(int flags, struct lock_object *lock, const char *fmt, ...) va_list ap; int i, n; - if (witness_cold || witness_dead || panicstr != NULL) + if (witness_cold || witness_watch == 0 || panicstr != NULL) return (0); n = 0; td = curthread; @@ -1050,7 +1080,7 @@ witness_file(struct lock_object *lock) { struct witness *w; - if (witness_cold || witness_dead || lock->lo_witness == NULL) + if (witness_cold || witness_watch == 0 || lock->lo_witness == NULL) return ("?"); w = lock->lo_witness; return (w->w_file); @@ -1061,7 +1091,7 @@ witness_line(struct lock_object *lock) { struct witness *w; - if (witness_cold || witness_dead || lock->lo_witness == NULL) + if (witness_cold || witness_watch == 0 || lock->lo_witness == NULL) return (0); w = lock->lo_witness; return (w->w_line); @@ -1072,7 +1102,7 @@ enroll(const char *description, struct lock_class *lock_class) { struct witness *w; - if (!witness_watch || witness_dead || panicstr != NULL) + if (!witness_watch || witness_watch == 0 || panicstr != NULL) return (NULL); if ((lock_class->lc_flags & LC_SPINLOCK) && witness_skipspin) return (NULL); @@ -1428,12 +1458,12 @@ witness_get(void) { struct witness *w; - if (witness_dead) { + if (witness_watch == 0) { mtx_unlock_spin(&w_mtx); return (NULL); } if (STAILQ_EMPTY(&w_free)) { - witness_dead = 1; + witness_watch = 0; mtx_unlock_spin(&w_mtx); printf("%s: witness exhausted\n", __func__); return (NULL); @@ -1456,13 +1486,13 @@ witness_child_get(void) { struct witness_child_list_entry *wcl; - if (witness_dead) { + if (witness_watch == 0) { mtx_unlock_spin(&w_mtx); return (NULL); } wcl = w_child_free; if (wcl == NULL) { - witness_dead = 1; + witness_watch = 0; mtx_unlock_spin(&w_mtx); printf("%s: witness exhausted\n", __func__); return (NULL); @@ -1485,12 +1515,12 @@ witness_lock_list_get(void) { struct lock_list_entry *lle; - if (witness_dead) + if (witness_watch == 0) return (NULL); mtx_lock_spin(&w_mtx); lle = w_lock_list_free; if (lle == NULL) { - witness_dead = 1; + witness_watch = 0; mtx_unlock_spin(&w_mtx); printf("%s: witness exhausted\n", __func__); return (NULL); @@ -1563,7 +1593,7 @@ witness_save(struct lock_object *lock, const char **filep, int *linep) struct lock_instance *instance; KASSERT(!witness_cold, ("%s: witness_cold", __func__)); - if (lock->lo_witness == NULL || witness_dead || panicstr != NULL) + if (lock->lo_witness == NULL || witness_watch == 0 || panicstr != NULL) return; if ((lock->lo_class->lc_flags & LC_SLEEPLOCK) == 0) panic("%s: lock (%s) %s is not a sleep lock", __func__, @@ -1582,7 +1612,7 @@ witness_restore(struct lock_object *lock, const char *file, int line) struct lock_instance *instance; KASSERT(!witness_cold, ("%s: witness_cold", __func__)); - if (lock->lo_witness == NULL || witness_dead || panicstr != NULL) + if (lock->lo_witness == NULL || witness_watch == 0 || panicstr != NULL) return; if ((lock->lo_class->lc_flags & LC_SLEEPLOCK) == 0) panic("%s: lock (%s) %s is not a sleep lock", __func__, @@ -1603,7 +1633,7 @@ witness_assert(struct lock_object *lock, int flags, const char *file, int line) #ifdef INVARIANT_SUPPORT struct lock_instance *instance; - if (lock->lo_witness == NULL || witness_dead || panicstr != NULL) + if (lock->lo_witness == NULL || witness_watch == 0 || panicstr != NULL) return; if ((lock->lo_class->lc_flags & LC_SLEEPLOCK) != 0) instance = find_instance(curthread->td_sleeplocks, lock); @@ -1667,7 +1697,7 @@ witness_list(struct thread *td) KASSERT(!witness_cold, ("%s: witness_cold", __func__)); KASSERT(db_active, ("%s: not in the debugger", __func__)); - if (witness_dead) + if (witness_watch == 0) return; witness_list_locks(&td->td_sleeplocks); |