Module Name:    src
Committed By:   ad
Date:           Tue Jan 21 20:31:57 UTC 2020

Modified Files:
        src/sys/kern: kern_turnstile.c subr_lockdebug.c
        src/sys/sys: lwp.h

Log Message:
ddb's "show all locks":

- Make the output easier to scan quickly.

- Show every LWP that is blocked on a lock, and the details of the lock.


To generate a diff of this commit:
cvs rdiff -u -r1.35 -r1.36 src/sys/kern/kern_turnstile.c
cvs rdiff -u -r1.73 -r1.74 src/sys/kern/subr_lockdebug.c
cvs rdiff -u -r1.196 -r1.197 src/sys/sys/lwp.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_turnstile.c
diff -u src/sys/kern/kern_turnstile.c:1.35 src/sys/kern/kern_turnstile.c:1.36
--- src/sys/kern/kern_turnstile.c:1.35	Mon Dec 16 19:22:15 2019
+++ src/sys/kern/kern_turnstile.c	Tue Jan 21 20:31:57 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_turnstile.c,v 1.35 2019/12/16 19:22:15 ad Exp $	*/
+/*	$NetBSD: kern_turnstile.c,v 1.36 2020/01/21 20:31:57 ad Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007, 2009, 2019 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_turnstile.c,v 1.35 2019/12/16 19:22:15 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_turnstile.c,v 1.36 2020/01/21 20:31:57 ad Exp $");
 
 #include <sys/param.h>
 #include <sys/lockdebug.h>
@@ -536,29 +536,25 @@ turnstile_print(volatile void *obj, void
 	turnstile_t *ts;
 	tschain_t *tc;
 	sleepq_t *rsq, *wsq;
-	kmutex_t *lock;
 	u_int hash;
 	lwp_t *l;
 
 	hash = TS_HASH(obj);
 	tc = &turnstile_chains[hash];
-	lock = &turnstile_locks[hash].lock;
 
 	LIST_FOREACH(ts, tc, ts_chain)
 		if (ts->ts_obj == obj)
 			break;
 
-	(*pr)("Turnstile chain at %p with mutex %p.\n", tc, lock);
 	if (ts == NULL) {
-		(*pr)("=> No active turnstile for this lock.\n");
+		(*pr)("Turnstile: no active turnstile for this lock.\n");
 		return;
 	}
 
 	rsq = &ts->ts_sleepq[TS_READER_Q];
 	wsq = &ts->ts_sleepq[TS_WRITER_Q];
 
-	(*pr)("=> Turnstile at %p (wrq=%p, rdq=%p).\n", ts, rsq, wsq);
-
+	(*pr)("Turnstile:\n");
 	(*pr)("=> %d waiting readers:", TS_WAITERS(ts, TS_READER_Q));
 	TAILQ_FOREACH(l, rsq, l_sleepchain) {
 		(*pr)(" %p", l);

Index: src/sys/kern/subr_lockdebug.c
diff -u src/sys/kern/subr_lockdebug.c:1.73 src/sys/kern/subr_lockdebug.c:1.74
--- src/sys/kern/subr_lockdebug.c:1.73	Wed Jan  8 16:21:34 2020
+++ src/sys/kern/subr_lockdebug.c	Tue Jan 21 20:31:57 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_lockdebug.c,v 1.73 2020/01/08 16:21:34 ad Exp $	*/
+/*	$NetBSD: subr_lockdebug.c,v 1.74 2020/01/21 20:31:57 ad Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_lockdebug.c,v 1.73 2020/01/08 16:21:34 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_lockdebug.c,v 1.74 2020/01/21 20:31:57 ad Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -108,7 +108,8 @@ static void	lockdebug_abort1(const char 
     const char *, bool);
 static int	lockdebug_more(int);
 static void	lockdebug_init(void);
-static void	lockdebug_dump(lockdebug_t *, void (*)(const char *, ...)
+static void	lockdebug_dump(lwp_t *, lockdebug_t *,
+    void (*)(const char *, ...)
     __printflike(1, 2));
 
 static signed int
@@ -468,6 +469,9 @@ lockdebug_wantlock(const char *func, siz
 		    true);
 		return;
 	}
+	if (l->l_ld_wanted == NULL) {
+		l->l_ld_wanted = ld;
+	}
 	__cpu_simple_unlock(&ld->ld_spinlock);
 	splx(s);
 }
@@ -529,6 +533,9 @@ lockdebug_locked(const char *func, size_
 	ld->ld_cpu = (uint16_t)cpu_index(curcpu());
 	ld->ld_lwp = l;
 	__cpu_simple_unlock(&ld->ld_spinlock);
+	if (l->l_ld_wanted == ld) {
+		l->l_ld_wanted = NULL;
+	}
 	splx(s);
 }
 
@@ -692,7 +699,7 @@ lockdebug_barrier(const char *func, size
 			if (ld->ld_lockops->lo_type == LOCKOPS_CV)
 				continue;
 			if (ld->ld_lwp == l)
-				lockdebug_dump(ld, printf);
+				lockdebug_dump(l, ld, printf);
 		}
 		panic("%s,%zu: holding %d shared locks", func, line,
 		    l->l_shlocks);
@@ -744,7 +751,7 @@ lockdebug_mem_check(const char *func, si
  *	Dump information about a lock on panic, or for DDB.
  */
 static void
