mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 04:02:42 +01:00
Improve sys_timer_get_information (#7638)
* Improve sys_timer_get_information * sys_timer_disconnect_event_queue sets STATE_STOP regardless of port connection status. * sys_timer_get_information sets 0 for period and next_expire if the timer is stopped. * Fix two minor races in lv2_timer thread * If the timer thread is about to fire an event of queue x, then another thread disconnects the queue, then restarts the timer and connects the event queue, then the timer thread sends an event - event data combination (source, data1, data2, next) may be inaccurate. * If the timer thread is about to send an event (periodically), then another thread stops the timer and starts it again with sys_timer_start_periodic_absolute, timer.expire in info->timer_state in sys_timer_get_information may be inaccurate.
This commit is contained in:
parent
8e5a03f171
commit
50f51be06a
@ -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<sys_
|
||||
|
||||
const auto timer = idm::check<lv2_obj, lv2_timer>(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 {};
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user