Start the implementation of the scheduler and semaphore
Co-authored-by: Ezequiel Bellver <ebellver@itba.edu.ar> Co-authored-by: Juan Barmasch <jbarmasch@itba.edu.ar>
This commit is contained in:
parent
25b3f3c4f7
commit
60764ea9d7
|
@ -207,23 +207,23 @@ haltcpu:
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
_initialize_stack_frame:
|
_initialize_stack_frame:
|
||||||
mov rcx, rsp
|
mov r10, rsp
|
||||||
mov rsp, rsi
|
mov rsp, rsi
|
||||||
|
|
||||||
push 0x0 ; ss
|
push 0x0 ; ss
|
||||||
push rsi ; sp
|
push rsi ; sp
|
||||||
push 0x202 ; rflags
|
push 0x202 ; rflags
|
||||||
; 0x200 IF FLAG
|
|
||||||
; 0x002 always one
|
|
||||||
push 0x08 ; cs -- offset de la GDT
|
push 0x08 ; cs -- offset de la GDT
|
||||||
push rdi ; IP
|
push rdi ; IP
|
||||||
|
push rdx
|
||||||
|
push rcx
|
||||||
|
|
||||||
pushState
|
pushState
|
||||||
mov rdi, rsp
|
mov rdi, rsp
|
||||||
call newStack
|
call newStack
|
||||||
|
|
||||||
mov rax, rsp
|
mov rax, rsp
|
||||||
mov rsp, rcx
|
mov rsp, r10
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; System calls (int 80h)
|
; System calls (int 80h)
|
||||||
|
|
|
@ -4,7 +4,6 @@ section .text
|
||||||
|
|
||||||
forceTimer:
|
forceTimer:
|
||||||
int 20h
|
int 20h
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; tiene que ser uint32_t el parametro, no soporta más xchg. aunq también podría ser menos
|
; tiene que ser uint32_t el parametro, no soporta más xchg. aunq también podría ser menos
|
||||||
|
|
|
@ -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();
|
|
@ -0,0 +1 @@
|
||||||
|
typedef struct processCDT * processADT;
|
|
@ -5,7 +5,9 @@ static const long stackSize = 0x4000000; // 2^26
|
||||||
static const uint8_t * lastProcessAddress = (uint8_t *) 0x10000001; // 2^29 - 1
|
static const uint8_t * lastProcessAddress = (uint8_t *) 0x10000001; // 2^29 - 1
|
||||||
|
|
||||||
int activeProcesses = 0, currentProcess = -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() {
|
void cleanProcesses() {
|
||||||
activeProcesses = 0;
|
activeProcesses = 0;
|
||||||
|
@ -18,16 +20,16 @@ void newProcess(void (*fn)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void newStack(uint64_t rsp) {
|
void newStack(uint64_t rsp) {
|
||||||
processes[activeProcesses++] = rsp;
|
priority0[activeProcesses++] = rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t preserveStack(uint64_t rsp) {
|
uint64_t preserveStack(uint64_t rsp) {
|
||||||
if (currentProcess != -1) {
|
if (currentProcess != -1) {
|
||||||
processes[currentProcess] = rsp;
|
priority0[currentProcess] = rsp;
|
||||||
}
|
}
|
||||||
if (++currentProcess >= activeProcesses) currentProcess = 0;
|
if (++currentProcess >= activeProcesses) currentProcess = 0;
|
||||||
if (activeProcesses == 0) return 0;
|
if (activeProcesses == 0) return 0;
|
||||||
return processes[currentProcess];
|
return priority0[currentProcess];
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t sampleRSP;
|
static uint64_t sampleRSP;
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "queue.h"
|
||||||
|
#include "memManager.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
#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
|
||||||
|
*/
|
|
@ -0,0 +1,64 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
|
@ -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;
|
uint8_t chr = (uint8_t)c;
|
||||||
char * dst = (char*)destiation;
|
char * dst = (char*)destination;
|
||||||
|
|
||||||
while(length--)
|
while(length--)
|
||||||
dst[length] = chr;
|
dst[length] = chr;
|
||||||
|
|
||||||
return destiation;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue