[+] AuProcAddresses.Linux.*
This commit is contained in:
parent
1f173a8799
commit
737d3bb4d6
188
Source/AuProcAddresses.Linux.cpp
Normal file
188
Source/AuProcAddresses.Linux.cpp
Normal file
@ -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 <RuntimeInternal.hpp>
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
55
Source/AuProcAddresses.Linux.hpp
Normal file
55
Source/AuProcAddresses.Linux.hpp
Normal file
@ -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 <linux/aio_abi.h>
|
||||
|
||||
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);
|
||||
}
|
@ -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
|
||||
|
@ -23,50 +23,6 @@
|
||||
// ...TIME UTILS
|
||||
#include <Source/Time/Time.hpp>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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<robust_list_head *>(&this->futexArrayHeader.list), sizeof(robust_list_head)) != 0)
|
||||
if (Aurora::set_robust_list(AuReinterpretCast<robust_list_head *>(&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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -18,97 +18,6 @@
|
||||
#include <Source/IO/Loop/Loop.hpp>
|
||||
#include <Source/IO/Loop/LSEvent.hpp>
|
||||
|
||||
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);
|
||||
|
@ -14,8 +14,6 @@
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
#include <linux/futex.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#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
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
|
||||
|
@ -9,43 +9,11 @@
|
||||
#include "AuSemaphore.Generic.hpp"
|
||||
#include "SMTYield.hpp"
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
|
||||
#if !defined(_AURUNTIME_GENERIC_SEMAPHORE)
|
||||
#include <Source/Time/Time.hpp>
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user