From 60764ea9d70e787302270f4385b8ebb25be5b898 Mon Sep 17 00:00:00 2001 From: Santiago Lo Coco Date: Wed, 20 Oct 2021 21:45:25 -0300 Subject: [PATCH] Start the implementation of the scheduler and semaphore Co-authored-by: Ezequiel Bellver Co-authored-by: Juan Barmasch --- Kernel/asm/interrupts.asm | 8 +- Kernel/asm/libasm.asm | 1 - Kernel/include/queue.h | 8 ++ Kernel/include/scheduler.h | 1 + Kernel/utils/pcb.c | 10 +- Kernel/utils/pipe.c | 0 Kernel/utils/queue.c | 51 ++++++++ Kernel/utils/scheduler.c | 195 ++++++++++++++++++++++++++++ Kernel/utils/semaphore.c | 64 +++++++++ Userland/SampleCodeModule/_loader.c | 6 +- 10 files changed, 332 insertions(+), 12 deletions(-) create mode 100644 Kernel/include/queue.h create mode 100644 Kernel/include/scheduler.h create mode 100644 Kernel/utils/pipe.c create mode 100644 Kernel/utils/queue.c create mode 100644 Kernel/utils/scheduler.c create mode 100644 Kernel/utils/semaphore.c diff --git a/Kernel/asm/interrupts.asm b/Kernel/asm/interrupts.asm index eeaa19e..e16f843 100755 --- a/Kernel/asm/interrupts.asm +++ b/Kernel/asm/interrupts.asm @@ -207,23 +207,23 @@ haltcpu: %endmacro _initialize_stack_frame: - mov rcx, rsp + mov r10, rsp mov rsp, rsi push 0x0 ; ss push rsi ; sp push 0x202 ; rflags - ; 0x200 IF FLAG - ; 0x002 always one push 0x08 ; cs -- offset de la GDT push rdi ; IP + push rdx + push rcx pushState mov rdi, rsp call newStack mov rax, rsp - mov rsp, rcx + mov rsp, r10 ret ; System calls (int 80h) diff --git a/Kernel/asm/libasm.asm b/Kernel/asm/libasm.asm index b4d778a..82e1fc7 100644 --- a/Kernel/asm/libasm.asm +++ b/Kernel/asm/libasm.asm @@ -4,7 +4,6 @@ section .text forceTimer: int 20h - ret ; tiene que ser uint32_t el parametro, no soporta más xchg. aunq también podría ser menos diff --git a/Kernel/include/queue.h b/Kernel/include/queue.h new file mode 100644 index 0000000..1e34bd0 --- /dev/null +++ b/Kernel/include/queue.h @@ -0,0 +1,8 @@ +#include "scheduler.h" + +typedef struct queueCDT * queueADT; + +void queue(queueADT * my_queue, processADT * process); +char isEmpty(queueADT * my_queue); +processADT * dequeue(queueADT * my_queue); +queueADT createQueue(); \ No newline at end of file diff --git a/Kernel/include/scheduler.h b/Kernel/include/scheduler.h new file mode 100644 index 0000000..6fc7895 --- /dev/null +++ b/Kernel/include/scheduler.h @@ -0,0 +1 @@ +typedef struct processCDT * processADT; \ No newline at end of file diff --git a/Kernel/utils/pcb.c b/Kernel/utils/pcb.c index 7e852d3..c9c67dd 100644 --- a/Kernel/utils/pcb.c +++ b/Kernel/utils/pcb.c @@ -5,7 +5,9 @@ static const long stackSize = 0x4000000; // 2^26 static const uint8_t * lastProcessAddress = (uint8_t *) 0x10000001; // 2^29 - 1 int activeProcesses = 0, currentProcess = -1; -uint64_t processes[MAX_PROCESSES]; +uint64_t priority0[MAX_PROCESSES]; +uint64_t priority1[MAX_PROCESSES]; +uint64_t priority2[MAX_PROCESSES]; void cleanProcesses() { activeProcesses = 0; @@ -18,16 +20,16 @@ void newProcess(void (*fn)) { } void newStack(uint64_t rsp) { - processes[activeProcesses++] = rsp; + priority0[activeProcesses++] = rsp; } uint64_t preserveStack(uint64_t rsp) { if (currentProcess != -1) { - processes[currentProcess] = rsp; + priority0[currentProcess] = rsp; } if (++currentProcess >= activeProcesses) currentProcess = 0; if (activeProcesses == 0) return 0; - return processes[currentProcess]; + return priority0[currentProcess]; } static uint64_t sampleRSP; diff --git a/Kernel/utils/pipe.c b/Kernel/utils/pipe.c new file mode 100644 index 0000000..e69de29 diff --git a/Kernel/utils/queue.c b/Kernel/utils/queue.c new file mode 100644 index 0000000..5d001c5 --- /dev/null +++ b/Kernel/utils/queue.c @@ -0,0 +1,51 @@ +#include "queue.h" +#include "memManager.h" +#include + +typedef struct nodeT { + processADT * process; + struct nodeT * next; +} nodeT; + +typedef struct queueCDT { + nodeT * first; + nodeT * last; + int length; +} queueCDT; + +queueADT createQueue() { + queueADT aux = pvPortMalloc(sizeof(queueCDT)); + if (aux == NULL) + return NULL; + aux->first = NULL; + aux->last = NULL; + aux->length = 0; + return aux; +} + +void queue(queueADT * my_queue, processADT * process) { + if (my_queue == NULL) + return; + nodeT * new_node = pvPortMalloc(sizeof(nodeT)); + if (new_node == NULL) + return; + new_node->process = process; + new_node->next = NULL; + (*my_queue)->last->next = new_node; + (*my_queue)->last = new_node; + (*my_queue)->length++; +} + +processADT * dequeue(queueADT * my_queue) { + if (my_queue == NULL || isEmpty(my_queue)) + return NULL; + nodeT * aux = (*my_queue)->first; + (*my_queue)->first = (*my_queue)->first->next; + processADT * ans = aux->process; + vPortFree(aux); + return ans; +} + +char isEmpty(queueADT * my_queue) { + return (*my_queue)->length == 0; +} \ No newline at end of file diff --git a/Kernel/utils/scheduler.c b/Kernel/utils/scheduler.c new file mode 100644 index 0000000..bd2ad38 --- /dev/null +++ b/Kernel/utils/scheduler.c @@ -0,0 +1,195 @@ +#include "scheduler.h" +#include "queue.h" +#include +#include +#include "memManager.h" + +void forceTimer(); + +#define STACK_SIZE 1024 + +enum states {READY = 0, BLOCKED}; + +typedef struct processCDT { + char * name; + int pid; + int ppid; + uint64_t rsp; + uint64_t rbp; + char priority; + char foreground; + enum states state; +} processCDT; + +typedef struct nodeT { + processADT * process; + struct nodeT * next; + struct nodeT * previous; +} nodeT; + +typedef struct listT { + nodeT * first; + nodeT * last; + int length; +} listT; + +listT * ready = {NULL, NULL, 0}; +listT * blocked = {NULL, NULL, 0}; +nodeT * current = NULL; +int pids = 0; + +processADT * next() { + if (ready->first == NULL) + return NULL; + current = current->next; + if (current == NULL) + current = ready->first; + return current->process; +} + +// void init() { +// new(idle, ) +// } + +void idle() { + while (1) { + haltcpu(); + } +} + +void launchProcess(void (*fn) (int, char **), char priority, char foreground, int argc, char *argv[]) { + processADT proc = pvPortMalloc(sizeof(processCDT)); + nodeT * node = pvPortMalloc(sizeof(nodeT)); + uint64_t * rbp = pvPortMalloc(STACK_SIZE); + uint64_t * rsp = rbp; + + newProcess(proc, argv[0], priority, foreground); + + _initialize_stack_frame(fn, rbp, argc, argv); + + if (current != NULL && foreground) { + block((*current->process)->pid); + return; + } + + return; +} + +void newProcess(processADT process, char * name, char priority, char foreground) { + + + process->name = name; + process->pid = pids++; + process->ppid = (*current->process)->pid; + process->foreground = foreground; + process->priority = priority; + process->state = READY; + process->rbp = STACK_SIZE; +} + +void loader(int argc, char * argv[], void (*fn) (int, char **)) { + fn(argc, argv); + exit(); +} + +void exit() { + kill((*current->process)->pid); +} + +char block(int pid) { + nodeT * prev = NULL; + nodeT * del = search(&prev, pid, ready); + if (del == NULL) + return -1; + else { + if (prev != NULL) + prev->next = del->next; + else + ready->first = del->next; + } + + if (pid == (*del->process)->pid) + forceTimer(); + + return 0; +} + +char unblock(int pid) { + nodeT * prev = NULL; + nodeT * del = search(&prev, pid, blocked); + if (del == NULL) + return -1; + else { + if (prev != NULL) + prev->next = del->next; + else + blocked->first = del->next; + } + + if (pid == (*del->process)->pid) + forceTimer(); + + return 0; +} + +char kill(int pid) { + nodeT * prev = NULL; + nodeT * del = search(&prev, pid, ready); + if (del == NULL) { + del = search(&prev, pid, blocked); + if (del == NULL) + return -1; + else { + if (prev != NULL) + prev->next = del->next; + else + blocked->first = del->next; + } + } + else { + if (prev != NULL) + prev->next = del->next; + else + ready->first = del->next; + } + + if (pid == (*del->process)->pid) + forceTimer(); + + vPortFree((*del->process)->rsp); + vPortFree(del); + + return 0; +} + +nodeT * search(nodeT ** previous, int pid, listT * list) { + nodeT * curr = list->first; + * previous = NULL; + while (curr != NULL) { + if ((*curr->process)->pid == pid) { + break; + } + * previous = curr; + curr = curr->next; + } + if (curr == NULL) { + * previous = NULL; + return NULL; + } + if (curr = list->first) { + * previous = NULL; + return curr; + } + return curr; +} + +/* +● Crear un proceso. DEBERÁ soportar el pasaje de parámetros. +● Obtener el ID del proceso que llama. +● Listar todos los procesos: nombre, ID, prioridad, stack y base pointer, foreground y +cualquier otra variable que consideren necesaria. +● Matar un proceso arbitrario. +● Modificar la prioridad de un proceso arbitrario. +● Bloquear y desbloquear un proceso arbitrario. +● Renunciar al CPU +*/ \ No newline at end of file diff --git a/Kernel/utils/semaphore.c b/Kernel/utils/semaphore.c new file mode 100644 index 0000000..9761b3d --- /dev/null +++ b/Kernel/utils/semaphore.c @@ -0,0 +1,64 @@ +#include + +#define MAX_SEM 100 +#define MAX_NAME 100 + +void enter_region(uint32_t * lock); +void leave_region(uint32_t * lock); +static uint32_t semLock; + +typedef struct sem { + unsigned int value; + char name[MAX_NAME]; + // cola FIFO +} sem_t; + +// Podemos manejarnos con indices. +static sem_t semaphores[MAX_SEM]; +/* +int semOpen(char * name, unsigned int value) {} + +// int semClose(char * name) {} +int semClose(char semaphore) {} + +int semInit(char semaphore, unsigned int value) {} + +int semWait(char semaphore) {} + +int semPost(char semaphore) {} +*/ + +// o pasando la estructura de sem. esta es la q hace posix +sem_t * semOpen(char * name, unsigned int value) { + enter_region(&semLock); + leave_region(&semLock); +} + +int semClose(sem_t * semaphore) { + enter_region(&semLock); + leave_region(&semLock); +} + +int semWait(sem_t * semaphore) { + enter_region(&semLock); + + if (semaphore->value > 0) { + semaphore->value--; + } + else { + // leave_region(&semLock); + // enter_region(&semLock); + // semaphore->value--; + + // mandarlo a noni. es decir bloquearlo y solo despertarlo cuando alguien hace post + // block(con el pid) + // + } + + leave_region(&semLock); +} + +int semPost(sem_t * semaphore) { + enter_region(&semLock); + leave_region(&semLock); +} \ No newline at end of file diff --git a/Userland/SampleCodeModule/_loader.c b/Userland/SampleCodeModule/_loader.c index 46b29fa..c558fef 100644 --- a/Userland/SampleCodeModule/_loader.c +++ b/Userland/SampleCodeModule/_loader.c @@ -17,12 +17,12 @@ int _start() { } -void * memset(void * destiation, int32_t c, uint64_t length) { +void * memset(void * destination, int32_t c, uint64_t length) { uint8_t chr = (uint8_t)c; - char * dst = (char*)destiation; + char * dst = (char*)destination; while(length--) dst[length] = chr; - return destiation; + return destination; }