diff --git a/src/common/common.c b/src/common/common.c index 37a95c2..033d8c7 100644 --- a/src/common/common.c +++ b/src/common/common.c @@ -52,6 +52,10 @@ void kill(uint32_t pid) { asm volatile("mov $17, %%eax; mov %0, %%esi; int $0x7f" : : "m" (pid) : "esi"); } +void sleep(uint32_t time) { + asm volatile("mov $18, %%eax; mov %0, %%esi; int $0x7f" : : "m" (time) : "esi"); +} + void bindToKeyboard() { asm volatile ("mov $12, %%eax; int $0x7f" : : :); } diff --git a/src/common/common.h b/src/common/common.h index 3d12a6b..d9c67e2 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -22,6 +22,7 @@ void bindToKeyboard(); int fopen(char* filename); void fclose(uint32_t fh); void kill(uint32_t pid); +void sleep(uint32_t time); int int_to_decimal(unsigned int number, char* string_buffer); int int_to_hex(unsigned int number, char* string_buffer); diff --git a/src/kernel/datatypes/linkedlist.h b/src/kernel/datatypes/linkedlist.h index 7ea98de..45dcb44 100644 --- a/src/kernel/datatypes/linkedlist.h +++ b/src/kernel/datatypes/linkedlist.h @@ -105,10 +105,10 @@ namespace xnoe { current->next->prev = current->prev; if (current == start) - start = 0; + start = current->next; if (current = end) - end = 0; + end = current->prev; return; } diff --git a/src/kernel/idt.cpp b/src/kernel/idt.cpp index eff988c..f29c014 100644 --- a/src/kernel/idt.cpp +++ b/src/kernel/idt.cpp @@ -97,31 +97,33 @@ void context_switch(frame_struct* frame) { // - Determines if it has 2 or more elements // - If it has two, swap the first and last, update prev and next of each to be null or the other item // - If it has more than two, add the start to the end then set start to the second element - if (Global::currentProc) { - if (processes->start->next != 0) { - if (processes->end->prev == processes->start) { - xnoe::linkedlistelem* tmp = processes->start; - processes->start = processes->end; - processes->end = tmp; + do { + if (Global::currentProc) { + if (processes->start->next != 0) { + if (processes->end->prev == processes->start) { + xnoe::linkedlistelem* tmp = processes->start; + processes->start = processes->end; + processes->end = tmp; - processes->start->prev = 0; - processes->end->next = 0; - processes->end->prev = processes->start; - processes->start->next = processes->end; - } else { - processes->end->next = processes->start; - processes->start = processes->start->next; - processes->start->prev = 0; - xnoe::linkedlistelem* tmp = processes->end; - processes->end = processes->end->next; - processes->end->next = 0; - processes->end->prev = tmp; + processes->start->prev = 0; + processes->end->next = 0; + processes->end->prev = processes->start; + processes->start->next = processes->end; + } else { + processes->end->next = processes->start; + processes->start = processes->start->next; + processes->start->prev = 0; + xnoe::linkedlistelem* tmp = processes->end; + processes->end = processes->end->next; + processes->end->next = 0; + processes->end->prev = tmp; + } } } - } - - Global::currentProc = processes->start->elem; + Global::currentProc = processes->start->elem; + } while (Global::currentProc->state == Suspended); + // Select the next processes page directory frame->new_cr3 = Global::currentProc->PD->phys_addr; // Restore kernelStackPtr of the new process. @@ -134,7 +136,8 @@ void context_switch(frame_struct* frame) { } namespace Timer { - using TimedEvent = xnoe::tuple; + // counter, default count, function, argument, oneshot + using TimedEvent = xnoe::tuple; xnoe::linkedlist timed_events; void tick(frame_struct* frame) { xnoe::linkedlistelem* current = timed_events.start; @@ -144,17 +147,28 @@ namespace Timer { if (--count == 0) { xnoe::get<2>(t)(frame, xnoe::get<3>(t)); count = xnoe::get<1>(t); + + if (xnoe::get<4>(t)) { + xnoe::linkedlistelem* prev = current; + current = current->next; + timed_events.remove(prev); + delete prev; + } } - current->elem = TimedEvent(count, xnoe::get<1>(t), xnoe::get<2>(t), xnoe::get<3>(t)); + current->elem = TimedEvent(count, xnoe::get<1>(t), xnoe::get<2>(t), xnoe::get<3>(t), xnoe::get<4>(t)); current = current->next; } } - void register_event(uint32_t milliseconds, void(*function)(frame_struct*, void*), void* auxiliary) { - timed_events.append(TimedEvent(milliseconds, milliseconds, function, auxiliary)); + void register_event(uint32_t milliseconds, void(*function)(frame_struct*, void*), void* auxiliary, bool oneshot=false) { + timed_events.append(TimedEvent(milliseconds, milliseconds, function, auxiliary, oneshot)); } } +void awaken(frame_struct* frame, Process* p) { + p->state = Running; +} + void syscall(frame_struct* frame) { // Syscall ABI: // 0: X @@ -179,6 +193,8 @@ void syscall(frame_struct* frame) { // 17: kill :: int PID esi -> void // Destroys a process. + // 18: sleep :: int time ms esi -> void // Sleeps the current process for esi milliseconds. + // File handlers: // 0: Stdout // 1: Stdin @@ -324,6 +340,13 @@ void syscall(frame_struct* frame) { break; } + case 18: { + Global::currentProc->state = Suspended; + Timer::register_event(esi, &awaken, (void*)Global::currentProc, true); + context_switch(frame); + break; + } + default: break; } diff --git a/src/kernel/process.cpp b/src/kernel/process.cpp index 3eee21e..a2474b1 100644 --- a/src/kernel/process.cpp +++ b/src/kernel/process.cpp @@ -22,6 +22,7 @@ Process::Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageM this->page_remaining = 0; this->last_page_pointer = virt_alloc_base; this->stack = stack; + this->state = Running; } Process::Process(uint32_t PID) @@ -31,6 +32,7 @@ Process::Process(uint32_t PID) this->last_page_pointer = 0; this->stack = this->allocate(0x8000); this->kernelStackPtr = (new uint8_t[0x1000]) + 0x1000; + this->state = Running; } Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, uint32_t fh) @@ -43,6 +45,7 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, uin this->PID = PID; this->page_remaining = 0; this->last_page_pointer = 0; + this->state = Running; for (int index = inheritBase >> 22; index < 1024; index++) this->PD->page_directory[index] = inherit->page_directory[index]; diff --git a/src/kernel/process.h b/src/kernel/process.h index 65075a5..f780c19 100644 --- a/src/kernel/process.h +++ b/src/kernel/process.h @@ -20,6 +20,11 @@ struct AllocTracker { AllocTracker(void* base, uint32_t size, uint32_t count); }; +enum ProcessState { + Running, + Suspended +}; + class Process : public Allocator { private: uint32_t last_page_pointer; @@ -44,6 +49,8 @@ public: bool firstRun; + ProcessState state; + Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base); Process(uint32_t PID); Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, uint32_t fh); diff --git a/src/kernel/terminal.h b/src/kernel/terminal.h index 731367f..b90f699 100644 --- a/src/kernel/terminal.h +++ b/src/kernel/terminal.h @@ -14,7 +14,7 @@ struct frame_struct; namespace Timer { - void register_event(uint32_t milliseconds, void(*function)(frame_struct*, void*), void* auxiliary); + void register_event(uint32_t milliseconds, void(*function)(frame_struct*, void*), void* auxiliary, bool oneshot=false); } class Terminal: public ReadWriter { diff --git a/src/programs/timer/timer.c b/src/programs/timer/timer.c new file mode 100644 index 0000000..75e6694 --- /dev/null +++ b/src/programs/timer/timer.c @@ -0,0 +1,8 @@ +#include "common/common.h" + +int main() { + while (1) { + print("Hello, World!\n"); + sleep(200); + } +} \ No newline at end of file diff --git a/src/programs/world/world.c b/src/programs/world/world.c index 231fb30..e5a92ed 100644 --- a/src/programs/world/world.c +++ b/src/programs/world/world.c @@ -187,7 +187,7 @@ int main() { uint32_t p1out = bindStdout(p1); uint32_t p1in = bindStdin(p1); fclose(program); - program = fopen("/hello.bin"); + program = fopen("/timer.bin"); uint32_t p2 = fork(program); uint32_t p2out = bindStdout(p2); uint32_t p2in = bindStdin(p2);