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 <waddlesplash@gmail.com>
This commit is contained in:
Augustin Cavalier 2023-06-13 15:40:20 -04:00 committed by waddlesplash
parent f0e9ed4488
commit 6554d7448d
3 changed files with 70 additions and 42 deletions

View File

@ -97,6 +97,8 @@ protected:
friend struct ConditionVariableEntry; friend struct ConditionVariableEntry;
friend struct ConditionVariableHashDefinition; friend struct ConditionVariableHashDefinition;
friend ssize_t debug_condition_variable_type_strlcpy(ConditionVariable* cvar,
char* name, size_t size);
}; };

View File

@ -47,46 +47,6 @@ static ConditionVariableHash sConditionVariableHash;
static rw_spinlock sConditionVariableHashLock; 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 // #pragma mark - ConditionVariableEntry
@ -463,6 +423,9 @@ ConditionVariable::_NotifyLocked(bool all, status_t result)
} }
// #pragma mark -
/*static*/ void /*static*/ void
ConditionVariable::ListAll() 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 - // #pragma mark -
@ -517,5 +520,20 @@ condition_variable_init()
add_debugger_command_etc("cvars", &list_condition_variables, add_debugger_command_etc("cvars", &list_condition_variables,
"List condition variables", "List condition variables",
"\n" "\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);
} }

View File

@ -1701,8 +1701,16 @@ _dump_thread_info(Thread *thread, bool shortInfo)
} }
case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: 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; break;
}
case THREAD_BLOCK_TYPE_SNOOZE: case THREAD_BLOCK_TYPE_SNOOZE:
kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, ""); kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, "");