225 lines
5.7 KiB
C++
225 lines
5.7 KiB
C++
/***
|
|
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>
|
|
#include <sys/random.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(uint32_t *addr, uint32_t expected)
|
|
{
|
|
return futex(addr, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 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 | FUTEX_PRIVATE_FLAG, expected, timeout, 0, FUTEX_BITSET_MATCH_ANY);
|
|
}
|
|
else
|
|
{
|
|
return futex(addr, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, expected, timeout, 0, 0);
|
|
}
|
|
}
|
|
|
|
int futex_wait_shared(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 | FUTEX_PRIVATE_FLAG, nthreads, 0, 0, 0);
|
|
}
|
|
|
|
int futex_wake_shared(uint32_t *addr, uint32_t nthreads)
|
|
{
|
|
return futex(addr, FUTEX_WAKE, nthreads, 0, 0, 0);
|
|
}
|
|
|
|
int futex_wait(volatile uint32_t *addr, uint32_t expected)
|
|
{
|
|
return futex((uint32_t *)addr, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 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 | FUTEX_PRIVATE_FLAG, expected, timeout, 0, FUTEX_BITSET_MATCH_ANY);
|
|
}
|
|
else
|
|
{
|
|
return futex((uint32_t *)addr, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, expected, timeout, 0, 0);
|
|
}
|
|
}
|
|
|
|
int futex_wake(volatile uint32_t *addr, uint32_t nthreads)
|
|
{
|
|
return futex((uint32_t *)addr, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 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);
|
|
}
|
|
|
|
ssize_t sys_getrandom(void *pBuffer, size_t uLength)
|
|
{
|
|
static AuUInt32 gShouldNotGetRand {};
|
|
ssize_t ret {};
|
|
|
|
if (gShouldNotGetRand)
|
|
{
|
|
return ENOSYS;
|
|
}
|
|
|
|
ret = syscall(SYS_getrandom, pBuffer, uLength, 1);
|
|
if (ret == ENOSYS)
|
|
{
|
|
gShouldNotGetRand = 1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
} |