mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-09 12:31:06 -04:00
Implement some kind of Round Robin Priority Scheduling
This commit is contained in:
parent
01ca17a9f8
commit
2ebc0e22ac
@ -10,6 +10,7 @@
|
||||
|
||||
void __thor_assert(bool condition);
|
||||
void __thor_assert(bool condition, const char* message);
|
||||
void __thor_unreachable(const char* message);
|
||||
|
||||
#ifdef NASSERT
|
||||
inline void thor_assert(bool){}
|
||||
@ -24,4 +25,9 @@ inline void thor_assert(bool condition, const char* message){
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void thor_unreachable(const char* message){
|
||||
__thor_unreachable(message);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -16,9 +16,10 @@
|
||||
|
||||
namespace scheduler {
|
||||
|
||||
constexpr const size_t MAX_PRIORITY = 2;
|
||||
constexpr const size_t MAX_PRIORITY = 3;
|
||||
constexpr const size_t MIN_PRIORITY = 0;
|
||||
constexpr const size_t PRIORITY_LEVELS = MAX_PRIORITY - MIN_PRIORITY + 1;
|
||||
constexpr const size_t DEFAULT_PRIORITY = 2;
|
||||
|
||||
typedef size_t pid_t;
|
||||
|
||||
@ -37,6 +38,7 @@ struct segment_t {
|
||||
|
||||
struct process_t {
|
||||
pid_t pid;
|
||||
size_t priority;
|
||||
|
||||
bool system;
|
||||
|
||||
|
@ -8,9 +8,11 @@
|
||||
#ifndef ARRAY_H
|
||||
#define ARRAY_H
|
||||
|
||||
#include "stl/types.hpp"
|
||||
|
||||
namespace std {
|
||||
|
||||
template<typename T, uint64_t N>
|
||||
template<typename T, size_t N>
|
||||
class array {
|
||||
private:
|
||||
T data[N];
|
||||
@ -19,7 +21,7 @@ public:
|
||||
typedef T value_type;
|
||||
typedef value_type* iterator;
|
||||
typedef const value_type* const_iterator;
|
||||
typedef uint64_t size_type;
|
||||
typedef size_t size_type;
|
||||
|
||||
T& operator[](size_type pos){
|
||||
return data[pos];
|
||||
@ -57,11 +59,11 @@ public:
|
||||
typedef value_type* pointer_type;
|
||||
typedef value_type* iterator;
|
||||
typedef const value_type* const_iterator;
|
||||
typedef uint64_t size_type;
|
||||
typedef size_t size_type;
|
||||
|
||||
private:
|
||||
T* array;
|
||||
uint64_t _size;
|
||||
size_t _size;
|
||||
|
||||
public:
|
||||
unique_heap_array() : array(nullptr), _size(0) {}
|
||||
|
@ -19,3 +19,8 @@ void __thor_assert(bool condition, const char* message){
|
||||
suspend_kernel();
|
||||
}
|
||||
}
|
||||
|
||||
void __thor_unreachable(const char* message){
|
||||
k_print_line(message);
|
||||
suspend_kernel();
|
||||
}
|
||||
|
@ -5,6 +5,9 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#include "stl/array.hpp"
|
||||
#include "stl/vector.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
#include "paging.hpp"
|
||||
#include "assert.hpp"
|
||||
@ -12,8 +15,6 @@
|
||||
|
||||
#include "console.hpp"
|
||||
|
||||
#include "stl/array.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
struct process_control_t {
|
||||
@ -22,8 +23,12 @@ struct process_control_t {
|
||||
size_t rounds;
|
||||
};
|
||||
|
||||
//The Process Control Block
|
||||
std::array<process_control_t, scheduler::MAX_PROCESS> pcb;
|
||||
|
||||
//Define one run queue for each priority level
|
||||
std::array<std::vector<scheduler::pid_t>, scheduler::PRIORITY_LEVELS> run_queues;
|
||||
|
||||
bool started = false;
|
||||
|
||||
constexpr const size_t TURNOVER = 10;
|
||||
@ -44,6 +49,8 @@ char idle_kernel_stack[scheduler::kernel_stack_size];
|
||||
void create_idle_task(){
|
||||
auto& idle_process = scheduler::new_process();
|
||||
|
||||
idle_process.priority = scheduler::MIN_PRIORITY;
|
||||
|
||||
idle_process.system = true;
|
||||
idle_process.physical_cr3 = paging::get_physical_pml4t();
|
||||
idle_process.paging_size = 0;
|
||||
@ -95,28 +102,54 @@ void switch_to_process(const interrupt::syscall_regs& regs, size_t pid){
|
||||
*(stack_pointer - 14) = process.process.regs.ds;
|
||||
|
||||
asm volatile("mov cr3, %0" : : "r" (process.process.physical_cr3) : "memory");
|
||||
|
||||
/*asm volatile("mov rax, %0; mov ds, ax; mov es, ax; mov fs, ax; mov gs, ax;"
|
||||
: //No outputs
|
||||
: "r" (process.data_selector)
|
||||
: "rax");
|
||||
|
||||
asm volatile("mov cr3, %0" : : "r" (process.physical_cr3) : "memory");
|
||||
|
||||
asm volatile("push %0; push %1; pushfq; pop rax; or rax, 0x200; push rax; push %2; push %3; iretq"
|
||||
: //No outputs
|
||||
: "r" (process.data_selector), "r" (process.user_rsp), "r" (process.code_selector), "r" (process.rip)
|
||||
: "rax", "memory");*/
|
||||
}
|
||||
|
||||
size_t select_next_process(){
|
||||
auto next = (current_pid+ 1) % pcb.size();
|
||||
auto current_priority = pcb[current_pid].process.priority;
|
||||
|
||||
while(pcb[next].state != scheduler::process_state::READY){
|
||||
next = (next + 1) % pcb.size();
|
||||
//1. Run a process of higher priority, if any
|
||||
for(size_t p = scheduler::MAX_PRIORITY; p > current_priority; --p){
|
||||
for(auto pid : run_queues[p]){
|
||||
if(pcb[pid].state == scheduler::process_state::READY){
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next;
|
||||
//2. Run the next process of the same priority
|
||||
|
||||
auto& current_run_queue = run_queues[current_priority];
|
||||
|
||||
size_t next_index = 0;
|
||||
for(size_t i = 0; i < current_run_queue.size(); ++i){
|
||||
if(current_run_queue[i] == current_pid){
|
||||
next_index = (i + 1) % current_run_queue.size();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < current_run_queue.size(); ++i){
|
||||
auto index = (next_index + i) % current_run_queue.size();
|
||||
auto pid = current_run_queue[index];
|
||||
|
||||
if(pcb[pid].state == scheduler::process_state::READY){
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
|
||||
thor_assert(current_priority > 0, "The idle task should always be ready");
|
||||
|
||||
//3. Run a process of lower priority
|
||||
|
||||
for(size_t p = current_priority - 1; p >= scheduler::MIN_PRIORITY; --p){
|
||||
for(auto pid : run_queues[p]){
|
||||
if(pcb[pid].state == scheduler::process_state::READY){
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thor_unreachable("No process is READY");
|
||||
}
|
||||
|
||||
void save_context(const interrupt::syscall_regs& regs){
|
||||
@ -206,19 +239,30 @@ void scheduler::reschedule(const interrupt::syscall_regs& regs){
|
||||
}
|
||||
|
||||
scheduler::process_t& scheduler::new_process(){
|
||||
//TODO use get_free_pid() that searchs through the PCB
|
||||
auto pid = next_pid++;
|
||||
|
||||
auto& process = pcb[pid];
|
||||
|
||||
process.process.system = false;
|
||||
process.process.pid = pid;
|
||||
process.process.priority = scheduler::DEFAULT_PRIORITY;
|
||||
process.state = process_state::NEW;
|
||||
|
||||
return process.process;
|
||||
}
|
||||
|
||||
void scheduler::queue_process(scheduler::pid_t p){
|
||||
pcb[p].state = process_state::READY;
|
||||
void scheduler::queue_process(scheduler::pid_t pid){
|
||||
thor_assert(pid < scheduler::MAX_PROCESS, "pid out of bounds");
|
||||
|
||||
auto& process = pcb[pid];
|
||||
|
||||
thor_assert(process.process.priority <= scheduler::MAX_PRIORITY, "Invalid priority");
|
||||
thor_assert(process.process.priority >= scheduler::MIN_PRIORITY, "Invalid priority");
|
||||
|
||||
process.state = process_state::READY;
|
||||
|
||||
run_queues[process.process.priority].push_back(pid);
|
||||
}
|
||||
|
||||
scheduler::pid_t scheduler::get_pid(){
|
||||
|
Loading…
x
Reference in New Issue
Block a user