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

Improve thread aborting mechanism (#10490)

Call pseudo-virtual operator=(thread_state) of thread context.
This commit is contained in:
Eladash 2021-06-27 11:43:48 +03:00 committed by GitHub
parent 58847fa2ca
commit 0aed00a758
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 31 additions and 44 deletions

View File

@ -35,8 +35,6 @@ enum class thread_state : u32
mask = 3 mask = 3
}; };
class need_wakeup {};
template <class Context> template <class Context>
class named_thread; class named_thread;
@ -616,14 +614,14 @@ public:
// Join thread by thread_state::finished // Join thread by thread_state::finished
named_thread& operator=(thread_state s) named_thread& operator=(thread_state s)
{ {
if constexpr (std::is_assignable_v<Context&, thread_state>)
{
static_cast<Context&>(*this) = s;
}
if (s >= thread_state::aborting && thread::m_sync.fetch_op([](u64& v){ return !(v & 3) && (v |= 1); }).second) if (s >= thread_state::aborting && thread::m_sync.fetch_op([](u64& v){ return !(v & 3) && (v |= 1); }).second)
{ {
thread::m_sync.notify_one(1); thread::m_sync.notify_one(1);
if constexpr (std::is_base_of_v<need_wakeup, Context>)
{
this->wake_up();
}
} }
if (s == thread_state::finished) if (s == thread_state::finished)

View File

@ -812,6 +812,8 @@ bool cpu_thread::check_state() noexcept
void cpu_thread::notify() void cpu_thread::notify()
{ {
state.notify_one();
// Downcast to correct type // Downcast to correct type
if (id_type() == 1) if (id_type() == 1)
{ {
@ -827,6 +829,13 @@ void cpu_thread::notify()
} }
} }
cpu_thread& cpu_thread::operator=(thread_state)
{
state += cpu_flag::exit;
state.notify_one(cpu_flag::exit);
return *this;
}
std::string cpu_thread::get_name() const std::string cpu_thread::get_name() const
{ {
// Downcast to correct type // Downcast to correct type
@ -1099,29 +1108,6 @@ bool cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
return true; return true;
} }
void cpu_thread::stop_all() noexcept
{
if (g_tls_this_thread)
{
// Report unsupported but unnecessary case
sys_log.fatal("cpu_thread::stop_all() has been called from a CPU thread.");
return;
}
else
{
auto on_stop = [](u32, cpu_thread& cpu)
{
cpu.state += cpu_flag::exit;
cpu.state.notify_one(cpu_flag::exit);
};
idm::select<named_thread<ppu_thread>>(on_stop);
idm::select<named_thread<spu_thread>>(on_stop);
}
sys_log.notice("All CPU threads have been signaled.");
}
void cpu_thread::cleanup() noexcept void cpu_thread::cleanup() noexcept
{ {
ensure(!s_cpu_counter); ensure(!s_cpu_counter);

View File

@ -139,6 +139,7 @@ public:
u32* get_pc2(); // Last PC before stepping for the debugger (may be null) u32* get_pc2(); // Last PC before stepping for the debugger (may be null)
void notify(); void notify();
cpu_thread& operator=(thread_state);
public: public:
// Thread stats for external observation // Thread stats for external observation
@ -263,9 +264,6 @@ public:
} }
} }
// Stop all threads with cpu_flag::exit
static void stop_all() noexcept;
// Cleanup thread counting information // Cleanup thread counting information
static void cleanup() noexcept; static void cleanup() noexcept;

View File

@ -296,7 +296,7 @@ static void network_clear_queue(ppu_thread& ppu)
} }
// Object in charge of retransmiting packets for STREAM_P2P sockets // Object in charge of retransmiting packets for STREAM_P2P sockets
class tcp_timeout_monitor : public need_wakeup class tcp_timeout_monitor
{ {
public: public:
void add_message(s32 sock_id, const sockaddr_in *dst, std::vector<u8> data, u64 seq) void add_message(s32 sock_id, const sockaddr_in *dst, std::vector<u8> data, u64 seq)
@ -423,9 +423,10 @@ public:
} }
} }
void wake_up() tcp_timeout_monitor& operator=(thread_state)
{ {
wakey.notify_one(); wakey.notify_one();
return *this;
} }
public: public:

View File

@ -377,6 +377,12 @@ void signaling_handler::wake_up()
wakey.notify_one(); wakey.notify_one();
} }
signaling_handler& signaling_handler::operator=(thread_state)
{
wakey.notify_one();
return *this;
}
void signaling_handler::update_si_addr(std::shared_ptr<signaling_info>& si, u32 new_addr, u16 new_port) void signaling_handler::update_si_addr(std::shared_ptr<signaling_info>& si, u32 new_addr, u16 new_port)
{ {
ensure(si); ensure(si);

View File

@ -45,11 +45,12 @@ enum SignalingCommand : u32
signal_finished_ack, signal_finished_ack,
}; };
class signaling_handler : public need_wakeup class signaling_handler
{ {
public: public:
void operator()(); void operator()();
void wake_up(); void wake_up();
signaling_handler& operator=(thread_state);
void set_self_sig_info(SceNpId& npid); void set_self_sig_info(SceNpId& npid);
void set_self_sig2_info(u64 room_id, u16 member_id); void set_self_sig2_info(u64 room_id, u16 member_id);

View File

@ -1534,14 +1534,6 @@ void Emulator::Stop(bool restart)
} }
}); });
if (auto rsx = g_fxo->try_get<rsx::thread>())
{
// TODO: notify?
rsx->state += cpu_flag::exit;
}
cpu_thread::stop_all();
// Signal threads // Signal threads
for (const auto& [type, data] : *g_fxo) for (const auto& [type, data] : *g_fxo)
{ {
@ -1551,6 +1543,11 @@ void Emulator::Stop(bool restart)
} }
} }
sys_log.notice("All emulation threads have been signaled.");
// Wait fot newly created cpu_thread to see that emulation has been stopped
id_manager::g_mutex.lock_unlock();
GetCallbacks().on_stop(); GetCallbacks().on_stop();
// Join threads // Join threads