made all ecall handlers return optional_int and correctly handle erorrs

master
Anton Lydike 3 years ago
parent 828ea0c2e2
commit 4b31bd9fda

@ -5,7 +5,7 @@
#include "io.h" #include "io.h"
// this type is only used here, therefore we don't need it in the ktypes header // this type is only used here, therefore we don't need it in the ktypes header
typedef int (*ecall_handler)(int*,ProcessControlBlock*); typedef optional_int (*ecall_handler)(int*,ProcessControlBlock*);
ecall_handler ecall_table[ECALL_TABLE_LEN] = { 0 }; ecall_handler ecall_table[ECALL_TABLE_LEN] = { 0 };
@ -14,7 +14,7 @@ ecall_handler ecall_table[ECALL_TABLE_LEN] = { 0 };
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
int ecall_handle_spawn_thread(int* args_ptr, ProcessControlBlock* pcb) optional_int ecall_handle_spawn_thread(int* args_ptr, ProcessControlBlock* pcb)
{ {
void* entry = (void*) args_ptr[0]; // a0 void* entry = (void*) args_ptr[0]; // a0
void* args = (void*) args_ptr[1]; // a1 void* args = (void*) args_ptr[1]; // a1
@ -23,55 +23,57 @@ int ecall_handle_spawn_thread(int* args_ptr, ProcessControlBlock* pcb)
optional_pcbptr pcb_or_err = create_new_thread(pcb, entry, args, 1<<14); optional_pcbptr pcb_or_err = create_new_thread(pcb, entry, args, 1<<14);
if (has_error(pcb_or_err)) if (has_error(pcb_or_err))
return pcb_or_err.error; return (optional_int) { .error = pcb_or_err.error };
return EINVAL; return (optional_int) { .value = pcb_or_err.value->pid };
} }
int ecall_handle_sleep(int* args, ProcessControlBlock* pcb) optional_int ecall_handle_sleep(int* args, ProcessControlBlock* pcb)
{ {
int len = *args; int len = args[0];
if (len < 0) { if (len < 0) {
return EINVAL; return (optional_int) { .error = EINVAL };
} }
if (len > 0) {
pcb->asleep_until = read_time() + len; pcb->asleep_until = read_time() + len;
pcb->status = PROC_WAIT_SLEEP; pcb->status = PROC_WAIT_SLEEP;
}
return 0; return (optional_int) { .value = 0 };
} }
int ecall_handle_join(int* args, ProcessControlBlock* pcb) optional_int ecall_handle_join(int* args, ProcessControlBlock* pcb)
{ {
int pid = args[0]; // a0 int pid = args[0]; // a0
ProcessControlBlock* target = process_from_pid(pid); ProcessControlBlock* target = process_from_pid(pid);
if (target == NULL) if (target == NULL)
return ESRCH; return (optional_int) { .error = ESRCH };
if (target->status == PROC_DEAD) if (target->status == PROC_DEAD)
return target->exit_code; return (optional_int) { .value = target->exit_code };
pcb->status = PROC_WAIT_PROC; pcb->status = PROC_WAIT_PROC;
pcb->waiting_for_process = target; pcb->waiting_for_process = target;
int timeout = args[1]; int timeout = args[1];
if (timeout <= 0) if (timeout <= 0)
return 0; return (optional_int) { .value = 0 };
unsigned int len = (unsigned int) timeout; unsigned int len = (unsigned int) timeout;
pcb->asleep_until = read_time() + len; pcb->asleep_until = read_time() + len;
return 0; return (optional_int) { .value = 0 };
} }
int ecall_handle_kill(int* args, ProcessControlBlock* pcb) optional_int ecall_handle_kill(int* args, ProcessControlBlock* pcb)
{ {
return EINVAL; return (optional_int) { .error = EINVAL };
} }
int ecall_handle_exit(int* args, ProcessControlBlock* pcb) optional_int ecall_handle_exit(int* args, ProcessControlBlock* pcb)
{ {
pcb->status = PROC_DEAD; pcb->status = PROC_DEAD;
pcb->exit_code = *args; pcb->exit_code = *args;
@ -88,7 +90,7 @@ int ecall_handle_exit(int* args, ProcessControlBlock* pcb)
// recursively kill all child processes // recursively kill all child processes
kill_child_processes(pcb); kill_child_processes(pcb);
return 0; return (optional_int) { .value = 0 };
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -105,12 +107,14 @@ void trap_handle_ecall() {
if (code < 0 || code > ECALL_TABLE_LEN || ecall_table[code] == 0) { if (code < 0 || code > ECALL_TABLE_LEN || ecall_table[code] == 0) {
regs[REG_A0] = ENOCODE; regs[REG_A0] = ENOCODE;
} else { } else {
// get the corresponding ecall handler // run the corresponding ecall handler
ecall_handler handler = ecall_table[code]; optional_int handler_result = ecall_table[code](&regs[REG_A0], pcb);
regs[REG_A0] = handler(&regs[REG_A0], pcb); // populate registers with return value and error
regs[REG_A0] = handler_result.value;
regs[REG_A0 + 1] = handler_result.error;
} }
// increment pc of this process // increment pc of this process to move past ecall instruction
pcb->pc += 4; pcb->pc += 4;
// try to reschedule // try to reschedule

@ -20,15 +20,10 @@ enum ecall_codes {
// initializer for ecall lookup table // initializer for ecall lookup table
void init_ecall_table(); void init_ecall_table();
// syscall handlers, are setup in the mtvec csr // exception handler
int ecall_handle_spawn(int*, ProcessControlBlock*);
int ecall_handle_sleep(int*, ProcessControlBlock*);
int ecall_handle_join(int*, ProcessControlBlock*);
int ecall_handle_kill(int*, ProcessControlBlock*);
int ecall_handle_exit(int*, ProcessControlBlock*);
void handle_exception(int ecode, int mtval); void handle_exception(int ecode, int mtval);
// called by the assembly trap handler in boot.S
void __attribute__((__noreturn__)) trap_handle(int interrupt_bit, int code, int mtval); void __attribute__((__noreturn__)) trap_handle(int interrupt_bit, int code, int mtval);
#endif #endif
Loading…
Cancel
Save