summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_witness.c
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2009-01-21 04:19:18 +0000
committerthompsa <thompsa@FreeBSD.org>2009-01-21 04:19:18 +0000
commit50e14c608efac2da56f8271a909fc7bc5396f053 (patch)
tree1a88a1f2553a5d499bb94b56aedbe8ab634b7f12 /sys/kern/subr_witness.c
parent48be47ddbcdf20ebb6e51798a78ac0707dc19ed3 (diff)
downloadFreeBSD-src-50e14c608efac2da56f8271a909fc7bc5396f053.zip
FreeBSD-src-50e14c608efac2da56f8271a909fc7bc5396f053.tar.gz
Add functions WITNESS so it can be asserted that the lock is not released for a
section of code, this uses WITNESS_NORELEASE() and WITNESS_RELEASEOK() to mark the boundaries. Both functions require the lock to be held when calling. This is intended for scenarios like a bus asserting that the bus lock is not dropped during a driver call. There doesn't appear to be a man page to document this in. Reviewed by: jhb
Diffstat (limited to 'sys/kern/subr_witness.c')
-rw-r--r--sys/kern/subr_witness.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index ce6aad1..60ab288 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -127,6 +127,7 @@ __FBSDID("$FreeBSD$");
#define LI_RECURSEMASK 0x0000ffff /* Recursion depth of lock instance. */
#define LI_EXCLUSIVE 0x00010000 /* Exclusive lock instance. */
+#define LI_NORELEASE 0x00020000 /* Lock not allowed to be released. */
/* Define this to check for blessed mutexes */
#undef BLESSING
@@ -367,6 +368,7 @@ static struct witness_lock_order_data *witness_lock_order_get(
struct witness *parent,
struct witness *child);
static void witness_list_lock(struct lock_instance *instance);
+static void witness_setflag(struct lock_object *lock, int flag, int set);
#ifdef KDB
#define witness_debugger(c) _witness_debugger(c, __func__)
@@ -1509,6 +1511,11 @@ found:
instance->li_line);
panic("share->uexcl");
}
+ if ((instance->li_flags & LI_NORELEASE) != 0 && witness_watch > 0) {
+ printf("forbidden unlock of (%s) %s @ %s:%d\n", class->lc_name,
+ lock->lo_name, file, line);
+ panic("lock marked norelease");
+ }
/* If we are recursed, unrecurse. */
if ((instance->li_flags & LI_RECURSEMASK) > 0) {
@@ -2224,6 +2231,48 @@ witness_assert(struct lock_object *lock, int flags, const char *file, int line)
#endif /* INVARIANT_SUPPORT */
}
+static void
+witness_setflag(struct lock_object *lock, int flag, int set)
+{
+ struct lock_list_entry *lock_list;
+ struct lock_instance *instance;
+ struct lock_class *class;
+
+ if (lock->lo_witness == NULL || witness_watch == -1 || panicstr != NULL)
+ return;
+ class = LOCK_CLASS(lock);
+ if (class->lc_flags & LC_SLEEPLOCK)
+ lock_list = curthread->td_sleeplocks;
+ else {
+ if (witness_skipspin)
+ return;
+ lock_list = PCPU_GET(spinlocks);
+ }
+ instance = find_instance(lock_list, lock);
+ if (instance == NULL)
+ panic("%s: lock (%s) %s not locked", __func__,
+ class->lc_name, lock->lo_name);
+
+ if (set)
+ instance->li_flags |= flag;
+ else
+ instance->li_flags &= ~flag;
+}
+
+void
+witness_norelease(struct lock_object *lock)
+{
+
+ witness_setflag(lock, LI_NORELEASE, 1);
+}
+
+void
+witness_releaseok(struct lock_object *lock)
+{
+
+ witness_setflag(lock, LI_NORELEASE, 0);
+}
+
#ifdef DDB
static void
witness_ddb_list(struct thread *td)
OpenPOWER on IntegriCloud