[+] AuProcAddresses.Linux.*

This commit is contained in:
Reece Wilson 2023-08-12 10:16:20 +01:00
parent 1f173a8799
commit 737d3bb4d6
9 changed files with 250 additions and 240 deletions

View 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);
}
}

View 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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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()
{

View File

@ -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)
{