|
|
|
@ -2,36 +2,71 @@
|
|
|
|
|
#include "sched.h"
|
|
|
|
|
#include "csr.h"
|
|
|
|
|
|
|
|
|
|
void ecall_handle_spawn(void* entry, void* args)
|
|
|
|
|
typedef int (*ecall_handler)(int*,ProcessControlBlock*);
|
|
|
|
|
|
|
|
|
|
ecall_handler ecall_table[ECALL_TABLE_LEN] = { 0 };
|
|
|
|
|
|
|
|
|
|
int ecall_handle_spawn_thread(int* args_ptr, ProcessControlBlock* pcb)
|
|
|
|
|
{
|
|
|
|
|
void* entry = (void*) args_ptr[0];
|
|
|
|
|
void* args = (void*) args_ptr[1];
|
|
|
|
|
|
|
|
|
|
return EINVAL;
|
|
|
|
|
// void* entry, void* args
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ecall_handle_sleep(int until)
|
|
|
|
|
int ecall_handle_sleep(int* args, ProcessControlBlock* pcb)
|
|
|
|
|
{
|
|
|
|
|
int len = *args;
|
|
|
|
|
if (len < 0) {
|
|
|
|
|
return EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pcb->asleep_until = read_time() + len;
|
|
|
|
|
pcb->status = PROC_WAIT_SLEEP;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ecall_handle_join(int pid, int timeout)
|
|
|
|
|
int ecall_handle_join(int* args, ProcessControlBlock* pcb)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
return EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ecall_handle_kill(int pid)
|
|
|
|
|
int ecall_handle_kill(int* args, ProcessControlBlock* pcb)
|
|
|
|
|
{
|
|
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ecall_handle_exit(int status)
|
|
|
|
|
int ecall_handle_exit(int* args, ProcessControlBlock* pcb)
|
|
|
|
|
{
|
|
|
|
|
pcb->status = PROC_DEAD;
|
|
|
|
|
pcb->exit_code = *args;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void trap_handle_ecall() {
|
|
|
|
|
int *regs = get_current_process_registers();
|
|
|
|
|
ProcessControlBlock* pcb = get_current_process();
|
|
|
|
|
int *regs = pcb->regs;
|
|
|
|
|
int code = regs[16];
|
|
|
|
|
__asm__("ebreak");
|
|
|
|
|
HALT(18);
|
|
|
|
|
|
|
|
|
|
// check if the code is too large/small or if the handler is zero
|
|
|
|
|
if (code < 0 || code > ECALL_TABLE_LEN || ecall_table[code] == 0) {
|
|
|
|
|
regs[9] = ENOCODE;
|
|
|
|
|
__asm__("ebreak");
|
|
|
|
|
} else {
|
|
|
|
|
// get the corresponding ecall handler
|
|
|
|
|
ecall_handler handler = ecall_table[code];
|
|
|
|
|
regs[9] = handler(®s[9], pcb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// increment pc of this process
|
|
|
|
|
pcb->pc += 4;
|
|
|
|
|
|
|
|
|
|
// try to reschedule
|
|
|
|
|
scheduler_try_return_to(pcb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void trap_handle(int interrupt_bit, int code, int mtval)
|
|
|
|
@ -58,3 +93,12 @@ void trap_handle(int interrupt_bit, int code, int mtval)
|
|
|
|
|
HALT(1);
|
|
|
|
|
__builtin_unreachable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void init_ecall_table()
|
|
|
|
|
{
|
|
|
|
|
ecall_table[ECALL_SPAWN] = ecall_handle_spawn_thread;
|
|
|
|
|
ecall_table[ECALL_SLEEP] = ecall_handle_sleep;
|
|
|
|
|
ecall_table[ECALL_JOIN] = ecall_handle_join;
|
|
|
|
|
ecall_table[ECALL_KILL] = ecall_handle_kill;
|
|
|
|
|
ecall_table[ECALL_EXIT] = ecall_handle_exit;
|
|
|
|
|
}
|