-lockdebug_dump(lockdebug_t *ld, void (*pr)(const char *, ...)
+lockdebug_dump(lwp_t *l, lockdebug_t *ld, void (*pr)(const char *, ...)
     __printflike(1, 2))
 {
 	int sleeper = (ld->ld_flags & LD_SLEEPER);
@@ -761,13 +768,13 @@ lockdebug_dump(lockdebug_t *ld, void (*p
 		(*pr)("\n"
 		    "shared holds : %18u exclusive: %18u\n"
 		    "shares wanted: %18u exclusive: %18u\n"
-		    "current cpu  : %18u last held: %18u\n"
-		    "current lwp  : %#018lx last held: %#018lx\n"
+		    "relevant cpu : %18u last held: %18u\n"
+		    "relevant lwp : %#018lx last held: %#018lx\n"
 		    "last locked%c : %#018lx unlocked%c: %#018lx\n",
 		    (unsigned)ld->ld_shares, ((ld->ld_flags & LD_LOCKED) != 0),
 		    (unsigned)ld->ld_shwant, (unsigned)ld->ld_exwant,
-		    (unsigned)cpu_index(curcpu()), (unsigned)ld->ld_cpu,
-		    (long)curlwp, (long)ld->ld_lwp,
+		    (unsigned)cpu_index(l->l_cpu), (unsigned)ld->ld_cpu,
+		    (long)l, (long)ld->ld_lwp,
 		    ((ld->ld_flags & LD_LOCKED) ? '*' : ' '),
 		    (long)ld->ld_locked,
 		    ((ld->ld_flags & LD_LOCKED) ? ' ' : '*'),
@@ -778,7 +785,6 @@ lockdebug_dump(lockdebug_t *ld, void (*p
 		(*ld->ld_lockops->lo_dump)(ld->ld_lock, pr);
 
 	if (sleeper) {
-		(*pr)("\n");
 		turnstile_print(ld->ld_lock, pr);
 	}
 }
@@ -806,7 +812,7 @@ lockdebug_abort1(const char *func, size_
 
 	printf_nolog("%s error: %s,%zu: %s\n\n", ld->ld_lockops->lo_name,
 	    func, line, msg);
-	lockdebug_dump(ld, printf_nolog);
+	lockdebug_dump(curlwp, ld, printf_nolog);
 	__cpu_simple_unlock(&ld->ld_spinlock);
 	splx(s);
 	printf_nolog("\n");
@@ -837,7 +843,7 @@ lockdebug_lock_print(void *addr,
 		if (ld->ld_lock == NULL)
 			continue;
 		if (addr == NULL || ld->ld_lock == addr) {
-			lockdebug_dump(ld, pr);
+			lockdebug_dump(curlwp, ld, pr);
 			if (addr != NULL)
 				return;
 		}
@@ -853,15 +859,15 @@ lockdebug_lock_print(void *addr,
 
 #ifdef LOCKDEBUG
 static void
-lockdebug_show_one(lockdebug_t *ld, int i,
+lockdebug_show_one(lwp_t *l, lockdebug_t *ld, int i,
     void (*pr)(const char *, ...) __printflike(1, 2))
 {
 	const char *sym;
 
 	ksyms_getname(NULL, &sym, (vaddr_t)ld->ld_initaddr,
 	    KSYMS_CLOSEST|KSYMS_PROC|KSYMS_ANY);
-	(*pr)("Lock %d (initialized at %s)\n", i++, sym);
-	lockdebug_dump(ld, pr);
+	(*pr)("* Lock %d (initialized at %s)\n", i++, sym);
+	lockdebug_dump(l, ld, pr);
 }
 
 static void
@@ -882,16 +888,34 @@ lockdebug_show_all_locks_lwp(void (*pr)(
 		LIST_FOREACH(l, &p->p_lwps, l_sibling) {
 			lockdebug_t *ld;
 			int i = 0;
-			if (TAILQ_EMPTY(&l->l_ld_locks))
-				continue;
-			(*pr)("Locks held by an LWP (%s):\n",
-			    l->l_name ? l->l_name : p->p_comm);
-			TAILQ_FOREACH(ld, &l->l_ld_locks, ld_chain) {
-				lockdebug_show_one(ld, i++, pr);
+			if (TAILQ_EMPTY(&l->l_ld_locks) &&
+			    l->l_ld_wanted == NULL) {
+			    	continue;
 			}
-			if (show_trace)
+			(*pr)("\n****** LWP %d.%d (%s) @ %p, l_stat=%d\n",
+			    p->p_pid, l->l_lid,
+			    l->l_name ? l->l_name : p->p_comm, l, l->l_stat);
+			if (!TAILQ_EMPTY(&l->l_ld_locks)) {
+				(*pr)("\n*** Locks held: \n");
+				TAILQ_FOREACH(ld, &l->l_ld_locks, ld_chain) {
+					(*pr)("\n");
+					lockdebug_show_one(l, ld, i++, pr);
+				}
+			} else {
+				(*pr)("\n*** Locks held: none\n");
+			}
+
+			if (l->l_ld_wanted != NULL) {
+				(*pr)("\n*** Locks wanted: \n\n");
+				lockdebug_show_one(l, l->l_ld_wanted, 0, pr);
+			} else {
+				(*pr)("\n*** Locks wanted: none\n");
+			}
+			if (show_trace) {
+				(*pr)("\n*** Traceback: \n\n");
 				lockdebug_show_trace(l, pr);
-			(*pr)("\n");
+				(*pr)("\n");
+			}
 		}
 	}
 }
@@ -908,16 +932,18 @@ lockdebug_show_all_locks_cpu(void (*pr)(
 		int i = 0;
 		if (TAILQ_EMPTY(&ci->ci_data.cpu_ld_locks))
 			continue;
-		(*pr)("Locks held on CPU %u:\n", ci->ci_index);
+		(*pr)("\n******* Locks held on %s:\n", cpu_name(ci));
 		TAILQ_FOREACH(ld, &ci->ci_data.cpu_ld_locks, ld_chain) {
-			lockdebug_show_one(ld, i++, pr);
-			if (show_trace)
+			(*pr)("\n");
 #ifdef MULTIPROCESSOR
+			lockdebug_show_one(ci->ci_curlwp, ld, i++, pr);
+			if (show_trace)
 				lockdebug_show_trace(ci->ci_curlwp, pr);
 #else
+			lockdebug_show_one(curlwp, ld, i++, pr);
+			if (show_trace)
 				lockdebug_show_trace(curlwp, pr);
 #endif
-			(*pr)("\n");
 		}
 	}
 }

Index: src/sys/sys/lwp.h
diff -u src/sys/sys/lwp.h:1.196 src/sys/sys/lwp.h:1.197
--- src/sys/sys/lwp.h:1.196	Sun Jan 12 22:03:23 2020
+++ src/sys/sys/lwp.h	Tue Jan 21 20:31:57 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: lwp.h,v 1.196 2020/01/12 22:03:23 ad Exp $	*/
+/*	$NetBSD: lwp.h,v 1.197 2020/01/21 20:31:57 ad Exp $	*/
 
 /*
  * Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010, 2019
@@ -196,6 +196,7 @@ struct lwp {
 	uintptr_t	l_pfailaddr;	/* !: for kernel preemption */
 	uintptr_t	l_pfaillock;	/* !: for kernel preemption */
 	_TAILQ_HEAD(,struct lockdebug,volatile) l_ld_locks;/* !: locks held by LWP */
+	volatile void	*l_ld_wanted;	/* !: lock currently wanted by LWP */
 	uintptr_t	l_rwcallsite;	/* !: rwlock actual callsite */
 	int		l_tcgen;	/* !: for timecounter removal */
 

Reply via email to