]> 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 b2c8426ff3bd6a8eb6d2060f49826e060282f7bb..f8d964cde09156777d42432cf0d61e4e8255fb75 100644 (file)
@@ -117,6 +117,7 @@ enum {
     SYSCALL_WRITEV    = 82,
     SYSCALL_ALARM     = 83,
     SYSCALL_TIMES     = 84,
+    SYSCALL_FUTEX     = 85,
 };
 
 #endif
index 6d4abd8435ff99bc1c6e2fa4c7faea2897e6764b..8434ca430590e96a4a28df3a5db3af7694ad8d8e 100644 (file)
@@ -2281,7 +2281,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;
     }
@@ -2462,6 +2462,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..7094fa4
--- /dev/null
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2018, Tulio A M Mendes <[email protected]>
+ * All rights reserved.
+ * See LICENSE for details.
+ *
+ * Source: https://github.com/tadryanom/AdrOS
+ */
+
+#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 e2e9fb718b2a4305aeee9df78b5263cae091476d..ef02a53e8786a95a3147e5026a8aa7db983ded10 100644 (file)
@@ -76,6 +76,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..32cef87
--- /dev/null
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2018, Tulio A M Mendes <[email protected]>
+ * All rights reserved.
+ * See LICENSE for details.
+ *
+ * Source: https://github.com/tadryanom/AdrOS
+ */
+
+#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);
+}