]> 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 d0ac450e2d39cd97cbc5df052f75d8597cb3681f..87f9151f3cdd52f3fd5e53345143403da70c7b55 100644 (file)
@@ -118,6 +118,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 7cf2e934969a8d8058637d260c2c026ab6e3d83d..f9501f8790eb65b7b4f9a6daeba2e51dd55b4873 100644 (file)
@@ -43,6 +43,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 6948588d28686255c9bcf0c69cabc938b2296b97..2695a6363b91457c3fd87f4650821a40785c7477 100644 (file)
@@ -96,6 +96,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 65bb04be5976dc917b64cb776117770cd6910a39..d8c3f698329c88609c9acd8f23b8bbb48df76105 100644 (file)
@@ -91,6 +91,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 74df2cc954eadd0328d7224c8a6b1d14a3e404f1..950b846aa86e424190c473596d06ec969ab01936 100644 (file)
@@ -168,6 +168,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);
     }
 }