bottleros/Kernel/utils/scheduler.c

195 lines
4.1 KiB
C

#include "scheduler.h"
#include "queue.h"
#include <stdint.h>
#include <stddef.h>
#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
*/