rpcsx/orbis-kernel/src/sys/sys_sig.cpp
DH 9fbe1846c0 orbis-kernel: unblock signals only on wait operations
implement sys_cpuset_getaffinity, sys_cpuset_setaffinity, sys_rtprio_thread
fix hang on sys_select
simplify sys_thr_*_ucontext
2024-11-13 21:53:05 +03:00

154 lines
4.5 KiB
C++

#include "KernelContext.hpp"
#include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/Thread.hpp"
#include "ucontext.hpp"
#include "utils/Logs.hpp"
#include <csignal>
orbis::SysResult orbis::sys_sigaction(Thread *thread, sint sig,
ptr<SigAction> act, ptr<SigAction> oact) {
ORBIS_LOG_WARNING(__FUNCTION__, sig, act, oact);
auto &sigAct = thread->tproc->sigActions[sig];
if (oact != nullptr) {
if (auto errc = uwrite(oact, sigAct); errc != orbis::ErrorCode{}) {
return errc;
}
}
if (act != nullptr) {
if (auto errc = uread(sigAct, act); errc != ErrorCode{}) {
return errc;
}
ORBIS_LOG_WARNING(__FUNCTION__, sigAct.handler, sigAct.flags,
sigAct.mask.bits[0], sigAct.mask.bits[1],
sigAct.mask.bits[2], sigAct.mask.bits[3]);
}
return {};
}
orbis::SysResult orbis::sys_sigprocmask(Thread *thread, sint how,
ptr<SigSet> set, ptr<SigSet> oset) {
std::lock_guard lock(thread->mtx);
if (oset) {
ORBIS_RET_ON_ERROR(uwrite(oset, thread->sigMask));
}
if (set) {
SigSet _set;
ORBIS_RET_ON_ERROR(uread(_set, set));
auto newSigMask = thread->sigMask;
auto oldSigMask = newSigMask;
switch (how) {
case 1: // block
for (std::size_t i = 0; i < 4; ++i) {
newSigMask.bits[i] |= _set.bits[i];
}
break;
case 2: // unblock
for (std::size_t i = 0; i < 4; ++i) {
newSigMask.bits[i] &= ~_set.bits[i];
}
break;
case 3: // set
newSigMask = _set;
break;
default:
ORBIS_LOG_ERROR("sys_sigprocmask: unimplemented how", how);
thread->where();
return ErrorCode::INVAL;
}
newSigMask.clear(kSigKill);
newSigMask.clear(kSigStop);
thread->sigMask = newSigMask;
for (std::size_t word = 0; word < std::size(newSigMask.bits); ++word) {
auto unblockedBits = ~oldSigMask.bits[word] & newSigMask.bits[word];
std::uint32_t offset = word * 32 + 1;
for (std::uint32_t i = std::countr_zero(unblockedBits); i < 32;
i += std::countr_zero(unblockedBits >> (i + 1)) + 1) {
thread->notifyUnblockedSignal(offset + i);
}
}
}
return {};
}
orbis::SysResult orbis::sys_sigwait(Thread *thread, ptr<const SigSet> set,
ptr<sint> sig) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigtimedwait(Thread *thread, ptr<const SigSet> set,
ptr<struct siginfo> info,
ptr<const timespec> timeout) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigwaitinfo(Thread *thread, ptr<const SigSet> set,
ptr<struct siginfo> info) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigpending(Thread *thread, ptr<SigSet> set) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigsuspend(Thread *thread, ptr<const SigSet> set) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigaltstack(Thread *thread, ptr<struct stack_t> ss,
ptr<struct stack_t> oss) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_kill(Thread *thread, sint pid, sint signum) {
ORBIS_LOG_WARNING(__FUNCTION__, pid, signum);
int hostPid = pid;
if (pid > 0) {
auto process = g_context.findProcessById(pid);
if (process == nullptr) {
return ErrorCode::SRCH;
}
hostPid = process->hostPid;
}
// TODO: wrap signal
// int result = ::kill(hostPid, signum);
// if (result < 0) {
// return static_cast<ErrorCode>(errno);
// }
return {};
}
orbis::SysResult orbis::sys_pdkill(Thread *thread, sint fd, sint signum) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigqueue(Thread *thread, pid_t pid, sint signum,
ptr<void> value) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigreturn(Thread *thread, ptr<UContext> sigcntxp) {
ORBIS_LOG_WARNING(__FUNCTION__, sigcntxp);
// auto sigRet = thread->sigReturns.front();
// thread->sigReturns.erase(thread->sigReturns.begin(), thread->sigReturns.begin() + 1);
// writeRegister(thread->context, RegisterId::rip, sigRet.rip);
// writeRegister(thread->context, RegisterId::rsp, sigRet.rsp);
// ORBIS_LOG_ERROR(__FUNCTION__, sigRet.rip, sigRet.rsp);
return {};
}
orbis::SysResult orbis::nosys(Thread *thread) {
thread->sendSignal(kSigSys);
return{};
}