Files
FEX-Emu--FEX/Source/Tools/FEXLoader/LinuxSyscalls/x64/Semaphore.cpp
T

93 lines
2.7 KiB
C++

// SPDX-License-Identifier: MIT
/*
$info$
tags: LinuxSyscalls|syscalls-x86-64
$end_info$
*/
#include "LinuxSyscalls/Syscalls.h"
#include "LinuxSyscalls/x64/Syscalls.h"
#include "LinuxSyscalls/x64/Types.h"
#include <FEXHeaderUtils/Syscalls.h>
#include <linux/sem.h>
#include <stddef.h>
#include <stdint.h>
namespace FEXCore::Core {
struct CpuStateFrame;
}
ARG_TO_STR(FEX::HLE::x64::semun, "%lx")
namespace FEX::HLE::x64 {
void RegisterSemaphore(FEX::HLE::SyscallHandler *Handler) {
REGISTER_SYSCALL_IMPL_X64_PASS(semop, [](FEXCore::Core::CpuStateFrame *Frame, int semid, struct sembuf *sops, size_t nsops) -> uint64_t {
uint64_t Result = ::syscall(SYSCALL_DEF(semop), semid, sops, nsops);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64_PASS(semtimedop, [](FEXCore::Core::CpuStateFrame *Frame, int semid, struct sembuf *sops, size_t nsops, const struct timespec *timeout) -> uint64_t {
uint64_t Result = ::syscall(SYSCALL_DEF(semtimedop), semid, sops, nsops, timeout);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(semctl, [](FEXCore::Core::CpuStateFrame *Frame, int semid, int semnum, int cmd, FEX::HLE::x64::semun semun) -> uint64_t {
uint64_t Result{};
switch (cmd) {
case IPC_SET: {
struct semid64_ds buf{};
buf = *semun.buf;
Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, &buf);
if (Result != -1) {
*semun.buf = buf;
}
break;
}
case SEM_STAT:
case SEM_STAT_ANY:
case IPC_STAT: {
struct semid64_ds buf{};
Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, &buf);
if (Result != -1) {
*semun.buf = buf;
}
break;
}
case SEM_INFO:
case IPC_INFO: {
struct fex_seminfo si{};
Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, &si);
if (Result != -1) {
memcpy(semun.__buf, &si, sizeof(si));
}
break;
}
case GETALL:
case SETALL: {
// ptr is just a int32_t* in this case
Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, semun.array);
break;
}
case SETVAL: {
// ptr is just a int32_t in this case
Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, semun.val);
break;
}
case IPC_RMID:
case GETPID:
case GETNCNT:
case GETZCNT:
case GETVAL:
Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, semun);
break;
default:
LOGMAN_MSG_A_FMT("Unhandled semctl cmd: {}", cmd);
return -EINVAL;
}
SYSCALL_ERRNO();
});
}
}