Add WNOHANG option support to waitpid in kernel scheduler and syscall path, and include a userland smoke test.
// 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);
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);
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;
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;
}
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;
SYSCALL_FORK = 16,
};
+enum {
+ WNOHANG = 1,
+};
+
enum {
SEEK_SET = 0,
SEEK_CUR = 1,
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;