Added multiple threads per process

This commit is contained in:
Xnoe 2022-06-18 17:45:16 +01:00
parent f3b1bfc5ef
commit b00f6d6217
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
8 changed files with 138 additions and 74 deletions

View File

@ -27,3 +27,5 @@ syscall_hdlr_0(uint32_t, getCurrentTerminalWidth, "21");
syscall_hdlr_0(uint32_t, getCurrentTerminalHeight, "22");
syscall_hdlr_1(uint32_t, getProcessState, "23", uint32_t, PID);
syscall_hdlr_1(void, spawnThread, "24", uint32_t, functionPointer);

View File

@ -4,6 +4,7 @@ namespace Global {
Allocator* allocator = 0;
Kernel* kernel = 0;
Process* currentProc = 0;
Thread* currentThread = 0;
tss_struct* tss = 0;
bool currentProcValid = false;
uint32_t milliseconds_elapsed = 0;

View File

@ -6,6 +6,7 @@
class Kernel;
class Allocator;
class Process;
class Thread;
struct tss_struct;
class ReadWriter;
@ -13,6 +14,7 @@ namespace Global {
extern Allocator* allocator;
extern Kernel* kernel;
extern Process* currentProc;
extern Thread* currentThread;
extern tss_struct* tss;
extern bool currentProcValid;
extern uint32_t milliseconds_elapsed;

View File

@ -84,15 +84,15 @@ void context_switch(frame_struct* frame) {
asm ("cli"); // Disable interrupts whilst handling the context switch.
xnoe::linkedlist<Process*>* processes = &Global::kernel->processes;
xnoe::linkedlist<Thread*>* threads = &Global::kernel->threads;
if (!processes->start) {
if (!threads->start) {
Global::kernel->terminal->printf("[FATAL] No more processes! Halting!\n");
while (1) asm ("hlt");
}
if (Global::currentProcValid)
Global::currentProc->kernelStackPtr = frame->new_esp;
Global::currentThread->kernelStackPtr = frame->new_esp;
// This cursed bit of code first determines if the processes list is longer than 1 and if it is
// - Determines if it has 2 or more elements
@ -100,40 +100,41 @@ void context_switch(frame_struct* frame) {
// - If it has more than two, add the start to the end then set start to the second element
uint32_t count = 0;
do {
if (count++ == processes->length)
if (count++ == threads->length)
return;
if (Global::currentProc) {
if (processes->start->next != 0) {
if (processes->end->prev == processes->start) {
xnoe::linkedlistelem<Process*>* tmp = processes->start;
processes->start = processes->end;
processes->end = tmp;
if (Global::currentThread) {
if (threads->start->next != 0) {
if (threads->end->prev == threads->start) {
xnoe::linkedlistelem<Thread*>* tmp = threads->start;
threads->start = threads->end;
threads->end = tmp;
processes->start->prev = 0;
processes->end->next = 0;
processes->end->prev = processes->start;
processes->start->next = processes->end;
threads->start->prev = 0;
threads->end->next = 0;
threads->end->prev = threads->start;
threads->start->next = threads->end;
} else {
processes->end->next = processes->start;
processes->start = processes->start->next;
processes->start->prev = 0;
xnoe::linkedlistelem<Process*>* tmp = processes->end;
processes->end = processes->end->next;
processes->end->next = 0;
processes->end->prev = tmp;
threads->end->next = threads->start;
threads->start = threads->start->next;
threads->start->prev = 0;
xnoe::linkedlistelem<Thread*>* tmp = threads->end;
threads->end = threads->end->next;
threads->end->next = 0;
threads->end->prev = tmp;
}
}
}
Global::currentProc = processes->start->elem;
} while (Global::currentProc->state != Running);
Global::currentThread = threads->start->elem;
Global::currentProc = threads->start->elem->parent;
} while (Global::currentThread->state != Running);
// Select the next processes page directory
frame->new_cr3 = Global::currentProc->PD->phys_addr;
frame->new_cr3 = Global::currentThread->parent->PD->phys_addr;
// Restore kernelStackPtr of the new process.
frame->new_esp = Global::currentProc->kernelStackPtr;
frame->new_esp = Global::currentThread->kernelStackPtr;
Global::tss->esp0 = Global::currentProc->kernelStackPtrDefault;
Global::tss->esp0 = Global::currentThread->kernelStackPtrDefault;
// Set the current proc to valid
Global::currentProcValid = true;
@ -171,8 +172,8 @@ namespace Timer {
}
}
void awaken(frame_struct* frame, Process* p) {
p->state = Running;
void awaken(frame_struct* frame, Thread* t) {
t->state = Running;
}
void syscall(frame_struct* frame) {
@ -351,8 +352,8 @@ void syscall(frame_struct* frame) {
}
case 18: { // sleep
Global::currentProc->state = Suspended;
Timer::register_event(frame->ebx, &awaken, (void*)Global::currentProc, true);
Global::currentThread->state = Suspended;
Timer::register_event(frame->ebx, &awaken, (void*)Global::currentThread, true);
context_switch(frame);
break;
}
@ -375,11 +376,18 @@ void syscall(frame_struct* frame) {
xnoe::maybe<Process*> p = Global::kernel->pid_map->get(frame->ebx);
if (p.is_ok()) {
Process* proc = p.get();
rval = proc->state;
//rval = proc->state;
}
break;
}
case 24: { // Spawn Thread
Thread* thread = new Thread(Global::currentProc);
thread->initKernelStack(frame->ebx, thread->stack);
Global::kernel->threads.append(thread);
break;
}
default:
break;
}

View File

@ -25,7 +25,7 @@ Process* Kernel::createProcess(ReadWriter* file) {
this->pid_map->set(currentPID, p);
currentPID++;
this->processes.append(p);
this->threads.append(p->threads.start->elem);
return p;
}
@ -39,7 +39,11 @@ Process* Kernel::createProcess(ReadWriter* file, ReadWriter* stdout) {
void Kernel::destroyProcess(Process* p) {
if (Global::currentProc == p)
Global::currentProcValid = false;
this->processes.remove(p);
xnoe::linkedlistelem<Thread*>* currentThread = p->threads.start;
while (currentThread) {
this->threads.remove(currentThread->elem);
currentThread = currentThread->next;
}
this->pid_map->remove(p->PID);
delete p;
}

View File

@ -21,8 +21,6 @@ Process::Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageM
this->PID = PID;
this->page_remaining = 0;
this->last_page_pointer = virt_alloc_base;
this->stack = stack;
this->state = Running;
}
Process::Process(uint32_t PID)
@ -30,9 +28,6 @@ Process::Process(uint32_t PID)
this->PID = PID;
this->page_remaining = 0;
this->last_page_pointer = 0;
this->stack = this->allocate(0x8000);
this->kernelStackPtr = (new uint8_t[0x4000]) + 0x4000;
this->state = Running;
this->file_handlers = new xnoe::dynarray<ReadWriter*>(8);
}
@ -41,12 +36,9 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, Rea
this->stdout = 0;
this->stdin = 0;
this->firstRun = true;
this->PID = PID;
this->page_remaining = 0;
this->last_page_pointer = 0;
this->state = Running;
this->file_handlers = new xnoe::dynarray<ReadWriter*>(8);
@ -56,17 +48,14 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, Rea
uint32_t filesize = filereader->size();
uint8_t* program_data = this->allocate(filesize + 12) + 12;
uint8_t* argenvarea = this->allocate(0x2000);
this->stack = this->allocate(0x8000);
this->kernelStackPtr = (new uint8_t[0x4000]) + 0x4000;
this->kernelStackPtrDefault = this->kernelStackPtr;
Thread* thread = new Thread(this);
uint32_t pCR3;
asm ("mov %%cr3, %0" : "=a" (pCR3) :);
this->PD->select();
uint32_t* stack = this->stack + 0x8000;
uint32_t* stack = thread->stack + 0x8000;
uint8_t* argenvarea = this->allocate(0x2000);
uint32_t argenv = argenvarea + 0x2000;
for (int i=argc; i>0; i--) {
char* s = argv[i-1];
@ -79,14 +68,39 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, Rea
*(--stack) = argc;
// We also need to initialise ESP and the stack
filereader->seek(0);
filereader->read(filesize, program_data);
asm ("mov %0, %%cr3" : : "r" (pCR3));
thread->initKernelStack(program_data, stack);
this->threads.append(thread);
}
Thread::Thread(Process* parent) {
this->parent = parent;
this->stack = this->parent->allocate(0x8000);
this->kernelStackPtr = (new uint8_t[0x4000]) + 0x4000;
this->kernelStackPtrDefault = this->kernelStackPtr;
}
Thread::~Thread() {
delete kernelStackPtr;
}
void Thread::initKernelStack(void* entryPoint, void* esp) {
uint32_t pCR3;
asm ("mov %%cr3, %0" : "=a" (pCR3) :);
this->parent->PD->select();
uint32_t* stack32 = ((uint32_t)this->kernelStackPtr);
*(--stack32) = 0x23; // SS
*(--stack32) = ((uint32_t)stack); // ESP
*(--stack32) = ((uint32_t)esp); // ESP
*(--stack32) = 0x200; // EFLAGS
*(--stack32) = 27; // CS
*(--stack32) = (uint32_t)program_data; // EIP
*(--stack32) = ((uint32_t)stack); // EBP
*(--stack32) = (uint32_t)entryPoint; // EIP
*(--stack32) = ((uint32_t)esp); // EBP
uint32_t rEBP = stack32;
@ -100,10 +114,6 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, Rea
*(--stack32) = 0; // EDI
this->kernelStackPtr = stack32;
filereader->seek(0);
filereader->read(filesize, program_data);
asm ("mov %0, %%cr3" : : "r" (pCR3));
}
@ -127,7 +137,11 @@ Process::~Process() {
delete r.get();
}
delete kernelStackPtr;
xnoe::linkedlistelem<Thread*>* currentThread = threads.start;
while (currentThread) {
delete currentThread->elem;
currentThread = currentThread->next;
}
}
void* Process::allocate(uint32_t size) {

View File

@ -12,6 +12,22 @@
#include "datatypes/dynarray.h"
#include "filesystem/fstree.h"
class Process;
class Thread {
public:
void* stack;
void* kernelStackPtr;
void* kernelStackPtrDefault;
Process* parent;
ProcessState state;
bool firstRun;
Thread(Process* parent);
~Thread();
void Thread::initKernelStack(void* entryPoint, void* esp);
};
struct AllocTracker {
void* page_base;
uint32_t page_size;
@ -25,8 +41,6 @@ private:
uint32_t last_page_pointer;
uint32_t page_remaining;
void* stack;
// List of pages this process has allocated
xnoe::linkedlist<AllocTracker> allocations;
@ -40,15 +54,10 @@ public:
uint32_t PID;
uint32_t esp;
void* kernelStackPtr;
void* kernelStackPtrDefault;
ReadWriter* stdout;
ReadWriter* stdin;
bool firstRun;
ProcessState state;
xnoe::linkedlist<Thread*> threads;
Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base);
Process(uint32_t PID);

View File

@ -151,11 +151,38 @@ bool strcmpcnt(int count, char* a, char* b) {
return true;
}
procbuffer b1;
procbuffer b2;
int bufferWidth;
void displayBuffer1() {
char c[128];
int succ=0;
while (1) {
if (b1.process)
if (succ = read(128, b1.stdout, c))
writeCountToBuf(succ, c, &b1);
displayBuf(&b1, 2, 2);
}
}
void displayBuffer2() {
char c[128];
int succ=0;
while (1) {
if (b2.process)
if (succ = read(128, b2.stdout, c))
writeCountToBuf(succ, c, &b2);
displayBuf(&b2, bufferWidth+4, 2);
}
}
int main() {
int width = getCurrentTerminalWidth();
int height = getCurrentTerminalHeight();
int bufferWidth = (width - 4) / 2;
bufferWidth = (width - 4) / 2;
int bufferHeight = (height - 4);
bindToKeyboard();
@ -201,7 +228,7 @@ int main() {
uint32_t p2in = bindStdin(p2);
fclose(program);
procbuffer b1 = {
b1 = (procbuffer) {
.buffer = malloc(bufferWidth * bufferHeight),
.x = 0,
.y = 0,
@ -212,7 +239,7 @@ int main() {
.height = bufferHeight
};
procbuffer b2 = {
b2 = (procbuffer) {
.buffer = malloc(bufferWidth * bufferHeight),
.x = 0,
.y = 0,
@ -223,6 +250,9 @@ int main() {
.height = bufferHeight
};
spawnThread(&displayBuffer1);
spawnThread(&displayBuffer2);
procbuffer* selectedBuf = &b1;
writeStrToBuf("XoSH (XOS SHell) v0.0.1\nPress : to use commands.\n :help for help.\n", &b1);
@ -230,9 +260,6 @@ int main() {
while (1) {
char c[128];
int succ = 0;
if (b1.process)
if (succ = read(128, b1.stdout, c))
writeCountToBuf(succ, c, &b1);
if (b2.process)
if (succ = read(128, b2.stdout, c))
writeCountToBuf(succ, c, &b2);
@ -309,8 +336,5 @@ int main() {
write(1, selectedBuf->stdin, c);
}
}
displayBuf(&b1, 2, 2);
displayBuf(&b2, bufferWidth+4, 2);
}
}