From 610f3ad12fc023dee0e71bead17cf6ebd4eba09a Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 30 Dec 2019 19:23:13 +0100 Subject: [PATCH] Kernel: Add a basic thread boosting mechanism This patch introduces a syscall: int set_thread_boost(int tid, int amount) You can use this to add a permanent boost value to the effective thread priority of any thread with your UID (or any thread in the system if you are the superuser.) This is quite crude, but opens up some interesting opportunities. :^) --- Kernel/Process.cpp | 16 ++++++++++++++++ Kernel/Process.h | 1 + Kernel/Syscall.h | 3 ++- Kernel/Thread.cpp | 12 ++++++++++++ Kernel/Thread.h | 7 ++++++- Libraries/LibC/serenity.cpp | 7 +++++++ Libraries/LibC/serenity.h | 2 ++ 7 files changed, 46 insertions(+), 2 deletions(-) diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 0248557d02d..7196f44e3f6 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -3906,3 +3906,19 @@ int Process::sys$futex(const Syscall::SC_futex_params* params) return 0; } + +int Process::sys$set_thread_boost(int tid, int amount) +{ + if (amount < 0 || amount > 20) + return -EINVAL; + InterruptDisabler disabler; + auto* thread = Thread::from_tid(tid); + if (!thread) + return -ESRCH; + if (thread->state() == Thread::State::Dead || thread->state() == Thread::State::Dying) + return -ESRCH; + if (!is_superuser() && thread->process().uid() != euid()) + return -EPERM; + thread->set_priority_boost(amount); + return 0; +} diff --git a/Kernel/Process.h b/Kernel/Process.h index df904b5f256..5694f59b039 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -234,6 +234,7 @@ public: int sys$profiling_disable(pid_t); void* sys$get_kernel_info_page(); int sys$futex(const Syscall::SC_futex_params*); + int sys$set_thread_boost(int tid, int amount); static void initialize(); diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 3b5df184c48..7a595b7c81c 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -151,7 +151,8 @@ typedef u32 socklen_t; __ENUMERATE_SYSCALL(profiling_enable) \ __ENUMERATE_SYSCALL(profiling_disable) \ __ENUMERATE_SYSCALL(get_kernel_info_page) \ - __ENUMERATE_SYSCALL(futex) + __ENUMERATE_SYSCALL(futex) \ + __ENUMERATE_SYSCALL(set_thread_boost) namespace Syscall { diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index 92078cae45f..c5a9f638d0a 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -786,3 +786,15 @@ void Thread::wake_from_queue() ASSERT(state() == State::Queued); set_state(State::Runnable); } + +Thread* Thread::from_tid(int tid) +{ + ASSERT_INTERRUPTS_DISABLED(); + Thread* found_thread = nullptr; + Thread::for_each([&](auto& thread) { + if (thread.tid() == tid) + found_thread = &thread; + return IterationDecision::Continue; + }); + return found_thread; +} diff --git a/Kernel/Thread.h b/Kernel/Thread.h index 63e6941e813..681401909d8 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -49,6 +49,7 @@ public: explicit Thread(Process&); ~Thread(); + static Thread* from_tid(int); static void initialize(); static void finalize_dying_threads(); @@ -61,7 +62,10 @@ public: void set_priority(u32 p) { m_priority = p; } u32 priority() const { return m_priority; } - u32 effective_priority() const { return m_priority + m_extra_priority; } + void set_priority_boost(u32 boost) { m_priority_boost = boost; } + u32 priority_boost() const { return m_priority_boost; } + + u32 effective_priority() const { return m_priority + m_priority_boost + m_extra_priority; } void set_joinable(bool j) { m_is_joinable = j; } bool is_joinable() const { return m_is_joinable; } @@ -452,6 +456,7 @@ private: String m_name; u32 m_priority { THREAD_PRIORITY_NORMAL }; u32 m_extra_priority { 0 }; + u32 m_priority_boost { 0 }; bool m_has_used_fpu { false }; bool m_dump_backtrace_on_finalization { false }; bool m_should_die { false }; diff --git a/Libraries/LibC/serenity.cpp b/Libraries/LibC/serenity.cpp index 59564ecfdbc..379036f9199 100644 --- a/Libraries/LibC/serenity.cpp +++ b/Libraries/LibC/serenity.cpp @@ -28,6 +28,13 @@ int profiling_disable(pid_t pid) __RETURN_WITH_ERRNO(rc, rc, -1); } +int set_thread_boost(int tid, int amount) +{ + int rc = syscall(SC_set_thread_boost, tid, amount); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + + int futex(int32_t* userspace_address, int futex_op, int32_t value, const struct timespec* timeout) { Syscall::SC_futex_params params { userspace_address, futex_op, value, timeout }; diff --git a/Libraries/LibC/serenity.h b/Libraries/LibC/serenity.h index 08dbe96a8ef..fbc27507870 100644 --- a/Libraries/LibC/serenity.h +++ b/Libraries/LibC/serenity.h @@ -50,6 +50,8 @@ int profiling_disable(pid_t); #define THREAD_PRIORITY_HIGH 50 #define THREAD_PRIORITY_MAX 99 +int set_thread_boost(int tid, int amount); + #define FUTEX_WAIT 1 #define FUTEX_WAKE 2