]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
fix: add rq_enqueue on wake in keyboard, tty, pty drivers
authorTulio A M Mendes <[email protected]>
Tue, 10 Feb 2026 03:59:11 +0000 (00:59 -0300)
committerTulio A M Mendes <[email protected]>
Tue, 10 Feb 2026 03:59:11 +0000 (00:59 -0300)
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).

include/process.h
src/drivers/keyboard.c
src/kernel/pty.c
src/kernel/scheduler.c
src/kernel/tty.c

index ffadd94db4186588fdf43a0f174a4251ed867103..ba51960e54de842757e7dd0df2e3543ae87abb75 100644 (file)
@@ -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);
 
index f986ff2f0e4091baf05d541ff100ee22290e8cdc..4357aad32229f44939b887b371446bf0c56a18d7 100644 (file)
@@ -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;
     }
index 024818f63681b01f8836f2d38a6cd9c2657a8527..5a4d6c28643a79434550f0a1065d190010065a24 100644 (file)
@@ -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);
     }
 }
 
index 3eeaa33468914283efad45e945f5b212c18e53ff..958eabcbb7d0d1cb19135be6a81f7632c360d765 100644 (file)
@@ -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) {
index b813000b694c33f418ed0f993d78d9814cdf0441..0371a06d562a7d906cc5fd829328b0db020f586e 100644 (file)
@@ -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);
     }
 }