From: Tulio A M Mendes Date: Tue, 10 Feb 2026 03:59:11 +0000 (-0300) Subject: fix: add rq_enqueue on wake in keyboard, tty, pty drivers X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=5142e0b8ae152f75eb672ba3182968147c26e12b;p=AdrOS.git fix: add rq_enqueue on wake in keyboard, tty, pty drivers keyboard.c, tty.c, pty.c all transition processes from BLOCKED to READY without enqueuing them into the O(1) scheduler runqueue. This causes woken processes to be invisible to rq_pick_next(), leading to starvation until the active/expired swap rescues them. Add sched_enqueue_ready() public API in scheduler.c and call it from all three wake sites. Passes: make, cppcheck, QEMU smoke test (10s, all init tests OK). --- diff --git a/include/process.h b/include/process.h index ffadd94..ba51960 100644 --- a/include/process.h +++ b/include/process.h @@ -109,6 +109,10 @@ 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); +// Enqueue a READY process into the active O(1) runqueue. +// Must be called whenever a process transitions to PROCESS_READY from outside scheduler.c. +void sched_enqueue_ready(struct process* p); + // Kill a process (minimal signals). Returns 0 on success or -errno. int process_kill(uint32_t pid, int sig); diff --git a/src/drivers/keyboard.c b/src/drivers/keyboard.c index f986ff2..4357aad 100644 --- a/src/drivers/keyboard.c +++ b/src/drivers/keyboard.c @@ -34,6 +34,7 @@ static void hal_kbd_bridge(char c) { if (kbd_waiter) { if (kbd_waiter->state == PROCESS_BLOCKED) { kbd_waiter->state = PROCESS_READY; + sched_enqueue_ready(kbd_waiter); } kbd_waiter = NULL; } diff --git a/src/kernel/pty.c b/src/kernel/pty.c index 024818f..5a4d6c2 100644 --- a/src/kernel/pty.c +++ b/src/kernel/pty.c @@ -87,6 +87,7 @@ static void waitq_wake_one(struct process** q, uint32_t* head, uint32_t* tail) { struct process* p = waitq_pop(q, head, tail); if (p && p->state == PROCESS_BLOCKED) { p->state = PROCESS_READY; + sched_enqueue_ready(p); } } diff --git a/src/kernel/scheduler.c b/src/kernel/scheduler.c index 3eeaa33..958eabc 100644 --- a/src/kernel/scheduler.c +++ b/src/kernel/scheduler.c @@ -82,6 +82,15 @@ static struct process* rq_pick_next(void) { return NULL; // only idle task left } +void sched_enqueue_ready(struct process* p) { + if (!p) return; + uintptr_t flags = spin_lock_irqsave(&sched_lock); + if (p->state == PROCESS_READY) { + rq_enqueue(rq_active, p); + } + spin_unlock_irqrestore(&sched_lock, flags); +} + void thread_wrapper(void (*fn)(void)); static struct process* process_find_locked(uint32_t pid) { diff --git a/src/kernel/tty.c b/src/kernel/tty.c index b813000..0371a06 100644 --- a/src/kernel/tty.c +++ b/src/kernel/tty.c @@ -159,6 +159,7 @@ static void tty_wake_one(void) { struct process* p = waitq_pop(); if (p && p->state == PROCESS_BLOCKED) { p->state = PROCESS_READY; + sched_enqueue_ready(p); } }