summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2006-01-27 22:24:07 +0000
committerjhb <jhb@FreeBSD.org>2006-01-27 22:24:07 +0000
commit6160bb7d846b122c36841c02e2ac2106ed39191c (patch)
tree9f7260b793fc191d364e74dae4d8fa68b0221adc
parent2abda0c117f0bf476985583e91dbdcd9b67579d3 (diff)
downloadFreeBSD-src-6160bb7d846b122c36841c02e2ac2106ed39191c.zip
FreeBSD-src-6160bb7d846b122c36841c02e2ac2106ed39191c.tar.gz
Add a new ddb command 'show sleepq'. It takes a wait channel as an
argument and looks for a sleep queue associated with that wait channel. If it finds one it will display information such as the list of threads sleeping on that queue. If it can't find a sleep queue for that wait channel, then it will see if that address matches any of the active sleep queues. If so, it will display information about the sleepq at the specified address.
-rw-r--r--sys/kern/subr_sleepqueue.c66
1 files changed, 64 insertions, 2 deletions
diff --git a/sys/kern/subr_sleepqueue.c b/sys/kern/subr_sleepqueue.c
index 8443a7f..378fc69 100644
--- a/sys/kern/subr_sleepqueue.c
+++ b/sys/kern/subr_sleepqueue.c
@@ -59,11 +59,12 @@
* variables.
*/
-#include "opt_sleepqueue_profiling.h"
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_sleepqueue_profiling.h"
+#include "opt_ddb.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
@@ -77,6 +78,10 @@ __FBSDID("$FreeBSD$");
#include <sys/sleepqueue.h>
#include <sys/sysctl.h>
+#ifdef DDB
+#include <ddb/ddb.h>
+#endif
+
/*
* Constants for the hash table of sleep queue chains. These constants are
* the same ones that 4BSD (and possibly earlier versions of BSD) used.
@@ -842,3 +847,60 @@ sleepq_abort(struct thread *td)
sleepq_remove(td, wchan);
mtx_lock_spin(&sched_lock);
}
+
+#ifdef DDB
+DB_SHOW_COMMAND(sleepq, db_show_sleepqueue)
+{
+ struct sleepqueue_chain *sc;
+ struct sleepqueue *sq;
+ struct lock_object *lock;
+ struct thread *td;
+ void *wchan;
+ int i;
+
+ if (!have_addr)
+ return;
+
+ /*
+ * First, see if there is an active sleep queue for the wait channel
+ * indicated by the address.
+ */
+ wchan = (void *)addr;
+ sc = SC_LOOKUP(wchan);
+ LIST_FOREACH(sq, &sc->sc_queues, sq_hash)
+ if (sq->sq_wchan == wchan)
+ goto found;
+
+ /*
+ * Second, see if there is an active sleep queue at the address
+ * indicated.
+ */
+ for (i = 0; i < SC_TABLESIZE; i++)
+ LIST_FOREACH(sq, &sleepq_chains[i].sc_queues, sq_hash) {
+ if (sq == (struct sleepqueue *)addr)
+ goto found;
+ }
+
+ db_printf("Unable to locate a sleep queue via %p\n", (void *)addr);
+ return;
+found:
+ db_printf("Wait channel: %p\n", sq->sq_wchan);
+#ifdef INVARIANTS
+ db_printf("Queue type: %d\n", sq->sq_type);
+ if (sq->sq_lock) {
+ lock = &sq->sq_lock->mtx_object;
+ db_printf("Associated Interlock: %p - (%s) %s\n", lock,
+ LOCK_CLASS(lock)->lc_name, lock->lo_name);
+ }
+#endif
+ db_printf("Blocked threads:\n");
+ if (TAILQ_EMPTY(&sq->sq_blocked))
+ db_printf("\tempty\n");
+ else
+ TAILQ_FOREACH(td, &sq->sq_blocked, td_slpq) {
+ db_printf("\t%p (tid %d, pid %d, \"%s\")\n", td,
+ td->td_tid, td->td_proc->p_pid,
+ td->td_proc->p_comm);
+ }
+}
+#endif
OpenPOWER on IntegriCloud