diff options
author | jhb <jhb@FreeBSD.org> | 2006-08-15 18:29:01 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2006-08-15 18:29:01 +0000 |
commit | 4e96206d8aa504d0b00ace5c45fcb104888b7dc3 (patch) | |
tree | cdceb81a7ecf499b8d0d51c3f275b40b0a836064 /sys/kern/kern_lock.c | |
parent | e092be01212a8a69fe2f62be7d44c909fe7002bb (diff) | |
download | FreeBSD-src-4e96206d8aa504d0b00ace5c45fcb104888b7dc3.zip FreeBSD-src-4e96206d8aa504d0b00ace5c45fcb104888b7dc3.tar.gz |
Add a new 'show sleepchain' ddb command similar to 'show lockchain' except
that it operates on lockmgr and sx locks. This can be useful for tracking
down vnode deadlocks in VFS for example. Note that this command is a bit
more fragile than 'show lockchain' as we have to poke around at the
wait channel of a thread to see if it points to either a struct lock or
a condition variable inside of a struct sx. If td_wchan points to
something unmapped, then this command will terminate early due to a fault,
but no harm will be done.
Diffstat (limited to 'sys/kern/kern_lock.c')
-rw-r--r-- | sys/kern/kern_lock.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index e9cff2e..c0b929a 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -589,6 +589,34 @@ lockmgr_printinfo(lkp) } #ifdef DDB +/* + * Check to see if a thread that is blocked on a sleep queue is actually + * blocked on a 'struct lock'. If so, output some details and return true. + * If the lock has an exclusive owner, return that in *ownerp. + */ +int +lockmgr_chain(struct thread *td, struct thread **ownerp) +{ + struct lock *lkp; + + lkp = td->td_wchan; + + /* Simple test to see if wchan points to a lockmgr lock. */ + if (lkp->lk_wmesg != td->td_wmesg) + return (0); + + /* Ok, we think we have a lockmgr lock, so output some details. */ + db_printf("blocked on lk \"%s\" ", lkp->lk_wmesg); + if (lkp->lk_sharecount) { + db_printf("SHARED (count %d)\n", lkp->lk_sharecount); + *ownerp = NULL; + } else { + db_printf("EXCL (count %d)\n", lkp->lk_exclusivecount); + *ownerp = lkp->lk_lockholder; + } + return (1); +} + DB_SHOW_COMMAND(lockmgr, db_show_lockmgr) { struct thread *td; |