From f83a6ace518f9cb4707e49250798960f8646cc97 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 8 Oct 2022 17:56:40 +0200 Subject: [PATCH] Kernel, libc: Add support for providing a status code to exit() The exit() libc function already accepted an integer, but didn't pass it on to the kernel since we had no mechanism for it to do that. Now, the kernel stores a task's exit status to display it later (and in the future, return it to userspace via wait()/waitpid()) --- apps/src/memeater.c | 1 + kernel/include/sys/Syscall.h | 2 +- kernel/include/thread/Scheduler.h | 6 +++--- kernel/include/thread/Task.h | 3 +++ kernel/src/interrupts/Entry.cpp | 4 ++-- kernel/src/main.cpp | 2 +- kernel/src/sys/Syscall.cpp | 2 +- kernel/src/sys/sched.cpp | 4 ++-- kernel/src/thread/Scheduler.cpp | 12 +++++++----- libs/libc/src/stdlib.cpp | 4 ++-- libs/libc/src/unistd.cpp | 2 +- 11 files changed, 24 insertions(+), 18 deletions(-) diff --git a/apps/src/memeater.c b/apps/src/memeater.c index a1c26c71..1fb24091 100644 --- a/apps/src/memeater.c +++ b/apps/src/memeater.c @@ -17,4 +17,5 @@ int main() } while ((allocated = malloc(CHUNK))); perror("malloc"); printf("Press any key to restart.\n"); + return 1; } \ No newline at end of file diff --git a/kernel/include/sys/Syscall.h b/kernel/include/sys/Syscall.h index 295e89fb..e9564a53 100644 --- a/kernel/include/sys/Syscall.h +++ b/kernel/include/sys/Syscall.h @@ -18,7 +18,7 @@ namespace Syscall void entry(Context* context); } -void sys_exit(Context* context); +void sys_exit(Context* context, int status); void sys_yield(Context* context); void sys_sleep(Context* context, uint64_t ms); void sys_write(Context* context, const char* addr, size_t size); diff --git a/kernel/include/thread/Scheduler.h b/kernel/include/thread/Scheduler.h index e6b81a28..3ccf8912 100644 --- a/kernel/include/thread/Scheduler.h +++ b/kernel/include/thread/Scheduler.h @@ -5,15 +5,15 @@ namespace Scheduler { void init(); void yield(); - void exit(); + void exit(int status); void sleep(unsigned long ms); void add_kernel_task(void (*task)(void)); void add_user_task(void* task); void load_user_task(const char* filename); - void task_exit(Context* context); - void task_misbehave(Context* context); + void task_exit(Context* context, int64_t status); + void task_misbehave(Context* context, int64_t status); Task* current_task(); diff --git a/kernel/include/thread/Task.h b/kernel/include/thread/Task.h index 3fb993d5..4803d275 100644 --- a/kernel/include/thread/Task.h +++ b/kernel/include/thread/Task.h @@ -16,6 +16,9 @@ struct Task Context regs; int64_t task_sleep = 0; + + int64_t exit_status; + int64_t task_time = 0; Task* next_task = nullptr; diff --git a/kernel/src/interrupts/Entry.cpp b/kernel/src/interrupts/Entry.cpp index 1d579474..d0d9883e 100644 --- a/kernel/src/interrupts/Entry.cpp +++ b/kernel/src/interrupts/Entry.cpp @@ -34,7 +34,7 @@ extern "C" void common_handler(Context* context) StackTracer tracer(context->rbp); tracer.trace_with_ip(context->rip); - Scheduler::task_misbehave(context); + Scheduler::task_misbehave(context, -2); } } if (context->number == 14) @@ -51,7 +51,7 @@ extern "C" void common_handler(Context* context) StackTracer tracer(context->rbp); tracer.trace_with_ip(context->rip); - Scheduler::task_misbehave(context); + Scheduler::task_misbehave(context, -3); } } if (context->number == 8) { int_panic(context, "Double fault, halting"); } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index fde65f46..4b5c71b9 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -163,5 +163,5 @@ extern "C" void _start() kinfoln("Found PCI device %x:%x, %s", dev.id().vendor, dev.id().device, pci_type_name(dev.type())); }); - Scheduler::exit(); + Scheduler::exit(0); } \ No newline at end of file diff --git a/kernel/src/sys/Syscall.cpp b/kernel/src/sys/Syscall.cpp index 26785759..70111a09 100644 --- a/kernel/src/sys/Syscall.cpp +++ b/kernel/src/sys/Syscall.cpp @@ -9,7 +9,7 @@ void Syscall::entry(Context* context) switch (context->rax) { case SYS_exit: // sys_exit - sys_exit(context); + sys_exit(context, (int)context->rdi); break; case SYS_yield: // sys_yield sys_yield(context); diff --git a/kernel/src/sys/sched.cpp b/kernel/src/sys/sched.cpp index 3681d520..952ead52 100644 --- a/kernel/src/sys/sched.cpp +++ b/kernel/src/sys/sched.cpp @@ -1,8 +1,8 @@ #include "thread/Scheduler.h" -void sys_exit(Context* context) +void sys_exit(Context* context, int status) { - Scheduler::task_exit(context); + Scheduler::task_exit(context, status); } void sys_yield(Context* context) diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 9978cefc..62b090ef 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -153,7 +153,7 @@ void Scheduler::reap_task(Task* task) task_num--; Task* exiting_task = task; ASSERT(task->id != 0); // WHY IN THE WORLD WOULD WE BE REAPING THE IDLE TASK? - kinfoln("reaping task %ld", exiting_task->id); + kinfoln("reaping task %ld, exited with code %ld", exiting_task->id, exiting_task->exit_status); if (exiting_task->allocated_stack) MemoryManager::release_pages((void*)exiting_task->allocated_stack, TASK_PAGES_IN_STACK); if (exiting_task->image) @@ -168,20 +168,22 @@ void Scheduler::reap_task(Task* task) delete exiting_task; } -void Scheduler::task_exit(Context* context) +void Scheduler::task_exit(Context* context, int64_t status) { ASSERT(Interrupts::is_in_handler()); kdbgln("exit: task %ld finished running, used %ld ms of cpu time", sched_current_task->id, sched_current_task->cpu_time); sched_current_task->state = sched_current_task->Exited; + sched_current_task->exit_status = status; task_yield(context); } -void Scheduler::task_misbehave(Context* context) +void Scheduler::task_misbehave(Context* context, int64_t status) { ASSERT(Interrupts::is_in_handler()); kdbgln("exit: task %ld misbehaved, used %ld ms of cpu time", sched_current_task->id, sched_current_task->cpu_time); sched_current_task->state = sched_current_task->Exited; + sched_current_task->exit_status = status; task_yield(context); } @@ -311,9 +313,9 @@ void Scheduler::yield() asm volatile("int $0x42" : : "a"(1)); } -void Scheduler::exit() +void Scheduler::exit(int status) { - asm volatile("int $0x42" : : "a"(0)); + asm volatile("int $0x42" : : "a"(0), "D"(status)); } void Scheduler::sleep(unsigned long ms) diff --git a/libs/libc/src/stdlib.cpp b/libs/libc/src/stdlib.cpp index bae18830..427c6ec7 100644 --- a/libs/libc/src/stdlib.cpp +++ b/libs/libc/src/stdlib.cpp @@ -15,9 +15,9 @@ extern "C" exit(-1); } - noreturn void exit(int) + noreturn void exit(int status) { - syscall(SYS_exit); + syscall(SYS_exit, status); __builtin_unreachable(); } diff --git a/libs/libc/src/unistd.cpp b/libs/libc/src/unistd.cpp index 84ae01d3..783c39b8 100644 --- a/libs/libc/src/unistd.cpp +++ b/libs/libc/src/unistd.cpp @@ -31,10 +31,10 @@ extern "C" va_start(ap, number); switch (number) { - case SYS_exit: case SYS_yield: case SYS_gettid: case SYS_rand: result = __luna_syscall0(number); break; + case SYS_exit: case SYS_sleep: result = __luna_syscall1(number, va_arg(ap, arg)); break; case SYS_write: case SYS_munmap: