changeset 765:f3ee19f4d8d0

synch: sanity check held type for lock destroy/lock/unlock Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Thu, 25 Jul 2019 13:36:54 -0400
parents ac06f315317e
children 041bab629917
files synch.c
diffstat 1 files changed, 34 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/synch.c	Thu Jul 25 13:12:00 2019 -0400
+++ b/synch.c	Thu Jul 25 13:36:54 2019 -0400
@@ -114,6 +114,23 @@
 	held_stack_count--;
 }
 
+/*
+ * Sanity check that the two synch types are equal.  In several places, we
+ * want to make sure that the held structure's type matches that it truly
+ * should be.  Since this is such an unlikely to fail check, we don't even
+ * try to make nice user friendly error messages.
+ *
+ * The only way this check could fail is if a lock got acquired, then
+ * re-initialized as a different type of a lock, and then destroyed.  E.g.,
+ * if the code acquires a mutex (struct lock), and then tries to destroy the
+ * same structure as a (struct rwlock).
+ */
+static inline void sanity_check_held_synch_type(struct held_lock *held,
+						enum synch_type exp)
+{
+	VERIFY3U(held->type, ==, exp);
+}
+
 #define LOCK_DEP_GRAPH()	VERIFY0(pthread_mutex_lock(&lockdep_lock))
 #define UNLOCK_DEP_GRAPH()	VERIFY0(pthread_mutex_unlock(&lockdep_lock))
 
@@ -497,10 +514,13 @@
 
 	/* check that we're not holding it */
 	for_each_held_lock(i, held) {
-		if (held->info == &l->info) {
-			error_destroy(held, where);
-			return;
-		}
+		if (held->info != &l->info)
+			continue;
+
+		sanity_check_held_synch_type(held, SYNCH_TYPE_MUTEX);
+
+		error_destroy(held, where);
+		return;
 	}
 #endif
 
@@ -524,10 +544,14 @@
 
 	/* check for deadlocks & recursive locking */
 	for_each_held_lock(i, held) {
-		if ((held->info == &l->info) || (held->info->lc == l->info.lc)) {
-			error_lock(held, l, where);
-			return;
-		}
+		if ((held->info != &l->info) && (held->info->lc != l->info.lc))
+			continue;
+
+		if (held->info == &l->info)
+			sanity_check_held_synch_type(held, SYNCH_TYPE_MUTEX);
+
+		error_lock(held, l, where);
+		return;
 	}
 
 	/* check for circular dependencies */
@@ -564,6 +588,8 @@
 		if (held->info != &l->info)
 			continue;
 
+		sanity_check_held_synch_type(held, SYNCH_TYPE_MUTEX);
+
 		held_stack_remove(held);
 
 		goto out;