From 6554d7448d541f4d46f2dc664669ce7b0a547bb8 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 13 Jun 2023 15:40:20 -0400 Subject: [PATCH] kernel: Print the first 4 chars of cvar names in KDL "threads" command. Condition variables are now a pretty common way the kernel blocks threads. That means the "threads" command was getting difficult to navigate, since at any given time, a lot of threads could be blocked on "cvar". Now we try (carefully, because it could fault!) to fetch the first 4 characters of the "type" name and display then. This suffices to distinguish the most common object block types in the list at a glance (e.g. "cvar:port" for port reads, the most common.) Change-Id: I94f4b59fd78b7ebdce913944551a5e98f0ca2e33 Reviewed-on: https://review.haiku-os.org/c/haiku/+/6605 Reviewed-by: waddlesplash --- headers/private/kernel/condition_variable.h | 2 + src/system/kernel/condition_variable.cpp | 100 ++++++++++++-------- src/system/kernel/thread.cpp | 10 +- 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/headers/private/kernel/condition_variable.h b/headers/private/kernel/condition_variable.h index 6f43805d2b..43ef0186c9 100644 --- a/headers/private/kernel/condition_variable.h +++ b/headers/private/kernel/condition_variable.h @@ -97,6 +97,8 @@ protected: friend struct ConditionVariableEntry; friend struct ConditionVariableHashDefinition; + friend ssize_t debug_condition_variable_type_strlcpy(ConditionVariable* cvar, + char* name, size_t size); }; diff --git a/src/system/kernel/condition_variable.cpp b/src/system/kernel/condition_variable.cpp index 019c07eb7d..1691645a6a 100644 --- a/src/system/kernel/condition_variable.cpp +++ b/src/system/kernel/condition_variable.cpp @@ -47,46 +47,6 @@ static ConditionVariableHash sConditionVariableHash; static rw_spinlock sConditionVariableHashLock; -static int -list_condition_variables(int argc, char** argv) -{ - ConditionVariable::ListAll(); - return 0; -} - - -static int -dump_condition_variable(int argc, char** argv) -{ - if (argc != 2) { - print_debugger_command_usage(argv[0]); - return 0; - } - - addr_t address = parse_expression(argv[1]); - if (address == 0) - return 0; - - ConditionVariable* variable = sConditionVariableHash.Lookup((void*)address); - - if (variable == NULL) { - // It must be a direct pointer to a condition variable. - variable = (ConditionVariable*)address; - } - - if (variable != NULL) { - variable->Dump(); - - set_debug_variable("_cvar", (addr_t)variable); - set_debug_variable("_object", (addr_t)variable->Object()); - - } else - kprintf("no condition variable at or with key %p\n", (void*)address); - - return 0; -} - - // #pragma mark - ConditionVariableEntry @@ -463,6 +423,9 @@ ConditionVariable::_NotifyLocked(bool all, status_t result) } +// #pragma mark - + + /*static*/ void ConditionVariable::ListAll() { @@ -494,6 +457,46 @@ ConditionVariable::Dump() const } +static int +list_condition_variables(int argc, char** argv) +{ + ConditionVariable::ListAll(); + return 0; +} + + +static int +dump_condition_variable(int argc, char** argv) +{ + if (argc != 2) { + print_debugger_command_usage(argv[0]); + return 0; + } + + addr_t address = parse_expression(argv[1]); + if (address == 0) + return 0; + + ConditionVariable* variable = sConditionVariableHash.Lookup((void*)address); + + if (variable == NULL) { + // It must be a direct pointer to a condition variable. + variable = (ConditionVariable*)address; + } + + if (variable != NULL) { + variable->Dump(); + + set_debug_variable("_cvar", (addr_t)variable); + set_debug_variable("_object", (addr_t)variable->Object()); + + } else + kprintf("no condition variable at or with key %p\n", (void*)address); + + return 0; +} + + // #pragma mark - @@ -517,5 +520,20 @@ condition_variable_init() add_debugger_command_etc("cvars", &list_condition_variables, "List condition variables", "\n" - "Lists all existing condition variables\n", 0); + "Lists all published condition variables\n", 0); +} + + +ssize_t +debug_condition_variable_type_strlcpy(ConditionVariable* cvar, char* name, size_t size) +{ + const int32 typePointerOffset = offsetof(ConditionVariable, fObjectType); + + const char* pointer; + status_t status = debug_memcpy(B_CURRENT_TEAM, &pointer, + (int8*)cvar + typePointerOffset, sizeof(const char*)); + if (status != B_OK) + return status; + + return debug_strlcpy(B_CURRENT_TEAM, name, pointer, size); } diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index f90afcea6c..3329dcb3f1 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -1701,8 +1701,16 @@ _dump_thread_info(Thread *thread, bool shortInfo) } case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: - kprintf("cvar %p ", thread->wait.object); + { + char name[5]; + ssize_t length = debug_condition_variable_type_strlcpy( + (ConditionVariable*)thread->wait.object, name, sizeof(name)); + if (length > 0) + kprintf("cvar:%*s %p ", 4, name, thread->wait.object); + else + kprintf("cvar %p ", thread->wait.object); break; + } case THREAD_BLOCK_TYPE_SNOOZE: kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, "");