[kernel] Change to one-shot timer scheduler

Instead of many timer interrupts and decrementing a process' remaining
quanta, change to setting a single timer for when a process should be
preempted. If it uses its whole timeslice, demote it. If it uses less
than half before blocking, promote it. Determine timeslice based on
priority as well.

This change also required changing the apic timer interface to be purely
interval (in microseconds) based instead of its previous interval/tick
hybrid.
This commit is contained in:
Justin C. Miller
2020-06-03 20:56:59 -07:00
parent ea1224e213
commit a10aca573d
7 changed files with 125 additions and 77 deletions

View File

@@ -19,10 +19,11 @@ class scheduler
{
public:
static const uint8_t num_priorities = 8;
static const uint8_t max_priority = num_priorities - 1;
static const uint8_t default_priority = num_priorities / 2;
/// How long the timer quantum is
static const uint64_t quantum_micros = 1000;
/// How long the base timer quantum is, in us
static const uint64_t quantum_micros = 5000;
/// How many quanta a process gets before being rescheduled
static const uint16_t process_quanta = 10;
@@ -38,9 +39,18 @@ public:
void load_process(const char *name, const void *data, size_t size);
/// Create a new kernel task
/// \arg pid Pid to use for this task, must be negative
/// \arg proc Function to run as a kernel task
void create_kernel_task(pid_t pid, void (*task)());
/// \arg pid Pid to use for this task, must be negative
/// \arg proc Function to run as a kernel task
/// \arg priority Priority to start the process with
/// \arg flags Flags to add to the process
void create_kernel_task(
pid_t pid,
void (*task)(),
uint8_t priority,
process_flags flags = process_flags::none);
/// Get the quantum for a given priority.
uint32_t quantum(int priority);
/// Start the scheduler working. This may involve starting
/// timer interrupts or other preemption methods.
@@ -64,7 +74,6 @@ public:
private:
friend uintptr_t syscall_dispatch(uintptr_t, cpu_state &);
friend void isr_handler(cpu_state*);
friend class process;
/// Create a new process object. This process will have its pid
@@ -73,9 +82,6 @@ private:
/// \returns The new process object
process_node * create_process(pid_t pid = 0);
/// Handle a timer tick
void tick();
void prune(uint64_t now);
lapic *m_apic;