From 70fa577a7b9b25cdbd23ef832d3aa9bde04220c8 Mon Sep 17 00:00:00 2001 From: DH Date: Sun, 21 Sep 2025 08:46:28 +0300 Subject: [PATCH] orbis: implement initial guest signals support --- .../include/orbis/thread/ProcessOps.hpp | 1 + orbis-kernel/include/orbis/thread/Thread.hpp | 7 +- orbis-kernel/include/orbis/ucontext.hpp | 6 + .../include/orbis/utils/SharedAtomic.hpp | 2 +- orbis-kernel/src/KernelContext.cpp | 69 ++++++++++- orbis-kernel/src/sys/sys_sce.cpp | 10 +- orbis-kernel/src/sys/sys_sig.cpp | 23 ++-- orbis-kernel/src/umtx.cpp | 39 +++---- orbis-kernel/src/utils/SharedAtomic.cpp | 16 ++- rpcsx/ops.cpp | 6 + rpcsx/thread.cpp | 110 +++++++++++++++++- rpcsx/thread.hpp | 1 + 12 files changed, 239 insertions(+), 51 deletions(-) diff --git a/orbis-kernel/include/orbis/thread/ProcessOps.hpp b/orbis-kernel/include/orbis/thread/ProcessOps.hpp index 08cbf5251..527d77767 100644 --- a/orbis-kernel/include/orbis/thread/ProcessOps.hpp +++ b/orbis-kernel/include/orbis/thread/ProcessOps.hpp @@ -73,6 +73,7 @@ struct ProcessOps { SysResult (*thr_kill2)(Thread *thread, pid_t pid, slong id, sint sig); SysResult (*thr_suspend)(Thread *thread, ptr timeout); SysResult (*thr_wake)(Thread *thread, slong id); + SysResult (*sigreturn)(Thread *thread, ptr context); SysResult (*thr_set_name)(Thread *thread, slong id, ptr name); SysResult (*unmount)(Thread *thread, ptr path, sint flags); diff --git a/orbis-kernel/include/orbis/thread/Thread.hpp b/orbis-kernel/include/orbis/thread/Thread.hpp index 097037cb3..35c0d216c 100644 --- a/orbis-kernel/include/orbis/thread/Thread.hpp +++ b/orbis-kernel/include/orbis/thread/Thread.hpp @@ -41,6 +41,8 @@ struct Thread { kvector queuedSignals; shared_atomic32 suspendFlags{0}; + utils::shared_atomic32 interruptedMtx{ 0 }; + std::int64_t hostTid = -1; lwpid_t tid = -1; unsigned unblocked = 0; @@ -64,13 +66,14 @@ struct Thread { // Print backtrace void where(); - void unblock(); - void block(); + bool unblock(); + bool block(); void suspend(); void resume(); void sendSignal(int signo); void notifyUnblockedSignal(int signo); + void setSigMask(SigSet newSigMask); // FIXME: implement thread destruction void incRef() {} diff --git a/orbis-kernel/include/orbis/ucontext.hpp b/orbis-kernel/include/orbis/ucontext.hpp index 6882132b3..fa47726a3 100644 --- a/orbis-kernel/include/orbis/ucontext.hpp +++ b/orbis-kernel/include/orbis/ucontext.hpp @@ -162,4 +162,10 @@ struct SigInfo { } spare; } reason; }; + +struct SigFrame { + uint64_t handler; + UContext context; + SigInfo info; +}; } // namespace orbis diff --git a/orbis-kernel/include/orbis/utils/SharedAtomic.hpp b/orbis-kernel/include/orbis/utils/SharedAtomic.hpp index 890b0936d..0a8f6308a 100644 --- a/orbis-kernel/include/orbis/utils/SharedAtomic.hpp +++ b/orbis-kernel/include/orbis/utils/SharedAtomic.hpp @@ -23,7 +23,7 @@ static constexpr auto kRelaxSpinCount = 12; static constexpr auto kSpinCount = 16; inline namespace utils { -inline thread_local void (*g_scopedUnblock)(bool) = nullptr; +inline thread_local bool (*g_scopedUnblock)(bool) = nullptr; bool try_spin_wait(auto &&pred) { for (std::size_t i = 0; i < kSpinCount; ++i) { diff --git a/orbis-kernel/src/KernelContext.cpp b/orbis-kernel/src/KernelContext.cpp index 7e030fe76..da33bc43f 100644 --- a/orbis-kernel/src/KernelContext.cpp +++ b/orbis-kernel/src/KernelContext.cpp @@ -11,6 +11,7 @@ #include #include #include +#include static const std::uint64_t g_allocProtWord = 0xDEADBEAFBADCAFE1; static constexpr std::uintptr_t kHeapBaseAddress = 0x00000600'0000'0000; @@ -318,9 +319,31 @@ void Thread::suspend() { sendSignal(-1); } void Thread::resume() { sendSignal(-2); } void Thread::sendSignal(int signo) { + if (signo >= 0) { + if (!sigMask.test(signo)) { + return; + } + } + if (pthread_sigqueue(getNativeHandle(), SIGUSR1, {.sival_int = signo})) { perror("pthread_sigqueue"); } + + + // TODO: suspend uses another delivery confirmation + if (signo != -1) { + interruptedMtx.store(1, std::memory_order::release); + while (interruptedMtx.wait(1, std::chrono::microseconds(1000)) != + std::errc{}) { + if (interruptedMtx.load() == 0) { + return; + } + + if (pthread_sigqueue(getNativeHandle(), SIGUSR1, {.sival_int = -2})) { + perror("pthread_sigqueue"); + } + } + } } void Thread::notifyUnblockedSignal(int signo) { @@ -335,19 +358,55 @@ void Thread::notifyUnblockedSignal(int signo) { } } +void Thread::setSigMask(SigSet newSigMask) { + newSigMask.clear(kSigKill); + newSigMask.clear(kSigStop); + + auto oldSigMask = std::exchange(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) { + notifyUnblockedSignal(offset + i); + } + } +} + void Thread::where() { tproc->ops->where(this); } -void Thread::unblock() { tproc->ops->unblock(this); } -void Thread::block() { tproc->ops->block(this); } +bool Thread::unblock() { + if (interruptedMtx.load(std::memory_order::relaxed) != 0) { + return false; + } + + tproc->ops->unblock(this); + + return true; +} + +bool Thread::block() { + tproc->ops->block(this); + + std::uint32_t prev = interruptedMtx.exchange(0, std::memory_order::relaxed); + if (prev != 0) { + interruptedMtx.notify_one(); + } + + return prev == 0; +} scoped_unblock::scoped_unblock() { if (g_currentThread && g_currentThread->context) { g_scopedUnblock = [](bool unblock) { if (unblock) { - g_currentThread->unblock(); - } else { - g_currentThread->block(); + return g_currentThread->unblock(); } + + g_currentThread->block(); + return true; }; } } diff --git a/orbis-kernel/src/sys/sys_sce.cpp b/orbis-kernel/src/sys/sys_sce.cpp index f7f9a9435..fde1085c4 100644 --- a/orbis-kernel/src/sys/sys_sce.cpp +++ b/orbis-kernel/src/sys/sys_sce.cpp @@ -572,6 +572,7 @@ orbis::SysResult orbis::sys_osem_wait(Thread *thread, sint id, sint need, std::lock_guard lock(sem->mtx); bool timedout = false; + ErrorCode result{}; while (true) { if (sem->isDeleted) return ErrorCode::ACCES; @@ -591,7 +592,12 @@ orbis::SysResult orbis::sys_osem_wait(Thread *thread, sint id, sint need, } orbis::scoped_unblock unblock; - sem->cond.wait(sem->mtx, ut); + auto waitResult = sem->cond.wait(sem->mtx, ut); + + if (waitResult == std::errc::interrupted) { + result = ErrorCode::INTR; + break; + } } if (pTimeout) { @@ -613,7 +619,7 @@ orbis::SysResult orbis::sys_osem_wait(Thread *thread, sint id, sint need, if (timedout) { return SysResult::notAnError(ErrorCode::TIMEDOUT); } - return {}; + return result; } orbis::SysResult orbis::sys_osem_trywait(Thread *thread, sint id, sint need) { ORBIS_LOG_TRACE(__FUNCTION__, thread, id, need); diff --git a/orbis-kernel/src/sys/sys_sig.cpp b/orbis-kernel/src/sys/sys_sig.cpp index 5b63bc233..52725b25e 100644 --- a/orbis-kernel/src/sys/sys_sig.cpp +++ b/orbis-kernel/src/sys/sys_sig.cpp @@ -2,6 +2,7 @@ #include "sys/sysproto.hpp" #include "thread/Process.hpp" #include "thread/Thread.hpp" +#include "thread/ProcessOps.hpp" #include "ucontext.hpp" #include "utils/Logs.hpp" #include @@ -120,11 +121,11 @@ orbis::SysResult orbis::sys_kill(Thread *thread, sint pid, sint signum) { hostPid = process->hostPid; } - // TODO: wrap signal - // int result = ::kill(hostPid, signum); - // if (result < 0) { - // return static_cast(errno); - // } + // FIXME: invoke subscriber thread + int result = ::sigqueue(hostPid, SIGUSR1, {.sival_int = signum}); + if (result < 0) { + return static_cast(errno); + } return {}; } @@ -139,13 +140,11 @@ orbis::SysResult orbis::sys_sigqueue(Thread *thread, pid_t pid, sint signum, orbis::SysResult orbis::sys_sigreturn(Thread *thread, ptr 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 {}; + if (auto sigreturn = thread->tproc->ops->sigreturn) { + return sigreturn(thread, sigcntxp); + } + + return ErrorCode::NOSYS; } orbis::SysResult orbis::nosys(Thread *thread) { diff --git a/orbis-kernel/src/umtx.cpp b/orbis-kernel/src/umtx.cpp index 01939f784..430f1fe72 100644 --- a/orbis-kernel/src/umtx.cpp +++ b/orbis-kernel/src/umtx.cpp @@ -63,10 +63,6 @@ uint UmtxChain::notify_all(const UmtxKey &key) { } } // namespace orbis -static bool isSpuriousWakeup(orbis::ErrorCode errc) { - return errc == orbis::ErrorCode::AGAIN || errc == orbis::ErrorCode::INTR; -} - orbis::ErrorCode orbis::umtx_lock_umtx(Thread *thread, ptr umtx, ulong id, std::uint64_t ut) { ORBIS_LOG_TODO(__FUNCTION__, thread->tid, umtx, id, ut); @@ -97,8 +93,7 @@ orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr addr, ulong id, while (true) { orbis::scoped_unblock unblock; result = orbis::toErrorCode(node->second.cv.wait(chain.mtx)); - if ((result != ErrorCode{} && !isSpuriousWakeup(result)) || - node->second.thr != thread) + if ((result != ErrorCode{}) || node->second.thr != thread) break; } } else { @@ -117,7 +112,7 @@ orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr addr, ulong id, result = ErrorCode::TIMEDOUT; break; } - if (result != ErrorCode{} && !isSpuriousWakeup(result)) { + if (result != ErrorCode{}) { break; } } @@ -193,7 +188,7 @@ static ErrorCode do_lock_normal(Thread *thread, ptr m, uint flags, if (mode == umutex_lock_mode::try_) return ErrorCode::BUSY; - if (error != ErrorCode{} && !isSpuriousWakeup(error)) + if (error != ErrorCode{}) return error; auto node = chain.enqueue(key, thread); @@ -202,8 +197,8 @@ static ErrorCode do_lock_normal(Thread *thread, ptr m, uint flags, orbis::scoped_unblock unblock; error = orbis::toErrorCode(node->second.cv.wait(chain.mtx, ut)); } - if (error == ErrorCode{} && !isSpuriousWakeup(error) && - node->second.thr == thread && m->owner.load() != 0) { + if (error == ErrorCode{} && node->second.thr == thread && + m->owner.load() != 0) { error = ErrorCode::TIMEDOUT; } } @@ -358,12 +353,12 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr cv, ErrorCode result = umtx_unlock_umutex(thread, m); if (result == ErrorCode{}) { + orbis::scoped_unblock unblock; if (ut + 1 == 0) { while (true) { - orbis::scoped_unblock unblock; result = orbis::toErrorCode(node->second.cv.wait(chain.mtx, ut)); - if ((result != ErrorCode{} && !isSpuriousWakeup(result)) || - node->second.thr != thread) { + + if (result != ErrorCode{} || node->second.thr != thread) { break; } } @@ -371,7 +366,6 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr cv, auto start = std::chrono::steady_clock::now(); std::uint64_t udiff = 0; while (true) { - orbis::scoped_unblock unblock; result = orbis::toErrorCode(node->second.cv.wait(chain.mtx, ut - udiff)); if (node->second.thr != thread) { @@ -385,7 +379,7 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr cv, break; } - if (result != ErrorCode{} && !isSpuriousWakeup(result)) { + if (result != ErrorCode{}) { break; } } @@ -470,8 +464,7 @@ orbis::ErrorCode orbis::umtx_rw_rdlock(Thread *thread, ptr rwlock, while (true) { orbis::scoped_unblock unblock; result = orbis::toErrorCode(node->second.cv.wait(chain.mtx, ut)); - if ((result != ErrorCode{} && !isSpuriousWakeup(result)) || - node->second.thr != thread) { + if (result != ErrorCode{} || node->second.thr != thread) { break; } } @@ -492,7 +485,7 @@ orbis::ErrorCode orbis::umtx_rw_rdlock(Thread *thread, ptr rwlock, break; } - if (result != ErrorCode{} && !isSpuriousWakeup(result)) { + if (result != ErrorCode{}) { break; } } @@ -574,8 +567,7 @@ orbis::ErrorCode orbis::umtx_rw_wrlock(Thread *thread, ptr rwlock, while (true) { orbis::scoped_unblock unblock; error = orbis::toErrorCode(node->second.cv.wait(chain.mtx, ut)); - if ((error != ErrorCode{} && !isSpuriousWakeup(error)) || - node->second.thr != thread) { + if ((error != ErrorCode{}) || node->second.thr != thread) { break; } } @@ -595,7 +587,7 @@ orbis::ErrorCode orbis::umtx_rw_wrlock(Thread *thread, ptr rwlock, error = ErrorCode::TIMEDOUT; break; } - if (error != ErrorCode{} && !isSpuriousWakeup(error)) { + if (error != ErrorCode{}) { break; } } @@ -757,8 +749,7 @@ orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr sem, while (true) { orbis::scoped_unblock unblock; result = orbis::toErrorCode(node->second.cv.wait(chain.mtx, ut)); - if ((result != ErrorCode{} && !isSpuriousWakeup(result)) || - node->second.thr != thread) + if ((result != ErrorCode{}) || node->second.thr != thread) break; } } else { @@ -777,7 +768,7 @@ orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr sem, result = ErrorCode::TIMEDOUT; break; } - if (result != ErrorCode{} && !isSpuriousWakeup(result)) { + if (result != ErrorCode{}) { break; } } diff --git a/orbis-kernel/src/utils/SharedAtomic.cpp b/orbis-kernel/src/utils/SharedAtomic.cpp index 3f069d7ec..846845e37 100644 --- a/orbis-kernel/src/utils/SharedAtomic.cpp +++ b/orbis-kernel/src/utils/SharedAtomic.cpp @@ -19,18 +19,28 @@ std::errc shared_atomic32::wait_impl(std::uint32_t oldValue, g_scopedUnblock != nullptr; if (unblock) { - g_scopedUnblock(true); + if (!g_scopedUnblock(true)) { + return std::errc::interrupted; + } } int result = syscall(SYS_futex, this, FUTEX_WAIT, oldValue, useTimeout ? &timeout : nullptr); + auto errorCode = result < 0 ? static_cast(errno) : std::errc{}; + if (unblock) { - g_scopedUnblock(false); + if (!g_scopedUnblock(false)) { + if (result < 0) { + return std::errc::interrupted; + } + + return {}; + } } if (result < 0) { - return static_cast(errno); + return errorCode; } return {}; diff --git a/rpcsx/ops.cpp b/rpcsx/ops.cpp index ca4fb7a8a..7d1567bae 100644 --- a/rpcsx/ops.cpp +++ b/rpcsx/ops.cpp @@ -650,6 +650,11 @@ SysResult thr_wake(orbis::Thread *thread, orbis::slong id) { ORBIS_LOG_FATAL(__FUNCTION__, id); return ErrorCode::NOTSUP; } +SysResult sigreturn(orbis::Thread *thread, + orbis::ptr context) { + rx::thread::setContext(thread, *context); + return{}; +} SysResult thr_set_name(orbis::Thread *thread, orbis::slong id, orbis::ptr name) { ORBIS_LOG_WARNING(__FUNCTION__, name, id, thread->tid); @@ -1023,6 +1028,7 @@ ProcessOps rx::procOpsTable = { .thr_kill2 = thr_kill2, .thr_suspend = thr_suspend, .thr_wake = thr_wake, + .sigreturn = sigreturn, .thr_set_name = thr_set_name, .unmount = unmount, .nmount = nmount, diff --git a/rpcsx/thread.cpp b/rpcsx/thread.cpp index c9a65011b..9e354e9eb 100644 --- a/rpcsx/thread.cpp +++ b/rpcsx/thread.cpp @@ -4,6 +4,7 @@ #include "orbis/thread/Process.hpp" #include "orbis/thread/Thread.hpp" #include "orbis/utils/Logs.hpp" +#include "rx/debug.hpp" #include "rx/mem.hpp" #include #include @@ -125,6 +126,53 @@ handleSigUser(int sig, siginfo_t *info, void *ucontext) { } // ORBIS_LOG_ERROR("thread wake", thread->tid); + } else if (guestSignal >= 0) { + ORBIS_LOG_WARNING(__FUNCTION__, "handled signal", guestSignal, inGuestCode, + ::getpid(), thread->tid); + auto it = thread->tproc->sigActions.find(guestSignal); + + if (it != thread->tproc->sigActions.end()) { + auto guestContext = reinterpret_cast( + inGuestCode ? context : thread->context); + + auto sigact = it->second; + thread->setSigMask(sigact.mask); + auto handlerPtr = reinterpret_cast(sigact.handler); + + auto rsp = guestContext->uc_mcontext.gregs[REG_RSP]; + + ORBIS_LOG_WARNING(__FUNCTION__, "invoking signal handler", guestSignal, + rsp, thread->stackStart, thread->stackEnd); + + // FIXME: alt stack? + rsp -= 128; // redzone + rsp -= sizeof(orbis::SigFrame); + + // FIXME handle flags + auto &sigFrame = *std::bit_cast(rsp); + sigFrame = {}; + + rx::thread::copyContext(thread, sigFrame.context, *guestContext); + sigFrame.info.signo = guestSignal; + sigFrame.handler = handlerPtr; + + guestContext->uc_mcontext.gregs[REG_RDI] = guestSignal; // arg1, signo + guestContext->uc_mcontext.gregs[REG_RSI] = + std::bit_cast(&sigFrame.info); // arg2, siginfo + guestContext->uc_mcontext.gregs[REG_RDX] = + std::bit_cast(&sigFrame.context); // arg3, ucontext + guestContext->uc_mcontext.gregs[REG_RCX] = 0; // arg4, si_addr + guestContext->uc_mcontext.gregs[REG_RIP] = handlerPtr; + + guestContext->uc_mcontext.gregs[REG_RSP] = rx::alignDown(rsp, 16); + } + } + + if (inGuestCode && guestSignal != -1) { + std::uint32_t prevValue = 1; + if (thread->interruptedMtx.compare_exchange_strong(prevValue, 0)) { + thread->interruptedMtx.notify_one(); + } } if (inGuestCode) { @@ -187,11 +235,69 @@ void rx::thread::copyContext(orbis::Thread *thread, orbis::UContext &dst, dst = {}; dst.stack.sp = thread->stackStart; dst.stack.size = (char *)thread->stackEnd - (char *)thread->stackStart; - dst.stack.align = 0x10000; + dst.stack.align = 16; dst.sigmask = thread->sigMask; copyContext(dst.mcontext, src.uc_mcontext); } +void rx::thread::setContext(orbis::Thread *thread, const orbis::UContext &src) { + auto &context = *std::bit_cast(thread->context); + thread->stackStart = src.stack.sp; + thread->stackEnd = (char *)thread->stackStart + src.stack.size; + thread->setSigMask(src.sigmask); + + // dst.onstack = src.gregs[REG_ONSTACK]; + context.uc_mcontext.gregs[REG_RDI] = src.mcontext.rdi; + context.uc_mcontext.gregs[REG_RSI] = src.mcontext.rsi; + context.uc_mcontext.gregs[REG_RDX] = src.mcontext.rdx; + context.uc_mcontext.gregs[REG_RCX] = src.mcontext.rcx; + context.uc_mcontext.gregs[REG_R8] = src.mcontext.r8; + context.uc_mcontext.gregs[REG_R9] = src.mcontext.r9; + context.uc_mcontext.gregs[REG_RAX] = src.mcontext.rax; + context.uc_mcontext.gregs[REG_RBX] = src.mcontext.rbx; + context.uc_mcontext.gregs[REG_RBP] = src.mcontext.rbp; + context.uc_mcontext.gregs[REG_R10] = src.mcontext.r10; + context.uc_mcontext.gregs[REG_R11] = src.mcontext.r11; + context.uc_mcontext.gregs[REG_R12] = src.mcontext.r12; + context.uc_mcontext.gregs[REG_R13] = src.mcontext.r13; + context.uc_mcontext.gregs[REG_R14] = src.mcontext.r14; + context.uc_mcontext.gregs[REG_R15] = src.mcontext.r15; + + context.uc_mcontext.gregs[REG_TRAPNO] = src.mcontext.trapno; + + // in perfect world: + // std::uint64_t csgsfs = 0; + // csgsfs |= src.mcontext.fs; + // csgsfs |= static_cast(src.mcontext.gs) << 16; + // csgsfs |= static_cast(src.mcontext.cs) << 32; + // context.uc_mcontext.gregs[REG_CSGSFS] = csgsfs; + + context.uc_mcontext.gregs[REG_CSGSFS] &= ~0xff'ffull; + context.uc_mcontext.gregs[REG_CSGSFS] |= src.mcontext.fs; + + // dst.addr = src.gregs[REG_ADDR]; + // dst.flags = src.gregs[REG_FLAGS]; + // dst.es = src.gregs[REG_ES]; + // dst.ds = src.gregs[REG_DS]; + context.uc_mcontext.gregs[REG_ERR] = src.mcontext.err; + context.uc_mcontext.gregs[REG_RIP] = src.mcontext.rip; + context.uc_mcontext.gregs[REG_EFL] = src.mcontext.rflags; + context.uc_mcontext.gregs[REG_RSP] = src.mcontext.rsp; + // dst.ss = src.gregs[REG_SS]; + // dst.len = sizeof(orbis::MContext); + // dst.fpformat = src.gregs[REG_FPFORMAT]; + // dst.ownedfp = src.gregs[REG_OWNEDFP]; + // dst.lbrfrom = src.gregs[REG_LBRFROM]; + // dst.lbrto = src.gregs[REG_LBRTO]; + // dst.aux1 = src.gregs[REG_AUX1]; + // dst.aux2 = src.gregs[REG_AUX2]; + // dst.fpstate = src.gregs[REG_FPSTATE]; + // dst.fsbase = src.gregs[REG_FSBASE]; + // dst.gsbase = src.gregs[REG_GSBASE]; + // dst.xfpustate = src.gregs[REG_XFPUSTATE]; + // dst.xfpustate_len = src.gregs[REG_XFPUSTATE_LEN]; +} + void rx::thread::initialize() { struct sigaction act{}; act.sa_sigaction = handleSigSys; @@ -271,6 +377,6 @@ void rx::thread::invoke(orbis::Thread *thread) { _writefsbase_u64(thread->fsBase); auto context = reinterpret_cast(thread->context); - setContext(context->uc_mcontext); + ::setContext(context->uc_mcontext); _writefsbase_u64(hostFs); } diff --git a/rpcsx/thread.hpp b/rpcsx/thread.hpp index f36523111..75fb1ac5b 100644 --- a/rpcsx/thread.hpp +++ b/rpcsx/thread.hpp @@ -13,5 +13,6 @@ void setupThisThread(); void copyContext(orbis::MContext &dst, const mcontext_t &src); void copyContext(orbis::Thread *thread, orbis::UContext &dst, const ucontext_t &src); +void setContext(orbis::Thread *thread, const orbis::UContext &src); void invoke(orbis::Thread *thread); } // namespace rx::thread