mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-12 01:38:37 +12:00
LV2: Improve IPC support (#10206)
* Remove custom event queue's IPC management of favour of universal LV2 approach. * Move ipc_manager to FXO. * Fix ipc_manager internal storage memory leak: deallocate entry when IPC object destroyed. * Rewrite lv2_obj::create to be simpler (remove many duplicated code). * Always execute lv2_obj::create under both IPC and IDM mutexes at once (not in non-atomic single-steps). Fixing potential case where concurrency can cause IDM to contain 2 or more different objects with the same IPC key with SYS_SYNC_NOT_CARE (instead of the same object). * Do not rely on smart ptr reference count to tell if the object exists. Use similar approach as event queues as it makes error checkings accurate. * Optimize lv2_event_port by using std::shared_ptr for queue which wasn't allowed before.
This commit is contained in:
parent
a043e95d24
commit
7b6482c01d
14 changed files with 146 additions and 240 deletions
|
@ -11,8 +11,6 @@
|
|||
|
||||
LOG_CHANNEL(sys_event);
|
||||
|
||||
template<> DECLARE(ipc_manager<lv2_event_queue, u64>::g_ipc) {};
|
||||
|
||||
std::shared_ptr<lv2_event_queue> lv2_event_queue::find(u64 ipc_key)
|
||||
{
|
||||
if (ipc_key == SYS_EVENT_QUEUE_LOCAL)
|
||||
|
@ -21,14 +19,7 @@ std::shared_ptr<lv2_event_queue> lv2_event_queue::find(u64 ipc_key)
|
|||
return {};
|
||||
}
|
||||
|
||||
auto queue = ipc_manager<lv2_event_queue, u64>::get(ipc_key);
|
||||
|
||||
if (queue && !queue->exists)
|
||||
{
|
||||
queue.reset();
|
||||
}
|
||||
|
||||
return queue;
|
||||
return g_fxo->get<ipc_manager<lv2_event_queue, u64>>().get(ipc_key);
|
||||
}
|
||||
|
||||
bool lv2_event_queue::check(const std::weak_ptr<lv2_event_queue>& wkptr)
|
||||
|
@ -93,11 +84,11 @@ CellError lv2_event_queue::send(lv2_event event)
|
|||
return {};
|
||||
}
|
||||
|
||||
error_code sys_event_queue_create(cpu_thread& cpu, vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attribute_t> attr, u64 event_queue_key, s32 size)
|
||||
error_code sys_event_queue_create(cpu_thread& cpu, vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attribute_t> attr, u64 ipc_key, s32 size)
|
||||
{
|
||||
cpu.state += cpu_flag::wait;
|
||||
|
||||
sys_event.warning("sys_event_queue_create(equeue_id=*0x%x, attr=*0x%x, event_queue_key=0x%llx, size=%d)", equeue_id, attr, event_queue_key, size);
|
||||
sys_event.warning("sys_event_queue_create(equeue_id=*0x%x, attr=*0x%x, ipc_key=0x%llx, size=%d)", equeue_id, attr, ipc_key, size);
|
||||
|
||||
if (size <= 0 || size > 127)
|
||||
{
|
||||
|
@ -120,42 +111,19 @@ error_code sys_event_queue_create(cpu_thread& cpu, vm::ptr<u32> equeue_id, vm::p
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
auto queue = std::make_shared<lv2_event_queue>(protocol, type, attr->name_u64, event_queue_key, size);
|
||||
const u32 pshared = ipc_key == SYS_EVENT_QUEUE_LOCAL ? SYS_SYNC_NOT_PROCESS_SHARED : SYS_SYNC_NOT_PROCESS_SHARED;
|
||||
constexpr u32 flags = SYS_SYNC_NEWLY_CREATED; // NOTE: This is inaccurate for multi-process
|
||||
const u64 name = attr->name_u64;
|
||||
|
||||
CellError error = CELL_EAGAIN;
|
||||
|
||||
if (event_queue_key == SYS_EVENT_QUEUE_LOCAL)
|
||||
if (const auto error = lv2_obj::create<lv2_event_queue>(pshared, ipc_key, flags, [&]()
|
||||
{
|
||||
// Not an IPC queue
|
||||
if (const u32 _id = idm::import<lv2_obj, lv2_event_queue>([&]() { if ((error = queue->on_id_create())) queue.reset(); return std::move(queue); } ))
|
||||
{
|
||||
*equeue_id = _id;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
// Create IPC queue
|
||||
if (!ipc_manager<lv2_event_queue, u64>::add(event_queue_key, [&]() -> std::shared_ptr<lv2_event_queue>
|
||||
{
|
||||
if (const u32 _id = idm::import<lv2_obj, lv2_event_queue>([&]() { if ((error = queue->on_id_create())) return decltype(queue){}; return queue; } ))
|
||||
{
|
||||
*equeue_id = _id;
|
||||
return std::move(queue);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return std::make_shared<lv2_event_queue>(protocol, type, name, ipc_key, size);
|
||||
}))
|
||||
{
|
||||
return CELL_EEXIST;
|
||||
}
|
||||
|
||||
if (queue)
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
*equeue_id = idm::last_id();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -179,7 +147,7 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
|
|||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
queue.exists--;
|
||||
lv2_obj::on_id_destroy(queue, queue.key == SYS_EVENT_QUEUE_LOCAL ? SYS_SYNC_NOT_PROCESS_SHARED : SYS_SYNC_PROCESS_SHARED, queue.key);
|
||||
return {};
|
||||
});
|
||||
|
||||
|
@ -521,11 +489,11 @@ error_code sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3)
|
|||
|
||||
const auto port = idm::get<lv2_obj, lv2_event_port>(eport_id, [&](lv2_event_port& port) -> CellError
|
||||
{
|
||||
if (const auto queue = port.queue.lock(); lv2_event_queue::check(queue))
|
||||
if (lv2_event_queue::check(port.queue))
|
||||
{
|
||||
const u64 source = port.name ? port.name : (s64{process_getpid()} << 32) | u64{eport_id};
|
||||
|
||||
return queue->send(source, data1, data2, data3);
|
||||
return port.queue->send(source, data1, data2, data3);
|
||||
}
|
||||
|
||||
return CELL_ENOTCONN;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue