summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndrew Kaster <andrewdkaster@gmail.com>2019-12-07 12:45:26 -0700
committerAndreas Kling <awesomekling@gmail.com>2019-12-08 14:09:29 +0100
commit9058962712201336ec5e20638137d3828951950e (patch)
tree7cdd32c7d2e6c62fc9273fc6ac394eb1695b463e /Kernel
parent875ab0cf107894cf7311ea6d779cdae980e88627 (diff)
downloadserenity-9058962712201336ec5e20638137d3828951950e.zip
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.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/FileSystem/ProcFS.cpp1
-rw-r--r--Kernel/Process.cpp68
-rw-r--r--Kernel/Process.h2
-rw-r--r--Kernel/Syscall.h4
-rw-r--r--Kernel/Thread.cpp1
-rw-r--r--Kernel/Thread.h4
6 files changed, 78 insertions, 2 deletions
diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp
index 2d8ac68288..768e8beade 100644
--- a/Kernel/FileSystem/ProcFS.cpp
+++ b/Kernel/FileSystem/ProcFS.cpp
@@ -721,6 +721,7 @@ Optional<KBuffer> procfs$all(InodeIdentifier)
process.for_each_thread([&](const Thread& thread) {
auto thread_object = thread_array.add_object();
thread_object.add("tid", thread.tid());
+ thread_object.add("name", thread.name());
thread_object.add("times_scheduled", thread.times_scheduled());
thread_object.add("ticks", thread.ticks());
thread_object.add("state", thread.state_string());
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index be12cef937..0fb8073832 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -542,6 +542,7 @@ int Process::do_exec(String path, Vector<String> arguments, Vector<String> envir
Scheduler::prepare_to_modify_tss(main_thread());
m_name = parts.take_last();
+ main_thread().set_name(m_name);
// ss0 sp!!!!!!!!!
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);
+ // 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_joinable(is_thread_joinable);
@@ -2980,6 +2989,63 @@ int Process::sys$join_thread(int tid, void** exit_value)
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()
{
return current->tid();
@@ -3241,7 +3307,7 @@ KBuffer Process::backtrace(ProcessInspectionHandle& handle) const
{
KBufferBuilder builder;
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));
return IterationDecision::Continue;
});
diff --git a/Kernel/Process.h b/Kernel/Process.h
index bfa31ee58d..ee1c935c28 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -205,6 +205,8 @@ public:
void sys$exit_thread(void*);
int sys$join_thread(int tid, void** exit_value);
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$systrace(pid_t);
int sys$mknod(const char* pathname, mode_t, dev_t);
diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h
index dcafa120e2..aa70ab1699 100644
--- a/Kernel/Syscall.h
+++ b/Kernel/Syscall.h
@@ -142,7 +142,9 @@ typedef u32 socklen_t;
__ENUMERATE_SYSCALL(join_thread) \
__ENUMERATE_SYSCALL(module_load) \
__ENUMERATE_SYSCALL(module_unload) \
- __ENUMERATE_SYSCALL(detach_thread)
+ __ENUMERATE_SYSCALL(detach_thread) \
+ __ENUMERATE_SYSCALL(set_thread_name) \
+ __ENUMERATE_SYSCALL(get_thread_name)
namespace Syscall {
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp
index bdef8c15f4..dbf30bb9eb 100644
--- a/Kernel/Thread.cpp
+++ b/Kernel/Thread.cpp
@@ -44,6 +44,7 @@ HashTable<Thread*>& thread_table()
Thread::Thread(Process& process)
: m_process(process)
, 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());
set_default_signal_dispositions();
diff --git a/Kernel/Thread.h b/Kernel/Thread.h
index a682a56c4b..afc7de0c0f 100644
--- a/Kernel/Thread.h
+++ b/Kernel/Thread.h
@@ -73,6 +73,9 @@ public:
String backtrace(ProcessInspectionHandle&) const;
+ const String& name() const { return m_name; }
+ void set_name(StringView s) { m_name = s; }
+
void finalize();
enum State : u8 {
@@ -463,6 +466,7 @@ private:
FPUState* m_fpu_state { nullptr };
State m_state { Invalid };
+ String m_name;
ThreadPriority m_priority { ThreadPriority::Normal };
bool m_has_used_fpu { false };
bool m_dump_backtrace_on_finalization { false };