1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

named_thread: implement "default" event loop

Fixup "sleepy" thread at startup on Windows.
Permit threads which lack operator()() overload.
This commit is contained in:
Nekotekina 2021-02-24 13:56:02 +03:00
parent 29e7eda887
commit 3aaa0172d5
3 changed files with 22 additions and 8 deletions

View File

@ -2336,16 +2336,14 @@ bool thread_base::join(bool dtor) const
if (i > 20 && Emu.IsStopped()) if (i > 20 && Emu.IsStopped())
{ {
stamp0 = __rdtsc();
atomic_wait_engine::raw_notify(0, get_native_id()); atomic_wait_engine::raw_notify(0, get_native_id());
stamp0 = __rdtsc() - stamp0;
warn = true; warn = true;
} }
} }
if (warn) if (warn)
{ {
sig_log.error(u8"Thread [%s] is too sleepy. Took %.3fµs to wake it up!", *m_tname.load(), stamp0 / (utils::get_tsc_freq() / 1000000.)); sig_log.error(u8"Thread [%s] is too sleepy. Took %.3fµs to wake it up!", *m_tname.load(), (__rdtsc() - stamp0) / (utils::get_tsc_freq() / 1000000.));
} }
return (m_sync & 3) == 3; return (m_sync & 3) == 3;

View File

@ -42,6 +42,8 @@ class need_wakeup {};
template <class Context> template <class Context>
class named_thread; class named_thread;
class thread_base;
template <typename Ctx, typename X = void, typename... Args> template <typename Ctx, typename X = void, typename... Args>
struct result_storage struct result_storage
{ {
@ -234,7 +236,7 @@ public:
} }
// Wait for both thread sync var and provided atomic var // Wait for both thread sync var and provided atomic var
template <typename T, atomic_wait::op op = atomic_wait::op::eq, typename U> template <atomic_wait::op Op = atomic_wait::op::eq, typename T, typename U>
static inline void wait_on(T& wait, U old, u64 usec = -1) static inline void wait_on(T& wait, U old, u64 usec = -1)
{ {
auto _this = g_tls_this_thread; auto _this = g_tls_this_thread;
@ -245,7 +247,7 @@ public:
} }
atomic_wait::list<2> list{}; atomic_wait::list<2> list{};
list.set<0, op>(wait, old); list.set<0, Op>(wait, old);
list.set<1>(_this->m_sync, 0, 4 + 1); list.set<1>(_this->m_sync, 0, 4 + 1);
list.wait(atomic_wait_timeout{usec <= 0xffff'ffff'ffff'ffff / 1000 ? usec * 1000 : 0xffff'ffff'ffff'ffff}); list.wait(atomic_wait_timeout{usec <= 0xffff'ffff'ffff'ffff / 1000 ? usec * 1000 : 0xffff'ffff'ffff'ffff});
} }
@ -329,12 +331,23 @@ class named_thread final : public Context, result_storage<Context>, thread_base
if constexpr (result::empty) if constexpr (result::empty)
{ {
// No result // No result
if constexpr (std::is_invocable_v<Context>)
{
Context::operator()(); Context::operator()();
} }
else else
{
// Default event loop
while (thread_ctrl::state() != thread_state::aborting)
{
thread_ctrl::wait();
}
}
}
else
{ {
// Construct the result using placement new (copy elision should happen) // Construct the result using placement new (copy elision should happen)
new (result::get()) typename result::type(Context::operator()()); new (result::get()) decltype(auto)(Context::operator()());
} }
return thread::finalize(thread_state::finished); return thread::finalize(thread_state::finished);

View File

@ -377,8 +377,11 @@ int main(int argc, char** argv)
} }
#endif #endif
// Initialize TSC freq (in case it isn't)
static_cast<void>(utils::get_tsc_freq());
// Initialize thread pool finalizer (on first use) // Initialize thread pool finalizer (on first use)
named_thread("", []{})(); static_cast<void>(named_thread("", [](int) {}));
static std::unique_ptr<logs::listener> log_file; static std::unique_ptr<logs::listener> log_file;
{ {