Add Scheduler wireframe.

Right now does nothing but has containing classes for process and thread
information.
This commit is contained in:
Drew Galbraith 2023-05-18 12:43:53 -07:00
parent de2c96b848
commit 960cbf9519
8 changed files with 208 additions and 1 deletions

View File

@ -8,6 +8,9 @@ add_executable(zion
memory/kernel_heap.cpp
memory/paging_util.cpp
memory/physical_memory.cpp
scheduler/process.cpp
scheduler/scheduler.cpp
scheduler/thread.cpp
zion.cpp)
target_include_directories(zion

View File

@ -0,0 +1,34 @@
#include "scheduler/process.h"
#include "debug/debug.h"
#include "scheduler/thread.h"
namespace {
static uint64_t gNextId = 1;
}
Process* Process::RootProcess() {
uint64_t pml4_addr = 0;
asm volatile("mov %%cr3, %0;" : "=r"(pml4_addr));
Process* proc = new Process(0, pml4_addr);
proc->thread_list_front_ = new ThreadEntry{
.thread = new Thread(proc, 0),
.next = nullptr,
};
proc->next_thread_id_ = 1;
return proc;
}
Thread* Process::GetThread(uint64_t tid) {
ThreadEntry* entry = thread_list_front_;
while (entry != nullptr) {
if (entry->thread->tid() == tid) {
return entry->thread;
}
}
panic("Bad thread access.");
return nullptr;
}

32
zion/scheduler/process.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include <stdint.h>
// Forward decl due to cyclic dependency.
class Thread;
class Process {
public:
// Caller takes ownership of returned process.
static Process* RootProcess();
Process();
uint64_t id() { return id_; }
Thread* CreateThread();
Thread* GetThread(uint64_t tid);
private:
Process(uint64_t id, uint64_t cr3) : id_(id), cr3_(cr3) {}
uint64_t id_;
uint64_t cr3_;
uint64_t next_thread_id_ = 0;
// FIXME: Make a better data structure for this.
struct ThreadEntry {
Thread* thread;
ThreadEntry* next;
};
ThreadEntry* thread_list_front_;
};

View File

@ -0,0 +1,84 @@
#include "scheduler/scheduler.h"
#include "debug/debug.h"
namespace sched {
namespace {
// Simple linked list class with the intent of eventually replacing this with a
// map.
class ProcList {
public:
ProcList() {}
// Takes ownership.
void InsertProcess(Process* proc) {
if (front_ == nullptr) {
front_ = new ProcEntry{
.proc = proc,
.next = nullptr,
};
return;
}
ProcEntry* back = front_;
while (back->next != nullptr) {
back = back->next;
}
back->next = new ProcEntry{
.proc = proc,
.next = nullptr,
};
}
private:
struct ProcEntry {
Process* proc;
ProcEntry* next;
};
ProcEntry* front_ = nullptr;
};
class Scheduler {
public:
Scheduler() {
Process* root = Process::RootProcess();
current_thread_ = root->GetThread(0);
proc_list_.InsertProcess(Process::RootProcess());
}
void Enable() { enabled_ = true; }
Process& CurrentProcess() { return current_thread_->process(); }
Thread& CurrentThread() { return *current_thread_; }
void Yield() {}
private:
bool enabled_ = false;
ProcList proc_list_;
Thread* current_thread_;
};
static Scheduler* gScheduler = nullptr;
Scheduler& GetScheduler() {
if (!gScheduler) {
panic("Scheduler not initialized");
}
return *gScheduler;
}
} // namespace
void InitScheduler() { gScheduler = new Scheduler(); }
void EnableScheduler() { GetScheduler().Enable(); }
void Yield() { GetScheduler().Yield(); }
Process& CurrentProcess() { return GetScheduler().CurrentProcess(); }
Thread& CurrentThread() { return GetScheduler().CurrentThread(); }
} // namespace sched

View File

@ -0,0 +1,24 @@
#pragma once
#include "scheduler/process.h"
#include "scheduler/thread.h"
namespace sched {
// Create the scheduler object in a disabled state,
// processes can be added but will not be scheduled.
void InitScheduler();
// Enables the scheduler such that processes will yield on ticks.
void EnableScheduler();
void Yield();
// Scheduler will take ownership
// of the created process.
void InsertProcess(Process* proc);
Process& CurrentProcess();
Thread& CurrentThread();
} // namespace sched

View File

@ -0,0 +1,5 @@
#include "scheduler/thread.h"
#include "scheduler/process.h"
uint64_t Thread::pid() { return process_->id(); }

23
zion/scheduler/thread.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include <stdint.h>
// Forward decl due to cyclic dependency.
class Process;
class Thread {
public:
Thread(Process* proc, uint64_t thread_id) : process_(proc), id_(thread_id) {}
uint64_t tid() { return id_; };
uint64_t pid();
Process& process() { return *process_; }
private:
Process* process_;
uint64_t id_;
// Next task in queue for quick scheduling.
Thread* next_task_;
};

View File

@ -6,6 +6,7 @@
#include "memory/kernel_heap.h"
#include "memory/paging_util.h"
#include "memory/physical_memory.h"
#include "scheduler/scheduler.h"
extern "C" void zion() {
InitGdt();
@ -15,7 +16,8 @@ extern "C" void zion() {
phys_mem::InitBootstrapPageAllocation();
KernelHeap heap(0xFFFFFFFF'40000000, 0xFFFFFFFF'80000000);
phys_mem::InitPhysicalMemoryManager();
heap.Allocate(0x2000);
sched::InitScheduler();
dbgln("Sleeping!");
while (1)