summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_witness.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2001-08-23 22:47:05 +0000
committerjhb <jhb@FreeBSD.org>2001-08-23 22:47:05 +0000
commit93fe8f866da9c2d2485f2d226feec9259756ba1c (patch)
tree97fce3663f339733cd33bb6f57b543754ea1a5ef /sys/kern/subr_witness.c
parent4c37bfb8ee93101b59e967c6303d9cdabe5b7819 (diff)
downloadFreeBSD-src-93fe8f866da9c2d2485f2d226feec9259756ba1c.zip
FreeBSD-src-93fe8f866da9c2d2485f2d226feec9259756ba1c.tar.gz
Add witness_upgrade() and witness_downgrade() for handling upgrades and
downgrades of shared/exclusive locks.
Diffstat (limited to 'sys/kern/subr_witness.c')
-rw-r--r--sys/kern/subr_witness.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 6e6dd5a..9ffb31a 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -348,6 +348,11 @@ witness_init(struct lock_object *lock)
panic("%s: lock (%s) %s can not be sleepable!\n", __func__,
class->lc_name, lock->lo_name);
+ if ((lock->lo_flags & LO_UPGRADABLE) != 0 &&
+ (class->lc_flags & LC_UPGRADABLE) == 0)
+ panic("%s: lock (%s) %s can not be upgradable!\n", __func__,
+ class->lc_name, lock->lo_name);
+
mtx_lock(&all_mtx);
STAILQ_INSERT_TAIL(&all_locks, lock, lo_list);
lock->lo_flags |= LO_INITIALIZED;
@@ -713,6 +718,72 @@ out:
}
void
+witness_upgrade(struct lock_object *lock, int flags, const char *file, int line)
+{
+ struct lock_instance *instance;
+ struct lock_class *class;
+
+ KASSERT(!witness_cold, ("%s: witness_cold\n", __func__));
+ if (lock->lo_witness == NULL || witness_dead || panicstr != NULL)
+ return;
+
+ class = lock->lo_class;
+ if ((lock->lo_flags & LO_UPGRADABLE) == 0)
+ panic("upgrade of non-upgradable lock (%s) %s @ %s:%d",
+ class->lc_name, lock->lo_name, file, line);
+ if ((flags & LOP_TRYLOCK) == 0)
+ panic("non-try upgrade of lock (%s) %s @ %s:%d", class->lc_name,
+ lock->lo_name, file, line);
+ if ((lock->lo_class->lc_flags & LC_SLEEPLOCK) == 0)
+ panic("upgrade of non-sleep lock (%s) %s @ %s:%d",
+ class->lc_name, lock->lo_name, file, line);
+ instance = find_instance(curproc->p_sleeplocks, lock);
+ if (instance == NULL)
+ panic("upgrade of unlocked lock (%s) %s @ %s:%d",
+ class->lc_name, lock->lo_name, file, line);
+ if ((instance->li_flags & LI_EXCLUSIVE) != 0)
+ panic("upgrade of exclusive lock (%s) %s @ %s:%d",
+ class->lc_name, lock->lo_name, file, line);
+ if ((instance->li_flags & LI_RECURSEMASK) != 0)
+ panic("upgrade of recursed lock (%s) %s r=%d @ %s:%d",
+ class->lc_name, lock->lo_name,
+ instance->li_flags & LI_RECURSEMASK, file, line);
+ instance->li_flags |= LI_EXCLUSIVE;
+}
+
+void
+witness_downgrade(struct lock_object *lock, int flags, const char *file,
+ int line)
+{
+ struct lock_instance *instance;
+ struct lock_class *class;
+
+ KASSERT(!witness_cold, ("%s: witness_cold\n", __func__));
+ if (lock->lo_witness == NULL || witness_dead || panicstr != NULL)
+ return;
+
+ class = lock->lo_class;
+ if ((lock->lo_flags & LO_UPGRADABLE) == 0)
+ panic("downgrade of non-upgradable lock (%s) %s @ %s:%d",
+ class->lc_name, lock->lo_name, file, line);
+ if ((lock->lo_class->lc_flags & LC_SLEEPLOCK) == 0)
+ panic("downgrade of non-sleep lock (%s) %s @ %s:%d",
+ class->lc_name, lock->lo_name, file, line);
+ instance = find_instance(curproc->p_sleeplocks, lock);
+ if (instance == NULL)
+ panic("downgrade of unlocked lock (%s) %s @ %s:%d",
+ class->lc_name, lock->lo_name, file, line);
+ if ((instance->li_flags & LI_EXCLUSIVE) == 0)
+ panic("downgrade of shared lock (%s) %s @ %s:%d",
+ class->lc_name, lock->lo_name, file, line);
+ if ((instance->li_flags & LI_RECURSEMASK) != 0)
+ panic("downgrade of recursed lock (%s) %s r=%d @ %s:%d",
+ class->lc_name, lock->lo_name,
+ instance->li_flags & LI_RECURSEMASK, file, line);
+ instance->li_flags &= ~LI_EXCLUSIVE;
+}
+
+void
witness_unlock(struct lock_object *lock, int flags, const char *file, int line)
{
struct lock_list_entry **lock_list, *lle;
OpenPOWER on IntegriCloud