mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 23:47:45 +00:00
Kernel: Rework Process::Priority into ThreadPriority
Scheduling priority is now set at the thread level instead of at the process level. This is a step towards allowing processes to set different priorities for threads. There's no userspace API for that yet, since only the main thread's priority is affected by sched_setparam().
This commit is contained in:
parent
e33bbdb6ba
commit
083c5f8b89
7 changed files with 46 additions and 46 deletions
|
@ -688,7 +688,7 @@ Optional<KBuffer> procfs$all(InodeIdentifier)
|
||||||
process_object.add("amount_resident", (u32)process.amount_resident());
|
process_object.add("amount_resident", (u32)process.amount_resident());
|
||||||
process_object.add("amount_shared", (u32)process.amount_shared());
|
process_object.add("amount_shared", (u32)process.amount_shared());
|
||||||
process_object.add("ticks", process.main_thread().ticks());
|
process_object.add("ticks", process.main_thread().ticks());
|
||||||
process_object.add("priority", to_string(process.priority()));
|
process_object.add("priority", to_string(process.main_thread().priority()));
|
||||||
process_object.add("syscall_count", process.syscall_count());
|
process_object.add("syscall_count", process.syscall_count());
|
||||||
process_object.add("inode_faults", process.inode_faults());
|
process_object.add("inode_faults", process.inode_faults());
|
||||||
process_object.add("zero_faults", process.zero_faults());
|
process_object.add("zero_faults", process.zero_faults());
|
||||||
|
|
|
@ -2555,10 +2555,10 @@ int Process::sys$sched_setparam(pid_t pid, const struct sched_param* param)
|
||||||
if (!is_superuser() && m_euid != peer->m_uid && m_uid != peer->m_uid)
|
if (!is_superuser() && m_euid != peer->m_uid && m_uid != peer->m_uid)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
if (param->sched_priority < Process::FirstPriority || param->sched_priority > Process::LastPriority)
|
if (param->sched_priority < (int)ThreadPriority::First || param->sched_priority > (int)ThreadPriority::Last)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
peer->set_priority(Priority(param->sched_priority));
|
peer->main_thread().set_priority((ThreadPriority)param->sched_priority);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2578,7 +2578,7 @@ int Process::sys$sched_getparam(pid_t pid, struct sched_param* param)
|
||||||
if (!is_superuser() && m_euid != peer->m_uid && m_uid != peer->m_uid)
|
if (!is_superuser() && m_euid != peer->m_uid && m_uid != peer->m_uid)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
param->sched_priority = peer->priority();
|
param->sched_priority = (int)peer->main_thread().priority();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2755,23 +2755,6 @@ int Process::sys$get_shared_buffer_size(int shared_buffer_id)
|
||||||
return shared_buffer.size();
|
return shared_buffer.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* to_string(Process::Priority priority)
|
|
||||||
{
|
|
||||||
switch (priority) {
|
|
||||||
case Process::IdlePriority:
|
|
||||||
return "Idle";
|
|
||||||
case Process::LowPriority:
|
|
||||||
return "Low";
|
|
||||||
case Process::NormalPriority:
|
|
||||||
return "Normal";
|
|
||||||
case Process::HighPriority:
|
|
||||||
return "High";
|
|
||||||
}
|
|
||||||
kprintf("to_string(Process::Priority): Invalid priority: %u\n", priority);
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Process::terminate_due_to_signal(u8 signal)
|
void Process::terminate_due_to_signal(u8 signal)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
|
|
|
@ -44,15 +44,6 @@ public:
|
||||||
static Vector<pid_t> all_pids();
|
static Vector<pid_t> all_pids();
|
||||||
static Vector<Process*> all_processes();
|
static Vector<Process*> all_processes();
|
||||||
|
|
||||||
enum Priority : u8 {
|
|
||||||
IdlePriority,
|
|
||||||
FirstPriority = IdlePriority,
|
|
||||||
LowPriority,
|
|
||||||
NormalPriority,
|
|
||||||
HighPriority,
|
|
||||||
LastPriority = HighPriority,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum RingLevel : u8 {
|
enum RingLevel : u8 {
|
||||||
Ring0 = 0,
|
Ring0 = 0,
|
||||||
Ring3 = 3,
|
Ring3 = 3,
|
||||||
|
@ -75,9 +66,6 @@ public:
|
||||||
|
|
||||||
static Process* from_pid(pid_t);
|
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; }
|
const String& name() const { return m_name; }
|
||||||
pid_t pid() const { return m_pid; }
|
pid_t pid() const { return m_pid; }
|
||||||
pid_t sid() const { return m_sid; }
|
pid_t sid() const { return m_sid; }
|
||||||
|
@ -351,7 +339,6 @@ private:
|
||||||
Vector<FileDescriptionAndFlags> m_fds;
|
Vector<FileDescriptionAndFlags> m_fds;
|
||||||
|
|
||||||
RingLevel m_ring { Ring0 };
|
RingLevel m_ring { Ring0 };
|
||||||
Priority m_priority { NormalPriority };
|
|
||||||
u8 m_termination_status { 0 };
|
u8 m_termination_status { 0 };
|
||||||
u8 m_termination_signal { 0 };
|
u8 m_termination_signal { 0 };
|
||||||
|
|
||||||
|
@ -429,7 +416,7 @@ private:
|
||||||
Process& m_process;
|
Process& m_process;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const char* to_string(Process::Priority);
|
const char* to_string(ThreadPriority);
|
||||||
|
|
||||||
extern InlineLinkedList<Process>* g_processes;
|
extern InlineLinkedList<Process>* g_processes;
|
||||||
|
|
||||||
|
|
|
@ -27,17 +27,17 @@ void Scheduler::update_state_for_thread(Thread& thread)
|
||||||
//#define SCHEDULER_DEBUG
|
//#define SCHEDULER_DEBUG
|
||||||
//#define SCHEDULER_RUNNABLE_DEBUG
|
//#define SCHEDULER_RUNNABLE_DEBUG
|
||||||
|
|
||||||
static u32 time_slice_for(Process::Priority priority)
|
static u32 time_slice_for(ThreadPriority priority)
|
||||||
{
|
{
|
||||||
// One time slice unit == 1ms
|
// One time slice unit == 1ms
|
||||||
switch (priority) {
|
switch (priority) {
|
||||||
case Process::HighPriority:
|
case ThreadPriority::High:
|
||||||
return 50;
|
return 50;
|
||||||
case Process::NormalPriority:
|
case ThreadPriority::Normal:
|
||||||
return 15;
|
return 15;
|
||||||
case Process::LowPriority:
|
case ThreadPriority::Low:
|
||||||
return 5;
|
return 5;
|
||||||
case Process::IdlePriority:
|
case ThreadPriority::Idle:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
@ -387,7 +387,7 @@ bool Scheduler::donate_to(Thread* beneficiary, const char* reason)
|
||||||
if (!beneficiary || beneficiary->state() != Thread::Runnable || ticks_left <= 1)
|
if (!beneficiary || beneficiary->state() != Thread::Runnable || ticks_left <= 1)
|
||||||
return yield();
|
return yield();
|
||||||
|
|
||||||
unsigned ticks_to_donate = min(ticks_left - 1, time_slice_for(beneficiary->process().priority()));
|
unsigned ticks_to_donate = min(ticks_left - 1, time_slice_for(beneficiary->priority()));
|
||||||
#ifdef SCHEDULER_DEBUG
|
#ifdef SCHEDULER_DEBUG
|
||||||
dbgprintf("%s(%u:%u) donating %u ticks to %s(%u:%u), reason=%s\n", current->process().name().characters(), current->pid(), current->tid(), ticks_to_donate, beneficiary->process().name().characters(), beneficiary->pid(), beneficiary->tid(), reason);
|
dbgprintf("%s(%u:%u) donating %u ticks to %s(%u:%u), reason=%s\n", current->process().name().characters(), current->pid(), current->tid(), ticks_to_donate, beneficiary->process().name().characters(), beneficiary->pid(), beneficiary->tid(), reason);
|
||||||
#endif
|
#endif
|
||||||
|
@ -429,7 +429,7 @@ void Scheduler::switch_now()
|
||||||
|
|
||||||
bool Scheduler::context_switch(Thread& thread)
|
bool Scheduler::context_switch(Thread& thread)
|
||||||
{
|
{
|
||||||
thread.set_ticks_left(time_slice_for(thread.process().priority()));
|
thread.set_ticks_left(time_slice_for(thread.priority()));
|
||||||
thread.did_schedule();
|
thread.did_schedule();
|
||||||
|
|
||||||
if (current == &thread)
|
if (current == &thread)
|
||||||
|
@ -521,7 +521,7 @@ void Scheduler::initialize()
|
||||||
initialize_redirection();
|
initialize_redirection();
|
||||||
s_colonel_process = Process::create_kernel_process("colonel", nullptr);
|
s_colonel_process = Process::create_kernel_process("colonel", nullptr);
|
||||||
// Make sure the colonel uses a smallish time slice.
|
// Make sure the colonel uses a smallish time slice.
|
||||||
s_colonel_process->set_priority(Process::IdlePriority);
|
s_colonel_process->main_thread().set_priority(ThreadPriority::Idle);
|
||||||
load_task_register(s_redirection.selector);
|
load_task_register(s_redirection.selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -670,3 +670,20 @@ const LogStream& operator<<(const LogStream& stream, const Thread& value)
|
||||||
{
|
{
|
||||||
return stream << value.process().name() << "(" << value.pid() << ":" << value.tid() << ")";
|
return stream << value.process().name() << "(" << value.pid() << ":" << value.tid() << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* to_string(ThreadPriority priority)
|
||||||
|
{
|
||||||
|
switch (priority) {
|
||||||
|
case ThreadPriority::Idle:
|
||||||
|
return "Idle";
|
||||||
|
case ThreadPriority::Low:
|
||||||
|
return "Low";
|
||||||
|
case ThreadPriority::Normal:
|
||||||
|
return "Normal";
|
||||||
|
case ThreadPriority::High:
|
||||||
|
return "High";
|
||||||
|
}
|
||||||
|
dbg() << "to_string(ThreadPriority): Invalid priority: " << (u32)priority;
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
|
@ -34,6 +34,15 @@ struct ThreadSpecificData {
|
||||||
ThreadSpecificData* self;
|
ThreadSpecificData* self;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ThreadPriority : u8 {
|
||||||
|
Idle,
|
||||||
|
Low,
|
||||||
|
Normal,
|
||||||
|
High,
|
||||||
|
First = Idle,
|
||||||
|
Last = High,
|
||||||
|
};
|
||||||
|
|
||||||
class Thread {
|
class Thread {
|
||||||
friend class Process;
|
friend class Process;
|
||||||
friend class Scheduler;
|
friend class Scheduler;
|
||||||
|
@ -51,6 +60,9 @@ public:
|
||||||
int tid() const { return m_tid; }
|
int tid() const { return m_tid; }
|
||||||
int pid() const;
|
int pid() const;
|
||||||
|
|
||||||
|
void set_priority(ThreadPriority p) { m_priority = p; }
|
||||||
|
ThreadPriority priority() const { return m_priority; }
|
||||||
|
|
||||||
Process& process() { return m_process; }
|
Process& process() { return m_process; }
|
||||||
const Process& process() const { return m_process; }
|
const Process& process() const { return m_process; }
|
||||||
|
|
||||||
|
@ -341,6 +353,7 @@ private:
|
||||||
Blocker* m_blocker { nullptr };
|
Blocker* m_blocker { nullptr };
|
||||||
FPUState* m_fpu_state { nullptr };
|
FPUState* m_fpu_state { nullptr };
|
||||||
State m_state { Invalid };
|
State m_state { Invalid };
|
||||||
|
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 };
|
||||||
|
|
||||||
|
|
|
@ -170,7 +170,7 @@ VFS* vfs;
|
||||||
kprintf("init_stage2: error spawning Shell: %d\n", error);
|
kprintf("init_stage2: error spawning Shell: %d\n", error);
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
shell_process->set_priority(Process::HighPriority);
|
shell_process->main_thread().set_priority(ThreadPriority::High);
|
||||||
} else {
|
} else {
|
||||||
tty0->set_graphical(true);
|
tty0->set_graphical(true);
|
||||||
auto* system_server_process = Process::create_user_process("/bin/SystemServer", (uid_t)0, (gid_t)0, (pid_t)0, error, {}, {}, tty0);
|
auto* system_server_process = Process::create_user_process("/bin/SystemServer", (uid_t)0, (gid_t)0, (pid_t)0, error, {}, {}, tty0);
|
||||||
|
@ -178,7 +178,7 @@ VFS* vfs;
|
||||||
kprintf("init_stage2: error spawning SystemServer: %d\n", error);
|
kprintf("init_stage2: error spawning SystemServer: %d\n", error);
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
system_server_process->set_priority(Process::HighPriority);
|
system_server_process->main_thread().set_priority(ThreadPriority::High);
|
||||||
}
|
}
|
||||||
Process::create_kernel_process("NetworkTask", NetworkTask_main);
|
Process::create_kernel_process("NetworkTask", NetworkTask_main);
|
||||||
|
|
||||||
|
@ -313,7 +313,7 @@ extern "C" [[noreturn]] void init()
|
||||||
});
|
});
|
||||||
Process::create_kernel_process("Finalizer", [] {
|
Process::create_kernel_process("Finalizer", [] {
|
||||||
g_finalizer = current;
|
g_finalizer = current;
|
||||||
current->process().set_priority(Process::LowPriority);
|
current->set_priority(ThreadPriority::Low);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Thread::finalize_dying_threads();
|
Thread::finalize_dying_threads();
|
||||||
(void)current->block<Thread::SemiPermanentBlocker>(Thread::SemiPermanentBlocker::Reason::Lurking);
|
(void)current->block<Thread::SemiPermanentBlocker>(Thread::SemiPermanentBlocker::Reason::Lurking);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue