mirror of
https://github.com/RPCS3/rpcs3
synced 2024-11-02 10:51:44 +00:00
cellSysutil: Implement dispatcher callback unloading
This commit is contained in:
parent
fe9bb31b09
commit
6fbe4c3e2e
3 changed files with 92 additions and 9 deletions
|
@ -14,6 +14,7 @@
|
|||
#include "Utilities/lockless.h"
|
||||
|
||||
#include <span>
|
||||
#include <deque>
|
||||
|
||||
LOG_CHANNEL(cellSysutil);
|
||||
|
||||
|
@ -58,6 +59,8 @@ void fmt_class_string<CellBgmplaybackError>::format(std::string& out, u64 arg)
|
|||
});
|
||||
}
|
||||
|
||||
atomic_t<usz> g_sysutil_callback_id_assigner = 0;
|
||||
|
||||
struct sysutil_cb_manager
|
||||
{
|
||||
struct alignas(8) registered_dispatcher
|
||||
|
@ -65,6 +68,7 @@ struct sysutil_cb_manager
|
|||
u32 event_code = 0;
|
||||
u32 func_addr = 0;
|
||||
};
|
||||
|
||||
std::array<atomic_t<registered_dispatcher>, 32> dispatchers{};
|
||||
|
||||
struct alignas(8) registered_cb
|
||||
|
@ -77,7 +81,26 @@ struct sysutil_cb_manager
|
|||
|
||||
atomic_t<registered_cb> callbacks[4]{};
|
||||
|
||||
lf_queue<std::function<s32(ppu_thread&)>> registered;
|
||||
struct dispatcher_cb
|
||||
{
|
||||
std::function<s32(ppu_thread&)> func;
|
||||
std::shared_ptr<atomic_t<bool>> call_active;
|
||||
};
|
||||
|
||||
std::deque<lf_queue<std::shared_ptr<atomic_t<bool>>>> registered_callbacks_abort_handles = []()
|
||||
{
|
||||
// Do resize for deque (cheap container which can store all non-movable value types)
|
||||
std::deque<lf_queue<std::shared_ptr<atomic_t<bool>>>> result;
|
||||
|
||||
for (usz i = 0 ; i < g_sysutil_callback_id_assigner; i++)
|
||||
{
|
||||
result.emplace_back();
|
||||
}
|
||||
|
||||
return result;
|
||||
}();
|
||||
|
||||
lf_queue<dispatcher_cb> registered;
|
||||
|
||||
atomic_t<bool> draw_cb_started{};
|
||||
atomic_t<u64> read_counter{0};
|
||||
|
@ -98,11 +121,40 @@ struct sysutil_cb_manager
|
|||
}
|
||||
};
|
||||
|
||||
void sysutil_register_cb_with_id_internal(std::function<s32(ppu_thread&)>&& cb, usz call_id)
|
||||
{
|
||||
auto& cbm = *ensure(g_fxo->try_get<sysutil_cb_manager>());
|
||||
|
||||
sysutil_cb_manager::dispatcher_cb info{std::move(cb)};
|
||||
|
||||
if (call_id != umax)
|
||||
{
|
||||
info.call_active = std::make_shared<atomic_t<bool>>(true);
|
||||
::at32(cbm.registered_callbacks_abort_handles, call_id).push(info.call_active);
|
||||
}
|
||||
|
||||
cbm.registered.push(std::move(info));
|
||||
}
|
||||
|
||||
extern void sysutil_unregister_cb_with_id_internal(usz call_id)
|
||||
{
|
||||
const auto cbm = g_fxo->try_get<sysutil_cb_manager>();
|
||||
|
||||
if (!cbm)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto&& abort_handle : ::at32(cbm->registered_callbacks_abort_handles, call_id).pop_all())
|
||||
{
|
||||
// Deactivate the existing event once
|
||||
abort_handle->store(false);
|
||||
}
|
||||
}
|
||||
|
||||
extern void sysutil_register_cb(std::function<s32(ppu_thread&)>&& cb)
|
||||
{
|
||||
auto& cbm = g_fxo->get<sysutil_cb_manager>();
|
||||
|
||||
cbm.registered.push(std::move(cb));
|
||||
sysutil_register_cb_with_id_internal(std::move(cb), umax);
|
||||
}
|
||||
|
||||
extern s32 sysutil_send_system_cmd(u64 status, u64 param)
|
||||
|
@ -136,12 +188,12 @@ extern s32 sysutil_send_system_cmd(u64 status, u64 param)
|
|||
{
|
||||
if (cb.callback)
|
||||
{
|
||||
cbm->registered.push([=](ppu_thread& ppu) -> s32
|
||||
cbm->registered.push(sysutil_cb_manager::dispatcher_cb{[=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
// TODO: check it and find the source of the return value (void isn't equal to CELL_OK)
|
||||
cb.callback(ppu, status, param, cb.user_data);
|
||||
return CELL_OK;
|
||||
});
|
||||
}});
|
||||
|
||||
count++;
|
||||
}
|
||||
|
@ -532,9 +584,14 @@ error_code cellSysutilCheckCallback(ppu_thread& ppu)
|
|||
|
||||
for (auto&& func : cbm.registered.pop_all())
|
||||
{
|
||||
if (func.call_active && !*func.call_active)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
read = true;
|
||||
|
||||
if (s32 res = func(ppu))
|
||||
if (s32 res = func.func(ppu))
|
||||
{
|
||||
// Currently impossible
|
||||
return not_an_error(res);
|
||||
|
|
|
@ -323,6 +323,26 @@ struct SysutilEventStatus
|
|||
atomic_t<bool> active = false;
|
||||
};
|
||||
|
||||
extern atomic_t<usz> g_sysutil_callback_id_assigner;
|
||||
|
||||
extern void sysutil_register_cb_with_id_internal(std::function<s32(ppu_thread&)>&& cb, usz call_id);
|
||||
extern void sysutil_unregister_cb_with_id_internal(usz call_id);
|
||||
|
||||
template <typename T>
|
||||
const usz g_sysutil_dispatcher_id = g_sysutil_callback_id_assigner++;
|
||||
|
||||
template <typename T>
|
||||
void sysutil_register_cb_with_id(std::function<s32(ppu_thread&)>&& cb)
|
||||
{
|
||||
sysutil_register_cb_with_id_internal(std::move(cb), g_sysutil_dispatcher_id<T>);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void sysutil_unregister_cb_with_id()
|
||||
{
|
||||
sysutil_unregister_cb_with_id_internal(g_sysutil_dispatcher_id<T>);
|
||||
}
|
||||
|
||||
using SysutilMenuOpenStatus = SysutilEventStatus<CELL_SYSUTIL_SYSTEM_MENU_OPEN>;
|
||||
|
||||
extern void sysutil_register_cb(std::function<s32(ppu_thread&)>&&);
|
||||
|
|
|
@ -112,6 +112,9 @@ struct avc2_settings
|
|||
}
|
||||
};
|
||||
|
||||
// Callback handle tag type
|
||||
struct avc2_cb_handle_t{};
|
||||
|
||||
error_code cellSysutilAvc2GetPlayerInfo(vm::cptr<SceNpMatching2RoomMemberId> player_id, vm::ptr<CellSysutilAvc2PlayerInfo> player_info)
|
||||
{
|
||||
cellSysutilAvc2.todo("cellSysutilAvc2GetPlayerInfo(player_id=*0x%x, player_info=*0x%x)", player_id, player_info);
|
||||
|
@ -434,6 +437,7 @@ error_code cellSysutilAvc2Unload()
|
|||
return CELL_AVC2_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
sysutil_unregister_cb_with_id<avc2_cb_handle_t>();
|
||||
settings.avc2_cb = vm::null;
|
||||
settings.avc2_cb_arg = vm::null;
|
||||
|
||||
|
@ -455,6 +459,7 @@ error_code cellSysutilAvc2UnloadAsync()
|
|||
});
|
||||
}
|
||||
|
||||
sysutil_unregister_cb_with_id<avc2_cb_handle_t>();
|
||||
settings.avc2_cb = vm::null;
|
||||
settings.avc2_cb_arg = vm::null;
|
||||
|
||||
|
@ -572,7 +577,7 @@ error_code cellSysutilAvc2JoinChatRequest(vm::cptr<SceNpMatching2RoomId> room_id
|
|||
|
||||
if (settings.avc2_cb)
|
||||
{
|
||||
sysutil_register_cb([=, avc2_cb = settings.avc2_cb, avc2_cb_arg = settings.avc2_cb_arg](ppu_thread& cb_ppu) -> s32
|
||||
sysutil_register_cb_with_id<avc2_cb_handle_t>([=, avc2_cb = settings.avc2_cb, avc2_cb_arg = settings.avc2_cb_arg](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
avc2_cb(cb_ppu, CELL_AVC2_EVENT_JOIN_SUCCEEDED, 0, avc2_cb_arg);
|
||||
return 0;
|
||||
|
@ -1032,7 +1037,7 @@ error_code cellSysutilAvc2Unload2(u32 mediaType)
|
|||
}
|
||||
|
||||
// TODO: return error if the video chat is still loaded (probably CELL_AVC2_ERROR_INVALID_STATUS)
|
||||
|
||||
sysutil_unregister_cb_with_id<avc2_cb_handle_t>();
|
||||
settings.avc2_cb = vm::null;
|
||||
settings.avc2_cb_arg = vm::null;
|
||||
break;
|
||||
|
@ -1073,6 +1078,7 @@ error_code cellSysutilAvc2UnloadAsync2(u32 mediaType)
|
|||
|
||||
if (mediaType == CELL_SYSUTIL_AVC2_VOICE_CHAT)
|
||||
{
|
||||
sysutil_unregister_cb_with_id<avc2_cb_handle_t>();
|
||||
settings.avc2_cb = vm::null;
|
||||
settings.avc2_cb_arg = vm::null;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue