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.
This commit is contained in:
parent
1d919413b1
commit
e611636f76
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: ddb.4,v 1.175 2018/03/16 04:37:55 ozaki-r Exp $
|
||||
.\" $NetBSD: ddb.4,v 1.176 2018/03/16 04:44:51 ozaki-r Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1997 - 2009 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
|
@ -556,6 +556,13 @@ Display information about callouts in the system.
|
|||
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 printed additionally.
|
||||
This command is useful only 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: db_command.c,v 1.150 2018/03/16 04:37:55 ozaki-r Exp $ */
|
||||
/* $NetBSD: db_command.c,v 1.151 2018/03/16 04:44:51 ozaki-r 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.150 2018/03/16 04:37:55 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.151 2018/03/16 04:44:51 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_aio.h"
|
||||
|
@ -190,6 +190,7 @@ static void db_event_print_cmd(db_expr_t, bool, db_expr_t, const char *);
|
|||
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_lockstat(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 *);
|
||||
|
@ -226,6 +227,8 @@ static const struct db_command db_show_cmds[] = {
|
|||
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,
|
||||
|
@ -1230,6 +1233,16 @@ db_lock_print_cmd(db_expr_t addr, bool have_addr,
|
|||
#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_lockstat(db_expr_t addr, bool have_addr,
|
||||
db_expr_t count, const char *modif)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: subr_lockdebug.c,v 1.61 2018/03/16 04:43:37 ozaki-r Exp $ */
|
||||
/* $NetBSD: subr_lockdebug.c,v 1.62 2018/03/16 04:44:51 ozaki-r 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.61 2018/03/16 04:43:37 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: subr_lockdebug.c,v 1.62 2018/03/16 04:44:51 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_ddb.h"
|
||||
|
@ -51,6 +51,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_lockdebug.c,v 1.61 2018/03/16 04:43:37 ozaki-r
|
|||
#include <sys/atomic.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/rbtree.h>
|
||||
#include <sys/ksyms.h>
|
||||
|
||||
#include <machine/lock.h>
|
||||
|
||||
|
@ -815,6 +816,9 @@ lockdebug_abort1(const char *func, size_t line, lockdebug_t *ld, int s,
|
|||
* 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 *, ...))
|
||||
{
|
||||
|
@ -839,6 +843,93 @@ lockdebug_lock_print(void *addr, void (*pr)(const char *, ...))
|
|||
#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)("Initialized at %s\n", sym);
|
||||
(*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_lockstat(void (*pr)(const char *, ...))
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: lockdebug.h,v 1.17 2018/03/16 04:37:55 ozaki-r Exp $ */
|
||||
/* $NetBSD: lockdebug.h,v 1.18 2018/03/16 04:44:51 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -58,6 +58,8 @@ void lockdebug_abort(const char *, size_t, const volatile void *,
|
|||
|
||||
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_lockstat(void (*)(const char *, ...) __printflike(1, 2));
|
||||
|
||||
#ifdef LOCKDEBUG
|
||||
|
|
Loading…
Reference in New Issue