From 0f5bd483283f46c075983338bc9321e2f1867ead Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Sun, 15 Feb 2026 15:21:18 +0100 Subject: [PATCH] Suspend process waiting for keyboard input --- include/m/status.h | 1 - init/init.c | 19 +++++----------- kernel/amd64/intr.c | 7 ++++-- kernel/amd64/intr_defs.h | 1 - kernel/amd64/intr_stub.S | 1 - kernel/device/device.h | 5 ++++- kernel/device/ps2_kb.c | 48 +++++++++++++++++++++++++++++++--------- kernel/device/ps2_kb.h | 5 ++++- kernel/device/terminal.c | 21 ++++++++++++------ kernel/device/terminal.h | 5 ++++- kernel/irq/irq.c | 2 +- kernel/irq/irq.h | 5 +++-- kernel/proc/proc.c | 5 +++-- kernel/syscall/syscall.c | 7 +++++- 14 files changed, 87 insertions(+), 45 deletions(-) diff --git a/include/m/status.h b/include/m/status.h index 3376f65..f31d84b 100644 --- a/include/m/status.h +++ b/include/m/status.h @@ -14,6 +14,5 @@ #define ST_OOB_ERROR 10 #define ST_BAD_PATH 11 #define ST_EXEC_ERROR 12 -#define ST_TRY_AGAIN 13 #endif // _M_STATUS_H diff --git a/init/init.c b/init/init.c index 9964aa4..b86e519 100644 --- a/init/init.c +++ b/init/init.c @@ -19,7 +19,8 @@ void app_proc (void) { mutex_lock (MUTEX); for (int i = 0; i < 3; i++) - terminal_print (&letter, 1); + test (letter); + /* terminal_print (&letter, 1); */ for (volatile int i = 0; i < 1000 * 1000; i++) ; @@ -37,9 +38,9 @@ void app_main (void) { /* process_exec ("ramdisk:/ce"); */ - /* process_spawn (&app_proc, (void*)'b'); */ - /* process_spawn (&app_proc, (void*)'c'); */ - /* process_spawn (&app_proc, (void*)'d'); */ + process_spawn (&app_proc, (void*)'b'); + process_spawn (&app_proc, (void*)'c'); + process_spawn (&app_proc, (void*)'d'); for (;;) { int ch = kb_read_key (); @@ -48,15 +49,5 @@ void app_main (void) { continue; terminal_print ((char*)&ch, 1); - - /* mutex_lock (MUTEX); */ - - /* for (int i = 0; i < 3; i++) */ - /* terminal_print (&letter, 1); */ - - /* for (volatile int i = 0; i < 1000 * 1000; i++) */ - /* ; */ - - /* mutex_unlock (MUTEX); */ } } diff --git a/kernel/amd64/intr.c b/kernel/amd64/intr.c index ae8f472..861d6b9 100644 --- a/kernel/amd64/intr.c +++ b/kernel/amd64/intr.c @@ -121,7 +121,6 @@ static void amd64_idt_init (void) { IDT_ENTRY (44, 1); IDT_ENTRY (45, 1); IDT_ENTRY (46, 1); IDT_ENTRY (47, 1); IDT_ENTRY (SCHED_PREEMPT_TIMER, 1); - IDT_ENTRY (TLB_SHOOTDOWN, 1); IDT_ENTRY (CPU_REQUEST_SCHED, 1); IDT_ENTRY (CPU_SPURIOUS, 1); /* clang-format on */ @@ -187,7 +186,11 @@ void amd64_intr_handler (void* stack_ptr) { struct irq* irq = irq_find (regs->trap); if (irq != NULL) { - irq->func (irq->arg, stack_ptr); + struct cpu* reschedule_cpu = NULL; + bool reschedule = irq->func (&reschedule_cpu, irq->arg, stack_ptr); + + if (reschedule) + cpu_request_sched (reschedule_cpu); } } } diff --git a/kernel/amd64/intr_defs.h b/kernel/amd64/intr_defs.h index 7279e1f..af19eb6 100644 --- a/kernel/amd64/intr_defs.h +++ b/kernel/amd64/intr_defs.h @@ -4,7 +4,6 @@ #define PS2KB 32 #define SCHED_PREEMPT_TIMER 80 -#define TLB_SHOOTDOWN 81 #define CPU_REQUEST_SCHED 82 #define CPU_SPURIOUS 255 diff --git a/kernel/amd64/intr_stub.S b/kernel/amd64/intr_stub.S index 0ccbf30..f668e05 100644 --- a/kernel/amd64/intr_stub.S +++ b/kernel/amd64/intr_stub.S @@ -95,6 +95,5 @@ make_intr_stub(no_err, 46) make_intr_stub(no_err, 47) make_intr_stub(no_err, SCHED_PREEMPT_TIMER) -make_intr_stub(no_err, TLB_SHOOTDOWN) make_intr_stub(no_err, CPU_REQUEST_SCHED) make_intr_stub(no_err, CPU_SPURIOUS) diff --git a/kernel/device/device.h b/kernel/device/device.h index 6a3399e..307662f 100644 --- a/kernel/device/device.h +++ b/kernel/device/device.h @@ -2,10 +2,13 @@ #define _KERNEL_DEVICE_DEVICE_H #include +#include #include #include +#include -typedef int (*device_op_func_t) (struct proc* proc, void* a1, void* a2, void* a3, void* a4); +typedef bool (*device_op_func_t) (struct proc* proc, struct cpu** reschedule_cpu, int* ret, + void* a1, void* a2, void* a3, void* a4); struct device { int id; diff --git a/kernel/device/ps2_kb.c b/kernel/device/ps2_kb.c index a8c61a4..274cb9f 100644 --- a/kernel/device/ps2_kb.c +++ b/kernel/device/ps2_kb.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,7 @@ static struct ringbuffer ps2kb_ringbuffer; static spin_lock_t ps2kb_ringbuffer_lock = SPIN_LOCK_INIT; +static struct proc_suspension_q ps2kb_sq; static uint8_t shiftcode[0x100] = { [0x1d] = KB_CTL, [0x2a] = KB_SHIFT, [0x36] = KB_SHIFT, @@ -161,35 +163,61 @@ int32_t ps2kb_keycode (void) { return c; } -void ps2kb_irq (void* arg, void* regs) { +bool ps2kb_irq (struct cpu** reschedule_cpu, void* arg, void* regs) { int32_t keycode = ps2kb_keycode (); - if (keycode >= 0) { - spin_lock (&ps2kb_ringbuffer_lock); - ringbuffer_push (uint8_t, &ps2kb_ringbuffer, (uint8_t)keycode); + if (keycode <= 0) + return PROC_NO_RESCHEDULE; + + spin_lock (&ps2kb_ringbuffer_lock); + spin_lock (&ps2kb_sq.lock); + + ringbuffer_push (uint8_t, &ps2kb_ringbuffer, (uint8_t)keycode); + + struct list_node_link* node = ps2kb_sq.proc_list; + + if (node) { + struct proc_sq_entry* sq_entry = list_entry (node, struct proc_sq_entry, sq_link); + struct proc* resumed_proc = sq_entry->proc; + + spin_unlock (&ps2kb_sq.lock); spin_unlock (&ps2kb_ringbuffer_lock); + + return proc_sq_resume (resumed_proc, sq_entry, reschedule_cpu); } + + spin_unlock (&ps2kb_sq.lock); + spin_unlock (&ps2kb_ringbuffer_lock); + + return PROC_NO_RESCHEDULE; } -int ps2kb_read_key (struct proc* proc, void* a1, void* a2, void* a3, void* a4) { - if (!(proc->procgroup->capabilities & PROC_CAP_KB)) - return -ST_PERMISSION_ERROR; +bool ps2kb_read_key (struct proc* proc, struct cpu** reschedule_cpu, int* ret, void* a1, void* a2, + void* a3, void* a4) { + if (!(proc->procgroup->capabilities & PROC_CAP_KB)) { + *ret = -ST_PERMISSION_ERROR; + return PROC_NO_RESCHEDULE; + } uint8_t* chbuf = (uint8_t*)a1; spin_lock (&ps2kb_ringbuffer_lock); size_t prev_count = ps2kb_ringbuffer.count; + ringbuffer_pop (uint8_t, &ps2kb_ringbuffer, chbuf); + size_t new_count = ps2kb_ringbuffer.count; - spin_unlock (&ps2kb_ringbuffer_lock); + *ret = ST_OK; /* didn't pop anything */ if (prev_count == new_count) - return -ST_TRY_AGAIN; + return proc_sq_suspend (proc, &ps2kb_sq, &ps2kb_ringbuffer_lock, reschedule_cpu); - return ST_OK; + spin_unlock (&ps2kb_ringbuffer_lock); + + return PROC_NO_RESCHEDULE; } bool ps2kb_init (void* arg) { diff --git a/kernel/device/ps2_kb.h b/kernel/device/ps2_kb.h index 391362b..402cb12 100644 --- a/kernel/device/ps2_kb.h +++ b/kernel/device/ps2_kb.h @@ -1,9 +1,12 @@ #ifndef _KERNEL_DEVICE_PS2_KB_H #define _KERNEL_DEVICE_PS2_KB_H +#include #include +#include -int ps2kb_read_key (struct proc* proc, void* a1, void* a2, void* a3, void* a4); +bool ps2kb_read_key (struct proc* proc, struct cpu** reschedule_cpu, int* ret, void* a1, void* a2, + void* a3, void* a4); bool ps2kb_init (void* arg); void ps2kb_fini (void); diff --git a/kernel/device/terminal.c b/kernel/device/terminal.c index 9ef1f79..4b1c447 100644 --- a/kernel/device/terminal.c +++ b/kernel/device/terminal.c @@ -8,6 +8,7 @@ #include #include #include +#include struct flanterm_context* ft_ctx; @@ -34,19 +35,25 @@ bool terminal_init (void* arg) { void terminal_fini (void) {} -int terminal_putstr (struct proc* proc, void* a1, void* a2, void* a3, void* a4) { - (void)a2, (void)a3, (void)a4; +bool terminal_putstr (struct proc* proc, struct cpu** reschedule_cpu, int* ret, void* a1, void* a2, + void* a3, void* a4) { + (void)reschedule_cpu, (void)a2, (void)a3, (void)a4; - if (!(proc->procgroup->capabilities & PROC_CAP_TERMINAL)) - return -ST_PERMISSION_ERROR; + if (!(proc->procgroup->capabilities & PROC_CAP_TERMINAL)) { + *ret = -ST_PERMISSION_ERROR; + return PROC_NO_RESCHEDULE; + } char* string = (char*)a1; size_t* len = (size_t*)a2; - if (string == NULL || len == NULL) - return -ST_BAD_ADDRESS_SPACE; + if (string == NULL || len == NULL) { + *ret = -ST_BAD_ADDRESS_SPACE; + return PROC_NO_RESCHEDULE; + } flanterm_write (ft_ctx, string, *len); - return ST_OK; + *ret = ST_OK; + return PROC_NO_RESCHEDULE; } diff --git a/kernel/device/terminal.h b/kernel/device/terminal.h index f7678da..1042088 100644 --- a/kernel/device/terminal.h +++ b/kernel/device/terminal.h @@ -1,10 +1,13 @@ #ifndef _KERNEL_DEVICE_TERMINAL_H #define _KERNEL_DEVICE_TERMINAL_H +#include #include +#include bool terminal_init (void* arg); void terminal_fini (void); -int terminal_putstr (struct proc* proc, void* a1, void* a2, void* a3, void* a4); +bool terminal_putstr (struct proc* proc, struct cpu** reschedule_cpu, int* ret, void* a1, void* a2, + void* a3, void* a4); #endif // _KERNEL_DEVICE_TERMINAL_H diff --git a/kernel/irq/irq.c b/kernel/irq/irq.c index 33a58d2..dfceca4 100644 --- a/kernel/irq/irq.c +++ b/kernel/irq/irq.c @@ -13,7 +13,7 @@ static struct rb_node_link* irq_tree = NULL; static spin_lock_t irqs_lock = SPIN_LOCK_INIT; -bool irq_attach (void (*func) (void*, void*), void* arg, uint32_t irq_num) { +bool irq_attach (irq_func_t func, void* arg, uint32_t irq_num) { struct irq* irq = malloc (sizeof (*irq)); if (irq == NULL) { return false; diff --git a/kernel/irq/irq.h b/kernel/irq/irq.h index 0263620..4759b6e 100644 --- a/kernel/irq/irq.h +++ b/kernel/irq/irq.h @@ -3,8 +3,9 @@ #include #include +#include -typedef void (*irq_func_t) (void* arg, void* regs); +typedef bool (*irq_func_t) (struct cpu** reschedule_cpu, void* arg, void* regs); struct irq { uint32_t irq_num; @@ -14,7 +15,7 @@ struct irq { void* arg; }; -bool irq_attach (irq_func_t, void* arg, uint32_t irq_num); +bool irq_attach (irq_func_t func, void* arg, uint32_t irq_num); void irq_detach (uint32_t irq_num); struct irq* irq_find (uint32_t irq_num); diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index 7582a44..42096c6 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -288,9 +288,10 @@ bool proc_kill (struct proc* proc, struct cpu** reschedule_cpu) { return PROC_NEED_RESCHEDULE; } -static void proc_irq_sched (void* arg, void* regs) { - (void)arg; +static bool proc_irq_sched (struct cpu** reschedule_cpu, void* arg, void* regs) { + (void)arg, (void)regs, (void)reschedule_cpu; proc_sched (); + return PROC_NO_RESCHEDULE; } void proc_init (void) { diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 6f917bb..d3e02f4 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -211,9 +211,14 @@ DEFINE_SYSCALL (sys_device_do) { if (device == NULL) return SYSRESULT (-ST_NOT_FOUND); + int ret; + spin_lock (&device->lock); - int ret = device->ops[cmd](proc, (void*)ka1, (void*)ka2, (void*)ka3, (void*)ka4); + if (device->ops[cmd](proc, reschedule_cpu, &ret, (void*)ka1, (void*)ka2, (void*)ka3, + (void*)ka4) == PROC_NEED_RESCHEDULE) { + *reschedule = true; + } spin_unlock (&device->lock);