mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-29 22:20:48 +00:00
Thread.h: Fix a bug by adding thread_state::destroying_context
This commit is contained in:
parent
036693a14d
commit
6165c2d8b3
@ -33,7 +33,8 @@ enum class thread_state : u32
|
|||||||
aborting = 1, // The thread has been joined in the destructor or explicitly aborted
|
aborting = 1, // The thread has been joined in the destructor or explicitly aborted
|
||||||
errored = 2, // Set after the emergency_exit call
|
errored = 2, // Set after the emergency_exit call
|
||||||
finished = 3, // Final state, always set at the end of thread execution
|
finished = 3, // Final state, always set at the end of thread execution
|
||||||
mask = 3
|
mask = 3,
|
||||||
|
destroying_context = 7, // Special value assigned to destroy data explicitly before the destructor
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Context>
|
template <class Context>
|
||||||
@ -702,14 +703,17 @@ public:
|
|||||||
thread::m_sync.notify_all();
|
thread::m_sync.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s == thread_state::finished)
|
if (s == thread_state::finished || s == thread_state::destroying_context)
|
||||||
{
|
{
|
||||||
// This participates in emulation stopping, use destruction-alike semantics
|
// This participates in emulation stopping, use destruction-alike semantics
|
||||||
thread::join(true);
|
thread::join(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s == thread_state::destroying_context)
|
||||||
|
{
|
||||||
if constexpr (std::is_assignable_v<Context&, thread_state>)
|
if constexpr (std::is_assignable_v<Context&, thread_state>)
|
||||||
{
|
{
|
||||||
static_cast<Context&>(*this) = thread_state::finished;
|
static_cast<Context&>(*this) = thread_state::destroying_context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ void lv2_config::remove_service_event(u32 id)
|
|||||||
|
|
||||||
lv2_config_service_event& lv2_config_service_event::operator=(thread_state s) noexcept
|
lv2_config_service_event& lv2_config_service_event::operator=(thread_state s) noexcept
|
||||||
{
|
{
|
||||||
if (s == thread_state::finished)
|
if (s == thread_state::destroying_context && !m_destroyed.exchange(true))
|
||||||
{
|
{
|
||||||
if (auto global = g_fxo->try_get<lv2_config>())
|
if (auto global = g_fxo->try_get<lv2_config>())
|
||||||
{
|
{
|
||||||
|
@ -362,6 +362,10 @@ class lv2_config_service_event
|
|||||||
return g_fxo->get<service_event_id>().next_id++;
|
return g_fxo->get<service_event_id>().next_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_t<bool> m_destroyed = false;
|
||||||
|
|
||||||
|
friend class lv2_config;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const u32 id;
|
const u32 id;
|
||||||
|
|
||||||
@ -393,8 +397,7 @@ public:
|
|||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
lv2_config_service_event& operator=(thread_state s) noexcept;
|
lv2_config_service_event& operator=(thread_state s) noexcept;
|
||||||
|
~lv2_config_service_event() noexcept;
|
||||||
~lv2_config_service_event() noexcept = default;
|
|
||||||
|
|
||||||
// Notify queue that this event exists
|
// Notify queue that this event exists
|
||||||
bool notify() const;
|
bool notify() const;
|
||||||
|
@ -178,7 +178,7 @@ void lv2_socket::queue_wake(ppu_thread* ppu)
|
|||||||
|
|
||||||
lv2_socket& lv2_socket::operator=(thread_state s) noexcept
|
lv2_socket& lv2_socket::operator=(thread_state s) noexcept
|
||||||
{
|
{
|
||||||
if (s == thread_state::finished)
|
if (s == thread_state::destroying_context)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
@ -805,8 +805,8 @@ public:
|
|||||||
{
|
{
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
constexpr thread_state finished{3};
|
constexpr thread_state destroying_context{7};
|
||||||
*static_cast<Get*>(ptr.get()) = finished;
|
*static_cast<Get*>(ptr.get()) = destroying_context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -837,8 +837,8 @@ public:
|
|||||||
{
|
{
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
constexpr thread_state finished{3};
|
constexpr thread_state destroying_context{7};
|
||||||
*static_cast<Get*>(ptr.get()) = finished;
|
*static_cast<Get*>(ptr.get()) = destroying_context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,6 +347,19 @@ namespace stx
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Order semi-destructors before the actual destructors
|
||||||
|
// This allows to safely access data that may be deallocated or destroyed from other members of FXO regardless of their intialization time
|
||||||
|
for (u32 i = 0; i < _max; i++)
|
||||||
|
{
|
||||||
|
const auto info = (*std::prev(m_info, i + 1));
|
||||||
|
|
||||||
|
if (auto op = info->thread_op)
|
||||||
|
{
|
||||||
|
constexpr thread_state destroying_context{7};
|
||||||
|
op(*std::prev(m_order, i + 1), destroying_context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Destroy objects in reverse order
|
// Destroy objects in reverse order
|
||||||
for (; _max; _max--)
|
for (; _max; _max--)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user