mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 08:00:15 +02:00
Merge DeferredSignalMutex.h and ScopedSignalMask.h into a single file
Using a single file makes sense now that the individual files are much shorter and share common utility classes.
This commit is contained in:
1 parent
5ca35bf77c
commit
92e4e75217
7 files changed
+35
-77
No files matched your search
@@ -14,8 +14,8 @@
|
||||
#include <FEXCore/Core/SignalDelegator.h>
|
||||
#include <FEXCore/Debug/InternalThreadState.h>
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/Utils/DeferredSignalMutex.h>
|
||||
#include <FEXCore/Utils/Event.h>
|
||||
#include <FEXCore/Utils/SignalScopeGuards.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/set.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
@@ -9,7 +9,6 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include "FEXCore/Utils/DeferredSignalMutex.h"
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/LookupCache.h"
|
||||
#include "Interface/Core/CPUID.h"
|
||||
@@ -45,6 +44,7 @@ $end_info$
|
||||
#include <FEXCore/Utils/Event.h>
|
||||
#include <FEXCore/Utils/File.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include "FEXCore/Utils/SignalScopeGuards.h"
|
||||
#include <FEXCore/Utils/Threads.h>
|
||||
#include <FEXCore/Utils/Profiler.h>
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/Utils/MathUtils.h>
|
||||
#include <FEXCore/Utils/SignalScopeGuards.h>
|
||||
#include <FEXCore/fextl/sstream.h>
|
||||
#include <FEXCore/Utils/DeferredSignalMutex.h>
|
||||
#include <FEXHeaderUtils/Syscalls.h>
|
||||
#include <FEXHeaderUtils/TypeDefines.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
+29
-1
@@ -111,6 +111,7 @@ namespace FEXCore {
|
||||
};
|
||||
#endif
|
||||
|
||||
// Helper class to manage deferred signal refcounting within a block scope
|
||||
class DeferredSignalRefCountGuard final {
|
||||
public:
|
||||
explicit DeferredSignalRefCountGuard(FEXCore::Core::InternalThreadState *Thread) : Thread(Thread) {
|
||||
@@ -148,7 +149,7 @@ namespace FEXCore {
|
||||
};
|
||||
|
||||
#ifndef _WIN32
|
||||
// TODO: Duplicated, unify with ScopedSignalMask
|
||||
// Helper class to mask POSIX signals within a block scope
|
||||
class ScopedSignalMasker final {
|
||||
public:
|
||||
explicit ScopedSignalMasker(uint64_t Mask) : OriginalMask(0) {
|
||||
@@ -173,6 +174,33 @@ namespace FEXCore {
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Produces a wrapper object around a scoped lock of the given mutex
|
||||
* while ensuring POSIX signals are masked while the mutex is locked
|
||||
*
|
||||
* Use this to prevent reentrancy issues of C++ mutexes with certain signal handlers.
|
||||
* Common examples of such issues are:
|
||||
* - C++ mutexes not unlocking due to a signal handler calling longjmp from within a scope owning the mutex
|
||||
* - The signal handler itself using a mutex that would be re-locked if the handler gets invoked
|
||||
* again before unlocking
|
||||
*
|
||||
* Ownership of the returned object may be moved, but it is NOT SAFE to move across threads.
|
||||
*/
|
||||
template<template<typename> class LockType = std::unique_lock, typename MutexType>
|
||||
[[nodiscard]] static auto MaskSignalsAndLockMutex(MutexType& mutex, uint64_t Mask = ~0ULL) {
|
||||
#ifndef _WIN32
|
||||
// Signals are masked first, and then the lock is acquired
|
||||
struct {
|
||||
ScopedSignalMasker mask;
|
||||
LockType<MutexType> lock;
|
||||
} scope_guard { ScopedSignalMasker { Mask }, LockType<MutexType> { mutex } };
|
||||
return scope_guard;
|
||||
#else
|
||||
// TODO: Doesn't block signals which may or may not cause issues.
|
||||
return LockType<MutexType> { mutex };
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Produces a wrapper object around a scoped lock of the given mutex
|
||||
* while bumping the Thread's deferred signal refcount while the mutex is
|
||||
@@ -1,69 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#ifndef _WIN32
|
||||
#include <signal.h>
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
namespace FHU {
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* Masks POSIX signals for the scope the object is active in
|
||||
*/
|
||||
class ScopedSignalMasker final {
|
||||
public:
|
||||
explicit ScopedSignalMasker(uint64_t Mask) : OriginalMask(0) {
|
||||
// Mask all signals, storing the original incoming mask
|
||||
::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &Mask, &*OriginalMask, sizeof(*OriginalMask));
|
||||
}
|
||||
|
||||
// Move-only type
|
||||
ScopedSignalMasker(const ScopedSignalMasker&) = delete;
|
||||
ScopedSignalMasker& operator=(ScopedSignalMasker&) = delete;
|
||||
ScopedSignalMasker(ScopedSignalMasker&& rhs) : OriginalMask(rhs.OriginalMask) {
|
||||
rhs.OriginalMask.reset();
|
||||
}
|
||||
|
||||
~ScopedSignalMasker() {
|
||||
if (OriginalMask) {
|
||||
::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &OriginalMask, nullptr, sizeof(*OriginalMask));
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::optional<uint64_t> OriginalMask{};
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Produces a wrapper object around a scoped lock of the given mutex
|
||||
* while ensuring POSIX signals are masked while the mutex is locked
|
||||
*
|
||||
* Use this to prevent reentrancy issues of C++ mutexes with certain signal handlers.
|
||||
* Common examples of such issues are:
|
||||
* - C++ mutexes not unlocking due to a signal handler calling longjmp from within a scope owning the mutex
|
||||
* - The signal handler itself using a mutex that would be re-locked if the handler gets invoked
|
||||
* again before unlocking
|
||||
*
|
||||
* Ownership of the returned object may be moved, but it is NOT SAFE to move across threads.
|
||||
*/
|
||||
template<template<typename> class LockType = std::unique_lock, typename MutexType>
|
||||
[[nodiscard]] static auto MaskSignalsAndLockMutex(MutexType& mutex, uint64_t Mask = ~0ULL) {
|
||||
#ifndef _WIN32
|
||||
// Signals are masked first, and then the lock is acquired
|
||||
struct {
|
||||
ScopedSignalMasker mask;
|
||||
LockType<MutexType> lock;
|
||||
} scope_guard { ScopedSignalMasker { Mask }, LockType<MutexType> { mutex } };
|
||||
return scope_guard;
|
||||
#else
|
||||
// TODO: Doesn't block signals which may or may not cause issues.
|
||||
return LockType<MutexType> { mutex };
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ $end_info$
|
||||
#include <FEXCore/HLE/SourcecodeResolver.h>
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/Utils/DeferredSignalMutex.h>
|
||||
#include <FEXCore/Utils/SignalScopeGuards.h>
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
#include <FEXCore/fextl/map.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
@@ -16,11 +16,10 @@ $end_info$
|
||||
#include "LinuxSyscalls/Syscalls.h"
|
||||
|
||||
#include <FEXHeaderUtils/TypeDefines.h>
|
||||
#include <FEXHeaderUtils/ScopedSignalMask.h>
|
||||
#include <FEXCore/Debug/InternalThreadState.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/Utils/MathUtils.h>
|
||||
#include <FEXCore/Utils/DeferredSignalMutex.h>
|
||||
#include <FEXCore/Utils/SignalScopeGuards.h>
|
||||
|
||||
namespace FEX::HLE {
|
||||
|
||||
@@ -55,7 +54,7 @@ bool SyscallHandler::HandleSegfault(FEXCore::Core::InternalThreadState *Thread,
|
||||
|
||||
{
|
||||
// Can't use the deferred signal lock in the SIGSEGV handler.
|
||||
auto lk = FHU::MaskSignalsAndLockMutex<std::shared_lock>(_SyscallHandler->VMATracking.Mutex);
|
||||
auto lk = FEXCore::MaskSignalsAndLockMutex<std::shared_lock>(_SyscallHandler->VMATracking.Mutex);
|
||||
|
||||
auto VMATracking = &_SyscallHandler->VMATracking;
|
||||
|
||||
|
||||
Reference in new issue
Block a user