From 71b9ec1ae00db9206506dca95930db24c989d530 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 7 Feb 2019 12:21:17 +0100 Subject: [PATCH] Kernel: Add basic process priority support. For now, the WindowServer process will run with high priority, while the Finalizer process will run with low priority. Everyone else gets to be "normal". At the moment, priority simply determines the size of your time slices. --- Kernel/ProcFS.cpp | 5 +++-- Kernel/Process.h | 21 +++++++++++++++++++++ Kernel/Scheduler.cpp | 15 +++++++++++++-- Kernel/init.cpp | 1 + Userland/top.cpp | 10 +++++++--- WindowServer/main.cpp | 1 + 6 files changed, 46 insertions(+), 7 deletions(-) diff --git a/Kernel/ProcFS.cpp b/Kernel/ProcFS.cpp index 117caaff6b..3caf1eb6b9 100644 --- a/Kernel/ProcFS.cpp +++ b/Kernel/ProcFS.cpp @@ -496,7 +496,7 @@ ByteBuffer procfs$all(InodeIdentifier) auto processes = Process::all_processes(); StringBuilder builder; auto build_process_line = [&builder] (Process* process) { - builder.appendf("%u,%u,%u,%u,%u,%u,%u,%s,%u,%u,%s,%s,%u,%u,%u,%u,%u\n", + builder.appendf("%u,%u,%u,%u,%u,%u,%u,%s,%u,%u,%s,%s,%u,%u,%u,%u,%u,%s\n", process->pid(), process->times_scheduled(), process->tty() ? process->tty()->pgid() : 0, @@ -513,7 +513,8 @@ ByteBuffer procfs$all(InodeIdentifier) process->amount_resident(), process->amount_shared(), process->amount_in_bitmaps(), - process->ticks() + process->ticks(), + to_string(process->priority()) ); }; build_process_line(Scheduler::colonel()); diff --git a/Kernel/Process.h b/Kernel/Process.h index 2b0806626c..a61e5a1dbd 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -80,6 +80,12 @@ public: BlockedSelect, }; + enum Priority { + LowPriority, + NormalPriority, + HighPriority, + }; + enum RingLevel { Ring0 = 0, Ring3 = 3, @@ -100,6 +106,9 @@ public: static Process* from_pid(pid_t); + void set_priority(Priority p) { m_priority = p; } + Priority priority() const { return m_priority; } + const String& name() const { return m_name; } pid_t pid() const { return m_pid; } pid_t sid() const { return m_sid; } @@ -328,6 +337,7 @@ private: dword m_stack_top3 { 0 }; FarPtr m_far_ptr; State m_state { Invalid }; + Priority m_priority { NormalPriority }; dword m_wakeup_time { 0 }; TSS32 m_tss; TSS32 m_tss_to_resume_kernel; @@ -464,6 +474,17 @@ static inline const char* to_string(Process::State state) return nullptr; } +static inline const char* to_string(Process::Priority state) +{ + switch (state) { + case Process::LowPriority: return "Low"; + case Process::NormalPriority: return "Normal"; + case Process::HighPriority: return "High"; + } + ASSERT_NOT_REACHED(); + return nullptr; +} + extern void block(Process::State); extern void sleep(dword ticks); diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index f573fe3f95..deb665c265 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -8,7 +8,18 @@ //#define LOG_EVERY_CONTEXT_SWITCH //#define SCHEDULER_DEBUG -static const dword time_slice = 20; // *1ms +static dword time_slice_for(Process::Priority priority) +{ + // One time slice unit == 1ms + switch (priority) { + case Process::LowPriority: + return 5; + case Process::NormalPriority: + return 15; + case Process::HighPriority: + return 50; + } +} Process* current; Process* g_last_fpu_process; @@ -244,7 +255,7 @@ void Scheduler::switch_now() bool Scheduler::context_switch(Process& process) { - process.set_ticks_left(time_slice); + process.set_ticks_left(time_slice_for(process.priority())); process.did_schedule(); if (current == &process) diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 0417434a63..492e90420c 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -187,6 +187,7 @@ void init() }); Process::create_kernel_process("Finalizer", [] { g_finalizer = current; + current->set_priority(Process::LowPriority); for (;;) { Process::finalize_dying_processes(); current->block(Process::BlockedLurking); diff --git a/Userland/top.cpp b/Userland/top.cpp index cc5c79e9c4..5718addf4f 100644 --- a/Userland/top.cpp +++ b/Userland/top.cpp @@ -15,6 +15,7 @@ struct Process { String name; String state; String user; + String priority; unsigned linear; unsigned committed; unsigned in_bitmaps; @@ -43,7 +44,7 @@ static Snapshot get_snapshot() if (!ptr) break; auto parts = String(buf, Chomp).split(','); - if (parts.size() < 17) + if (parts.size() < 18) break; bool ok; pid_t pid = parts[0].to_uint(ok); @@ -57,6 +58,7 @@ static Snapshot get_snapshot() unsigned uid = parts[5].to_uint(ok); ASSERT(ok); process.user = s_usernames->get(uid); + process.priority = parts[17]; process.state = parts[7]; process.name = parts[11]; process.linear = parts[12].to_uint(ok); @@ -88,8 +90,9 @@ int main(int, char**) auto sum_diff = current.sum_nsched - prev.sum_nsched; printf("\033[3J\033[H\033[2J"); - printf("\033[47;30m%6s % 8s %8s %6s %6s %6s %4s %s\033[K\033[0m\n", + printf("\033[47;30m%6s %3s % 8s % 8s %6s %6s %6s %4s %s\033[K\033[0m\n", "PID", + "PRI", "USER", "STATE", "LINEAR", @@ -120,8 +123,9 @@ int main(int, char**) }); for (auto* process : processes) { - printf("%6d % 8s %8s %6u %6u %6u %2u.%1u %s\n", + printf("%6d %c % 8s % 8s %6u %6u %6u %2u.%1u %s\n", process->pid, + process->priority[0], process->user.characters(), process->state.characters(), process->linear / 1024, diff --git a/WindowServer/main.cpp b/WindowServer/main.cpp index 23d1090445..4decc24038 100644 --- a/WindowServer/main.cpp +++ b/WindowServer/main.cpp @@ -10,6 +10,7 @@ void WindowServer_main() { + current->set_priority(Process::HighPriority); auto info = current->set_video_resolution(1024, 768); dbgprintf("Screen is %ux%ux%ubpp\n", info.width, info.height, info.bpp);