overlays: add "thread bits" to wait on and avoid lockup

Add TLS variable to store its own bit.
This commit is contained in:
Nekotekina 2020-02-27 17:28:42 +03:00
parent d0b2eecc9a
commit ecd68dfc70
4 changed files with 48 additions and 20 deletions

View file

@ -242,10 +242,10 @@ namespace rsx
{ {
if (!exit) if (!exit)
{ {
thread_count++; g_fxo->init<named_thread>("MsgDialog Thread", [&, tbit = alloc_thread_bit()]()
g_fxo->init<named_thread>("MsgDialog Thread", [&]()
{ {
g_thread_bit = tbit;
if (interactive) if (interactive)
{ {
auto ref = g_fxo->get<display_manager>()->get(uid); auto ref = g_fxo->get<display_manager>()->get(uid);
@ -267,15 +267,13 @@ namespace rsx
if (!g_fxo->get<display_manager>()) if (!g_fxo->get<display_manager>())
{ {
rsx_log.fatal("display_manager was improperly destroyed"); rsx_log.fatal("display_manager was improperly destroyed");
return; break;
} }
} }
} }
if (!--thread_count) thread_bits &= ~tbit;
{ thread_bits.notify_all();
thread_count.notify_all();
}
}); });
} }
} }

View file

@ -208,19 +208,17 @@ namespace rsx
fade_animation.duration = 0.5f; fade_animation.duration = 0.5f;
fade_animation.active = true; fade_animation.active = true;
thread_count++; g_fxo->init<named_thread>("OSK Thread", [this, tbit = alloc_thread_bit()]
g_fxo->init<named_thread>("OSK Thread", [this]
{ {
g_thread_bit = tbit;
if (auto error = run_input_loop()) if (auto error = run_input_loop())
{ {
rsx_log.error("Osk input loop exited with error code=%d", error); rsx_log.error("Osk input loop exited with error code=%d", error);
} }
if (!--thread_count) thread_bits &= ~tbit;
{ thread_bits.notify_all();
thread_count.notify_all();
}
}); });
} }

View file

@ -10,6 +10,33 @@ namespace rsx
{ {
namespace overlays namespace overlays
{ {
thread_local DECLARE(user_interface::g_thread_bit) = 0;
u64 user_interface::alloc_thread_bit()
{
auto [_old, ok] = this->thread_bits.fetch_op([](u64& bits)
{
if (~bits)
{
// Set lowest clear bit
bits |= bits + 1;
return true;
}
return false;
});
if (!ok)
{
::overlays.fatal("Out of thread bits in user interface");
return 0;
}
const u64 r = u64{1} << utils::cnttz64(~_old, false);
::overlays.trace("Bit allocated (%u)", r);
return r;
}
// Singleton instance declaration // Singleton instance declaration
fontmgr* fontmgr::m_instance = nullptr; fontmgr* fontmgr::m_instance = nullptr;
@ -159,14 +186,15 @@ namespace rsx
// Force unload // Force unload
exit.release(true); exit.release(true);
while (u32 i = thread_count) while (u64 b = thread_bits)
{ {
thread_count.wait(i); if (b == g_thread_bit)
if (thread_ctrl::state() == thread_state::aborting)
{ {
// Don't wait for its own bit
break; break;
} }
thread_bits.wait(b);
} }
pad::SetIntercepted(false); pad::SetIntercepted(false);

View file

@ -72,7 +72,11 @@ namespace rsx
protected: protected:
Timer input_timer; Timer input_timer;
atomic_t<bool> exit = false; atomic_t<bool> exit = false;
atomic_t<u32> thread_count = 0; atomic_t<u64> thread_bits = 0;
static thread_local u64 g_thread_bit;
u64 alloc_thread_bit();
std::function<void(s32 status)> on_close; std::function<void(s32 status)> on_close;