diff --git a/kernel/debug.c b/kernel/debug.c index b7e8c5f2..ba5bb58f 100644 --- a/kernel/debug.c +++ b/kernel/debug.c @@ -28,13 +28,15 @@ #include static int cmd_threads(int argc, const console_cmd_args *argv); +static int cmd_threads_panic(int argc, const console_cmd_args *argv); static int cmd_threadstats(int argc, const console_cmd_args *argv); static int cmd_threadload(int argc, const console_cmd_args *argv); static int cmd_kevlog(int argc, const console_cmd_args *argv); STATIC_COMMAND_START #if LK_DEBUGLEVEL > 1 -STATIC_COMMAND_MASKED("threads", "list kernel threads", &cmd_threads, CMD_AVAIL_ALWAYS) +STATIC_COMMAND("threads", "list kernel threads", &cmd_threads) +STATIC_COMMAND_MASKED("threads", "list kernel threads", &cmd_threads_panic, CMD_AVAIL_PANIC) #endif #if THREAD_STATS STATIC_COMMAND("threadstats", "thread level statistics", &cmd_threadstats) @@ -52,6 +54,16 @@ static int cmd_threads(int argc, const console_cmd_args *argv) { return 0; } + +static int cmd_threads_panic(int argc, const console_cmd_args *argv) { + /* call the unsafe version of the thread dump routine since the + * thread lock may be held at crash time. + */ + printf("thread list:\n"); + dump_all_threads_unlocked(); + + return 0; +} #endif #if THREAD_STATS diff --git a/kernel/include/kernel/thread.h b/kernel/include/kernel/thread.h index 14f32704..ddfe983f 100644 --- a/kernel/include/kernel/thread.h +++ b/kernel/include/kernel/thread.h @@ -162,6 +162,7 @@ status_t thread_set_real_time(thread_t *t); void dump_thread(thread_t *t); void arch_dump_thread(thread_t *t); void dump_all_threads(void); +void dump_all_threads_unlocked(void); /* scheduler routines */ void thread_yield(void); /* give up the cpu voluntarily */ diff --git a/kernel/thread.c b/kernel/thread.c index ed13be7e..0b3ddf23 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -988,13 +988,8 @@ void dump_thread(thread_t *t) { arch_dump_thread(t); } -/** - * @brief Dump debugging info about all threads - */ -void dump_all_threads(void) { +void dump_all_threads_unlocked(void) { thread_t *t; - - THREAD_LOCK(state); list_for_every_entry(&thread_list, t, thread_t, thread_list_node) { if (t->magic != THREAD_MAGIC) { dprintf(INFO, "bad magic on thread struct %p, aborting.\n", t); @@ -1003,6 +998,14 @@ void dump_all_threads(void) { } dump_thread(t); } +} + +/** + * @brief Dump debugging info about all threads + */ +void dump_all_threads(void) { + THREAD_LOCK(state); + dump_all_threads_unlocked(); THREAD_UNLOCK(state); }