Added multiple threads per process
This commit is contained in:
parent
f3b1bfc5ef
commit
b00f6d6217
@ -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);
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user