The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=75fc6f86c38807f1fb305c065c6affcf7617b029

commit 75fc6f86c38807f1fb305c065c6affcf7617b029
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2023-04-10 15:54:58 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2023-04-11 12:59:49 +0000

    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
---
 sys/kern/subr_witness.c | 58 ++++++++++++++++++++++++++++++++++++++++---------
 sys/sys/lock.h          |  1 +
 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 *);

Reply via email to