Skip to content

Commit

Permalink
Thread.h: Fix a bug by adding thread_state::destroying_context
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Jan 5, 2025
1 parent d04f235 commit 36a0cc3
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 11 deletions.
10 changes: 7 additions & 3 deletions Utilities/Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ enum class thread_state : u32
aborting = 1, // The thread has been joined in the destructor or explicitly aborted
errored = 2, // Set after the emergency_exit call
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>
Expand Down Expand Up @@ -702,14 +703,17 @@ class named_thread final : public Context, result_storage<Context>, thread_base
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
thread::join(true);
}

if (s == thread_state::destroying_context)
{
if constexpr (std::is_assignable_v<Context&, thread_state>)
{
static_cast<Context&>(*this) = thread_state::finished;
static_cast<Context&>(*this) = thread_state::destroying_context;
}
}

Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/lv2/sys_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
if (s == thread_state::finished)
if (s == thread_state::destroying_context && !m_destroyed.exchange(true))
{
if (auto global = g_fxo->try_get<lv2_config>())
{
Expand Down
7 changes: 5 additions & 2 deletions rpcs3/Emu/Cell/lv2/sys_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ class lv2_config_service_event
return g_fxo->get<service_event_id>().next_id++;
}

atomic_t<bool> m_destroyed = false;

friend class lv2_config;

public:
const u32 id;

Expand Down Expand Up @@ -393,8 +397,7 @@ class lv2_config_service_event

// Destructor
lv2_config_service_event& operator=(thread_state s) noexcept;

~lv2_config_service_event() noexcept = default;
~lv2_config_service_event() noexcept;

// Notify queue that this event exists
bool notify() const;
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ void lv2_socket::queue_wake(ppu_thread* ppu)

lv2_socket& lv2_socket::operator=(thread_state s) noexcept
{
if (s == thread_state::finished)
if (s == thread_state::destroying_context)
{
close();
}
Expand Down
8 changes: 4 additions & 4 deletions rpcs3/Emu/IdManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -805,8 +805,8 @@ class idm
{
if (ptr)
{
constexpr thread_state finished{3};
*static_cast<Get*>(ptr.get()) = finished;
constexpr thread_state destroying_context{7};
*static_cast<Get*>(ptr.get()) = destroying_context;
}
}

Expand Down Expand Up @@ -837,8 +837,8 @@ class idm
{
if (ptr)
{
constexpr thread_state finished{3};
*static_cast<Get*>(ptr.get()) = finished;
constexpr thread_state destroying_context{7};
*static_cast<Get*>(ptr.get()) = destroying_context;
}
}

Expand Down
13 changes: 13 additions & 0 deletions rpcs3/util/fixed_typemap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
for (; _max; _max--)
{
Expand Down

0 comments on commit 36a0cc3

Please sign in to comment.