From: Tulio A M Mendes Date: Sat, 7 Feb 2026 19:22:30 +0000 (-0300) Subject: tty: make stdin (fd 0) blocking via keyboard waiter X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=e48551df73044c9b19099facf4be178d934ad2e6;p=AdrOS.git tty: make stdin (fd 0) blocking via keyboard waiter --- diff --git a/include/keyboard.h b/include/keyboard.h index 9542aeb..31cc041 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -11,4 +11,6 @@ void keyboard_set_callback(keyboard_callback_t callback); int keyboard_read_nonblock(char* out, uint32_t max_len); +int keyboard_read_blocking(char* out, uint32_t max_len); + #endif diff --git a/src/drivers/keyboard.c b/src/drivers/keyboard.c index 4011f91..f986ff2 100644 --- a/src/drivers/keyboard.c +++ b/src/drivers/keyboard.c @@ -4,6 +4,9 @@ #include "hal/keyboard.h" +#include "process.h" +#include "spinlock.h" + static keyboard_callback_t active_callback = NULL; #define KBD_BUF_SIZE 256 @@ -11,6 +14,9 @@ static volatile uint32_t kbd_head = 0; static volatile uint32_t kbd_tail = 0; static char kbd_buf[KBD_BUF_SIZE]; +static spinlock_t kbd_lock = {0}; +static struct process* kbd_waiter = NULL; + static void kbd_push_char(char c) { uint32_t next = (kbd_head + 1U) % KBD_BUF_SIZE; if (next == kbd_tail) { @@ -21,7 +27,19 @@ static void kbd_push_char(char c) { } static void hal_kbd_bridge(char c) { + // IRQ context: push to buffer and wake a single blocked waiter (if any) + uintptr_t flags = spin_lock_irqsave(&kbd_lock); kbd_push_char(c); + + if (kbd_waiter) { + if (kbd_waiter->state == PROCESS_BLOCKED) { + kbd_waiter->state = PROCESS_READY; + } + kbd_waiter = NULL; + } + + spin_unlock_irqrestore(&kbd_lock, flags); + if (active_callback) { active_callback(c); } @@ -29,8 +47,10 @@ static void hal_kbd_bridge(char c) { void keyboard_init(void) { uart_print("[KBD] Initializing Keyboard Driver...\n"); + spinlock_init(&kbd_lock); kbd_head = 0; kbd_tail = 0; + kbd_waiter = NULL; hal_keyboard_init(hal_kbd_bridge); } @@ -41,11 +61,34 @@ void keyboard_set_callback(keyboard_callback_t callback) { int keyboard_read_nonblock(char* out, uint32_t max_len) { if (!out || max_len == 0) return 0; + uintptr_t flags = spin_lock_irqsave(&kbd_lock); + uint32_t count = 0; while (count < max_len) { if (kbd_tail == kbd_head) break; out[count++] = kbd_buf[kbd_tail]; kbd_tail = (kbd_tail + 1U) % KBD_BUF_SIZE; } + + spin_unlock_irqrestore(&kbd_lock, flags); return (int)count; } + +int keyboard_read_blocking(char* out, uint32_t max_len) { + if (!out || max_len == 0) return 0; + if (!current_process) return 0; + + while (1) { + int rd = keyboard_read_nonblock(out, max_len); + if (rd > 0) return rd; + + uintptr_t flags = spin_lock_irqsave(&kbd_lock); + if (kbd_waiter == NULL) { + kbd_waiter = current_process; + current_process->state = PROCESS_BLOCKED; + } + spin_unlock_irqrestore(&kbd_lock, flags); + + schedule(); + } +} diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index fc18743..2b228c5 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -87,8 +87,8 @@ static int syscall_read_impl(int fd, void* user_buf, uint32_t len) { char kbuf[256]; uint32_t chunk = len; if (chunk > sizeof(kbuf)) chunk = (uint32_t)sizeof(kbuf); - int rd = keyboard_read_nonblock(kbuf, chunk); - if (rd <= 0) return 0; + int rd = keyboard_read_blocking(kbuf, chunk); + if (rd <= 0) return -1; if (copy_to_user(user_buf, kbuf, (size_t)rd) < 0) return -1; return rd; }