/*** 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 #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(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; } }