From f126e754e00e67f9fb6bbff1542fa2062e8d2ab9 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Fri, 27 Jan 2006 22:24:07 +0000 Subject: [PATCH] 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. --- sys/kern/subr_sleepqueue.c | 66 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/sys/kern/subr_sleepqueue.c b/sys/kern/subr_sleepqueue.c index 8443a7ffeaf..378fc691ead 100644 --- a/sys/kern/subr_sleepqueue.c +++ b/sys/kern/subr_sleepqueue.c @@ -59,11 +59,12 @@ * variables. */ -#include "opt_sleepqueue_profiling.h" - #include __FBSDID("$FreeBSD$"); +#include "opt_sleepqueue_profiling.h" +#include "opt_ddb.h" + #include #include #include @@ -77,6 +78,10 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef DDB +#include +#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