mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 05:51:27 +12:00
named_thread: install atomic wait callback
This commit is contained in:
parent
1668d6ee1b
commit
faba366f89
2 changed files with 72 additions and 13 deletions
|
@ -1667,11 +1667,14 @@ void thread_base::start(native_entry entry)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread_base::initialize()
|
void thread_base::initialize(bool(*wait_cb)(const void*))
|
||||||
{
|
{
|
||||||
// Initialize TLS variable
|
// Initialize TLS variable
|
||||||
thread_ctrl::g_tls_this_thread = this;
|
thread_ctrl::g_tls_this_thread = this;
|
||||||
|
|
||||||
|
// Initialize atomic wait callback
|
||||||
|
atomic_storage_futex::set_wait_callback(wait_cb);
|
||||||
|
|
||||||
g_tls_log_prefix = []
|
g_tls_log_prefix = []
|
||||||
{
|
{
|
||||||
return thread_ctrl::g_tls_this_thread->m_name.get();
|
return thread_ctrl::g_tls_this_thread->m_name.get();
|
||||||
|
@ -1718,6 +1721,14 @@ void thread_base::initialize()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void thread_base::notify_abort() noexcept
|
||||||
|
{
|
||||||
|
// For now
|
||||||
|
notify();
|
||||||
|
|
||||||
|
atomic_storage_futex::raw_notify(+m_state_notifier);
|
||||||
|
}
|
||||||
|
|
||||||
bool thread_base::finalize(int) noexcept
|
bool thread_base::finalize(int) noexcept
|
||||||
{
|
{
|
||||||
// Report pending errors
|
// Report pending errors
|
||||||
|
|
|
@ -34,7 +34,7 @@ enum class thread_class : u32
|
||||||
ppu
|
ppu
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class thread_state
|
enum class thread_state : u32
|
||||||
{
|
{
|
||||||
created, // Initial state
|
created, // Initial state
|
||||||
detached, // The thread has been detached to destroy its own named_thread object (can be dangerously misused)
|
detached, // The thread has been detached to destroy its own named_thread object (can be dangerously misused)
|
||||||
|
@ -95,6 +95,13 @@ struct thread_on_cleanup : std::bool_constant<false> {};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct thread_on_cleanup<T, decltype(named_thread<T>::on_cleanup(std::declval<named_thread<T>*>()))> : std::bool_constant<true> {};
|
struct thread_on_cleanup<T, decltype(named_thread<T>::on_cleanup(std::declval<named_thread<T>*>()))> : std::bool_constant<true> {};
|
||||||
|
|
||||||
|
// Detect on_wait() method (should return bool)
|
||||||
|
template <typename T, typename = bool>
|
||||||
|
struct thread_on_wait : std::bool_constant<false> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct thread_on_wait<T, decltype(std::declval<named_thread<T>&>().on_wait())> : std::bool_constant<true> {};
|
||||||
|
|
||||||
// Thread base class
|
// Thread base class
|
||||||
class thread_base
|
class thread_base
|
||||||
{
|
{
|
||||||
|
@ -123,6 +130,9 @@ class thread_base
|
||||||
// Thread state
|
// Thread state
|
||||||
atomic_t<thread_state> m_state = thread_state::created;
|
atomic_t<thread_state> m_state = thread_state::created;
|
||||||
|
|
||||||
|
// Thread state notification info
|
||||||
|
atomic_t<const void*> m_state_notifier{nullptr};
|
||||||
|
|
||||||
// Thread name
|
// Thread name
|
||||||
lf_value<std::string> m_name;
|
lf_value<std::string> m_name;
|
||||||
|
|
||||||
|
@ -133,7 +143,10 @@ class thread_base
|
||||||
void start(native_entry);
|
void start(native_entry);
|
||||||
|
|
||||||
// Called at the thread start
|
// Called at the thread start
|
||||||
void initialize();
|
void initialize(bool(*wait_cb)(const void*));
|
||||||
|
|
||||||
|
// May be called in destructor
|
||||||
|
void notify_abort() noexcept;
|
||||||
|
|
||||||
// Called at the thread end, returns true if needs destruction
|
// Called at the thread end, returns true if needs destruction
|
||||||
bool finalize(int) noexcept;
|
bool finalize(int) noexcept;
|
||||||
|
@ -314,7 +327,47 @@ class named_thread final : public Context, result_storage_t<Context>, thread_bas
|
||||||
|
|
||||||
bool entry_point()
|
bool entry_point()
|
||||||
{
|
{
|
||||||
thread::initialize();
|
thread::initialize([](const void* data)
|
||||||
|
{
|
||||||
|
const auto _this = thread_ctrl::get_current();
|
||||||
|
|
||||||
|
if (_this->m_state >= thread_state::aborting)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (thread_on_wait<Context>())
|
||||||
|
{
|
||||||
|
if (!static_cast<named_thread*>(_this)->on_wait())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_this->m_state_notifier.release(data);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_this->m_state >= thread_state::aborting)
|
||||||
|
{
|
||||||
|
_this->m_state_notifier.release(nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (thread_on_wait<Context>())
|
||||||
|
{
|
||||||
|
if (!static_cast<named_thread*>(_this)->on_wait())
|
||||||
|
{
|
||||||
|
_this->m_state_notifier.release(nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
if constexpr (result::empty)
|
if constexpr (result::empty)
|
||||||
{
|
{
|
||||||
|
@ -394,12 +447,7 @@ public:
|
||||||
// Try to abort/detach
|
// Try to abort/detach
|
||||||
named_thread& operator=(thread_state s)
|
named_thread& operator=(thread_state s)
|
||||||
{
|
{
|
||||||
if (s != thread_state::aborting && s != thread_state::detached)
|
if (s < thread_state::finished && thread::m_state.compare_and_swap_test(thread_state::created, s))
|
||||||
{
|
|
||||||
ASSUME(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thread::m_state.compare_and_swap_test(thread_state::created, s))
|
|
||||||
{
|
{
|
||||||
if (s == thread_state::aborting)
|
if (s == thread_state::aborting)
|
||||||
{
|
{
|
||||||
|
@ -408,9 +456,9 @@ public:
|
||||||
{
|
{
|
||||||
Context::on_abort();
|
Context::on_abort();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
thread::notify();
|
thread::notify_abort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -419,7 +467,7 @@ public:
|
||||||
// Context type doesn't need virtual destructor
|
// Context type doesn't need virtual destructor
|
||||||
~named_thread()
|
~named_thread()
|
||||||
{
|
{
|
||||||
*this = thread_state::aborting;
|
operator=(thread_state::aborting);
|
||||||
thread::join();
|
thread::join();
|
||||||
|
|
||||||
if constexpr (!result::empty)
|
if constexpr (!result::empty)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue