Module Name:    src
Committed By:   martin
Date:           Mon Apr  2 09:07:53 UTC 2018

Modified Files:
        src/share/man/man4 [netbsd-8]: ddb.4
        src/sys/arch/x86/x86 [netbsd-8]: db_memrw.c
        src/sys/ddb [netbsd-8]: db_command.c
        src/sys/kern [netbsd-8]: kern_mutex.c kern_mutex_obj.c kern_rwlock.c
            kern_rwlock_obj.c subr_lockdebug.c subr_xcall.c
        src/sys/rump/librump/rumpkern [netbsd-8]: locks.c
        src/sys/sys [netbsd-8]: lockdebug.h

Log Message:
Pull up following revision(s) (requested by ozaki-r in ticket #687):
        sys/kern/kern_rwlock_obj.c: revision 1.4
        sys/rump/librump/rumpkern/locks.c: revision 1.80
        sys/kern/kern_rwlock.c: revision 1.50
        sys/arch/x86/x86/db_memrw.c: revision 1.5,1.6
        sys/ddb/db_command.c: revision 1.150-1.153
        share/man/man4/ddb.4: revision 1.175 (via patch),1.176-1.178
        sys/kern/kern_mutex_obj.c: revision 1.6
        sys/kern/subr_lockdebug.c: revision 1.61-1.64
        sys/sys/lockdebug.h: revision 1.17
        sys/kern/kern_mutex.c: revision 1.71
        sys/sys/lockdebug.h: revision 1.18,1.19
        sys/kern/subr_xcall.c: revision 1.26

Obtain proper initialized addresses of locks allocated by mutex_obj_alloc or 
rw_obj_alloc

Initialized addresses of locks allocated by mutex_obj_alloc or rw_obj_alloc
were not useful because the addresses were mutex_obj_alloc or rw_obj_alloc
itself. What we want to know are callers of them.

Spinkle ASSERT_SLEEPABLE to xcall functions

Use db_printf instead of printf in ddb

Add a new command, show lockstat, which shows statistics of locks
Currently the command shows the number of allocated locks.
The command is useful only if LOCKDEBUG is enabled.

Add a new command, show all locks, which shows information of active locks

The command shows information of all active (i.e., being held) locks that are
tracked through either of LWPs or CPUs by the LOCKDEBUG facility.  The /t
modifier additionally shows a backtrace for each LWP additionally.  This
feature is useful for debugging especially to analyze deadlocks.
The command is useful only if LOCKDEBUG is enabled.

Don't pass a unset address to lockdebug_lock_print

x86: avoid accessing invalid addresses in ddb like arm32
This avoids that a command stops in the middle of an execution if
a fault occurs due to an access to an invalid address.

Get rid of a redundant output

Improve wording. Fix a Cm argument.

ddb: rename "show lockstat" to "show lockstats" to avoid conflicting with 
lockstat(8)
Requested by mrg@


To generate a diff of this commit:
cvs rdiff -u -r1.166 -r1.166.6.1 src/share/man/man4/ddb.4
cvs rdiff -u -r1.2 -r1.2.10.1 src/sys/arch/x86/x86/db_memrw.c
cvs rdiff -u -r1.148 -r1.148.8.1 src/sys/ddb/db_command.c
cvs rdiff -u -r1.65.2.1 -r1.65.2.2 src/sys/kern/kern_mutex.c
cvs rdiff -u -r1.5 -r1.5.46.1 src/sys/kern/kern_mutex_obj.c
cvs rdiff -u -r1.46.6.1 -r1.46.6.2 src/sys/kern/kern_rwlock.c
cvs rdiff -u -r1.3 -r1.3.48.1 src/sys/kern/kern_rwlock_obj.c
cvs rdiff -u -r1.57 -r1.57.2.1 src/sys/kern/subr_lockdebug.c
cvs rdiff -u -r1.19.8.1 -r1.19.8.2 src/sys/kern/subr_xcall.c
cvs rdiff -u -r1.74.2.1 -r1.74.2.2 src/sys/rump/librump/rumpkern/locks.c
cvs rdiff -u -r1.15 -r1.15.6.1 src/sys/sys/lockdebug.h

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

Modified files:

Index: src/share/man/man4/ddb.4
diff -u src/share/man/man4/ddb.4:1.166 src/share/man/man4/ddb.4:1.166.6.1
--- src/share/man/man4/ddb.4:1.166	Thu Jan 12 13:14:41 2017
+++ src/share/man/man4/ddb.4	Mon Apr  2 09:07:52 2018
@@ -1,4 +1,4 @@
-.\"	$NetBSD: ddb.4,v 1.166 2017/01/12 13:14:41 wiz Exp $
+.\"	$NetBSD: ddb.4,v 1.166.6.1 2018/04/02 09:07:52 martin Exp $
 .\"
 .\" Copyright (c) 1997 - 2009 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -56,7 +56,7 @@
 .\" any improvements or extensions that they make and grant Carnegie Mellon
 .\" the rights to redistribute these changes.
 .\"
-.Dd January 12, 2017
+.Dd March 19, 2018
 .Dt DDB 4
 .Os
 .Sh NAME
@@ -258,7 +258,7 @@ is taken to be 1 for printing commands, 
 .Pp
 The syntax:
 .Bd -ragged -offset indent
-.Cm , Ns Ar count
+.Cm \&, Ns Ar count
 .Ed
 .Pp
 repeats the previous command, just as a blank line does, but with
@@ -564,6 +564,13 @@ Display information about callouts in th
 See
 .Xr callout 9
 for more information on callouts.
+.It Ic show all locks Ns Op Cm /t
+Display details information about all active locks.
+If
+.Cm /t
+is specified, stack traces of LWPs holding locks are also printed.
+This command is only useful if a kernel is compiled with
+.Cd options LOCKDEBUG .
 .It Ic show all pages
 Display basic information about all physical pages managed by the VM system.
 For more detailed information about a single page, use
@@ -656,7 +663,11 @@ be displayed.
 .It Ic show lock Ar address
 Display information about a lock at
 .Ar address .
-This command is useful only if a kernel is compiled with
+This command is only useful if a kernel is compiled with
+.Cd options LOCKDEBUG .
+.It Ic show lockstats
+Display information about lock statistics.
+This command is only useful if a kernel is compiled with
 .Cd options LOCKDEBUG .
 .It Ic show map Ns Oo Cm /f Oc Ar address
 Print the vm_map at

Index: src/sys/arch/x86/x86/db_memrw.c
diff -u src/sys/arch/x86/x86/db_memrw.c:1.2 src/sys/arch/x86/x86/db_memrw.c:1.2.10.1
--- src/sys/arch/x86/x86/db_memrw.c:1.2	Thu May 12 06:45:16 2016
+++ src/sys/arch/x86/x86/db_memrw.c	Mon Apr  2 09:07:52 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: db_memrw.c,v 1.2 2016/05/12 06:45:16 maxv Exp $	*/
+/*	$NetBSD: db_memrw.c,v 1.2.10.1 2018/04/02 09:07:52 martin Exp $	*/
 
 /*-
  * Copyright (c) 1996, 2000 The NetBSD Foundation, Inc.
@@ -53,7 +53,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_memrw.c,v 1.2 2016/05/12 06:45:16 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_memrw.c,v 1.2.10.1 2018/04/02 09:07:52 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -62,6 +62,23 @@ __KERNEL_RCSID(0, "$NetBSD: db_memrw.c,v
 #include <machine/db_machdep.h>
 
 #include <ddb/db_access.h>
+#include <ddb/db_output.h>
+
+static int
+db_validate_address(vaddr_t addr)
+{
+	struct proc *p = curproc;
+	struct pmap *pmap;
+
+	if (!p || !p->p_vmspace || !p->p_vmspace->vm_map.pmap ||
+	    addr >= VM_MIN_KERNEL_ADDRESS
+	   )
+		pmap = pmap_kernel();
+	else
+		pmap = p->p_vmspace->vm_map.pmap;
+
+	return (pmap_extract(pmap, addr, NULL) == false);
+}
 
 /*
  * Read bytes from kernel address space for debugger.
@@ -73,6 +90,11 @@ db_read_bytes(vaddr_t addr, size_t size,
 
 	src = (char *)addr;
 
+	if (db_validate_address((vaddr_t)src)) {
+		db_printf("address %p is invalid\n", src);
+		return;
+	}
+
 	if (size == 8) {
 		*((long *)data) = *((long *)src);
 		return;
@@ -88,8 +110,14 @@ db_read_bytes(vaddr_t addr, size_t size,
 		return;
 	}
 
-	while (size-- > 0)
+	while (size-- > 0) {
+		if (db_validate_address((vaddr_t)src)) {
+			db_printf("address %p is invalid\n", src);
+			return;
+		}
+
 		*data++ = *src++;
+	}
 }
 
 /*
@@ -117,7 +145,7 @@ db_write_text(vaddr_t addr, size_t size,
 		pte = *ppte;
 
 		if ((pte & PG_V) == 0) {
-			printf(" address %p not a valid page\n", dst);
+			db_printf(" address %p not a valid page\n", dst);
 			return;
 		}
 

Index: src/sys/ddb/db_command.c
diff -u src/sys/ddb/db_command.c:1.148 src/sys/ddb/db_command.c:1.148.8.1
--- src/sys/ddb/db_command.c:1.148	Wed Jan 11 12:17:34 2017
+++ src/sys/ddb/db_command.c	Mon Apr  2 09:07:52 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: db_command.c,v 1.148 2017/01/11 12:17:34 joerg Exp $	*/
+/*	$NetBSD: db_command.c,v 1.148.8.1 2018/04/02 09:07:52 martin Exp $	*/
 
 /*
  * Copyright (c) 1996, 1997, 1998, 1999, 2002, 2009 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.148 2017/01/11 12:17:34 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.148.8.1 2018/04/02 09:07:52 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_aio.h"
@@ -190,6 +190,8 @@ static void	db_event_print_cmd(db_expr_t
 static void	db_fncall(db_expr_t, bool, db_expr_t, const char *);
 static void     db_help_print_cmd(db_expr_t, bool, db_expr_t, const char *);
 static void	db_lock_print_cmd(db_expr_t, bool, db_expr_t, const char *);
+static void	db_show_all_locks(db_expr_t, bool, db_expr_t, const char *);
+static void	db_show_lockstats(db_expr_t, bool, db_expr_t, const char *);
 static void	db_mount_print_cmd(db_expr_t, bool, db_expr_t, const char *);
 static void	db_mbuf_print_cmd(db_expr_t, bool, db_expr_t, const char *);
 static void	db_map_print_cmd(db_expr_t, bool, db_expr_t, const char *);
@@ -225,6 +227,8 @@ static const struct db_command db_show_c
 	    0 ,"List all processes.",NULL,NULL) },
 	{ DDB_ADD_CMD("pools",	db_show_all_pools,
 	    0 ,"Show all pools",NULL,NULL) },
+	{ DDB_ADD_CMD("locks",	db_show_all_locks,
+	    0 ,"Show all held locks", "[/t]", NULL) },
 #ifdef AIO
 	/*added from all sub cmds*/
 	{ DDB_ADD_CMD("aio_jobs",	db_show_aio_jobs,	0,
@@ -247,6 +251,9 @@ static const struct db_command db_show_c
 	    "Print the files open by process at address",
 	    "[/f] address", NULL) },
 	{ DDB_ADD_CMD("lock",	db_lock_print_cmd,	0,NULL,NULL,NULL) },
+	{ DDB_ADD_CMD("lockstats",
+				db_show_lockstats,	0,
+	    "Print statistics of locks", NULL, NULL) },
 	{ DDB_ADD_CMD("map",	db_map_print_cmd,	0,
 	    "Print the vm_map at address.", "[/f] address",NULL) },
 	{ DDB_ADD_CMD("module", db_show_module_cmd,	0,
@@ -1221,7 +1228,28 @@ db_lock_print_cmd(db_expr_t addr, bool h
 {
 
 #ifdef _KERNEL	/* XXX CRASH(8) */
-	lockdebug_lock_print((void *)(uintptr_t)addr, db_printf);
+	lockdebug_lock_print(have_addr ? (void *)(uintptr_t)addr : NULL,
+	    db_printf);
+#endif
+}
+
+static void
+db_show_all_locks(db_expr_t addr, bool have_addr,
+    db_expr_t count, const char *modif)
+{
+
+#ifdef _KERNEL	/* XXX CRASH(8) */
+	lockdebug_show_all_locks(db_printf, modif);
+#endif
+}
+
+static void
+db_show_lockstats(db_expr_t addr, bool have_addr,
+    db_expr_t count, const char *modif)
+{
+
+#ifdef _KERNEL	/* XXX CRASH(8) */
+	lockdebug_show_lockstats(db_printf);
 #endif
 }
 

Index: src/sys/kern/kern_mutex.c
diff -u src/sys/kern/kern_mutex.c:1.65.2.1 src/sys/kern/kern_mutex.c:1.65.2.2
--- src/sys/kern/kern_mutex.c:1.65.2.1	Sat Jan 13 21:57:11 2018
+++ src/sys/kern/kern_mutex.c	Mon Apr  2 09:07:52 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_mutex.c,v 1.65.2.1 2018/01/13 21:57:11 snj Exp $	*/
+/*	$NetBSD: kern_mutex.c,v 1.65.2.2 2018/04/02 09:07:52 martin Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -40,7 +40,7 @@
 #define	__MUTEX_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_mutex.c,v 1.65.2.1 2018/01/13 21:57:11 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_mutex.c,v 1.65.2.2 2018/04/02 09:07:52 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -326,8 +326,10 @@ mutex_abort(const char *func, size_t lin
  *	sleeps - see comments in mutex_vector_enter() about releasing
  *	mutexes unlocked.
  */
+void _mutex_init(kmutex_t *, kmutex_type_t, int, uintptr_t);
 void
-mutex_init(kmutex_t *mtx, kmutex_type_t type, int ipl)
+_mutex_init(kmutex_t *mtx, kmutex_type_t type, int ipl,
+    uintptr_t return_address)
 {
 	bool dodebug;
 
@@ -353,18 +355,17 @@ mutex_init(kmutex_t *mtx, kmutex_type_t 
 
 	switch (type) {
 	case MUTEX_NODEBUG:
-		dodebug = LOCKDEBUG_ALLOC(mtx, NULL,
-		    (uintptr_t)__builtin_return_address(0));
+		dodebug = LOCKDEBUG_ALLOC(mtx, NULL, return_address);
 		MUTEX_INITIALIZE_SPIN(mtx, dodebug, ipl);
 		break;
 	case MUTEX_ADAPTIVE:
 		dodebug = LOCKDEBUG_ALLOC(mtx, &mutex_adaptive_lockops,
-		    (uintptr_t)__builtin_return_address(0));
+		    return_address);
 		MUTEX_INITIALIZE_ADAPTIVE(mtx, dodebug);
 		break;
 	case MUTEX_SPIN:
 		dodebug = LOCKDEBUG_ALLOC(mtx, &mutex_spin_lockops,
-		    (uintptr_t)__builtin_return_address(0));
+		    return_address);
 		MUTEX_INITIALIZE_SPIN(mtx, dodebug, ipl);
 		break;
 	default:
@@ -373,6 +374,13 @@ mutex_init(kmutex_t *mtx, kmutex_type_t 
 	}
 }
 
+void
+mutex_init(kmutex_t *mtx, kmutex_type_t type, int ipl)
+{
+
+	_mutex_init(mtx, type, ipl, (uintptr_t)__builtin_return_address(0));
+}
+
 /*
  * mutex_destroy:
  *

Index: src/sys/kern/kern_mutex_obj.c
diff -u src/sys/kern/kern_mutex_obj.c:1.5 src/sys/kern/kern_mutex_obj.c:1.5.46.1
--- src/sys/kern/kern_mutex_obj.c:1.5	Tue Sep 27 01:02:38 2011
+++ src/sys/kern/kern_mutex_obj.c	Mon Apr  2 09:07:52 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_mutex_obj.c,v 1.5 2011/09/27 01:02:38 jym Exp $	*/
+/*	$NetBSD: kern_mutex_obj.c,v 1.5.46.1 2018/04/02 09:07:52 martin Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_mutex_obj.c,v 1.5 2011/09/27 01:02:38 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_mutex_obj.c,v 1.5.46.1 2018/04/02 09:07:52 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -87,9 +87,11 @@ kmutex_t *
 mutex_obj_alloc(kmutex_type_t type, int ipl)
 {
 	struct kmutexobj *mo;
+	extern void _mutex_init(kmutex_t *, kmutex_type_t, int, uintptr_t);
 
 	mo = pool_cache_get(mutex_obj_cache, PR_WAITOK);
-	mutex_init(&mo->mo_lock, type, ipl);
+	_mutex_init(&mo->mo_lock, type, ipl,
+	    (uintptr_t)__builtin_return_address(0));
 	mo->mo_refcnt = 1;
 
 	return (kmutex_t *)mo;

Index: src/sys/kern/kern_rwlock.c
diff -u src/sys/kern/kern_rwlock.c:1.46.6.1 src/sys/kern/kern_rwlock.c:1.46.6.2
--- src/sys/kern/kern_rwlock.c:1.46.6.1	Sat Jan 13 21:57:11 2018
+++ src/sys/kern/kern_rwlock.c	Mon Apr  2 09:07:52 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_rwlock.c,v 1.46.6.1 2018/01/13 21:57:11 snj Exp $	*/
+/*	$NetBSD: kern_rwlock.c,v 1.46.6.2 2018/04/02 09:07:52 martin Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_rwlock.c,v 1.46.6.1 2018/01/13 21:57:11 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_rwlock.c,v 1.46.6.2 2018/04/02 09:07:52 martin Exp $");
 
 #define	__RWLOCK_PRIVATE
 
@@ -197,18 +197,25 @@ rw_abort(const char *func, size_t line, 
  *
  *	Initialize a rwlock for use.
  */
+void _rw_init(krwlock_t *, uintptr_t);
 void
-rw_init(krwlock_t *rw)
+_rw_init(krwlock_t *rw, uintptr_t return_address)
 {
 	bool dodebug;
 
 	memset(rw, 0, sizeof(*rw));
 
-	dodebug = LOCKDEBUG_ALLOC(rw, &rwlock_lockops,
-	    (uintptr_t)__builtin_return_address(0));
+	dodebug = LOCKDEBUG_ALLOC(rw, &rwlock_lockops, return_address);
 	RW_SETDEBUG(rw, dodebug);
 }
 
+void
+rw_init(krwlock_t *rw)
+{
+
+	_rw_init(rw, (uintptr_t)__builtin_return_address(0));
+}
+
 /*
  * rw_destroy:
  *

Index: src/sys/kern/kern_rwlock_obj.c
diff -u src/sys/kern/kern_rwlock_obj.c:1.3 src/sys/kern/kern_rwlock_obj.c:1.3.48.1
--- src/sys/kern/kern_rwlock_obj.c:1.3	Fri May 13 22:16:43 2011
+++ src/sys/kern/kern_rwlock_obj.c	Mon Apr  2 09:07:52 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_rwlock_obj.c,v 1.3 2011/05/13 22:16:43 rmind Exp $	*/
+/*	$NetBSD: kern_rwlock_obj.c,v 1.3.48.1 2018/04/02 09:07:52 martin Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_rwlock_obj.c,v 1.3 2011/05/13 22:16:43 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_rwlock_obj.c,v 1.3.48.1 2018/04/02 09:07:52 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -87,9 +87,10 @@ krwlock_t *
 rw_obj_alloc(void)
 {
 	struct krwobj *ro;
+	extern void _rw_init(krwlock_t *, uintptr_t);
 
 	ro = pool_cache_get(rw_obj_cache, PR_WAITOK);
-	rw_init(&ro->ro_lock);
+	_rw_init(&ro->ro_lock, (uintptr_t)__builtin_return_address(0));
 	ro->ro_refcnt = 1;
 
 	return (krwlock_t *)ro;

Index: src/sys/kern/subr_lockdebug.c
diff -u src/sys/kern/subr_lockdebug.c:1.57 src/sys/kern/subr_lockdebug.c:1.57.2.1
--- src/sys/kern/subr_lockdebug.c:1.57	Thu Jun  1 02:45:13 2017
+++ src/sys/kern/subr_lockdebug.c	Mon Apr  2 09:07:52 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_lockdebug.c,v 1.57 2017/06/01 02:45:13 chs Exp $	*/
+/*	$NetBSD: subr_lockdebug.c,v 1.57.2.1 2018/04/02 09:07:52 martin Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_lockdebug.c,v 1.57 2017/06/01 02:45:13 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_lockdebug.c,v 1.57.2.1 2018/04/02 09:07:52 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -51,6 +51,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_lockdeb
 #include <sys/atomic.h>
 #include <sys/lock.h>
 #include <sys/rbtree.h>
+#include <sys/ksyms.h>
 
 #include <machine/lock.h>
 
@@ -811,6 +812,9 @@ lockdebug_abort1(const char *func, size_
  *	Handle the DDB 'show lock' command.
  */
 #ifdef DDB
+#include <machine/db_machdep.h>
+#include <ddb/db_interface.h>
+
 void
 lockdebug_lock_print(void *addr, void (*pr)(const char *, ...))
 {
@@ -834,6 +838,142 @@ lockdebug_lock_print(void *addr, void (*
 	(*pr)("Sorry, kernel not built with the LOCKDEBUG option.\n");
 #endif	/* LOCKDEBUG */
 }
+
+#ifdef LOCKDEBUG
+static void
+lockdebug_show_all_locks_lwp(void (*pr)(const char *, ...), bool show_trace)
+{
+	struct proc *p;
+
+	LIST_FOREACH(p, &allproc, p_list) {
+		struct lwp *l;
+		LIST_FOREACH(l, &p->p_lwps, l_sibling) {
+			lockdebug_t *ld;
+			const char *sym;
+			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) {
+				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);
+			}
+			if (show_trace) {
+				db_stack_trace_print((db_expr_t)(intptr_t)l,
+				    true,
+				    32 /* Limit just in case */,
+				    "a", pr);
+			}
+			(*pr)("\n");
+		}
+	}
+}
+
+static void
+lockdebug_show_all_locks_cpu(void (*pr)(const char *, ...), bool show_trace)
+{
+	lockdebug_t *ld;
+	CPU_INFO_ITERATOR cii;
+	struct cpu_info *ci;
+	const char *sym;
+
+	for (CPU_INFO_FOREACH(cii, ci)) {
+		int i = 0;
+		if (TAILQ_EMPTY(&ci->ci_data.cpu_ld_locks))
+			continue;
+		(*pr)("Locks held on CPU %u:\n", ci->ci_index);
+		TAILQ_FOREACH(ld, &ci->ci_data.cpu_ld_locks, ld_chain) {
+			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);
+			if (show_trace) {
+				db_stack_trace_print(
+				    (db_expr_t)(intptr_t)ci->ci_curlwp,
+				    true,
+				    32 /* Limit just in case */,
+				    "a", pr);
+			}
+			(*pr)("\n");
+		}
+	}
+}
+#endif	/* LOCKDEBUG */
+
+void
+lockdebug_show_all_locks(void (*pr)(const char *, ...), const char *modif)
+{
+#ifdef LOCKDEBUG
+	bool show_trace = false;
+	if (modif[0] == 't')
+		show_trace = true;
+
+	(*pr)("[Locks tracked through LWPs]\n");
+	lockdebug_show_all_locks_lwp(pr, show_trace);
+	(*pr)("\n");
+
+	(*pr)("[Locks tracked through CPUs]\n");
+	lockdebug_show_all_locks_cpu(pr, show_trace);
+	(*pr)("\n");
+#else
+	(*pr)("Sorry, kernel not built with the LOCKDEBUG option.\n");
+#endif	/* LOCKDEBUG */
+}
+
+void
+lockdebug_show_lockstats(void (*pr)(const char *, ...))
+{
+#ifdef LOCKDEBUG
+	lockdebug_t *ld;
+	void *_ld;
+	uint32_t n_null = 0;
+	uint32_t n_spin_mutex = 0;
+	uint32_t n_adaptive_mutex = 0;
+	uint32_t n_rwlock = 0;
+	uint32_t n_cv = 0;
+	uint32_t n_others = 0;
+
+	RB_TREE_FOREACH(_ld, &ld_rb_tree) {
+		ld = _ld;
+		if (ld->ld_lock == NULL) {
+			n_null++;
+			continue;
+		}
+		if (ld->ld_lockops->lo_type == LOCKOPS_CV) {
+			n_cv++;
+			continue;
+		}
+		if (ld->ld_lockops->lo_name[0] == 'M') {
+			if (ld->ld_lockops->lo_type == LOCKOPS_SLEEP)
+				n_adaptive_mutex++;
+			else
+				n_spin_mutex++;
+			continue;
+		}
+		if (ld->ld_lockops->lo_name[0] == 'R') {
+			n_rwlock++;
+			continue;
+		}
+		n_others++;
+	}
+	(*pr)(
+	    "condvar: %u\n"
+	    "spin mutex: %u\n"
+	    "adaptive mutex: %u\n"
+	    "rwlock: %u\n"
+	    "null locks: %u\n"
+	    "others: %u\n",
+	    n_cv,  n_spin_mutex, n_adaptive_mutex, n_rwlock,
+	    n_null, n_others);
+#else
+	(*pr)("Sorry, kernel not built with the LOCKDEBUG option.\n");
+#endif	/* LOCKDEBUG */
+}
 #endif	/* DDB */
 
 /*

Index: src/sys/kern/subr_xcall.c
diff -u src/sys/kern/subr_xcall.c:1.19.8.1 src/sys/kern/subr_xcall.c:1.19.8.2
--- src/sys/kern/subr_xcall.c:1.19.8.1	Mon Feb 19 18:33:38 2018
+++ src/sys/kern/subr_xcall.c	Mon Apr  2 09:07:52 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_xcall.c,v 1.19.8.1 2018/02/19 18:33:38 snj Exp $	*/
+/*	$NetBSD: subr_xcall.c,v 1.19.8.2 2018/04/02 09:07:52 martin Exp $	*/
 
 /*-
  * Copyright (c) 2007-2010 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_xcall.c,v 1.19.8.1 2018/02/19 18:33:38 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_xcall.c,v 1.19.8.2 2018/04/02 09:07:52 martin Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -257,6 +257,7 @@ xc_broadcast(unsigned int flags, xcfunc_
 {
 
 	KASSERT(!cpu_intr_p() && !cpu_softintr_p());
+	ASSERT_SLEEPABLE();
 
 	if ((flags & XC_HIGHPRI) != 0) {
 		int ipl = xc_extract_ipl(flags);
@@ -278,6 +279,7 @@ xc_unicast(unsigned int flags, xcfunc_t 
 
 	KASSERT(ci != NULL);
 	KASSERT(!cpu_intr_p() && !cpu_softintr_p());
+	ASSERT_SLEEPABLE();
 
 	if ((flags & XC_HIGHPRI) != 0) {
 		int ipl = xc_extract_ipl(flags);
@@ -298,6 +300,7 @@ xc_wait(uint64_t where)
 	xc_state_t *xc;
 
 	KASSERT(!cpu_intr_p() && !cpu_softintr_p());
+	ASSERT_SLEEPABLE();
 
 	/* Determine whether it is high or low priority cross-call. */
 	if ((where & XC_PRI_BIT) != 0) {

Index: src/sys/rump/librump/rumpkern/locks.c
diff -u src/sys/rump/librump/rumpkern/locks.c:1.74.2.1 src/sys/rump/librump/rumpkern/locks.c:1.74.2.2
--- src/sys/rump/librump/rumpkern/locks.c:1.74.2.1	Sat Jan 13 21:57:11 2018
+++ src/sys/rump/librump/rumpkern/locks.c	Mon Apr  2 09:07:52 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: locks.c,v 1.74.2.1 2018/01/13 21:57:11 snj Exp $	*/
+/*	$NetBSD: locks.c,v 1.74.2.2 2018/04/02 09:07:52 martin Exp $	*/
 
 /*
  * Copyright (c) 2007-2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: locks.c,v 1.74.2.1 2018/01/13 21:57:11 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: locks.c,v 1.74.2.2 2018/04/02 09:07:52 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/kmem.h>
@@ -66,9 +66,9 @@ static lockops_t rw_lockops = {
 	.lo_dump = NULL,
 };
 
-#define ALLOCK(lock, ops)				\
+#define ALLOCK(lock, ops, return_address)		\
 	lockdebug_alloc(__func__, __LINE__, lock, ops,	\
-	    (uintptr_t)__builtin_return_address(0))
+	    return_address)
 #define FREELOCK(lock)					\
 	lockdebug_free(__func__, __LINE__, lock)
 #define WANTLOCK(lock, shar)				\
@@ -83,7 +83,7 @@ static lockops_t rw_lockops = {
 #define BARRIER(lock, slp)				\
 	lockdebug_barrier(__func__, __LINE__, lock, slp)
 #else
-#define ALLOCK(a, b)	do {} while (0)
+#define ALLOCK(a, b, c)	do {} while (0)
 #define FREELOCK(a)	do {} while (0)
 #define WANTLOCK(a, b)	do {} while (0)
 #define LOCKED(a, b)	do {} while (0)
@@ -105,8 +105,9 @@ static lockops_t rw_lockops = {
 
 #define RUMPMTX(mtx) (*(struct rumpuser_mtx **)(mtx))
 
+void _mutex_init(kmutex_t *, kmutex_type_t, int, uintptr_t);
 void
-mutex_init(kmutex_t *mtx, kmutex_type_t type, int ipl)
+_mutex_init(kmutex_t *mtx, kmutex_type_t type, int ipl, uintptr_t return_address)
 {
 	int ruflags = RUMPUSER_MTX_KMUTEX;
 	int isspin;
@@ -135,9 +136,16 @@ mutex_init(kmutex_t *mtx, kmutex_type_t 
 		ruflags |= RUMPUSER_MTX_SPIN;
 	rumpuser_mutex_init((struct rumpuser_mtx **)mtx, ruflags);
 	if (isspin)
-		ALLOCK(mtx, &mutex_spin_lockops);
+		ALLOCK(mtx, &mutex_spin_lockops, return_address);
 	else
-		ALLOCK(mtx, &mutex_adaptive_lockops);
+		ALLOCK(mtx, &mutex_adaptive_lockops, return_address);
+}
+
+void
+mutex_init(kmutex_t *mtx, kmutex_type_t type, int ipl)
+{
+
+	_mutex_init(mtx, type, ipl, (uintptr_t)__builtin_return_address(0));
 }
 
 void
@@ -238,14 +246,22 @@ krw2rumprw(const krw_t op)
 	}
 }
 
+void _rw_init(krwlock_t *, uintptr_t);
 void
-rw_init(krwlock_t *rw)
+_rw_init(krwlock_t *rw, uintptr_t return_address)
 {
 
 	CTASSERT(sizeof(krwlock_t) >= sizeof(void *));
 
 	rumpuser_rw_init((struct rumpuser_rw **)rw);
-	ALLOCK(rw, &rw_lockops);
+	ALLOCK(rw, &rw_lockops, return_address);
+}
+
+void
+rw_init(krwlock_t *rw)
+{
+
+	_rw_init(rw, (uintptr_t)__builtin_return_address(0));
 }
 
 void

Index: src/sys/sys/lockdebug.h
diff -u src/sys/sys/lockdebug.h:1.15 src/sys/sys/lockdebug.h:1.15.6.1
--- src/sys/sys/lockdebug.h:1.15	Thu Jan 26 04:11:56 2017
+++ src/sys/sys/lockdebug.h	Mon Apr  2 09:07:53 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: lockdebug.h,v 1.15 2017/01/26 04:11:56 christos Exp $	*/
+/*	$NetBSD: lockdebug.h,v 1.15.6.1 2018/04/02 09:07:53 martin Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -58,6 +58,9 @@ void	lockdebug_abort(const char *, size_
 
 void	lockdebug_lock_print(void *, void (*)(const char *, ...)
     __printflike(1, 2));
+void	lockdebug_show_all_locks(void (*)(const char *, ...) __printflike(1, 2),
+	    const char *);
+void	lockdebug_show_lockstats(void (*)(const char *, ...) __printflike(1, 2));
 
 #ifdef LOCKDEBUG
 

Reply via email to