diff --git a/rpcs3/Emu/Cell/lv2/sys_timer.cpp b/rpcs3/Emu/Cell/lv2/sys_timer.cpp index abf34c076c..073ce21927 100644 --- a/rpcs3/Emu/Cell/lv2/sys_timer.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_timer.cpp @@ -21,12 +21,18 @@ void lv2_timer_context::operator()() if (state == SYS_TIMER_STATE_RUN) { const u64 _now = get_guest_system_time(); - const u64 next = expire; + u64 next = expire; if (_now >= next) { std::lock_guard lock(mutex); + if (next = expire; _now < next) + { + // expire was updated in the middle, don't send an event + continue; + } + if (const auto queue = port.lock()) { queue->send(source, data1, data2, next); @@ -34,7 +40,7 @@ void lv2_timer_context::operator()() if (period) { - // Set next expiration time and check again (HACK) + // Set next expiration time and check again expire += period; continue; } @@ -49,7 +55,7 @@ void lv2_timer_context::operator()() continue; } - thread_ctrl::wait_for(10000); + thread_ctrl::wait(); } } @@ -106,11 +112,20 @@ error_code sys_timer_get_information(ppu_thread& ppu, u32 timer_id, vm::ptr(timer_id, [&](lv2_timer& timer) { - std::lock_guard lock(timer.mutex); + std::shared_lock lock(timer.mutex); - info->next_expire = timer.expire; - info->period = timer.period; - info->timer_state = timer.state; + if (timer.state == SYS_TIMER_STATE_RUN) + { + info->timer_state = SYS_TIMER_STATE_RUN; + info->next_expire = timer.expire; + info->period = timer.period; + } + else + { + info->timer_state = SYS_TIMER_STATE_STOP; + info->next_expire = 0; + info->period = 0; + } }); if (!timer) @@ -252,12 +267,13 @@ error_code sys_timer_disconnect_event_queue(ppu_thread& ppu, u32 timer_id) { std::lock_guard lock(timer.mutex); + timer.state = SYS_TIMER_STATE_STOP; + if (timer.port.expired()) { return CELL_ENOTCONN; } - timer.state = SYS_TIMER_STATE_STOP; timer.port.reset(); return {}; });