diff --git a/Source/AuProcAddresses.Linux.cpp b/Source/AuProcAddresses.Linux.cpp new file mode 100644 index 00000000..161a9ab5 --- /dev/null +++ b/Source/AuProcAddresses.Linux.cpp @@ -0,0 +1,188 @@ +/*** + Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: AuProcAddresses.Linux.cpp + Date: 2023-8-11 + Author: Reece +***/ +#include +#include +#include + +namespace Aurora +{ + #define read_barrier() __asm__ __volatile__("lfence" ::: "memory") + + static const auto kAioRingMagic = 0xa10a10a1u; + + void InitLinuxAddresses() + { + + } + + int pidfd_getfd(int pidfd, int targetfd, + unsigned int flags) + { + return syscall(SYS_pidfd_getfd, pidfd, targetfd, flags); + } + + int pidfd_open(pid_t pid, unsigned int flags) + { + return syscall(SYS_pidfd_open, pid, flags); + } + + long set_robust_list(struct robust_list_head *head, size_t len) + { + return syscall(SYS_set_robust_list, head, len); + } + + long get_robust_list(int pid, struct robust_list_head **head_ptr, size_t *len_ptr) + { + return syscall(SYS_get_robust_list, pid, head_ptr, len_ptr); + } + + static int futex(uint32_t *uaddr, int futex_op, uint32_t val, + const struct timespec *timeout, + uint32_t *uaddr2, uint32_t val3) + { + return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); + } + + int futex_wait(volatile uint32_t *addr, uint32_t expected) + { + return futex((uint32_t *)addr, FUTEX_WAIT, expected, 0, 0, 0); + } + + int futex_wait(volatile uint32_t *addr, uint32_t expected, const struct timespec *timeout) + { + if (timeout) + { + return futex((uint32_t *)addr, FUTEX_WAIT_BITSET, expected, timeout, 0, FUTEX_BITSET_MATCH_ANY); + } + else + { + return futex((uint32_t *)addr, FUTEX_WAIT, expected, timeout, 0, 0); + } + } + + int futex_wake(volatile uint32_t *addr, uint32_t nthreads) + { + return futex((uint32_t *)addr, FUTEX_WAKE, nthreads, 0, 0, 0); + } + + int futex_wait(uint32_t *addr, uint32_t expected) + { + return futex(addr, FUTEX_WAIT, expected, 0, 0, 0); + } + + int futex_wait(uint32_t *addr, uint32_t expected, const struct timespec *timeout) + { + if (timeout) + { + return futex(addr, FUTEX_WAIT_BITSET, expected, timeout, 0, FUTEX_BITSET_MATCH_ANY); + } + else + { + return futex(addr, FUTEX_WAIT, expected, timeout, 0, 0); + } + } + + int futex_wake(uint32_t *addr, uint32_t nthreads) + { + return futex(addr, FUTEX_WAKE, nthreads, 0, 0, 0); + } + + int io_setup(unsigned nr, aio_context_t *ctxp) + { + return syscall(__NR_io_setup, nr, ctxp); + } + + int io_destroy(aio_context_t ctx) + { + return syscall(__NR_io_destroy, ctx); + } + + int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) + { + return syscall(__NR_io_submit, ctx, nr, iocbpp); + } + + #if 0 + int io_getevents(aio_context_t ctx, long min_nr, long max_nr, + struct io_event *events, + struct timespec *timeout) + { + return syscall(__NR_io_getevents, ctx, min_nr, max_nr, events, timeout); + } + #endif + + struct aio_ring + { + unsigned id; + unsigned nr; + unsigned head; + unsigned tail; + + unsigned magic; + unsigned compat_features; + unsigned incompat_features; + unsigned header_length; + + struct io_event events[0]; + }; + + int io_getevents(aio_context_t ctx, + long min_nr, long max_nr, + struct io_event *events, + struct timespec *timeout) + { + int i {}; + + auto pRing = (struct aio_ring *)ctx; + + if (!pRing || + pRing->magic != kAioRingMagic) + { + goto do_syscall; + } + + while (i < max_nr) + { + auto head = pRing->head; + if (head == pRing->tail) + { + break; + } + + events[i++] = pRing->events[head]; + read_barrier(); + pRing->head = (head + 1) % pRing->nr; + } + + if (!i && + timeout && + !timeout->tv_sec && + !timeout->tv_nsec) + { + return 0; + } + + if (i && + i >= min_nr) + { + return i; + } + + do_syscall: + return syscall(__NR_io_getevents, + ctx, min_nr - i, + max_nr - i, + &events[i], timeout) + i; + } + + int io_cancel(aio_context_t ctx_id, struct iocb *iocb, + struct io_event *result) + { + return syscall(SYS_io_cancel, ctx_id, iocb, result); + } +} \ No newline at end of file diff --git a/Source/AuProcAddresses.Linux.hpp b/Source/AuProcAddresses.Linux.hpp new file mode 100644 index 00000000..1ea12280 --- /dev/null +++ b/Source/AuProcAddresses.Linux.hpp @@ -0,0 +1,55 @@ +/*** + Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: AuProcAddresses.Linux.hpp + Date: 2023-8-11 + Author: Reece +***/ +#pragma once + + +#include + +struct robust_list_head; + +namespace Aurora +{ + void InitLinuxAddresses(); + + int pidfd_getfd(int pidfd, int targetfd, + unsigned int flags); + + int pidfd_open(pid_t pid, unsigned int flags); + + long get_robust_list(int pid, struct robust_list_head **head_ptr, size_t *len_ptr); + + long set_robust_list(struct robust_list_head *head, size_t len); + + int futex_wake(volatile uint32_t *addr, uint32_t nthreads); + + int futex_wait(volatile uint32_t *addr, uint32_t expected, + const struct timespec *timeout); + + int futex_wait(volatile uint32_t *addr, uint32_t expected); + + int futex_wake(uint32_t *addr, uint32_t nthreads); + + int futex_wait(uint32_t *addr, uint32_t expected, + const struct timespec *timeout); + + int futex_wait(uint32_t *addr, uint32_t expected); + + + int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp); + + int io_cancel(aio_context_t ctx_id, struct iocb *iocb, + struct io_event *result); + + int io_destroy(aio_context_t ctx); + + int io_setup(unsigned nr, aio_context_t *ctxp); + + int io_getevents(aio_context_t ctx, long min_nr, long max_nr, + struct io_event *events, + struct timespec *timeout); +} \ No newline at end of file diff --git a/Source/AuProcAddresses.hpp b/Source/AuProcAddresses.hpp index cf025421..f76349d6 100644 --- a/Source/AuProcAddresses.hpp +++ b/Source/AuProcAddresses.hpp @@ -9,6 +9,8 @@ #if defined(AURORA_IS_MODERNNT_DERIVED) #include "AuProcAddresses.NT.hpp" +#elif defined(AURORA_IS_LINUX_DERIVED) + #include "AuProcAddresses.Linux.hpp" #endif namespace Aurora diff --git a/Source/IO/IPC/AuIPCMutexFutex.Linux.cpp b/Source/IO/IPC/AuIPCMutexFutex.Linux.cpp index 6cd625ab..69aac763 100644 --- a/Source/IO/IPC/AuIPCMutexFutex.Linux.cpp +++ b/Source/IO/IPC/AuIPCMutexFutex.Linux.cpp @@ -23,50 +23,6 @@ // ...TIME UTILS #include -//////////////////////////////////////////////////////////////////////////////////// -// SYSCALLS -//////////////////////////////////////////////////////////////////////////////////// - -static int futex(uint32_t *uaddr, int futex_op, uint32_t val, - const struct timespec *timeout, /* or: uint32_t val2 */ - uint32_t *uaddr2, uint32_t val3) -{ - return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); -} - -static int futex_wait(uint32_t *addr, uint32_t expected) -{ - return futex(addr, FUTEX_WAIT, expected, 0, 0, 0); -} - -static int futex_wait(uint32_t *addr, uint32_t expected, const struct timespec *timeout) -{ - if (timeout) - { - return futex(addr, FUTEX_WAIT_BITSET, expected, timeout, 0, FUTEX_BITSET_MATCH_ANY); - } - else - { - return futex(addr, FUTEX_WAIT, expected, timeout, 0, 0); - } -} - -static int futex_wake(uint32_t *addr, uint32_t nthreads) -{ - return futex(addr, FUTEX_WAKE, nthreads, 0, 0, 0); -} - -static long set_robust_list(struct robust_list_head *head, size_t len) -{ - return syscall(SYS_set_robust_list, head, len); -} - -static long get_robust_list(int pid, struct robust_list_head **head_ptr, size_t *len_ptr) -{ - return syscall(SYS_get_robust_list, pid, head_ptr, len_ptr); -} - - //////////////////////////////////////////////////////////////////////////////////// // CONSTANTS //////////////////////////////////////////////////////////////////////////////////// @@ -202,7 +158,7 @@ bool FutexContext::SetGrugSelf() this->futexArrayHeader.list_op_pending = NULL; // Update TLS - if (::set_robust_list(AuReinterpretCast(&this->futexArrayHeader.list), sizeof(robust_list_head)) != 0) + if (Aurora::set_robust_list(AuReinterpretCast(&this->futexArrayHeader.list), sizeof(robust_list_head)) != 0) { SysPushErrorIO("Set robust list failed"); return false; @@ -366,7 +322,7 @@ static bool LinuxLockFutex(AuUInt32 *futex, AuUInt32 timeout) bContended = old != kFutexValueUnlocked; if (bContended) { - int res = ::futex_wait(futex, old, timeout ? &tspec : nullptr); + int res = Aurora::futex_wait(futex, old, timeout ? &tspec : nullptr); if (res < 0) { if (res == ETIMEDOUT || errno == ETIMEDOUT) @@ -419,7 +375,7 @@ static bool LinuxUnlockFutex(AuUInt32 *futex) return false; } - ::futex_wake(futex, 1); + Aurora::futex_wake(futex, 1); return true; } diff --git a/Source/IO/UNIX/FDIpcServer.cpp b/Source/IO/UNIX/FDIpcServer.cpp index e14abc17..3a6bbf21 100644 --- a/Source/IO/UNIX/FDIpcServer.cpp +++ b/Source/IO/UNIX/FDIpcServer.cpp @@ -16,17 +16,6 @@ #if defined(AURORA_IS_LINUX_DERIVED) -static int pidfd_getfd(int pidfd, int targetfd, - unsigned int flags) -{ - return syscall(SYS_pidfd_getfd, pidfd, targetfd, flags); -} - -static int pidfd_open(pid_t pid, unsigned int flags) -{ - return syscall(SYS_pidfd_open, pid, flags); -} - #if !defined(PIDFD_NONBLOCK) #define PIDFD_NONBLOCK O_NONBLOCK #endif @@ -397,14 +386,14 @@ namespace Aurora::IO::UNIX { #if defined(AURORA_IS_LINUX_DERIVED) - int pid = ::pidfd_open(handle.ToUnixPid(), 0); + int pid = pidfd_open(handle.ToUnixPid(), 0); if (pid <= 0) { SysPushErrorIO("Couldn't open IPC server pid, error: {}", pid); return false; } - int result = ::pidfd_getfd(pid, handle.cookie, 0); + int result = pidfd_getfd(pid, handle.cookie, 0); if (result <= 0) { SysPushErrorIO("Couldn't get IPC fd, error: {} {}", result, errno); diff --git a/Source/IO/UNIX/IOSubmit.Linux.cpp b/Source/IO/UNIX/IOSubmit.Linux.cpp index caecdee8..4fc3fa73 100644 --- a/Source/IO/UNIX/IOSubmit.Linux.cpp +++ b/Source/IO/UNIX/IOSubmit.Linux.cpp @@ -18,97 +18,6 @@ #include #include -static int io_setup(unsigned nr, aio_context_t *ctxp) -{ - return syscall(__NR_io_setup, nr, ctxp); -} - -static int io_destroy(aio_context_t ctx) -{ - return syscall(__NR_io_destroy, ctx); -} - -static int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) -{ - return syscall(__NR_io_submit, ctx, nr, iocbpp); -} - -#if 0 -static int io_getevents(aio_context_t ctx, long min_nr, long max_nr, - struct io_event *events, - struct timespec *timeout) -{ - return syscall(__NR_io_getevents, ctx, min_nr, max_nr, events, timeout); -} -#endif - -#define read_barrier() __asm__ __volatile__("lfence" ::: "memory") - -#define AIO_RING_MAGIC 0xa10a10a1 - -struct aio_ring { - unsigned id; /** kernel internal index number */ - unsigned nr; /** number of io_events */ - unsigned head; - unsigned tail; - - unsigned magic; - unsigned compat_features; - unsigned incompat_features; - unsigned header_length; /** size of aio_ring */ - - struct io_event events[0]; -}; - -/* Code based on axboe/fio: - * https://github.com/axboe/fio/blob/702906e9e3e03e9836421d5e5b5eaae3cd99d398/engines/libaio.c#L149-L172 -*/ -static int io_getevents(aio_context_t ctx, long min_nr, long max_nr, - struct io_event *events, - struct timespec *timeout) -{ - int i = 0; - - struct aio_ring *ring = (struct aio_ring *)ctx; - if (ring == NULL || ring->magic != AIO_RING_MAGIC) { - goto do_syscall; - } - - while (i < max_nr) { - unsigned head = ring->head; - if (head == ring->tail) { - /* There are no more completions */ - break; - } else { - /* There is another completion to reap */ - events[i] = ring->events[head]; - read_barrier(); - ring->head = (head + 1) % ring->nr; - i++; - } - } - - if (i == 0 && timeout != NULL && timeout->tv_sec == 0 && - timeout->tv_nsec == 0) { - /* Requested non blocking operation. */ - return 0; - } - - if (i && i >= min_nr) { - return i; - } - -do_syscall: - return syscall(__NR_io_getevents, ctx, min_nr - i, max_nr - i, - &events[i], timeout) + i; -} - -static int io_cancel(aio_context_t ctx_id, struct iocb *iocb, - struct io_event *result) -{ - return syscall(SYS_io_cancel, ctx_id, iocb, result); -} - namespace Aurora::IO::UNIX { static bool LinuxOverlappedSubmit(int fd, int op, AuUInt offset, ASubmittable *context, AuLoop::ILSEvent *optEvent); diff --git a/Source/Threading/AuWakeOnAddress.cpp b/Source/Threading/AuWakeOnAddress.cpp index 654e7859..59e2ff26 100644 --- a/Source/Threading/AuWakeOnAddress.cpp +++ b/Source/Threading/AuWakeOnAddress.cpp @@ -14,8 +14,6 @@ #endif #if defined(AURORA_IS_LINUX_DERIVED) - #include - #include #include #endif @@ -32,32 +30,6 @@ namespace Aurora::Threading static thread_local WaitEntry tlsWaitEntry; #endif -#if defined(AURORA_IS_LINUX_DERIVED) - static int futex(uint32_t *uaddr, int futex_op, uint32_t val, - const struct timespec *timeout, - uint32_t *uaddr2, uint32_t val3) - { - return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); - } - - static int futex_wait(uint32_t *addr, uint32_t expected, const struct timespec *timeout) - { - if (timeout) - { - return futex(addr, FUTEX_WAIT_BITSET, expected, timeout, 0, FUTEX_BITSET_MATCH_ANY); - } - else - { - return futex(addr, FUTEX_WAIT, expected, timeout, 0, 0); - } - } - - static int futex_wake(uint32_t *addr, uint32_t nthreads) - { - return futex(addr, FUTEX_WAKE, nthreads, 0, 0, 0); - } -#endif - static ProcessWaitContainer gProcessWaitables; static int gShouldSpinOnlyInCPU = 1; // TODO: havent decided diff --git a/Source/Threading/Primitives/AuMutex.Linux.cpp b/Source/Threading/Primitives/AuMutex.Linux.cpp index 63f50579..17743c4b 100755 --- a/Source/Threading/Primitives/AuMutex.Linux.cpp +++ b/Source/Threading/Primitives/AuMutex.Linux.cpp @@ -20,35 +20,6 @@ namespace Aurora::Threading::Primitives #define barrier() __asm__ __volatile__("sfence": : :"memory") #define compilerReorderBarrier() __asm__ __volatile__("": : :"memory") - static int futex(uint32_t *uaddr, int futex_op, uint32_t val, - const struct timespec *timeout, - uint32_t *uaddr2, uint32_t val3) - { - return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); - } - - static int futex_wait(volatile uint32_t *addr, uint32_t expected) - { - return futex((uint32_t *)addr, FUTEX_WAIT, expected, 0, 0, 0); - } - - static int futex_wait(volatile uint32_t *addr, uint32_t expected, const struct timespec *timeout) - { - if (timeout) - { - return futex((uint32_t *)addr, FUTEX_WAIT_BITSET, expected, timeout, 0, FUTEX_BITSET_MATCH_ANY); - } - else - { - return futex((uint32_t *)addr, FUTEX_WAIT, expected, timeout, 0, 0); - } - } - - static int futex_wake(volatile uint32_t *addr, uint32_t nthreads) - { - return futex((uint32_t *)addr, FUTEX_WAKE, nthreads, 0, 0, 0); - } - MutexImpl::MutexImpl() { diff --git a/Source/Threading/Primitives/AuSemaphore.Linux.cpp b/Source/Threading/Primitives/AuSemaphore.Linux.cpp index 5879ff03..28bed5ae 100644 --- a/Source/Threading/Primitives/AuSemaphore.Linux.cpp +++ b/Source/Threading/Primitives/AuSemaphore.Linux.cpp @@ -9,43 +9,11 @@ #include "AuSemaphore.Generic.hpp" #include "SMTYield.hpp" -#include -#include - #if !defined(_AURUNTIME_GENERIC_SEMAPHORE) #include namespace Aurora::Threading::Primitives { - static int futex(uint32_t *uaddr, int futex_op, uint32_t val, - const struct timespec *timeout, - uint32_t *uaddr2, uint32_t val3) - { - return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); - } - - static int futex_wait(uint32_t *addr, uint32_t expected) - { - return futex(addr, FUTEX_WAIT, expected, 0, 0, 0); - } - - static int futex_wait(uint32_t *addr, uint32_t expected, const struct timespec *timeout) - { - if (timeout) - { - return futex(addr, FUTEX_WAIT_BITSET, expected, timeout, 0, FUTEX_BITSET_MATCH_ANY); - } - else - { - return futex(addr, FUTEX_WAIT, expected, timeout, 0, 0); - } - } - - static int futex_wake(uint32_t *addr, uint32_t nthreads) - { - return futex(addr, FUTEX_WAKE, nthreads, 0, 0, 0); - } - SemaphoreImpl::SemaphoreImpl(long intialValue) : value_(intialValue) {