From: Tulio A M Mendes Date: Thu, 12 Feb 2026 03:53:40 +0000 (-0300) Subject: feat: futex syscall (85) — FUTEX_WAIT/FUTEX_WAKE with global waiter table + ulibc... X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=aa90b30d122dae4d44c5a0ec3e609c6f060c4c4e;p=AdrOS.git feat: futex syscall (85) — FUTEX_WAIT/FUTEX_WAKE with global waiter table + ulibc wrapper --- diff --git a/include/syscall.h b/include/syscall.h index b53b86b..f1b67dc 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -108,6 +108,7 @@ enum { SYSCALL_WRITEV = 82, SYSCALL_ALARM = 83, SYSCALL_TIMES = 84, + SYSCALL_FUTEX = 85, }; #endif diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index ee9053a..d0821f2 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -2272,7 +2272,7 @@ void syscall_handler(struct registers* regs) { return; } - if (syscall_no == SYSCALL_TIMES) { + if (syscall_no == SYSCALL_TIMES || syscall_no == SYSCALL_FUTEX) { posix_ext_syscall_dispatch(regs, syscall_no); return; } @@ -2453,6 +2453,62 @@ static void posix_ext_syscall_dispatch(struct registers* regs, uint32_t syscall_ return; } + if (syscall_no == SYSCALL_FUTEX) { + #define FUTEX_WAIT 0 + #define FUTEX_WAKE 1 + #define FUTEX_MAX_WAITERS 32 + static struct { uintptr_t addr; struct process* proc; } futex_waiters[FUTEX_MAX_WAITERS]; + + uint32_t* uaddr = (uint32_t*)regs->ebx; + int op = (int)regs->ecx; + uint32_t val = regs->edx; + + if (!uaddr) { regs->eax = (uint32_t)-EFAULT; return; } + + if (op == FUTEX_WAIT) { + uint32_t cur = 0; + if (copy_from_user(&cur, uaddr, sizeof(cur)) < 0) { + regs->eax = (uint32_t)-EFAULT; return; + } + if (cur != val) { regs->eax = (uint32_t)-EAGAIN; return; } + /* Add to waiter list and sleep */ + int slot = -1; + for (int i = 0; i < FUTEX_MAX_WAITERS; i++) { + if (!futex_waiters[i].proc) { slot = i; break; } + } + if (slot < 0) { regs->eax = (uint32_t)-ENOMEM; return; } + futex_waiters[slot].addr = (uintptr_t)uaddr; + futex_waiters[slot].proc = current_process; + extern void schedule(void); + current_process->state = PROCESS_SLEEPING; + current_process->wake_at_tick = get_tick_count() + 5000; /* 100s timeout */ + schedule(); + futex_waiters[slot].proc = 0; + futex_waiters[slot].addr = 0; + regs->eax = 0; + return; + } + + if (op == FUTEX_WAKE) { + int woken = 0; + int max_wake = (int)val; + if (max_wake <= 0) max_wake = 1; + for (int i = 0; i < FUTEX_MAX_WAITERS && woken < max_wake; i++) { + if (futex_waiters[i].proc && futex_waiters[i].addr == (uintptr_t)uaddr) { + futex_waiters[i].proc->state = PROCESS_READY; + futex_waiters[i].proc = 0; + futex_waiters[i].addr = 0; + woken++; + } + } + regs->eax = (uint32_t)woken; + return; + } + + regs->eax = (uint32_t)-ENOSYS; + return; + } + if (syscall_no == SYSCALL_TIMES) { if (!current_process) { regs->eax = (uint32_t)-EINVAL; return; } struct { uint32_t tms_utime; uint32_t tms_stime; uint32_t tms_cutime; uint32_t tms_cstime; } tms; diff --git a/user/ulibc/include/linux/futex.h b/user/ulibc/include/linux/futex.h new file mode 100644 index 0000000..bace856 --- /dev/null +++ b/user/ulibc/include/linux/futex.h @@ -0,0 +1,11 @@ +#ifndef ULIBC_LINUX_FUTEX_H +#define ULIBC_LINUX_FUTEX_H + +#include + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +int futex(uint32_t* uaddr, int op, uint32_t val); + +#endif diff --git a/user/ulibc/include/syscall.h b/user/ulibc/include/syscall.h index 31cbe78..ebc3bcc 100644 --- a/user/ulibc/include/syscall.h +++ b/user/ulibc/include/syscall.h @@ -67,6 +67,7 @@ enum { SYS_WRITEV = 82, SYS_ALARM = 83, SYS_TIMES = 84, + SYS_FUTEX = 85, }; /* Raw syscall wrappers — up to 5 args via INT 0x80 */ diff --git a/user/ulibc/src/futex.c b/user/ulibc/src/futex.c new file mode 100644 index 0000000..c84917d --- /dev/null +++ b/user/ulibc/src/futex.c @@ -0,0 +1,6 @@ +#include "linux/futex.h" +#include "syscall.h" + +int futex(uint32_t* uaddr, int op, uint32_t val) { + return _syscall3(SYS_FUTEX, (int)uaddr, op, (int)val); +}