summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configfrag.ac2
-rw-r--r--kern/lock.c28
-rw-r--r--kern/lock.h14
3 files changed, 42 insertions, 2 deletions
diff --git a/configfrag.ac b/configfrag.ac
index e41a3a1..c0e04b3 100644
--- a/configfrag.ac
+++ b/configfrag.ac
@@ -63,7 +63,7 @@ AC_DEFINE([MACH_IPC_DEBUG], [1], [MACH_IPC_DEBUG])
# Testing code/printfs.
AC_DEFINE([MACH_IPC_TEST], [0], [MACH_IPC_TEST])
-# Sanity-check simple locking.
+# Sanity-check locking.
AC_DEFINE([MACH_LDEBUG], [0], [MACH_LDEBUG])
# MP lock monitoring. Registers use of locks, contention. Depending on
diff --git a/kern/lock.c b/kern/lock.c
index de22795..46c78da 100644
--- a/kern/lock.c
+++ b/kern/lock.c
@@ -318,6 +318,9 @@ void lock_write(
simple_lock(&l->interlock);
}
}
+#if MACH_LDEBUG
+ l->writer = current_thread();
+#endif /* MACH_LDEBUG */
simple_unlock(&l->interlock);
}
@@ -334,8 +337,12 @@ void lock_done(
else
if (l->want_upgrade)
l->want_upgrade = FALSE;
- else
+ else {
l->want_write = FALSE;
+#if MACH_LDEBUG
+ l->writer = THREAD_NULL;
+#endif /* MACH_LDEBUG */
+ }
/*
* There is no reason to wakeup a waiting thread
@@ -452,6 +459,9 @@ boolean_t lock_read_to_write(
}
}
+#if MACH_LDEBUG
+ l->writer = current_thread();
+#endif /* MACH_LDEBUG */
simple_unlock(&l->interlock);
return FALSE;
}
@@ -460,6 +470,9 @@ void lock_write_to_read(
lock_t l)
{
simple_lock(&l->interlock);
+#if MACH_LDEBUG
+ assert(l->writer == current_thread());
+#endif /* MACH_LDEBUG */
l->read_count++;
if (l->recursion_depth != 0)
@@ -475,6 +488,9 @@ void lock_write_to_read(
thread_wakeup(l);
}
+#if MACH_LDEBUG
+ l->writer = THREAD_NULL;
+#endif /* MACH_LDEBUG */
simple_unlock(&l->interlock);
}
@@ -514,6 +530,9 @@ boolean_t lock_try_write(
*/
l->want_write = TRUE;
+#if MACH_LDEBUG
+ l->writer = current_thread();
+#endif /* MACH_LDEBUG */
simple_unlock(&l->interlock);
return TRUE;
}
@@ -590,6 +609,9 @@ boolean_t lock_try_read_to_write(
simple_lock(&l->interlock);
}
+#if MACH_LDEBUG
+ l->writer = current_thread();
+#endif /* MACH_LDEBUG */
simple_unlock(&l->interlock);
return TRUE;
}
@@ -602,6 +624,10 @@ void lock_set_recursive(
lock_t l)
{
simple_lock(&l->interlock);
+#if MACH_LDEBUG
+ assert(l->writer == current_thread());
+#endif /* MACH_LDEBUG */
+
if (!l->want_write) {
panic("lock_set_recursive: don't have write lock");
}
diff --git a/kern/lock.h b/kern/lock.h
index e88e182..2781a48 100644
--- a/kern/lock.h
+++ b/kern/lock.h
@@ -174,6 +174,9 @@ struct lock {
/* boolean_t */ can_sleep:1, /* Can attempts to lock go to sleep? */
recursion_depth:12, /* Depth of recursion */
:0;
+#if MACH_LDEBUG
+ struct thread *writer;
+#endif /* MACH_LDEBUG */
decl_simple_lock_data(,interlock)
/* Hardware interlock field.
Last in the structure so that
@@ -203,6 +206,17 @@ extern boolean_t lock_try_read_to_write(lock_t);
extern void lock_set_recursive(lock_t);
extern void lock_clear_recursive(lock_t);
+/* Lock debugging support. */
+#if ! MACH_LDEBUG
+#define have_read_lock(l) 1
+#define have_write_lock(l) 1
+#else /* MACH_LDEBUG */
+/* XXX: We don't keep track of readers, so this is an approximation. */
+#define have_read_lock(l) ((l)->read_count > 0)
+#define have_write_lock(l) ((l)->writer == current_thread())
+#endif /* MACH_LDEBUG */
+#define have_lock(l) (have_read_lock(l) || have_write_lock(l))
+
void db_show_all_slocks(void);
#endif /* _KERN_LOCK_H_ */