Kernel: Allow setting thread names

The main thread of each kernel/user process will take the name of
the process. Extra threads will get a fancy new name
"ProcessName[<tid>]".

Thread backtraces now list the thread name in addtion to tid.

Add the thread name to /proc/all (should it get its own proc
file?).

Add two new syscalls, set_thread_name and get_thread_name.
This commit is contained in:
Andrew Kaster 2019-12-07 12:45:26 -07:00 committed by Andreas Kling
parent 875ab0cf10
commit 9058962712
Notes: sideshowbarker 2024-07-19 10:55:50 +09:00
6 changed files with 78 additions and 2 deletions

View File

@ -721,6 +721,7 @@ Optional<KBuffer> procfs$all(InodeIdentifier)
process.for_each_thread([&](const Thread& thread) { process.for_each_thread([&](const Thread& thread) {
auto thread_object = thread_array.add_object(); auto thread_object = thread_array.add_object();
thread_object.add("tid", thread.tid()); thread_object.add("tid", thread.tid());
thread_object.add("name", thread.name());
thread_object.add("times_scheduled", thread.times_scheduled()); thread_object.add("times_scheduled", thread.times_scheduled());
thread_object.add("ticks", thread.ticks()); thread_object.add("ticks", thread.ticks());
thread_object.add("state", thread.state_string()); thread_object.add("state", thread.state_string());

View File

@ -542,6 +542,7 @@ int Process::do_exec(String path, Vector<String> arguments, Vector<String> envir
Scheduler::prepare_to_modify_tss(main_thread()); Scheduler::prepare_to_modify_tss(main_thread());
m_name = parts.take_last(); m_name = parts.take_last();
main_thread().set_name(m_name);
// ss0 sp!!!!!!!!! // ss0 sp!!!!!!!!!
u32 old_esp0 = main_thread().m_tss.esp0; u32 old_esp0 = main_thread().m_tss.esp0;
@ -2882,6 +2883,14 @@ int Process::sys$create_thread(void* (*entry)(void*), void* argument, const Sysc
auto* thread = new Thread(*this); auto* thread = new Thread(*this);
// We know this thread is not the main_thread,
// So give it a unique name until the user calls $set_thread_name on it
// length + 4 to give space for our extra junk at the end
StringBuilder builder(m_name.length() + 4);
builder.append(m_name);
builder.appendf("[%d]", thread->tid());
thread->set_name(builder.to_string());
thread->set_priority(requested_thread_priority); thread->set_priority(requested_thread_priority);
thread->set_joinable(is_thread_joinable); thread->set_joinable(is_thread_joinable);
@ -2980,6 +2989,63 @@ int Process::sys$join_thread(int tid, void** exit_value)
return 0; return 0;
} }
int Process::sys$set_thread_name(int tid, const char* buffer, int buffer_size)
{
if (!validate_read(buffer, buffer_size))
return -EFAULT;
const size_t max_thread_name_size = 64;
if (strnlen(buffer, buffer_size) > max_thread_name_size)
return -EINVAL;
Thread* thread = nullptr;
for_each_thread([&](auto& child_thread) {
if (child_thread.tid() == tid) {
thread = &child_thread;
return IterationDecision::Break;
}
return IterationDecision::Continue;
});
if (!thread)
return -ESRCH;
// Forbid renaming the main thread of a process
// That guy should always be named after the process
if (thread == &current->process().main_thread())
return -EINVAL;
thread->set_name({buffer, buffer_size});
return 0;
}
int Process::sys$get_thread_name(int tid, char* buffer, int buffer_size)
{
if (buffer_size <= 0)
return -EINVAL;
if (!validate_write(buffer, buffer_size))
return -EFAULT;
Thread* thread = nullptr;
for_each_thread([&](auto& child_thread) {
if (child_thread.tid() == tid) {
thread = &child_thread;
return IterationDecision::Break;
}
return IterationDecision::Continue;
});
if (!thread)
return -ESRCH;
if (thread->name().length() >= buffer_size)
return -ENAMETOOLONG;
strncpy(buffer, thread->name().characters(), buffer_size);
return 0;
}
int Process::sys$gettid() int Process::sys$gettid()
{ {
return current->tid(); return current->tid();
@ -3241,7 +3307,7 @@ KBuffer Process::backtrace(ProcessInspectionHandle& handle) const
{ {
KBufferBuilder builder; KBufferBuilder builder;
for_each_thread([&](Thread& thread) { for_each_thread([&](Thread& thread) {
builder.appendf("Thread %d:\n", thread.tid()); builder.appendf("Thread %d (%s):\n", thread.tid(), thread.name().characters());
builder.append(thread.backtrace(handle)); builder.append(thread.backtrace(handle));
return IterationDecision::Continue; return IterationDecision::Continue;
}); });

View File

@ -205,6 +205,8 @@ public:
void sys$exit_thread(void*); void sys$exit_thread(void*);
int sys$join_thread(int tid, void** exit_value); int sys$join_thread(int tid, void** exit_value);
int sys$detach_thread(int tid); int sys$detach_thread(int tid);
int sys$set_thread_name(int tid, const char* buffer, int buffer_size);
int sys$get_thread_name(int tid, char* buffer, int buffer_size);
int sys$rename(const char* oldpath, const char* newpath); int sys$rename(const char* oldpath, const char* newpath);
int sys$systrace(pid_t); int sys$systrace(pid_t);
int sys$mknod(const char* pathname, mode_t, dev_t); int sys$mknod(const char* pathname, mode_t, dev_t);

View File

@ -142,7 +142,9 @@ typedef u32 socklen_t;
__ENUMERATE_SYSCALL(join_thread) \ __ENUMERATE_SYSCALL(join_thread) \
__ENUMERATE_SYSCALL(module_load) \ __ENUMERATE_SYSCALL(module_load) \
__ENUMERATE_SYSCALL(module_unload) \ __ENUMERATE_SYSCALL(module_unload) \
__ENUMERATE_SYSCALL(detach_thread) __ENUMERATE_SYSCALL(detach_thread) \
__ENUMERATE_SYSCALL(set_thread_name) \
__ENUMERATE_SYSCALL(get_thread_name)
namespace Syscall { namespace Syscall {

View File

@ -44,6 +44,7 @@ HashTable<Thread*>& thread_table()
Thread::Thread(Process& process) Thread::Thread(Process& process)
: m_process(process) : m_process(process)
, m_tid(process.m_next_tid++) , m_tid(process.m_next_tid++)
, m_name(process.name())
{ {
dbgprintf("Thread{%p}: New thread TID=%u in %s(%u)\n", this, m_tid, process.name().characters(), process.pid()); dbgprintf("Thread{%p}: New thread TID=%u in %s(%u)\n", this, m_tid, process.name().characters(), process.pid());
set_default_signal_dispositions(); set_default_signal_dispositions();

View File

@ -73,6 +73,9 @@ public:
String backtrace(ProcessInspectionHandle&) const; String backtrace(ProcessInspectionHandle&) const;
const String& name() const { return m_name; }
void set_name(StringView s) { m_name = s; }
void finalize(); void finalize();
enum State : u8 { enum State : u8 {
@ -463,6 +466,7 @@ private:
FPUState* m_fpu_state { nullptr }; FPUState* m_fpu_state { nullptr };
State m_state { Invalid }; State m_state { Invalid };
String m_name;
ThreadPriority m_priority { ThreadPriority::Normal }; ThreadPriority m_priority { ThreadPriority::Normal };
bool m_has_used_fpu { false }; bool m_has_used_fpu { false };
bool m_dump_backtrace_on_finalization { false }; bool m_dump_backtrace_on_finalization { false };