mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-08 20:58:41 +00:00
equeue: Few fixes for sceKernelWaitEqueue (#3548)
This commit is contained in:
@@ -97,7 +97,14 @@ bool EqueueInternal::RemoveEvent(u64 id, s16 filter) {
|
||||
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 a small timer is set, just wait for it to expire.
|
||||
return WaitForSmallTimer(ev, num, micros);
|
||||
@@ -111,9 +118,11 @@ int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, u32 micros) {
|
||||
};
|
||||
|
||||
if (micros == 0) {
|
||||
// Wait indefinitely for events
|
||||
std::unique_lock lock{m_mutex};
|
||||
m_cond.wait(lock, predicate);
|
||||
} else {
|
||||
// Wait up until the timeout value
|
||||
std::unique_lock lock{m_mutex};
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -159,18 +162,27 @@ bool EqueueInternal::TriggerEvent(u64 ident, s16 filter, void* trigger_data) {
|
||||
|
||||
int EqueueInternal::GetTriggeredEvents(SceKernelEvent* ev, int num) {
|
||||
int count = 0;
|
||||
for (auto& event : m_events) {
|
||||
if (event.IsTriggered()) {
|
||||
// Event should not trigger again
|
||||
event.ResetTriggerState();
|
||||
for (auto it = m_events.begin(); it != m_events.end();) {
|
||||
if (it->IsTriggered()) {
|
||||
ev[count++] = it->event;
|
||||
|
||||
if (event.event.flags & SceKernelEvent::Flags::Clear) {
|
||||
event.Clear();
|
||||
// Event should not trigger again
|
||||
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) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,19 +289,11 @@ int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, SceKernelEvent* ev, int
|
||||
}
|
||||
|
||||
if (num < 1) {
|
||||
*out = 0;
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
if (timo == nullptr) {
|
||||
// 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);
|
||||
}
|
||||
*out = eq->WaitForEvents(ev, num, timo);
|
||||
|
||||
if (*out == 0) {
|
||||
return ORBIS_KERNEL_ERROR_ETIMEDOUT;
|
||||
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
bool ScheduleEvent(u64 id, s16 filter,
|
||||
void (*callback)(SceKernelEqueue, const SceKernelEvent&));
|
||||
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);
|
||||
int GetTriggeredEvents(SceKernelEvent* ev, int num);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user