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.
This commit is contained in:
parent
6966c33482
commit
f126e754e0
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user