diff --git a/Makefile b/Makefile index 64e64a3..419bad7 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,9 @@ setup: build: cmake --build build -j +clean: + cmake --build build --target clean + run: $(QEMU) $(QEMUFLAGS) @@ -77,7 +80,7 @@ format: checks: lint build test_cov -clean: - rm -rf *.bin qemu_log.txt drive.img build/ +# clean: +# rm -rf *.bin qemu_log.txt drive.img build/ -.PHONY: setup build run debug boot-debug dump dump-kernel test test_cov coverage lint format checks clean +.PHONY: setup build clean run debug boot-debug dump dump-kernel test test_cov coverage lint format checks clean diff --git a/src/apps/shell/src/shell.c b/src/apps/shell/src/shell.c index 96cb61e..f898c9d 100644 --- a/src/apps/shell/src/shell.c +++ b/src/apps/shell/src/shell.c @@ -335,6 +335,11 @@ static void exec_buff() { printf("Unknown command '%s'\n", argv[0]); term_last_ret = 1; } + + int exit_status = 0; + if (!proc_wait_pid(pid, &exit_status) && exit_status) { + printf("Process exited with status %d\n", exit_status); + } } // Free parsed args diff --git a/src/kernel/include/process_manager.h b/src/kernel/include/process_manager.h index d9e95a3..aae0c61 100644 --- a/src/kernel/include/process_manager.h +++ b/src/kernel/include/process_manager.h @@ -9,6 +9,7 @@ typedef struct _proc_man { process_t * first_task; + process_t * current_task; process_t * foreground_task; } proc_man_t; @@ -25,7 +26,6 @@ int pm_set_foreground_proc(proc_man_t * pm, int pid); int pm_resume_process(proc_man_t * pm, int pid); -// TODO move to scheduler process_t * pm_get_next(proc_man_t * pm); int pm_push_event(proc_man_t * pm, ebus_event_t * event); diff --git a/src/kernel/src/kernel/system_call_proc.c b/src/kernel/src/kernel/system_call_proc.c index 7f64008..45638fc 100644 --- a/src/kernel/src/kernel/system_call_proc.c +++ b/src/kernel/src/kernel/system_call_proc.c @@ -29,8 +29,19 @@ int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { } case SYS_CALL_PROC_EXIT: { - KLOG_DEBUG("Setting process %u state from %u to %u", proc->pid, proc->state, PROCESS_STATE_DEAD); - proc->state = PROCESS_STATE_DEAD; + struct _args { + int code; + } * args = (struct _args *)args_data; + KLOG_DEBUG("Setting process %u state from %u to %u with status code %d", proc->pid, proc->state, PROCESS_STATE_DEAD, args->code); + + proc->state = PROCESS_STATE_DEAD; + proc->status_code = args->code; + + ebus_event_t event; + event.event_id = EBUS_EVENT_PROC_CLOSE; + event.proc_close.pid = proc->pid; + event.proc_close.status_code = args->code; + kernel_queue_event(&event); enable_interrupts(); kernel_switch_task(); @@ -41,13 +52,19 @@ int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { case SYS_CALL_PROC_ABORT: { KLOG_DEBUG("System call proc abort"); struct _args { - uint8_t code; + int code; const char * msg; } * args = (struct _args *)args_data; printf("Proc abort with code %u\n", args->code); puts(args->msg); proc->state = PROCESS_STATE_DEAD; + ebus_event_t event; + event.event_id = EBUS_EVENT_PROC_CLOSE; + event.proc_close.pid = proc->pid; + event.proc_close.status_code = args->code; + kernel_queue_event(&event); + enable_interrupts(); kernel_switch_task(); @@ -77,6 +94,12 @@ int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { proc->state = PROCESS_STATE_DEAD; + ebus_event_t event; + event.event_id = EBUS_EVENT_PROC_CLOSE; + event.proc_close.pid = proc->pid; + event.proc_close.status_code = -1; + kernel_queue_event(&event); + enable_interrupts(); kernel_switch_task(); @@ -144,6 +167,46 @@ int sys_call_proc_cb(uint32_t call_id, void * args_data, registers_t * regs) { return pm_set_foreground_proc(kernel_get_proc_man(), args->pid); } break; + + case SYS_CALL_PROC_WAIT_PID: { + struct _args { + int pid; + int * exit_status; + } * args = (struct _args *)args_data; + + process_t * child = pm_find_pid(kernel_get_proc_man(), args->pid); + if (!child) { + KLOG_WARNING("Tried to wait on pid %u which is not found", args->pid); + return -1; + } + + if (child->state >= PROCESS_STATE_DEAD) { + KLOG_WARNING("Tried to wait on pid %u which is dead in state %u", args->pid, child->state); + return -1; + } + + proc->next_event.event_id = 0; + proc->filter_event.event_id = EBUS_EVENT_PROC_CLOSE; + proc->filter_event.proc_close.pid = args->pid; + proc->state = PROCESS_STATE_WAITING; + + do { + enable_interrupts(); + kernel_switch_task(); + KLOG_TRACE("Back from timer %u", timer_id); + } while (proc->next_event.proc_close.pid != args->pid); + + if (!(proc->next_event.event_id == proc->filter_event.event_id)) { + KPANIC("Tried to resume process but the event does not match filter"); + } + if (args->exit_status) { + KLOG_TRACE("Sending exist status %d of pid %u back to caller", proc->next_event.proc_close.pid, proc->next_event.proc_close.status_code); + *args->exit_status = proc->next_event.proc_close.status_code; + } + + proc->filter_event.event_id = 0; + proc->next_event.event_id = 0; + } break; } return 0; diff --git a/src/kernel/src/process_manager.c b/src/kernel/src/process_manager.c index 9e21faf..4f4be40 100644 --- a/src/kernel/src/process_manager.c +++ b/src/kernel/src/process_manager.c @@ -38,6 +38,10 @@ process_t * pm_find_pid(proc_man_t * pm, int pid) { return 0; } + if (pm->current_task && pm->current_task->pid == pid) { + return pm->current_task; + } + if (pm->foreground_task && pm->foreground_task->pid == pid) { return pm->foreground_task; } @@ -71,6 +75,7 @@ int pm_add_proc(proc_man_t * pm, process_t * proc) { if (!pm->first_task) { KLOG_INFO("Assigning first process to be %u", proc->pid); pm->first_task = proc; + pm->current_task = proc; pm->foreground_task = proc; // Link to self @@ -127,6 +132,11 @@ int pm_remove_proc(proc_man_t * pm, int pid) { return -1; } + if (proc == pm->current_task) { + KLOG_ERROR("Cannot remove current process"); + return -1; + } + if (proc == pm->foreground_task) { KLOG_ERROR("Cannot remove foreground process"); return -1; @@ -173,7 +183,7 @@ int pm_resume_process(proc_man_t * pm, int pid) { return -1; } - pm->foreground_task = proc; + pm->current_task = proc; if (proc->filter_event.event_id) { // TODO assert next_event has an event of the correct type @@ -191,9 +201,9 @@ process_t * pm_get_next(proc_man_t * pm) { return 0; } - process_t * proc = pm->foreground_task->next; + process_t * proc = pm->current_task->next; - KLOG_TRACE("Start looking for next process after %u", pm->foreground_task->pid); + KLOG_TRACE("Start looking for next process after %u", pm->current_task->pid); do { KLOG_TRACE("Looking at pid %u in state %u to see if it's ready", proc->pid, proc->state); @@ -214,9 +224,9 @@ process_t * pm_get_next(proc_man_t * pm) { KLOG_TRACE("Process with pid %u is not alive", proc->pid); } - KLOG_TRACE("Going to next process %u, fg is %u", proc->next->pid, pm->foreground_task->pid); + KLOG_TRACE("Going to next process %u, fg is %u", proc->next->pid, pm->current_task->pid); proc = proc->next; - } while (proc != pm->foreground_task->next); + } while (proc != pm->current_task->next); KLOG_TRACE("Finish looking for next process"); diff --git a/src/libc/include/libc/proc.h b/src/libc/include/libc/proc.h index b3acfd9..29abc87 100644 --- a/src/libc/include/libc/proc.h +++ b/src/libc/include/libc/proc.h @@ -25,8 +25,8 @@ typedef void (*_libc_config_queue_event_fn)(ebus_event_t *); -void proc_exit(uint8_t code); -void proc_abort(uint8_t code, const char * msg); +void proc_exit(int code); +void proc_abort(int code, const char * msg); NO_RETURN void proc_panic(const char * msg, const char * file, unsigned int line); void queue_event(ebus_event_t * event); @@ -36,6 +36,7 @@ void yield(void); // return pid int proc_open(const char * filename, size_t argc, char ** argv); int proc_set_foreground(int pid); +int proc_wait_pid(int pid, int * exit_status); int getpid(void); diff --git a/src/libc/src/proc.c b/src/libc/src/proc.c index 9a6b155..61a2cad 100644 --- a/src/libc/src/proc.c +++ b/src/libc/src/proc.c @@ -4,11 +4,11 @@ static _libc_config_queue_event_fn __queue_event = _sys_queue_event; -void proc_exit(uint8_t code) { +void proc_exit(int code) { _sys_proc_exit(code); } -void proc_abort(uint8_t code, const char * msg) { +void proc_abort(int code, const char * msg) { _sys_proc_abort(code, msg); } @@ -43,6 +43,10 @@ int proc_set_foreground(int pid) { _sys_proc_set_foreground(pid); } +int proc_wait_pid(int pid, int * exit_status) { + return _sys_proc_wait_pid(pid, exit_status); +} + void _libc_config_queue_event_call(_libc_config_queue_event_fn fn) { __queue_event = fn; } diff --git a/src/libk/include/libk/defs.h b/src/libk/include/libk/defs.h index 5feabd9..70bdf1e 100644 --- a/src/libk/include/libk/defs.h +++ b/src/libk/include/libk/defs.h @@ -28,6 +28,7 @@ #define SYS_CALL_PROC_YIELD ((SYS_CALL_FAMILY_PROC << 16) | 0x0007) #define SYS_CALL_PROC_EXEC ((SYS_CALL_FAMILY_PROC << 16) | 0x0008) #define SYS_CALL_PROC_SET_FOREGROUND ((SYS_CALL_FAMILY_PROC << 16) | 0x0009) +#define SYS_CALL_PROC_WAIT_PID ((SYS_CALL_FAMILY_PROC << 16) | 0x000a) #define SYS_CALL_PROC_LIST_OPEN #define SYS_CALL_PROC_LIST_CLOSE diff --git a/src/libk/include/libk/sys_call.h b/src/libk/include/libk/sys_call.h index bafeafb..243a0b6 100644 --- a/src/libk/include/libk/sys_call.h +++ b/src/libk/include/libk/sys_call.h @@ -23,8 +23,8 @@ void * _sys_mem_malloc(size_t size); void * _sys_mem_realloc(void * ptr, size_t size); void _sys_mem_free(void * ptr); -NO_RETURN void _sys_proc_exit(uint8_t code); -NO_RETURN void _sys_proc_abort(uint8_t code, const char * msg); +NO_RETURN void _sys_proc_exit(int code); +NO_RETURN void _sys_proc_abort(int code, const char * msg); NO_RETURN void _sys_proc_panic(const char * msg, const char * file, unsigned int line); int _sys_proc_exec(const char * filename, int argc, char ** argv); @@ -35,6 +35,7 @@ void _sys_register_signals(void * callback); void _sys_queue_event(ebus_event_t * event); void _sys_yield(void); int _sys_proc_set_foreground(int pid); +int _sys_proc_wait_pid(int pid, int * exit_status); int _sys_event_pull(int filter, ebus_event_t * event_out); diff --git a/src/libk/src/sys_call.c b/src/libk/src/sys_call.c index 68d1c65..6b752bf 100644 --- a/src/libk/src/sys_call.c +++ b/src/libk/src/sys_call.c @@ -43,12 +43,12 @@ void _sys_mem_free(void * ptr) { send_call(SYS_CALL_MEM_FREE, ptr); } -void _sys_proc_exit(uint8_t code) { +void _sys_proc_exit(int code) { // _sys_puts("libk: Proc exit\n"); send_call_noret(SYS_CALL_PROC_EXIT, code); } -void _sys_proc_abort(uint8_t code, const char * msg) { +void _sys_proc_abort(int code, const char * msg) { // _sys_puts("libk: Proc abort\n"); send_call_noret(SYS_CALL_PROC_ABORT, code, msg); } @@ -82,6 +82,10 @@ int _sys_proc_set_foreground(int pid) { return send_call(SYS_CALL_PROC_SET_FOREGROUND, pid); } +int _sys_proc_wait_pid(int pid, int * exit_status) { + return send_call(SYS_CALL_PROC_WAIT_PID, pid, exit_status); +} + int _sys_event_pull(int filter, ebus_event_t * event_out) { return send_call(SYS_CALL_EVENT_PULL, filter, event_out); } diff --git a/tests/Makefile b/tests/Makefile index ed7d703..aec99c2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -31,4 +31,7 @@ setup: build: setup cmake --build build -j -.PHONY: setup build test test_cov coverage test-ci +clean: + cmake --build build --target clean + +.PHONY: setup build clean test test_cov coverage test-ci diff --git a/tests/src/mocks/include/libc/proc.mock.h b/tests/src/mocks/include/libc/proc.mock.h index e741661..855a8dd 100644 --- a/tests/src/mocks/include/libc/proc.mock.h +++ b/tests/src/mocks/include/libc/proc.mock.h @@ -7,8 +7,8 @@ extern "C" { #include "fff.h" #include "libc/proc.h" -DECLARE_FAKE_VOID_FUNC(proc_exit, uint8_t); -DECLARE_FAKE_VOID_FUNC(proc_abort, uint8_t, const char *); +DECLARE_FAKE_VOID_FUNC(proc_exit, int); +DECLARE_FAKE_VOID_FUNC(proc_abort, int, const char *); DECLARE_FAKE_VOID_FUNC(proc_panic, const char *, const char *, unsigned int); DECLARE_FAKE_VOID_FUNC(set_next_pid, uint32_t); DECLARE_FAKE_VOID_FUNC(queue_event, ebus_event_t *); diff --git a/tests/src/mocks/include/libk/sys_call.mock.h b/tests/src/mocks/include/libk/sys_call.mock.h index ee2ed5b..e5dea13 100644 --- a/tests/src/mocks/include/libk/sys_call.mock.h +++ b/tests/src/mocks/include/libk/sys_call.mock.h @@ -8,8 +8,8 @@ extern "C" { #include "libk/sys_call.h" DECLARE_FAKE_VALUE_FUNC(void *, _sys_page_alloc, size_t); -DECLARE_FAKE_VOID_FUNC(_sys_proc_exit, uint8_t); -DECLARE_FAKE_VOID_FUNC(_sys_proc_abort, uint8_t, const char *); +DECLARE_FAKE_VOID_FUNC(_sys_proc_exit, int); +DECLARE_FAKE_VOID_FUNC(_sys_proc_abort, int, const char *); DECLARE_FAKE_VOID_FUNC(_sys_proc_panic, const char *, const char *, unsigned int); DECLARE_FAKE_VALUE_FUNC(int, _sys_proc_getpid); DECLARE_FAKE_VOID_FUNC(_sys_register_signals, void *); diff --git a/tests/src/mocks/src/libc.mock.c b/tests/src/mocks/src/libc.mock.c index d084884..3eee3e1 100644 --- a/tests/src/mocks/src/libc.mock.c +++ b/tests/src/mocks/src/libc.mock.c @@ -24,8 +24,8 @@ void reset_libc_memory_mock(void) { // libc/proc.h -DEFINE_FAKE_VOID_FUNC(proc_exit, uint8_t); -DEFINE_FAKE_VOID_FUNC(proc_abort, uint8_t, const char *); +DEFINE_FAKE_VOID_FUNC(proc_exit, int); +DEFINE_FAKE_VOID_FUNC(proc_abort, int, const char *); DEFINE_FAKE_VOID_FUNC(proc_panic, const char *, const char *, unsigned int); DEFINE_FAKE_VOID_FUNC(set_next_pid, uint32_t); DEFINE_FAKE_VOID_FUNC(queue_event, ebus_event_t *); diff --git a/tests/src/mocks/src/libk.mock.c b/tests/src/mocks/src/libk.mock.c index 5a1ff57..8ea958d 100644 --- a/tests/src/mocks/src/libk.mock.c +++ b/tests/src/mocks/src/libk.mock.c @@ -7,8 +7,8 @@ // libk/sys_call.h DEFINE_FAKE_VALUE_FUNC(void *, _sys_page_alloc, size_t); -DEFINE_FAKE_VOID_FUNC(_sys_proc_exit, uint8_t); -DEFINE_FAKE_VOID_FUNC(_sys_proc_abort, uint8_t, const char *); +DEFINE_FAKE_VOID_FUNC(_sys_proc_exit, int); +DEFINE_FAKE_VOID_FUNC(_sys_proc_abort, int, const char *); DEFINE_FAKE_VOID_FUNC(_sys_proc_panic, const char *, const char *, unsigned int); DEFINE_FAKE_VALUE_FUNC(int, _sys_proc_getpid); DEFINE_FAKE_VOID_FUNC(_sys_register_signals, void *);