mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 10:00:16 +02:00
ScopedSignalMask: Add shared mutex support, move constructors
This commit is contained in:
1 parent
db3854e391
commit
3cb8ae9a9c
1 file changed
+121
-8
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <signal.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
@@ -20,27 +21,139 @@ namespace FHU {
|
||||
* Destructor Order:
|
||||
* 1) Unlock Mutex
|
||||
* 2) Unmask signals
|
||||
*
|
||||
* Masking signals around mutex locks is needed for signal-reentrant safety
|
||||
*/
|
||||
class ScopedSignalMaskWithMutex final {
|
||||
public:
|
||||
|
||||
ScopedSignalMaskWithMutex(std::mutex &_Mutex, uint64_t Mask = ~0ULL)
|
||||
: Mutex {_Mutex} {
|
||||
: Mutex {&_Mutex} {
|
||||
// Mask all signals, storing the original incoming mask
|
||||
::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &Mask, &OriginalMask, sizeof(OriginalMask));
|
||||
|
||||
// Lock the mutex
|
||||
Mutex.lock();
|
||||
Mutex->lock();
|
||||
}
|
||||
|
||||
// No copy or assignment possible
|
||||
ScopedSignalMaskWithMutex(const ScopedSignalMaskWithMutex&) = delete;
|
||||
ScopedSignalMaskWithMutex& operator=(ScopedSignalMaskWithMutex&) = delete;
|
||||
|
||||
// Only move
|
||||
ScopedSignalMaskWithMutex(ScopedSignalMaskWithMutex &&rhs)
|
||||
: OriginalMask {rhs.OriginalMask}, Mutex {rhs.Mutex} {
|
||||
rhs.Mutex = nullptr;
|
||||
}
|
||||
|
||||
~ScopedSignalMaskWithMutex() {
|
||||
// Unlock the mutex
|
||||
Mutex.unlock();
|
||||
if (Mutex != nullptr) {
|
||||
// Unlock the mutex
|
||||
Mutex->unlock();
|
||||
|
||||
// Unmask back to the original signal mask
|
||||
::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &OriginalMask, nullptr, sizeof(OriginalMask));
|
||||
// Unmask back to the original signal mask
|
||||
::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &OriginalMask, nullptr, sizeof(OriginalMask));
|
||||
}
|
||||
}
|
||||
private:
|
||||
uint64_t OriginalMask{};
|
||||
std::mutex &Mutex;
|
||||
std::mutex *Mutex;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A class that masks signals and shared locks a shared mutex until it goes out of scope
|
||||
*
|
||||
* Constructor order:
|
||||
* 1) Mask signals
|
||||
* 2) Lock Mutex
|
||||
*
|
||||
* Destructor Order:
|
||||
* 1) Unlock Mutex
|
||||
* 2) Unmask signals
|
||||
*
|
||||
* Masking signals around mutex locks is needed for signal-rentrant safety
|
||||
*/
|
||||
class ScopedSignalMaskWithSharedLock final {
|
||||
public:
|
||||
ScopedSignalMaskWithSharedLock(std::shared_mutex &_Mutex, uint64_t Mask = ~0ULL)
|
||||
: Mutex {&_Mutex} {
|
||||
// Mask all signals, storing the original incoming mask
|
||||
::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &Mask, &OriginalMask, sizeof(OriginalMask));
|
||||
|
||||
// Lock the mutex
|
||||
Mutex->lock_shared();
|
||||
}
|
||||
|
||||
// No copy or assignment possible
|
||||
ScopedSignalMaskWithSharedLock(const ScopedSignalMaskWithSharedLock&) = delete;
|
||||
ScopedSignalMaskWithSharedLock& operator=(ScopedSignalMaskWithSharedLock&) = delete;
|
||||
|
||||
// Only move
|
||||
ScopedSignalMaskWithSharedLock(ScopedSignalMaskWithSharedLock &&rhs)
|
||||
: OriginalMask {rhs.OriginalMask}, Mutex {rhs.Mutex} {
|
||||
rhs.Mutex = nullptr;
|
||||
}
|
||||
|
||||
~ScopedSignalMaskWithSharedLock() {
|
||||
if (Mutex) {
|
||||
// Unlock the mutex
|
||||
Mutex->unlock_shared();
|
||||
|
||||
// Unmask back to the original signal mask
|
||||
::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &OriginalMask, nullptr, sizeof(OriginalMask));
|
||||
}
|
||||
}
|
||||
private:
|
||||
uint64_t OriginalMask{};
|
||||
std::shared_mutex *Mutex;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A class that masks signals and unique locks a shared mutex until it goes out of scope
|
||||
*
|
||||
* Constructor order:
|
||||
* 1) Mask signals
|
||||
* 2) Lock Mutex
|
||||
*
|
||||
* Destructor Order:
|
||||
* 1) Unlock Mutex
|
||||
* 2) Unmask signals
|
||||
*
|
||||
* Masking signals around mutex locks is needed for signal-rentrant safety
|
||||
*/
|
||||
class ScopedSignalMaskWithUniqueLock final {
|
||||
public:
|
||||
ScopedSignalMaskWithUniqueLock(std::shared_mutex &_Mutex, uint64_t Mask = ~0ULL)
|
||||
: Mutex {&_Mutex} {
|
||||
// Mask all signals, storing the original incoming mask
|
||||
::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &Mask, &OriginalMask, sizeof(OriginalMask));
|
||||
|
||||
// Lock the mutex
|
||||
Mutex->lock();
|
||||
}
|
||||
|
||||
// No copy or assignment possible
|
||||
ScopedSignalMaskWithUniqueLock(const ScopedSignalMaskWithSharedLock&) = delete;
|
||||
ScopedSignalMaskWithUniqueLock& operator=(ScopedSignalMaskWithSharedLock&) = delete;
|
||||
|
||||
ScopedSignalMaskWithUniqueLock(ScopedSignalMaskWithUniqueLock &&rhs)
|
||||
: OriginalMask {rhs.OriginalMask}, Mutex {rhs.Mutex} {
|
||||
rhs.Mutex = nullptr;
|
||||
}
|
||||
|
||||
~ScopedSignalMaskWithUniqueLock() {
|
||||
if (Mutex != nullptr)
|
||||
{
|
||||
// Unlock the mutex
|
||||
Mutex->unlock();
|
||||
|
||||
// Unmask back to the original signal mask
|
||||
::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &OriginalMask, nullptr, sizeof(OriginalMask));
|
||||
}
|
||||
}
|
||||
private:
|
||||
uint64_t OriginalMask{};
|
||||
std::shared_mutex *Mutex;
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user