parent
8d87791fa2
commit
a06c9dced4
|
@ -15,7 +15,7 @@ add_subdirectory(sys)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT disk.img
|
OUTPUT disk.img
|
||||||
COMMAND sudo sh ../scripts/build_image.sh disk.img
|
COMMAND sudo sh ../scripts/build_image.sh disk.img
|
||||||
DEPENDS zion
|
DEPENDS zion test
|
||||||
USES_TERMINAL
|
USES_TERMINAL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define Z_DEBUG_PRINT 100
|
#define Z_THREAD_EXIT 0x01
|
||||||
|
#define Z_DEBUG_PRINT 0x100
|
||||||
uint64_t ZDebug(const char* message);
|
|
||||||
|
|
||||||
|
uint64_t ZDebug(const char* message);
|
||||||
|
|
|
@ -25,7 +25,7 @@ Process* Process::RootProcess() {
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process::Process(uint64_t elf_ptr) : id_(gNextId++) {
|
Process::Process(uint64_t elf_ptr) : id_(gNextId++), state_(RUNNING) {
|
||||||
cr3_ = phys_mem::AllocatePage();
|
cr3_ = phys_mem::AllocatePage();
|
||||||
InitializePml4(cr3_);
|
InitializePml4(cr3_);
|
||||||
CreateThread(elf_ptr);
|
CreateThread(elf_ptr);
|
||||||
|
@ -60,3 +60,15 @@ Thread* Process::GetThread(uint64_t tid) {
|
||||||
panic("Bad thread access.");
|
panic("Bad thread access.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Process::CheckState() {
|
||||||
|
ThreadEntry* entry = thread_list_front_;
|
||||||
|
|
||||||
|
while (entry != nullptr) {
|
||||||
|
if (entry->thread->GetState() != Thread::FINISHED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
state_ = FINISHED;
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,12 @@ class Thread;
|
||||||
|
|
||||||
class Process {
|
class Process {
|
||||||
public:
|
public:
|
||||||
|
enum State {
|
||||||
|
UNSPECIFIED,
|
||||||
|
SETUP,
|
||||||
|
RUNNING,
|
||||||
|
FINISHED,
|
||||||
|
};
|
||||||
// Caller takes ownership of returned process.
|
// Caller takes ownership of returned process.
|
||||||
static Process* RootProcess();
|
static Process* RootProcess();
|
||||||
Process(uint64_t elf_ptr);
|
Process(uint64_t elf_ptr);
|
||||||
|
@ -17,10 +23,17 @@ class Process {
|
||||||
void CreateThread(uint64_t elf_ptr);
|
void CreateThread(uint64_t elf_ptr);
|
||||||
Thread* GetThread(uint64_t tid);
|
Thread* GetThread(uint64_t tid);
|
||||||
|
|
||||||
|
// Checks the state of all child threads and transitions to
|
||||||
|
// finished if all have finished.
|
||||||
|
void CheckState();
|
||||||
|
|
||||||
|
State GetState() { return state_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Process(uint64_t id, uint64_t cr3) : id_(id), cr3_(cr3) {}
|
Process(uint64_t id, uint64_t cr3) : id_(id), cr3_(cr3) {}
|
||||||
uint64_t id_;
|
uint64_t id_;
|
||||||
uint64_t cr3_;
|
uint64_t cr3_;
|
||||||
|
State state_;
|
||||||
|
|
||||||
uint64_t next_thread_id_ = 0;
|
uint64_t next_thread_id_ = 0;
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,15 @@ class ProcList {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DumpProcessStates() {
|
||||||
|
ProcEntry* p = front_;
|
||||||
|
dbgln("Process States:");
|
||||||
|
while (p != nullptr) {
|
||||||
|
dbgln("%u: %u", p->proc->id(), p->proc->GetState());
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ProcEntry {
|
struct ProcEntry {
|
||||||
Process* proc;
|
Process* proc;
|
||||||
|
@ -71,16 +80,26 @@ class Scheduler {
|
||||||
asm volatile("cli");
|
asm volatile("cli");
|
||||||
|
|
||||||
if (current_thread_->next_thread_ == nullptr) {
|
if (current_thread_->next_thread_ == nullptr) {
|
||||||
dbgln("No next thread, continue");
|
if (current_thread_->GetState() == Thread::RUNNING) {
|
||||||
return;
|
dbgln("No next thread, continue");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
proc_list_.DumpProcessStates();
|
||||||
|
panic("FIXME: Implement Sleep");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread* prev = current_thread_;
|
Thread* prev = current_thread_;
|
||||||
current_thread_ = current_thread_->next_thread_;
|
current_thread_ = current_thread_->next_thread_;
|
||||||
prev->next_thread_ = nullptr;
|
prev->next_thread_ = nullptr;
|
||||||
if (prev->pid() != 0) {
|
if (prev->pid() != 0 && prev->GetState() == Thread::RUNNING) {
|
||||||
|
prev->SetState(Thread::RUNNABLE);
|
||||||
Enqueue(prev);
|
Enqueue(prev);
|
||||||
}
|
}
|
||||||
|
if (current_thread_->GetState() != Thread::RUNNABLE) {
|
||||||
|
panic("Non-runnable thread in the queue");
|
||||||
|
}
|
||||||
|
current_thread_->SetState(Thread::RUNNING);
|
||||||
context_switch(prev->Rsp0Ptr(), current_thread_->Rsp0Ptr());
|
context_switch(prev->Rsp0Ptr(), current_thread_->Rsp0Ptr());
|
||||||
|
|
||||||
asm volatile("sti");
|
asm volatile("sti");
|
||||||
|
|
|
@ -47,3 +47,10 @@ void Thread::Init() {
|
||||||
SetRsp0(rsp0_start_);
|
SetRsp0(rsp0_start_);
|
||||||
jump_user_space(rip, rsp);
|
jump_user_space(rip, rsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Thread::Exit() {
|
||||||
|
dbgln("[%u.%u] Exiting", pid(), id_);
|
||||||
|
state_ = FINISHED;
|
||||||
|
process_->CheckState();
|
||||||
|
sched::Yield();
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,14 @@ class Process;
|
||||||
|
|
||||||
class Thread {
|
class Thread {
|
||||||
public:
|
public:
|
||||||
|
enum State {
|
||||||
|
UNSPECIFIED,
|
||||||
|
CREATED,
|
||||||
|
RUNNING,
|
||||||
|
RUNNABLE,
|
||||||
|
BLOCKED,
|
||||||
|
FINISHED,
|
||||||
|
};
|
||||||
static Thread* RootThread(Process* root_proc);
|
static Thread* RootThread(Process* root_proc);
|
||||||
|
|
||||||
explicit Thread(Process* proc, uint64_t tid, uint64_t elf_ptr);
|
explicit Thread(Process* proc, uint64_t tid, uint64_t elf_ptr);
|
||||||
|
@ -22,6 +30,11 @@ class Thread {
|
||||||
// Called the first time the thread starts up.
|
// Called the first time the thread starts up.
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
|
// State Management.
|
||||||
|
State GetState() { return state_; };
|
||||||
|
void SetState(State state) { state_ = state; }
|
||||||
|
void Exit();
|
||||||
|
|
||||||
// FIXME: Probably make this private.
|
// FIXME: Probably make this private.
|
||||||
Thread* next_thread_;
|
Thread* next_thread_;
|
||||||
|
|
||||||
|
@ -30,6 +43,7 @@ class Thread {
|
||||||
Thread(Process* proc) : process_(proc), id_(0) {}
|
Thread(Process* proc) : process_(proc), id_(0) {}
|
||||||
Process* process_;
|
Process* process_;
|
||||||
uint64_t id_;
|
uint64_t id_;
|
||||||
|
State state_ = RUNNABLE;
|
||||||
|
|
||||||
uint64_t elf_ptr_;
|
uint64_t elf_ptr_;
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,12 @@ void InitSyscall() {
|
||||||
extern "C" void SyscallHandler(uint64_t call_id, char* message) {
|
extern "C" void SyscallHandler(uint64_t call_id, char* message) {
|
||||||
Thread& thread = sched::CurrentThread();
|
Thread& thread = sched::CurrentThread();
|
||||||
switch (call_id) {
|
switch (call_id) {
|
||||||
|
case Z_THREAD_EXIT:
|
||||||
|
thread.Exit();
|
||||||
|
panic("Returned from thread exit");
|
||||||
|
break;
|
||||||
case Z_DEBUG_PRINT:
|
case Z_DEBUG_PRINT:
|
||||||
dbgln("[%u.%u] %s", thread.pid(), thread.tid(), message);
|
dbgln("[%u.%u] [Debug] %s", thread.pid(), thread.tid(), message);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Unhandled syscall number: %u", call_id);
|
panic("Unhandled syscall number: %u", call_id);
|
||||||
|
|
Loading…
Reference in New Issue