Skip to content

Commit

Permalink
Progress Dialog: Fix race on PPU compilation status
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Aug 21, 2023
1 parent 16c8f8c commit 32e0a24
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 16 deletions.
11 changes: 7 additions & 4 deletions rpcs3/Emu/Cell/PPUThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3971,7 +3971,7 @@ extern void ppu_initialize()
// Validate analyser results (not required)
_main.validate(0);

g_progr = "Scanning PPU Modules...";
progr = "Scanning PPU Modules...";

bool compile_main = false;

Expand Down Expand Up @@ -4523,10 +4523,13 @@ bool ppu_initialize(const ppu_module& info, bool check_only)
// Check object file
if (jit_compiler::check(cache_path + obj_name))
{
if (!jit && !check_only)
if (!jit)
{
ppu_log.success("LLVM: Module exists: %s", obj_name);
}

if (!check_only)
{
// Update progress dialog
g_progr_pdone++;
}
Expand Down Expand Up @@ -4556,7 +4559,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only)

if (!workload.empty())
{
g_progr = "Compiling PPU modules...";
*progr = "Compiling PPU modules...";
}

// Create worker threads for compilation (TODO: how many threads)
Expand Down Expand Up @@ -4624,7 +4627,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only)
if (workload.size() < link_workload.size())
{
// Only show this message if this task is relevant
g_progr = "Linking PPU modules...";
*progr = "Linking PPU modules...";
}

for (auto [obj_name, is_compiled] : link_workload)
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/SPURecompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ void spu_cache::initialize()
break;
}

g_progr_ptotal.wait(v);
thread_ctrl::wait_on(g_progr_ptotal, v);
}

g_progr_ptotal += ::size32(func_list);
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/System.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2678,7 +2678,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate)
{
// Show visual feedback to the user in case that stopping takes a while.
// This needs to be done before actually stopping, because otherwise the necessary threads will be terminated before we can show an image.
if (auto progress_dialog = g_fxo->try_get<named_thread<progress_dialog_server>>(); progress_dialog && +g_progr)
if (auto progress_dialog = g_fxo->try_get<named_thread<progress_dialog_server>>(); progress_dialog && g_progr.load())
{
// We are currently showing a progress dialog. Notify it that we are going to stop emulation.
g_system_progress_stopping = true;
Expand Down
10 changes: 5 additions & 5 deletions rpcs3/Emu/system_progress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
LOG_CHANNEL(sys_log, "SYS");

// Progress display server synchronization variables
atomic_t<const char*> g_progr{nullptr};
atomic_t<progress_dialog_string_t> g_progr{};
atomic_t<u32> g_progr_ftotal{0};
atomic_t<u32> g_progr_fdone{0};
atomic_t<u32> g_progr_ptotal{0};
Expand Down Expand Up @@ -40,7 +40,7 @@ void progress_dialog_server::operator()()
while (!g_system_progress_stopping && thread_ctrl::state() != thread_state::aborting)
{
// Wait for the start condition
auto text0 = +g_progr;
const char* text0 = g_progr.load();

while (!text0)
{
Expand All @@ -50,7 +50,7 @@ void progress_dialog_server::operator()()
}

thread_ctrl::wait_for(5000);
text0 = +g_progr;
text0 = g_progr.load();
}

if (g_system_progress_stopping || thread_ctrl::state() == thread_state::aborting)
Expand Down Expand Up @@ -120,7 +120,7 @@ void progress_dialog_server::operator()()
// Update progress
while (!g_system_progress_stopping && thread_ctrl::state() != thread_state::aborting)
{
const auto text_new = g_progr.load();
const auto text_new = +g_progr.load();

const u32 ftotal_new = g_progr_ftotal;
const u32 fdone_new = g_progr_fdone;
Expand Down Expand Up @@ -239,5 +239,5 @@ progress_dialog_server::~progress_dialog_server()
g_progr_fdone.release(0);
g_progr_ptotal.release(0);
g_progr_pdone.release(0);
g_progr.release(nullptr);
g_progr.release(progress_dialog_string_t{});
}
51 changes: 47 additions & 4 deletions rpcs3/Emu/system_progress.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,19 @@
#include "util/types.hpp"
#include "util/atomic.hpp"

extern atomic_t<const char*> g_progr;
struct alignas(16) progress_dialog_string_t
{
const char* m_text;
u32 m_user_count;
u32 m_updates;

operator const char*() const noexcept
{
return m_text;
}
};

extern atomic_t<progress_dialog_string_t> g_progr;
extern atomic_t<u32> g_progr_ftotal;
extern atomic_t<u32> g_progr_fdone;
extern atomic_t<u32> g_progr_ptotal;
Expand All @@ -15,21 +27,52 @@ extern atomic_t<bool> g_system_progress_stopping;
class scoped_progress_dialog final
{
// Saved previous value
const char* const m_prev;
const char* m_prev;
u32 m_prev_update;

public:
scoped_progress_dialog(const char* text) noexcept
: m_prev(g_progr.exchange(text ? text : ""))
{
std::tie(m_prev, m_prev_update) = g_progr.atomic_op([text = text ? text : ""](progress_dialog_string_t& progr)
{
const char* old = progr.m_text;
progr.m_user_count++;
progr.m_updates++;
progr.m_text = text;
return std::make_pair(old, progr.m_updates);
});
}

scoped_progress_dialog(const scoped_progress_dialog&) = delete;

scoped_progress_dialog& operator=(const scoped_progress_dialog&) = delete;

scoped_progress_dialog& operator=(const char* text) noexcept
{
g_progr.atomic_op([text = text ? text : ""](progress_dialog_string_t& progr)
{
progr.m_text = text;
progr.m_updates++;
});

return *this;
}

~scoped_progress_dialog() noexcept
{
g_progr.release(m_prev);
g_progr.atomic_op([this](progress_dialog_string_t& progr)
{
if (progr.m_user_count-- == 1)
{
// Clean text only on last user
progr.m_text = nullptr;
}
else if (m_prev && m_prev_update == progr.m_updates)
{
// Restore text only if no other updates were made by other threads
progr.m_text = m_prev;
}
});
}
};

Expand Down
2 changes: 1 addition & 1 deletion rpcs3/rpcs3qt/gs_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ bool gs_frame::get_mouse_lock_state()

void gs_frame::hide_on_close()
{
if (!(+g_progr))
if (!g_progr.load())
{
// Hide the dialog before stopping if no progress bar is being shown.
// Otherwise users might think that the game softlocked if stopping takes too long.
Expand Down

0 comments on commit 32e0a24

Please sign in to comment.