From 3169ec51cbd7194c8bb148bb26c01f563f8e7bae Mon Sep 17 00:00:00 2001 From: boreddevnl Date: Thu, 2 Apr 2026 20:21:06 +0200 Subject: [PATCH] FEAT: SYSTEM_CMD_PARALLEL_RUN --- src/sys/syscall.c | 67 ++++++++++++++++++++++++++++++++++++- src/sys/syscall.h | 1 + src/userland/libc/syscall.c | 4 +++ src/userland/libc/syscall.h | 1 + 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/sys/syscall.c b/src/sys/syscall.c index 9d8b8b8..310dd78 100644 --- a/src/sys/syscall.c +++ b/src/sys/syscall.c @@ -36,9 +36,44 @@ static inline void wrmsr(uint32_t msr, uint64_t value) { } extern void isr128_wrapper(void); +extern void* kmalloc(size_t size); +extern void kfree(void* ptr); + +typedef struct { + void (*fn)(void *); + void *arg; + uint64_t pml4_phys; + volatile int *completion_counter; +} smp_user_task_t; + +static void smp_user_wrapper(void *arg) { + smp_user_task_t *task = (smp_user_task_t *)arg; + if (!task) return; + + uint64_t old_cr3; + asm volatile("mov %%cr3, %0" : "=r"(old_cr3)); + + // Switch to user address space if necessary + bool switch_cr3 = (task->pml4_phys != 0 && task->pml4_phys != old_cr3); + if (switch_cr3) { + asm volatile("mov %0, %%cr3" :: "r"(task->pml4_phys) : "memory"); + } + + if (task->fn) { + task->fn(task->arg); + } + + if (switch_cr3) { + asm volatile("mov %0, %%cr3" :: "r"(old_cr3) : "memory"); + } + + if (task->completion_counter) { + __sync_fetch_and_add(task->completion_counter, -1); + } + +} void syscall_init(void) { - // SMP-Safe System Calls using int 0x80 (configured in idt.c) } static void user_window_close(Window *win) { @@ -1280,6 +1315,36 @@ static uint64_t syscall_handler_inner(registers_t *regs) { extern void get_os_info(os_info_t *info); get_os_info(info); return 0; + } else if (cmd == SYSTEM_CMD_PARALLEL_RUN) { + void (*user_fn)(void*) = (void (*)(void*))arg2; + void **args = (void **)arg3; + int count = (int)arg4; + + if (count <= 0) return 0; + if (count > 64) count = 64; + + volatile int completion_counter = count; + uint64_t current_pml4 = proc->pml4_phys; + + smp_user_task_t tasks[64]; + + for (int i = 0; i < count; i++) { + tasks[i].fn = user_fn; + tasks[i].arg = args[i]; + tasks[i].pml4_phys = current_pml4; + tasks[i].completion_counter = &completion_counter; + + extern void work_queue_submit(void (*fn)(void*), void *arg); + work_queue_submit(smp_user_wrapper, &tasks[i]); + } + + extern bool work_queue_drain_one(void); + while (completion_counter > 0) { + if (!work_queue_drain_one()) { + asm volatile("pause"); + } + } + return 0; } return -1; } diff --git a/src/sys/syscall.h b/src/sys/syscall.h index 2301165..86305d7 100644 --- a/src/sys/syscall.h +++ b/src/sys/syscall.h @@ -58,6 +58,7 @@ typedef struct { #define SYSTEM_CMD_SLEEP 46 #define SYSTEM_CMD_SET_RESOLUTION 47 #define SYSTEM_CMD_GET_OS_INFO 49 +#define SYSTEM_CMD_PARALLEL_RUN 50 void syscall_init(void); uint64_t syscall_handler_c(registers_t *regs); diff --git a/src/userland/libc/syscall.c b/src/userland/libc/syscall.c index 2be5e55..2148ccb 100644 --- a/src/userland/libc/syscall.c +++ b/src/userland/libc/syscall.c @@ -255,3 +255,7 @@ int sys_get_os_info(os_info_t *info) { return (int)syscall5(SYS_SYSTEM, SYSTEM_CMD_GET_OS_INFO, (uint64_t)info, 0, 0, 0); } +void sys_parallel_run(void (*fn)(void*), void **args, int count) { + syscall5(SYS_SYSTEM, SYSTEM_CMD_PARALLEL_RUN, (uint64_t)fn, (uint64_t)args, (uint64_t)count, 0); +} + diff --git a/src/userland/libc/syscall.h b/src/userland/libc/syscall.h index 595f952..95dd037 100644 --- a/src/userland/libc/syscall.h +++ b/src/userland/libc/syscall.h @@ -76,6 +76,7 @@ #define SYSTEM_CMD_TCP_RECV_NB 42 #define SYSTEM_CMD_YIELD 43 #define SYSTEM_CMD_GET_OS_INFO 49 +#define SYSTEM_CMD_PARALLEL_RUN 50 // Internal assembly entry into Ring 0 extern uint64_t syscall0(uint64_t sys_num);