From: Tulio A M Mendes Date: Sun, 8 Feb 2026 02:15:15 +0000 (-0300) Subject: posix: waitpid WNOHANG X-Git-Url: https://projects.tadryanom.me/sitemap.xml?a=commitdiff_plain;h=279dc8260174965261b032cb764e7681aa39b765;p=AdrOS.git posix: waitpid WNOHANG Add WNOHANG option support to waitpid in kernel scheduler and syscall path, and include a userland smoke test. --- diff --git a/include/process.h b/include/process.h index 4ee30de..09d65e0 100644 --- a/include/process.h +++ b/include/process.h @@ -67,8 +67,8 @@ extern void context_switch(uintptr_t* old_sp_ptr, uintptr_t new_sp); // Yield the CPU to the next process voluntarily void schedule(void); -// Wait for a child to exit. Returns child's pid on success, -1 on error. -int process_waitpid(int pid, int* status_out); +// Wait for a child to exit. Returns child's pid on success, 0 on WNOHANG no-status, -1 on error. +int process_waitpid(int pid, int* status_out, uint32_t options); // Mark current process as exiting and notify/wake a waiter (if any). void process_exit_notify(int status); diff --git a/src/kernel/scheduler.c b/src/kernel/scheduler.c index f36f76a..db0bea2 100644 --- a/src/kernel/scheduler.c +++ b/src/kernel/scheduler.c @@ -70,9 +70,11 @@ static void process_reap_locked(struct process* p) { kfree(p); } -int process_waitpid(int pid, int* status_out) { +int process_waitpid(int pid, int* status_out, uint32_t options) { if (!current_process) return -1; + const uint32_t WNOHANG = 1U; + while (1) { uintptr_t flags = spin_lock_irqsave(&sched_lock); @@ -104,6 +106,11 @@ int process_waitpid(int pid, int* status_out) { return -1; } + if ((options & WNOHANG) != 0) { + spin_unlock_irqrestore(&sched_lock, flags); + return 0; + } + current_process->waiting = 1; current_process->wait_pid = pid; current_process->wait_result_pid = -1; diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index c71e1c8..ae466aa 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -697,7 +697,6 @@ static void syscall_handler(struct registers* regs) { int pid = (int)regs->ebx; int* user_status = (int*)regs->ecx; uint32_t options = regs->edx; - (void)options; if (user_status && user_range_ok(user_status, sizeof(int)) == 0) { regs->eax = (uint32_t)-1; @@ -705,12 +704,17 @@ static void syscall_handler(struct registers* regs) { } int status = 0; - int retpid = process_waitpid(pid, &status); + int retpid = process_waitpid(pid, &status, options); if (retpid < 0) { regs->eax = (uint32_t)-1; return; } + if (retpid == 0) { + regs->eax = 0; + return; + } + if (user_status) { if (copy_to_user(user_status, &status, sizeof(status)) < 0) { regs->eax = (uint32_t)-1; diff --git a/user/init.c b/user/init.c index 8febdb7..5af0955 100644 --- a/user/init.c +++ b/user/init.c @@ -18,6 +18,10 @@ enum { SYSCALL_FORK = 16, }; +enum { + WNOHANG = 1, +}; + enum { SEEK_SET = 0, SEEK_CUR = 1, @@ -578,6 +582,27 @@ void _start(void) { children[i] = pid; } + { + int pid = sys_fork(); + if (pid == 0) { + volatile uint32_t x = 0; + for (uint32_t i = 0; i < 2000000U; i++) x += i; + sys_exit(7); + } + int st = 0; + int wp = sys_waitpid(pid, &st, WNOHANG); + if (wp == 0 || wp == pid) { + static const char msg[] = "[init] waitpid WNOHANG OK\n"; + (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1)); + } else { + static const char msg[] = "[init] waitpid WNOHANG failed\n"; + (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1)); + } + if (wp == 0) { + (void)sys_waitpid(pid, &st, 0); + } + } + int ok = 1; for (int i = 0; i < NCHILD; i++) { int st = 0;