mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 18:53:28 +01:00
sys_event_queue: Fix ports disconnection after queue destruction
This commit is contained in:
parent
37110098c7
commit
2b75df22d9
@ -2489,7 +2489,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
|
||||
|
||||
const auto queue = (std::lock_guard{group->mutex}, this->spup[spup].lock());
|
||||
|
||||
if (!queue)
|
||||
if (!lv2_event_queue::check(queue))
|
||||
{
|
||||
spu_log.warning("sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (value & 0x00ffffff), data);
|
||||
ch_in_mbox.set_values(1, CELL_ENOTCONN);
|
||||
@ -2521,7 +2521,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
|
||||
|
||||
const auto queue = (std::lock_guard{group->mutex}, this->spup[spup].lock());
|
||||
|
||||
if (!queue)
|
||||
if (!lv2_event_queue::check(queue))
|
||||
{
|
||||
spu_log.warning("sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (value & 0x00ffffff), data);
|
||||
return true;
|
||||
@ -2904,14 +2904,14 @@ bool spu_thread::stop_and_signal(u32 code)
|
||||
{
|
||||
queue = v.second.lock();
|
||||
|
||||
if (queue)
|
||||
if (lv2_event_queue::check(queue))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!queue)
|
||||
if (!lv2_event_queue::check(queue))
|
||||
{
|
||||
check_state();
|
||||
return ch_in_mbox.set_values(1, CELL_EINVAL), true; // TODO: check error value
|
||||
@ -3024,14 +3024,14 @@ bool spu_thread::stop_and_signal(u32 code)
|
||||
{
|
||||
if (spuq == v.first)
|
||||
{
|
||||
if ((queue = v.second.lock()))
|
||||
if (queue = v.second.lock(); lv2_event_queue::check(queue))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!queue)
|
||||
if (!lv2_event_queue::check(queue))
|
||||
{
|
||||
return ch_in_mbox.set_values(1, CELL_EINVAL), true;
|
||||
}
|
||||
|
@ -18,10 +18,29 @@ std::shared_ptr<lv2_event_queue> lv2_event_queue::find(u64 ipc_key)
|
||||
if (ipc_key == SYS_EVENT_QUEUE_LOCAL)
|
||||
{
|
||||
// Invalid IPC key
|
||||
return{};
|
||||
return {};
|
||||
}
|
||||
|
||||
return ipc_manager<lv2_event_queue, u64>::get(ipc_key);
|
||||
auto queue = ipc_manager<lv2_event_queue, u64>::get(ipc_key);
|
||||
|
||||
if (queue && !queue->exists)
|
||||
{
|
||||
queue.reset();
|
||||
}
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
bool lv2_event_queue::check(const std::weak_ptr<lv2_event_queue>& wkptr)
|
||||
{
|
||||
const auto queue = wkptr.lock();
|
||||
|
||||
return queue && queue->exists;
|
||||
}
|
||||
|
||||
bool lv2_event_queue::check(const std::shared_ptr<lv2_event_queue>& sptr)
|
||||
{
|
||||
return sptr && sptr->exists;
|
||||
}
|
||||
|
||||
bool lv2_event_queue::send(lv2_event event)
|
||||
@ -153,6 +172,7 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
queue.exists = false;
|
||||
return {};
|
||||
});
|
||||
|
||||
@ -367,7 +387,7 @@ error_code sys_event_port_destroy(ppu_thread& ppu, u32 eport_id)
|
||||
|
||||
const auto port = idm::withdraw<lv2_obj, lv2_event_port>(eport_id, [](lv2_event_port& port) -> CellError
|
||||
{
|
||||
if (!port.queue.expired())
|
||||
if (lv2_event_queue::check(port.queue))
|
||||
{
|
||||
return CELL_EISCONN;
|
||||
}
|
||||
@ -408,7 +428,7 @@ error_code sys_event_port_connect_local(u32 eport_id, u32 equeue_id)
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (!port->queue.expired())
|
||||
if (lv2_event_queue::check(port->queue))
|
||||
{
|
||||
return CELL_EISCONN;
|
||||
}
|
||||
@ -445,7 +465,7 @@ error_code sys_event_port_connect_ipc(ppu_thread& ppu, u32 eport_id, u64 ipc_key
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (!port->queue.expired())
|
||||
if (lv2_event_queue::check(port->queue))
|
||||
{
|
||||
return CELL_EISCONN;
|
||||
}
|
||||
@ -470,7 +490,7 @@ error_code sys_event_port_disconnect(ppu_thread& ppu, u32 eport_id)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (port->queue.expired())
|
||||
if (!lv2_event_queue::check(port->queue))
|
||||
{
|
||||
return CELL_ENOTCONN;
|
||||
}
|
||||
@ -490,7 +510,7 @@ 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())
|
||||
if (const auto queue = port.queue.lock(); lv2_event_queue::check(queue))
|
||||
{
|
||||
const u64 source = port.name ? port.name : (s64{process_getpid()} << 32) | u64{eport_id};
|
||||
|
||||
|
@ -85,6 +85,7 @@ struct lv2_event_queue final : public lv2_obj
|
||||
const u64 key;
|
||||
const s32 size;
|
||||
|
||||
atomic_t<bool> exists = true; // Existence validation (workaround for shared-ptr ref-counting)
|
||||
shared_mutex mutex;
|
||||
std::deque<lv2_event> events;
|
||||
std::deque<cpu_thread*> sq;
|
||||
@ -107,6 +108,10 @@ struct lv2_event_queue final : public lv2_obj
|
||||
|
||||
// Get event queue by its global key
|
||||
static std::shared_ptr<lv2_event_queue> find(u64 ipc_key);
|
||||
|
||||
// Check queue ptr validity (use 'exists' member)
|
||||
static bool check(const std::weak_ptr<lv2_event_queue>&);
|
||||
static bool check(const std::shared_ptr<lv2_event_queue>&);
|
||||
};
|
||||
|
||||
struct lv2_event_port final : lv2_obj
|
||||
|
@ -1298,7 +1298,7 @@ error_code sys_spu_thread_group_connect_event(ppu_thread& ppu, u32 id, u32 eq, u
|
||||
|
||||
std::lock_guard lock(group->mutex);
|
||||
|
||||
if (!ep->expired())
|
||||
if (lv2_event_queue::check(*ep))
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
@ -1340,7 +1340,7 @@ error_code sys_spu_thread_group_disconnect_event(ppu_thread& ppu, u32 id, u32 et
|
||||
|
||||
std::lock_guard lock(group->mutex);
|
||||
|
||||
if (ep->expired())
|
||||
if (!lv2_event_queue::check(*ep))
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
@ -1373,7 +1373,7 @@ error_code sys_spu_thread_connect_event(ppu_thread& ppu, u32 id, u32 eq, u32 et,
|
||||
|
||||
auto& port = thread->spup[spup];
|
||||
|
||||
if (!port.expired())
|
||||
if (lv2_event_queue::check(port))
|
||||
{
|
||||
return CELL_EISCONN;
|
||||
}
|
||||
@ -1406,7 +1406,7 @@ error_code sys_spu_thread_disconnect_event(ppu_thread& ppu, u32 id, u32 et, u8 s
|
||||
|
||||
auto& port = thread->spup[spup];
|
||||
|
||||
if (port.expired())
|
||||
if (!lv2_event_queue::check(port))
|
||||
{
|
||||
return CELL_ENOTCONN;
|
||||
}
|
||||
@ -1546,7 +1546,7 @@ error_code sys_spu_thread_group_connect_event_all_threads(ppu_thread& ppu, u32 i
|
||||
{
|
||||
if (t)
|
||||
{
|
||||
if (!t->spup[port].expired())
|
||||
if (lv2_event_queue::check(t->spup[port]))
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
|
@ -82,7 +82,7 @@ error_code sys_timer_destroy(ppu_thread& ppu, u32 timer_id)
|
||||
|
||||
const auto timer = idm::withdraw<lv2_obj, lv2_timer>(timer_id, [&](lv2_timer& timer) -> CellError
|
||||
{
|
||||
if (std::shared_lock lock(timer.mutex); !timer.port.expired())
|
||||
if (std::shared_lock lock(timer.mutex); lv2_event_queue::check(timer.port))
|
||||
{
|
||||
return CELL_EISCONN;
|
||||
}
|
||||
@ -231,7 +231,7 @@ error_code sys_timer_connect_event_queue(ppu_thread& ppu, u32 timer_id, u32 queu
|
||||
|
||||
std::lock_guard lock(timer.mutex);
|
||||
|
||||
if (!timer.port.expired())
|
||||
if (lv2_event_queue::check(timer.port))
|
||||
{
|
||||
return CELL_EISCONN;
|
||||
}
|
||||
@ -269,7 +269,7 @@ error_code sys_timer_disconnect_event_queue(ppu_thread& ppu, u32 timer_id)
|
||||
|
||||
timer.state = SYS_TIMER_STATE_STOP;
|
||||
|
||||
if (timer.port.expired())
|
||||
if (!lv2_event_queue::check(timer.port))
|
||||
{
|
||||
return CELL_ENOTCONN;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user