diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -2429,6 +2429,32 @@ 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 @@ 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 @@ #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 --- a/sys/sys/lock.h +++ b/sys/sys/lock.h @@ -237,6 +237,7 @@ 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 *);