diff --git a/kernel/api/futex.h b/kernel/api/futex.h index 6a330cd0..9a307677 100644 --- a/kernel/api/futex.h +++ b/kernel/api/futex.h @@ -4,9 +4,8 @@ #pragma once #include "types.h" -#define FUTEX_INIT 1 -#define FUTEX_DESTROY 2 -#define FUTEX_WAIT 3 +#define FUTEX_WAIT 1 +#define FUTEX_REGFD 2 __DECL_BEGIN diff --git a/kernel/syscall/futex.cpp b/kernel/syscall/futex.cpp index 0fac9f3c..516b2921 100644 --- a/kernel/syscall/futex.cpp +++ b/kernel/syscall/futex.cpp @@ -2,8 +2,10 @@ /* Copyright © 2016-2024 Byteduck */ #include "../tasking/Process.h" -#include "../kernel/api/futex.h" -#include "../kernel/memory/SafePointer.h" +#include "../api/futex.h" +#include "../memory/SafePointer.h" +#include "../filesystem/FileDescriptor.h" +#include "../tasking/Futex.h" int Process::sys_futex(UserspacePointer futex, int op) { auto addr = (uintptr_t) futex.raw(); @@ -17,29 +19,17 @@ int Process::sys_futex(UserspacePointer futex, int op) { return -EPERM; switch (op) { - case FUTEX_INIT: { - LOCK(m_futex_lock); - if (m_futexes.contains(addr)) - return -EEXIST; - m_futexes[addr] = kstd::Arc(new Futex(reg->object(), addr - reg->start())); - return SUCCESS; - } - case FUTEX_DESTROY: { - LOCK(m_futex_lock); - if (!m_futexes.contains(addr)) - return -ENOENT; - m_futexes.erase(addr); - } - case FUTEX_WAIT: { - auto k_futex = m_futex_lock.synced>([this, addr]() { - auto node = m_futexes.find_node(addr); - if (!node) - return kstd::Arc(); - return node->data.second; + case FUTEX_REGFD: + return m_fd_lock.synced([this, addr, reg] { + auto futex = kstd::Arc(new Futex(reg->object(), addr - reg->start())); + auto fd = kstd::Arc(new FileDescriptor(futex, this)); + _file_descriptors.push_back(fd); + fd->set_id((int) _file_descriptors.size() - 1); + return (int)_file_descriptors.size() - 1; }); - if (!k_futex) - return -ENOENT; - TaskManager::current_thread()->block(*k_futex); + case FUTEX_WAIT: { + Futex k_futex {reg->object(), addr - reg->start()}; + TaskManager::current_thread()->block(k_futex); return SUCCESS; } default: diff --git a/kernel/tasking/Futex.cpp b/kernel/tasking/Futex.cpp index cff1ced8..559e1e4b 100644 --- a/kernel/tasking/Futex.cpp +++ b/kernel/tasking/Futex.cpp @@ -14,4 +14,8 @@ Futex::Futex(kstd::Arc object, size_t offset_in_object): bool Futex::is_ready() { return m_var->load(MemoryOrder::Relaxed) > 0; -} \ No newline at end of file +} + +bool Futex::can_read(const FileDescriptor& fd) { + return is_ready(); +} diff --git a/kernel/tasking/Futex.h b/kernel/tasking/Futex.h index 96317815..a515828f 100644 --- a/kernel/tasking/Futex.h +++ b/kernel/tasking/Futex.h @@ -5,13 +5,18 @@ #include "Blocker.h" #include "../memory/VMRegion.h" +#include "../filesystem/File.h" -class Futex: public Blocker { +class Futex: public Blocker, public File { public: Futex(kstd::Arc object, size_t offset_in_object); + // Blocker bool is_ready() override; + // File + bool can_read(const FileDescriptor& fd) override; + private: kstd::Arc m_object; kstd::Arc m_k_region; diff --git a/kernel/tasking/Process.h b/kernel/tasking/Process.h index 425554e3..0382d256 100644 --- a/kernel/tasking/Process.h +++ b/kernel/tasking/Process.h @@ -30,7 +30,6 @@ #include "../api/mmap.h" #include "Tracer.h" #include "../kstd/KLog.h" -#include "Futex.h" class FileDescriptor; class Blocker; @@ -245,8 +244,6 @@ class Process { Mutex m_fd_lock { "Process::FileDescriptor" }; kstd::vector> _file_descriptors; kstd::Arc _cwd; - Mutex m_futex_lock { "Process::Futexes" }; - kstd::map> m_futexes; //Signals Signal::SigAction signal_actions[32] = {{Signal::SigAction()}}; diff --git a/libraries/libc/dlfcn.h b/libraries/libc/dlfcn.h index 82189d8a..54bc5718 100644 --- a/libraries/libc/dlfcn.h +++ b/libraries/libc/dlfcn.h @@ -12,6 +12,7 @@ __DECL_BEGIN #define RTLD_LAZY 2 #define RTLD_NOW 4 #define RTLD_LOCAL 8 +#define RTLD_GLOBAL 16 void* dlopen(const char*, int); int dlclose(void*); diff --git a/libraries/libc/sys/futex.c b/libraries/libc/sys/futex.c index 8ef3c277..97a1e84d 100644 --- a/libraries/libc/sys/futex.c +++ b/libraries/libc/sys/futex.c @@ -4,13 +4,8 @@ #include "futex.h" #include "syscall.h" -int futex_init(futex_t* futex, int val) { - *futex = val; - return syscall3(SYS_FUTEX, (int) futex, FUTEX_INIT); -} - -int futex_destroy(futex_t* futex) { - return syscall3(SYS_FUTEX, (int) futex, FUTEX_DESTROY); +int futex_open(futex_t* futex) { + return syscall3(SYS_FUTEX, (int) futex, FUTEX_REGFD); } void futex_wait(futex_t* futex) { @@ -20,13 +15,25 @@ void futex_wait(futex_t* futex) { if (__atomic_compare_exchange_n(futex, &exp, exp - 1, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) break; } else { - if (syscall3_noerr(SYS_FUTEX, (int) futex, FUTEX_WAIT)) - return; + syscall3_noerr(SYS_FUTEX, (int) futex, FUTEX_WAIT); exp = __atomic_load_n(futex, __ATOMIC_RELAXED); } } } +int futex_trywait(futex_t* futex) { + int exp = __atomic_load_n(futex, __ATOMIC_RELAXED); + while (1) { + if (exp > 0) { + if (__atomic_compare_exchange_n(futex, &exp, exp - 1, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) + break; + } else { + return 0; + } + } + return 1; +} + void futex_signal(futex_t* futex) { __atomic_fetch_add(futex, 1, __ATOMIC_ACQUIRE); } \ No newline at end of file diff --git a/libraries/libc/sys/futex.h b/libraries/libc/sys/futex.h index c0c8ed0a..f48e22df 100644 --- a/libraries/libc/sys/futex.h +++ b/libraries/libc/sys/futex.h @@ -7,19 +7,11 @@ __DECL_BEGIN /** - * Initializes a futex. + * Registers a futex to a file descriptor, so that it can be waited on using poll(). * @param futex Pointer to the futex_t to initialize. - * @param val The value to initialize the futex with. - * @return 0 on success, -1 on error (errno set). + * @return file descriptor on success, -1 on error (errno set). */ -int futex_init(futex_t* futex, int val); - -/** - * Destroys a futex. - * @param futex Pointer to the futex to destroy. - * @return 0 on success, -1 on error (errno set). - */ -int futex_destroy(futex_t* futex); +int futex_open(futex_t* futex); /** * Waits for a futex to be greater than zero and then subtracts one from its stored value. @@ -27,6 +19,13 @@ int futex_destroy(futex_t* futex); */ void futex_wait(futex_t* futex); +/** + * Tries to wait for a futex to be greater than zero and subtracts one from its stored value if successful. + * @param futex Pointer to the futex to try waiting on. + * @return 1 if the futex was waited on, 0 if not. + */ +int futex_trywait(futex_t* futex); + /** * Adds one to the futex's stored value. * @param futex Poitner to the futex to signal.