aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2023-04-10 15:54:58 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2023-04-11 12:59:49 +0000
commit75fc6f86c38807f1fb305c065c6affcf7617b029 (patch)
tree526be7d3b38527675dbe2e47aa3f31d938015ac6
parentafa8f8971b869b8b5d1468e431d18c615a35a63e (diff)
downloadsrc-75fc6f86c38807f1fb305c065c6affcf7617b029.tar.gz
src-75fc6f86c38807f1fb305c065c6affcf7617b029.zip
Add witness_is_owned(9)
which returns an indicator if the current thread owns the specified lock. Reviewed by: jah, markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D39477
-rw-r--r--sys/kern/subr_witness.c58
-rw-r--r--sys/sys/lock.h1
2 files changed, 49 insertions, 10 deletions
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 97f68c812a76..839e4a4ce54b 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -2429,6 +2429,32 @@ witness_restore(struct lock_object *lock, const char *file, int line)
instance->li_line = line;
}
+static bool
+witness_find_instance(const struct lock_object *lock,
+ struct lock_instance **instance)
+{
+#ifdef INVARIANT_SUPPORT
+ struct lock_class *class;
+
+ if (lock->lo_witness == NULL || witness_watch < 1 || KERNEL_PANICKED())
+ return (false);
+ class = LOCK_CLASS(lock);
+ if ((class->lc_flags & LC_SLEEPLOCK) != 0) {
+ *instance = find_instance(curthread->td_sleeplocks, lock);
+ return (true);
+ } else if ((class->lc_flags & LC_SPINLOCK) != 0) {
+ *instance = find_instance(PCPU_GET(spinlocks), lock);
+ return (true);
+ } else {
+ kassert_panic("Lock (%s) %s is not sleep or spin!",
+ class->lc_name, lock->lo_name);
+ return (false);
+ }
+#else
+ return (false);
+#endif
+}
+
void
witness_assert(const struct lock_object *lock, int flags, const char *file,
int line)
@@ -2437,18 +2463,9 @@ witness_assert(const struct lock_object *lock, int flags, const char *file,
struct lock_instance *instance;
struct lock_class *class;
- if (lock->lo_witness == NULL || witness_watch < 1 || KERNEL_PANICKED())
+ if (!witness_find_instance(lock, &instance))
return;
class = LOCK_CLASS(lock);
- if ((class->lc_flags & LC_SLEEPLOCK) != 0)
- instance = find_instance(curthread->td_sleeplocks, lock);
- else if ((class->lc_flags & LC_SPINLOCK) != 0)
- instance = find_instance(PCPU_GET(spinlocks), lock);
- else {
- kassert_panic("Lock (%s) %s is not sleep or spin!",
- class->lc_name, lock->lo_name);
- return;
- }
switch (flags) {
case LA_UNLOCKED:
if (instance != NULL)
@@ -2501,6 +2518,27 @@ witness_assert(const struct lock_object *lock, int flags, const char *file,
#endif /* INVARIANT_SUPPORT */
}
+/*
+ * Checks the ownership of the lock by curthread, consulting the witness list.
+ * Returns:
+ * 0 if witness is disabled or did not work
+ * -1 if not owned
+ * 1 if owned
+ */
+int
+witness_is_owned(const struct lock_object *lock)
+{
+#ifdef INVARIANT_SUPPORT
+ struct lock_instance *instance;
+
+ if (!witness_find_instance(lock, &instance))
+ return (0);
+ return (instance == NULL ? -1 : 1);
+#else
+ return (0);
+#endif
+}
+
static void
witness_setflag(struct lock_object *lock, int flag, int set)
{
diff --git a/sys/sys/lock.h b/sys/sys/lock.h
index 2db38f9df89a..4031f20946c0 100644
--- a/sys/sys/lock.h
+++ b/sys/sys/lock.h
@@ -237,6 +237,7 @@ int witness_list_locks(struct lock_list_entry **,
int (*)(const char *, ...));
int witness_warn(int, struct lock_object *, const char *, ...);
void witness_assert(const struct lock_object *, int, const char *, int);
+int witness_is_owned(const struct lock_object *lock);
void witness_display_spinlock(struct lock_object *, struct thread *,
int (*)(const char *, ...));
int witness_line(struct lock_object *);