]> 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 4ee30dedbb11f280e95832b00f8e78dccf179c70..09d65e07a09e56d07e137c60f36c19dc7d2c84be 100644 (file)
@@ -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);
index f36f76a1e6a238ca4dea0ac3ec9fb8e8c7dac2f1..db0bea2b324ddf3eefad3dbef57a96a0013c0304 100644 (file)
@@ -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;
index c71e1c85eae3243e7bcfba8d4c9d8fd1e426ce84..ae466aa38c5ea60305234a09036b549dad2e63e6 100644 (file)
@@ -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;
index 8febdb73ad2f6bc68c08c78efe13dd633978f980..5af095523169d3dab3923035af7663f4fb10cb0e 100644 (file)
@@ -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;