]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
posix: waitpid WNOHANG
authorTulio A M Mendes <[email protected]>
Sun, 8 Feb 2026 02:15:15 +0000 (23:15 -0300)
committerTulio A M Mendes <[email protected]>
Sun, 8 Feb 2026 02:15:15 +0000 (23:15 -0300)
Add WNOHANG option support to waitpid in kernel scheduler and syscall path, and include a userland smoke test.

include/process.h
src/kernel/scheduler.c
src/kernel/syscall.c
user/init.c

index 5b286f6a7ea6e65348744e200c174113eabbeb3c..3f16784f0379e66869b2544caa6ff7cd28ebd729 100644 (file)
@@ -76,8 +76,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);
index b29aa5e5846c4b72527e144fa3979c06ddd45428..6e2a728d540411f96ceb67af735ce7f0dff864a2 100644 (file)
@@ -79,9 +79,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);
 
@@ -113,6 +115,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;
index cea0839247059fb35d6a10237cd14e87936252f0..aee0eb94e5b290eb2514b49e7e1e263a0d207268 100644 (file)
@@ -706,7 +706,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;
@@ -714,12 +713,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;
index 8566738389cb2784bb41dbe0999b98a098f619d3..8713b2d845efafe7ee2dfc519b1faf8ce6a49339 100644 (file)
@@ -27,6 +27,10 @@ enum {
     SYSCALL_FORK = 16,
 };
 
+enum {
+    WNOHANG = 1,
+};
+
 enum {
     SEEK_SET = 0,
     SEEK_CUR = 1,
@@ -587,6 +591,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;