Skip to content

Commit

Permalink
Review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Sonicadvance1 committed Dec 20, 2024
1 parent 2b2acf8 commit a0159e1
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Source/Tools/LinuxEmulation/LinuxSyscalls/GdbServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ GdbServer::HandledPacketType GdbServer::ThreadAction(char action, uint32_t tid)
switch (action) {
case 'c': {
{
std::lock_guard lk(*SyscallHandler->TM.GetThreadsCreationMutex());
std::lock_guard lk(SyscallHandler->TM.GetThreadsCreationMutex());
auto Threads = SyscallHandler->TM.GetThreads();
for (auto& Thread : *Threads) {
Thread->ThreadSleeping.NotifyOne();
Expand Down
19 changes: 11 additions & 8 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ class SyscallHandler;
class SignalDelegator;

// A latch that can be inspected to see if there is a waiter currently active.
// This allows us to remove the race condition between a thread trying to go asleep and something else telling it to go to sleep or wake up.
//
// Only one thread can ever wait on a latch, while another thread signals it.
// In contrast to std::condition_variable, an InspectableLatch may be signaled *before* being waited on without change of effect.
class InspectableLatch final {
public:
bool Wait(struct timespec* Timeout = nullptr) {
LOGMAN_THROW_A_FMT(Mutex.load() != HAS_SIGNALED, "Stale signal mutex!");
LOGMAN_THROW_A_FMT(Mutex.load() != HAS_WAITER, "Can't have multiple waiters on a single InspectableLatch!");
while (true) {
uint32_t Expected = HAS_NO_WAITER;
const uint32_t Desired = HAS_WAITER;

if (Mutex.compare_exchange_strong(Expected, Desired)) {
// We have latched, now futex.
// We have latched, sleep using a futex syscall until signaled.
constexpr int Op = FUTEX_WAIT | FUTEX_PRIVATE_FLAG;
// WAIT will keep sleeping on the futex word while it is `val`
int Result = ::syscall(SYS_futex, &Mutex, Op,
Expand Down Expand Up @@ -64,6 +64,9 @@ class InspectableLatch final {
}

void NotifyOne() {
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
LOGMAN_THROW_A_FMT(Mutex.load() != HAS_SIGNALED, "Trying to double signal!");
#endif
DoNotify(1);
}

Expand All @@ -81,8 +84,8 @@ class InspectableLatch final {
uint32_t Expected = HAS_WAITER;
const uint32_t Desired = HAS_SIGNALED;

// If the mutex is in a waiting state and we have CAS exchanged it to HAS_SIGNALED, then execute a futex syscall.
// otherwise just leave since nothing was waiting.
// If the mutex is in a waiting state and we have CAS exchanged it to HAS_SIGNALED, then signal the thread to wake up with a futex
// syscall. otherwise just leave since nothing was waiting.
if (Mutex.compare_exchange_strong(Expected, Desired)) {
constexpr int Op = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;

Expand Down Expand Up @@ -243,8 +246,8 @@ class ThreadManager final {
}
}

FEXCore::ForkableUniqueMutex* GetThreadsCreationMutex() {
return &ThreadCreationMutex;
FEXCore::ForkableUniqueMutex& GetThreadsCreationMutex() {
return ThreadCreationMutex;
}

const fextl::vector<FEX::HLE::ThreadStateObject*>* GetThreads() const {
Expand Down

0 comments on commit a0159e1

Please sign in to comment.