mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 15:01:28 +12: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 "Utilities/lockless.h"
|
||||||
|
|
||||||
#include <span>
|
#include <span>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
LOG_CHANNEL(cellSysutil);
|
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 sysutil_cb_manager
|
||||||
{
|
{
|
||||||
struct alignas(8) registered_dispatcher
|
struct alignas(8) registered_dispatcher
|
||||||
|
@ -65,6 +68,7 @@ struct sysutil_cb_manager
|
||||||
u32 event_code = 0;
|
u32 event_code = 0;
|
||||||
u32 func_addr = 0;
|
u32 func_addr = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<atomic_t<registered_dispatcher>, 32> dispatchers{};
|
std::array<atomic_t<registered_dispatcher>, 32> dispatchers{};
|
||||||
|
|
||||||
struct alignas(8) registered_cb
|
struct alignas(8) registered_cb
|
||||||
|
@ -77,7 +81,26 @@ struct sysutil_cb_manager
|
||||||
|
|
||||||
atomic_t<registered_cb> callbacks[4]{};
|
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<bool> draw_cb_started{};
|
||||||
atomic_t<u64> read_counter{0};
|
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)
|
extern void sysutil_register_cb(std::function<s32(ppu_thread&)>&& cb)
|
||||||
{
|
{
|
||||||
auto& cbm = g_fxo->get<sysutil_cb_manager>();
|
sysutil_register_cb_with_id_internal(std::move(cb), umax);
|
||||||
|
|
||||||
cbm.registered.push(std::move(cb));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern s32 sysutil_send_system_cmd(u64 status, u64 param)
|
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)
|
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)
|
// 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);
|
cb.callback(ppu, status, param, cb.user_data);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
});
|
}});
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -532,9 +584,14 @@ error_code cellSysutilCheckCallback(ppu_thread& ppu)
|
||||||
|
|
||||||
for (auto&& func : cbm.registered.pop_all())
|
for (auto&& func : cbm.registered.pop_all())
|
||||||
{
|
{
|
||||||
|
if (func.call_active && !*func.call_active)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
read = true;
|
read = true;
|
||||||
|
|
||||||
if (s32 res = func(ppu))
|
if (s32 res = func.func(ppu))
|
||||||
{
|
{
|
||||||
// Currently impossible
|
// Currently impossible
|
||||||
return not_an_error(res);
|
return not_an_error(res);
|
||||||
|
|
|
@ -323,6 +323,26 @@ struct SysutilEventStatus
|
||||||
atomic_t<bool> active = false;
|
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>;
|
using SysutilMenuOpenStatus = SysutilEventStatus<CELL_SYSUTIL_SYSTEM_MENU_OPEN>;
|
||||||
|
|
||||||
extern void sysutil_register_cb(std::function<s32(ppu_thread&)>&&);
|
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)
|
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);
|
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;
|
return CELL_AVC2_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sysutil_unregister_cb_with_id<avc2_cb_handle_t>();
|
||||||
settings.avc2_cb = vm::null;
|
settings.avc2_cb = vm::null;
|
||||||
settings.avc2_cb_arg = 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 = vm::null;
|
||||||
settings.avc2_cb_arg = vm::null;
|
settings.avc2_cb_arg = vm::null;
|
||||||
|
|
||||||
|
@ -572,7 +577,7 @@ error_code cellSysutilAvc2JoinChatRequest(vm::cptr<SceNpMatching2RoomId> room_id
|
||||||
|
|
||||||
if (settings.avc2_cb)
|
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);
|
avc2_cb(cb_ppu, CELL_AVC2_EVENT_JOIN_SUCCEEDED, 0, avc2_cb_arg);
|
||||||
return 0;
|
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)
|
// 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 = vm::null;
|
||||||
settings.avc2_cb_arg = vm::null;
|
settings.avc2_cb_arg = vm::null;
|
||||||
break;
|
break;
|
||||||
|
@ -1073,6 +1078,7 @@ error_code cellSysutilAvc2UnloadAsync2(u32 mediaType)
|
||||||
|
|
||||||
if (mediaType == CELL_SYSUTIL_AVC2_VOICE_CHAT)
|
if (mediaType == CELL_SYSUTIL_AVC2_VOICE_CHAT)
|
||||||
{
|
{
|
||||||
|
sysutil_unregister_cb_with_id<avc2_cb_handle_t>();
|
||||||
settings.avc2_cb = vm::null;
|
settings.avc2_cb = vm::null;
|
||||||
settings.avc2_cb_arg = vm::null;
|
settings.avc2_cb_arg = vm::null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue