Skip to content

Commit e7e958d

Browse files
committed
ddb show allchains: avoid traps and show pointers for lockmgr and sx
When trying to walk lock chains, we have to deduce what a thread is blocked on. Checking LOCK_CLASS(td->td_wchan) is not a very reliable method by itself, as it just tests whether a particular 4 bits near where td_wchan points have a particular value. Misinterpreting wait channel pointers of other sleeps as lockmgr locks would frequently cause ddb show allchains (or show lockchain) to trap, or to produce incorrect output. Now, check the sleepq_type. When calling sleepq_add, we use SLEEPQ_LK for lockmgr locks and SLEEPQ_SX for sx locks. This is a more reliable indication that the td_wchan is actually a lock. While here, also make the output of lockmgr and sx locks consistent with the output for other locks (see print_lockchain). Outputting a pointer to the lock allows it to be inspected further with ddb show lock or other methods. Reviewed by: markj Sponsored by: Dell Inc. Differential Revision: https://reviews.freebsd.org/D52794
1 parent dfc9da6 commit e7e958d

File tree

2 files changed

+11
-6
lines changed

2 files changed

+11
-6
lines changed

sys/kern/kern_lock.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,9 +1780,11 @@ lockmgr_chain(struct thread *td, struct thread **ownerp)
17801780

17811781
lk = td->td_wchan;
17821782

1783-
if (LOCK_CLASS(&lk->lock_object) != &lock_class_lockmgr)
1783+
if (!TD_ON_SLEEPQ(td) || sleepq_type(td->td_wchan) != SLEEPQ_LK ||
1784+
LOCK_CLASS(&lk->lock_object) != &lock_class_lockmgr)
17841785
return (0);
1785-
db_printf("blocked on lockmgr %s", lk->lock_object.lo_name);
1786+
db_printf("blocked on lock %p (%s) \"%s\" ", &lk->lock_object,
1787+
lock_class_lockmgr.lc_name, lk->lock_object.lo_name);
17861788
if (lk->lk_lock & LK_SHARE)
17871789
db_printf("SHARED (count %ju)\n",
17881790
(uintmax_t)LK_SHARERS(lk->lk_lock));

sys/kern/kern_sx.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,16 +1539,19 @@ sx_chain(struct thread *td, struct thread **ownerp)
15391539

15401540
/*
15411541
* Check to see if this thread is blocked on an sx lock.
1542-
* First, we check the lock class. If that is ok, then we
1543-
* compare the lock name against the wait message.
1542+
* The thread should be on a sleep queue with type SLEEPQ_SX, the
1543+
* purported lock should have the lock class index of sx, and the lock
1544+
* name should match the wait message.
15441545
*/
15451546
sx = td->td_wchan;
1546-
if (LOCK_CLASS(&sx->lock_object) != &lock_class_sx ||
1547+
if (!TD_ON_SLEEPQ(td) || sleepq_type(td->td_wchan) != SLEEPQ_SX ||
1548+
LOCK_CLASS(&sx->lock_object) != &lock_class_sx ||
15471549
sx->lock_object.lo_name != td->td_wmesg)
15481550
return (0);
15491551

15501552
/* We think we have an sx lock, so output some details. */
1551-
db_printf("blocked on sx \"%s\" ", td->td_wmesg);
1553+
db_printf("blocked on lock %p (%s) \"%s\" ", &sx->lock_object,
1554+
lock_class_sx.lc_name, td->td_wmesg);
15521555
*ownerp = sx_xholder(sx);
15531556
if (sx->sx_lock & SX_LOCK_SHARED)
15541557
db_printf("SLOCK (count %ju)\n",

0 commit comments

Comments
 (0)