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
};
class need_wakeup {};
template <class Context>
class named_thread;
@ -616,14 +614,14 @@ public:
// Join thread by thread_state::finished
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)
{
thread::m_sync.notify_one(1);
if constexpr (std::is_base_of_v<need_wakeup, Context>)
{
this->wake_up();
}
}
if (s == thread_state::finished)

View file

@ -812,6 +812,8 @@ bool cpu_thread::check_state() noexcept
void cpu_thread::notify()
{
state.notify_one();
// Downcast to correct type
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
{
// Downcast to correct type
@ -1099,29 +1108,6 @@ bool cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
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
{
ensure(!s_cpu_counter);

View file

@ -139,6 +139,7 @@ public:
u32* get_pc2(); // Last PC before stepping for the debugger (may be null)
void notify();
cpu_thread& operator=(thread_state);
public:
// 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
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
class tcp_timeout_monitor : public need_wakeup
class tcp_timeout_monitor
{
public:
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();
return *this;
}
public:

View file

@ -377,6 +377,12 @@ void signaling_handler::wake_up()
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)
{
ensure(si);

View file

@ -45,11 +45,12 @@ enum SignalingCommand : u32
signal_finished_ack,
};
class signaling_handler : public need_wakeup
class signaling_handler
{
public:
void operator()();
void wake_up();
signaling_handler& operator=(thread_state);
void set_self_sig_info(SceNpId& npid);
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
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();
// Join threads