Files
jsix/src/kernel/scheduler.h
Justin C. Miller 5787aff866 [fb] Create fb driver
Create a new framebuffer driver. Also hackily passing frame buffer size
in the list of init handles to all processes and mapping the framebuffer
into all processes. Changed bootloader passing frame buffer as a module
to its own struct.
2020-12-27 18:49:38 -08:00

112 lines
3.0 KiB
C++

#pragma once
/// \file scheduler.h
/// The task scheduler and related definitions
#include <stdint.h>
#include "objects/thread.h"
class lapic;
class process;
struct page_table;
struct cpu_state;
extern "C" void isr_handler(cpu_state*);
extern "C" void task_switch(TCB *next);
/// The task scheduler
class scheduler
{
public:
/// Total number of priority levels
static const uint8_t num_priorities = 8;
/// Maximum (least urgent/interactive) priority
static const uint8_t max_priority = num_priorities - 1;
/// Default priority on process creation
static const uint8_t default_priority = 1;
/// Lowest (most urgent) priority achieved via promotion
static const uint8_t promote_limit = 1;
/// How long the base timer quantum is, in us
static const uint64_t quantum_micros = 500;
/// How many quanta a process gets before being rescheduled
static const uint16_t process_quanta = 10;
/// Constructor.
/// \arg apic Pointer to the local APIC object
scheduler(lapic *apic);
/// Create a new process from a program image in memory.
/// \arg phys Physical address of the loaded program image
/// \arg virt Virtual address of the loaded program image
/// \arg size Size of the program image, in bytes
/// \arg entry Virtual address of the program entrypoint
/// \returns The main thread of the loaded process
thread * load_process(uintptr_t phys, uintptr_t virt, size_t size, uintptr_t entry);
/// Create a new kernel task
/// \arg proc Function to run as a kernel task
/// \arg priority Priority to start the process with
/// \arg constant True if this task cannot be promoted/demoted
void create_kernel_task(
void (*task)(),
uint8_t priority,
bool constant = false);
/// 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.
void start();
/// Run the scheduler, possibly switching to a new task
void schedule();
/// Get the current TCB.
/// \returns A pointer to the current thread's TCB
inline TCB * current() { return m_current; }
inline void add_thread(TCB *t) { m_blocked.push_back(static_cast<tcb_node*>(t)); }
/// Get a reference to the system scheduler
/// \returns A reference to the global system scheduler
static scheduler & get() { return *s_instance; }
private:
friend uintptr_t syscall_dispatch(uintptr_t, cpu_state &);
friend class process;
static constexpr uint64_t promote_frequency = 10;
/// Create a new process object. This process will have its pid
/// set but nothing else.
/// \arg user True if this thread will enter userspace
/// \returns The new process' main thread
thread * create_process(bool user);
void prune(uint64_t now);
void check_promotions(uint64_t now);
lapic *m_apic;
uint32_t m_next_pid;
uint32_t m_tick_count;
process *m_kernel_process;
tcb_node *m_current;
tcb_list m_runlists[num_priorities];
tcb_list m_blocked;
// TODO: lol a real clock
uint64_t m_clock = 0;
uint64_t m_last_promotion;
static scheduler *s_instance;
};