equeue: Few fixes for sceKernelWaitEqueue (#3548)

This commit is contained in:
squidbus
2025-09-08 19:47:12 -07:00
committed by GitHub
parent f4531fd927
commit ac318b56ac
2 changed files with 29 additions and 25 deletions

View File

@@ -97,7 +97,14 @@ bool EqueueInternal::RemoveEvent(u64 id, s16 filter) {
return has_found; return has_found;
} }
int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, u32 micros) { int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, const SceKernelUseconds* timo) {
if (timo != nullptr && *timo == 0) {
// Effectively acts as a poll; only events that have already
// arrived at the time of this function call can be received
return GetTriggeredEvents(ev, num);
}
const auto micros = timo ? *timo : 0u;
if (HasSmallTimer()) { if (HasSmallTimer()) {
// If a small timer is set, just wait for it to expire. // If a small timer is set, just wait for it to expire.
return WaitForSmallTimer(ev, num, micros); return WaitForSmallTimer(ev, num, micros);
@@ -111,9 +118,11 @@ int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, u32 micros) {
}; };
if (micros == 0) { if (micros == 0) {
// Wait indefinitely for events
std::unique_lock lock{m_mutex}; std::unique_lock lock{m_mutex};
m_cond.wait(lock, predicate); m_cond.wait(lock, predicate);
} else { } else {
// Wait up until the timeout value
std::unique_lock lock{m_mutex}; std::unique_lock lock{m_mutex};
m_cond.wait_for(lock, std::chrono::microseconds(micros), predicate); m_cond.wait_for(lock, std::chrono::microseconds(micros), predicate);
} }
@@ -127,12 +136,6 @@ int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, u32 micros) {
} }
} }
if (ev->flags & SceKernelEvent::Flags::OneShot) {
for (auto ev_id = 0u; ev_id < count; ++ev_id) {
RemoveEvent(ev->ident, ev->filter);
}
}
return count; return count;
} }
@@ -159,18 +162,27 @@ bool EqueueInternal::TriggerEvent(u64 ident, s16 filter, void* trigger_data) {
int EqueueInternal::GetTriggeredEvents(SceKernelEvent* ev, int num) { int EqueueInternal::GetTriggeredEvents(SceKernelEvent* ev, int num) {
int count = 0; int count = 0;
for (auto& event : m_events) { for (auto it = m_events.begin(); it != m_events.end();) {
if (event.IsTriggered()) { if (it->IsTriggered()) {
// Event should not trigger again ev[count++] = it->event;
event.ResetTriggerState();
if (event.event.flags & SceKernelEvent::Flags::Clear) { // Event should not trigger again
event.Clear(); it->ResetTriggerState();
if (it->event.flags & SceKernelEvent::Flags::Clear) {
it->Clear();
} }
ev[count++] = event.event; if (it->event.flags & SceKernelEvent::Flags::OneShot) {
it = m_events.erase(it);
} else {
++it;
}
if (count == num) { if (count == num) {
break; break;
} }
} else {
++it;
} }
} }
@@ -277,19 +289,11 @@ int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, SceKernelEvent* ev, int
} }
if (num < 1) { if (num < 1) {
*out = 0;
return ORBIS_KERNEL_ERROR_EINVAL; return ORBIS_KERNEL_ERROR_EINVAL;
} }
if (timo == nullptr) { *out = eq->WaitForEvents(ev, num, timo);
// When the timeout is nullptr, we wait indefinitely
*out = eq->WaitForEvents(ev, num, 0);
} else if (*timo == 0) {
// Only events that have already arrived at the time of this function call can be received
*out = eq->GetTriggeredEvents(ev, num);
} else {
// Wait for up to the specified timeout value
*out = eq->WaitForEvents(ev, num, *timo);
}
if (*out == 0) { if (*out == 0) {
return ORBIS_KERNEL_ERROR_ETIMEDOUT; return ORBIS_KERNEL_ERROR_ETIMEDOUT;

View File

@@ -153,7 +153,7 @@ public:
bool ScheduleEvent(u64 id, s16 filter, bool ScheduleEvent(u64 id, s16 filter,
void (*callback)(SceKernelEqueue, const SceKernelEvent&)); void (*callback)(SceKernelEqueue, const SceKernelEvent&));
bool RemoveEvent(u64 id, s16 filter); bool RemoveEvent(u64 id, s16 filter);
int WaitForEvents(SceKernelEvent* ev, int num, u32 micros); int WaitForEvents(SceKernelEvent* ev, int num, const SceKernelUseconds* timo);
bool TriggerEvent(u64 ident, s16 filter, void* trigger_data); bool TriggerEvent(u64 ident, s16 filter, void* trigger_data);
int GetTriggeredEvents(SceKernelEvent* ev, int num); int GetTriggeredEvents(SceKernelEvent* ev, int num);