]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: futex syscall (85) — FUTEX_WAIT/FUTEX_WAKE with global waiter table + ulibc...
authorTulio A M Mendes <[email protected]>
Thu, 12 Feb 2026 03:53:40 +0000 (00:53 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:20:50 +0000 (23:20 -0300)
include/syscall.h
src/kernel/syscall.c
user/ulibc/include/linux/futex.h [new file with mode: 0644]
user/ulibc/include/syscall.h
user/ulibc/src/futex.c [new file with mode: 0644]

index b53b86be0f604711fb4941e8f7c4003b264ae922..f1b67dc9a0b7b5454572ee15c75b46035be8de58 100644 (file)
@@ -108,6 +108,7 @@ enum {
     SYSCALL_WRITEV    = 82,
     SYSCALL_ALARM     = 83,
     SYSCALL_TIMES     = 84,
+    SYSCALL_FUTEX     = 85,
 };
 
 #endif
index ee9053ae88e12f24bcdda5e873db1aa87e49e70b..d0821f2b5ebb3b2340d6c9704166eb36e2ac1205 100644 (file)
@@ -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 (file)
index 0000000..bace856
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef ULIBC_LINUX_FUTEX_H
+#define ULIBC_LINUX_FUTEX_H
+
+#include <stdint.h>
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+
+int futex(uint32_t* uaddr, int op, uint32_t val);
+
+#endif
index 31cbe78ac2f399cbf5d0156132826191d7e8a824..ebc3bccafc1b59373147c36679d9a2a9b43ef004 100644 (file)
@@ -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 (file)
index 0000000..c84917d
--- /dev/null
@@ -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);
+}