This commit is contained in:
Jordan Woyak 2025-04-19 14:31:03 +02:00 committed by GitHub
commit 94cdec7b88
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 58 additions and 21 deletions

View File

@ -239,8 +239,8 @@ private:
Flag m_stopped; // If this is set, Wait() shall not block.
Flag m_shutdown; // If this is set, the loop shall end.
Event m_new_work_event;
Event m_done_event;
TimedEvent m_new_work_event;
TimedEvent m_done_event;
enum RUNNING_TYPE
{

View File

@ -11,19 +11,22 @@
#pragma once
#ifdef _WIN32
#include <concrt.h>
#endif
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include "Common/Flag.h"
#if !defined(__APPLE__)
// std::atomic<T>::notify_one is "unavailable: introduced in macOS 11.0"
// TODO: Eliminate this when macOS required version is bumped to 11.0+
#define ATOMIC_NOTIFY_ONE_IS_AVAILABLE
#endif
namespace Common
{
class Event final
class TimedEvent final
{
public:
void Set()
@ -81,4 +84,38 @@ private:
std::mutex m_mutex;
};
#if defined(ATOMIC_NOTIFY_ONE_IS_AVAILABLE)
class Event final
{
public:
void Set()
{
m_flag.store(true, std::memory_order_release);
// `Reset` from another thread could happen *here* clearing m_flag before notification.
m_flag.notify_one();
}
void Wait()
{
m_flag.wait(false, std::memory_order_acquire);
Reset();
}
void Reset()
{
m_flag.store(false, std::memory_order_relaxed);
// `Reset` can run concurrently with `Set`, clearing m_flag before notification.
// "Missing" that event later is fine as long as its data is visible *now*.
// This store-load barrier prevents m_flag.store(false) ordering after data loads.
// Without it, we could observe stale data AND miss the next event, i.e. deadlock.
std::atomic_thread_fence(std::memory_order_seq_cst);
}
private:
std::atomic_bool m_flag{};
};
#else
using Event = TimedEvent;
#endif
} // namespace Common
#undef ATOMIC_NOTIFY_ONE_IS_AVAILABLE

View File

@ -121,7 +121,7 @@ struct HostJob
};
static std::mutex s_host_jobs_lock;
static std::queue<HostJob> s_host_jobs_queue;
static Common::Event s_cpu_thread_job_finished;
static Common::TimedEvent s_cpu_thread_job_finished;
static thread_local bool tls_is_cpu_thread = false;
static thread_local bool tls_is_gpu_thread = false;

View File

@ -127,7 +127,7 @@ void CPUManager::Run()
ExecutePendingJobs(state_lock);
CPUThreadConfigCallback::CheckForConfigChanges();
Common::Event gdb_step_sync_event;
Common::TimedEvent gdb_step_sync_event;
switch (m_state)
{
case State::Running:
@ -272,7 +272,7 @@ void CPUManager::Reset()
{
}
void CPUManager::StepOpcode(Common::Event* event)
void CPUManager::StepOpcode(Common::TimedEvent* event)
{
std::lock_guard state_lock(m_state_change_lock);
// If we're not stepping then this is pointless

View File

@ -12,7 +12,7 @@
namespace Common
{
class Event;
class TimedEvent;
}
namespace Core
{
@ -61,7 +61,7 @@ public:
void Reset();
// StepOpcode (Steps one Opcode)
void StepOpcode(Common::Event* event = nullptr);
void StepOpcode(Common::TimedEvent* event = nullptr);
// Enable or Disable Stepping. [Will deadlock if called from a system thread]
void SetStepping(bool stepping);
@ -134,9 +134,9 @@ private:
bool m_state_paused_and_locked = false;
bool m_state_system_request_stepping = false;
bool m_state_cpu_step_instruction = false;
Common::Event* m_state_cpu_step_instruction_sync = nullptr;
Common::TimedEvent* m_state_cpu_step_instruction_sync = nullptr;
std::queue<std::function<void()>> m_pending_jobs;
Common::Event m_time_played_finish_sync;
Common::TimedEvent m_time_played_finish_sync;
Core::System& m_system;
};

View File

@ -61,7 +61,7 @@ private:
std::vector<Memcard::GCIFile> m_saves;
std::string m_save_directory;
Common::Event m_flush_trigger;
Common::TimedEvent m_flush_trigger;
std::mutex m_write_mutex;
Common::Flag m_exiting;
std::thread m_flush_thread;

View File

@ -41,7 +41,7 @@ private:
std::unique_ptr<u8[]> m_flush_buffer;
std::thread m_flush_thread;
std::mutex m_flush_mutex;
Common::Event m_flush_trigger;
Common::TimedEvent m_flush_trigger;
Common::Flag m_dirty;
u32 m_memory_card_size;
};

View File

@ -202,7 +202,7 @@ private:
std::thread m_scan_thread;
Common::Flag m_scan_thread_running;
Common::Flag m_populate_devices;
Common::Event m_scan_mode_changed_or_population_event;
Common::TimedEvent m_scan_mode_changed_or_population_event;
std::atomic<WiimoteScanMode> m_scan_mode{WiimoteScanMode::DO_NOT_SCAN};
};

View File

@ -123,7 +123,7 @@ private:
u32 m_download_span = 2;
u32 m_mail_span = 1;
bool m_handle_mail;
Common::Event m_shutdown_event;
Common::TimedEvent m_shutdown_event;
std::mutex m_scheduler_lock;
std::thread m_scheduler_timer_thread;
};

View File

@ -501,7 +501,7 @@ void CodeWidget::Step()
if (!cpu.IsStepping())
return;
Common::Event sync_event;
Common::TimedEvent sync_event;
auto& power_pc = m_system.GetPowerPC();
PowerPC::CoreMode old_mode = power_pc.GetMode();

View File

@ -42,7 +42,7 @@ private:
void Run();
QWidget* m_parent;
Common::Flag m_stop_requested;
Common::Event m_wakeup_event;
Common::TimedEvent m_wakeup_event;
std::thread m_thread;
std::list<DiscordJoinRequestDialog> m_request_dialogs;
std::mutex m_request_dialogs_mutex;

View File

@ -68,7 +68,7 @@ private:
std::string m_last_error;
std::thread m_session_thread;
Common::Event m_session_thread_exit_event;
Common::TimedEvent m_session_thread_exit_event;
std::function<void()> m_error_callback = nullptr;
};