mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-14 10:21:21 +00:00
lv2_timer: manage timers by separate thread (#10445)
Substitutes missing abort op for lv2_obj manager.
This commit is contained in:
parent
c3415bcff2
commit
24e4a43ec4
@ -108,20 +108,20 @@ public:
|
||||
return str;
|
||||
}
|
||||
|
||||
// Find and remove the object from the container (deque or vector)
|
||||
// Find and remove the object from the deque container
|
||||
template <typename T, typename E>
|
||||
static T* unqueue(std::deque<T*>& queue, E* object)
|
||||
static T unqueue(std::deque<T>& queue, E object)
|
||||
{
|
||||
for (auto found = queue.cbegin(), end = queue.cend(); found != end; found++)
|
||||
{
|
||||
if (*found == object)
|
||||
{
|
||||
queue.erase(found);
|
||||
return static_cast<T*>(object);
|
||||
return static_cast<T>(object);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename E, typename T>
|
||||
|
@ -13,7 +13,17 @@
|
||||
|
||||
LOG_CHANNEL(sys_timer);
|
||||
|
||||
void lv2_timer_context::operator()()
|
||||
struct lv2_timer_thread
|
||||
{
|
||||
shared_mutex mutex;
|
||||
std::deque<std::shared_ptr<lv2_timer>> timers;
|
||||
|
||||
void operator()();
|
||||
|
||||
static constexpr auto thread_name = "Timer Thread"sv;
|
||||
};
|
||||
|
||||
u64 lv2_timer::check()
|
||||
{
|
||||
while (thread_ctrl::state() != thread_state::aborting)
|
||||
{
|
||||
@ -49,15 +59,48 @@ void lv2_timer_context::operator()()
|
||||
|
||||
// Stop after oneshot
|
||||
state.release(SYS_TIMER_STATE_STOP);
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: use single global dedicated thread for busy waiting, no timer threads
|
||||
lv2_obj::wait_timeout(next - _now);
|
||||
continue;
|
||||
return (next - _now);
|
||||
}
|
||||
|
||||
thread_ctrl::wait_on(state, _state);
|
||||
break;
|
||||
}
|
||||
|
||||
return umax;
|
||||
}
|
||||
|
||||
void lv2_timer_thread::operator()()
|
||||
{
|
||||
u64 sleep_time = umax;
|
||||
|
||||
while (thread_ctrl::state() != thread_state::aborting)
|
||||
{
|
||||
if (sleep_time != umax)
|
||||
{
|
||||
// Scale time
|
||||
sleep_time = std::min(sleep_time, u64{umax} / 100) * 100 / g_cfg.core.clocks_scale;
|
||||
}
|
||||
|
||||
thread_ctrl::wait_for(sleep_time);
|
||||
|
||||
sleep_time = umax;
|
||||
|
||||
reader_lock lock(mutex);
|
||||
|
||||
for (const auto& timer : timers)
|
||||
{
|
||||
if (lv2_obj::check(timer))
|
||||
{
|
||||
const u64 adviced_sleep_time = timer->check();
|
||||
|
||||
if (sleep_time > adviced_sleep_time)
|
||||
{
|
||||
sleep_time = adviced_sleep_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,9 +110,15 @@ error_code sys_timer_create(ppu_thread& ppu, vm::ptr<u32> timer_id)
|
||||
|
||||
sys_timer.warning("sys_timer_create(timer_id=*0x%x)", timer_id);
|
||||
|
||||
if (const u32 id = idm::make<lv2_obj, lv2_timer>("Timer Thread"))
|
||||
if (auto ptr = idm::make_ptr<lv2_obj, lv2_timer>())
|
||||
{
|
||||
*timer_id = id;
|
||||
auto& thread = g_fxo->get<named_thread<lv2_timer_thread>>();
|
||||
{
|
||||
std::lock_guard lock(thread.mutex);
|
||||
thread.timers.emplace_back(std::move(ptr));
|
||||
}
|
||||
|
||||
*timer_id = idm::last_id();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -82,14 +131,14 @@ error_code sys_timer_destroy(ppu_thread& ppu, u32 timer_id)
|
||||
|
||||
sys_timer.warning("sys_timer_destroy(timer_id=0x%x)", timer_id);
|
||||
|
||||
const auto timer = idm::withdraw<lv2_obj, lv2_timer>(timer_id, [&](lv2_timer& timer) -> CellError
|
||||
auto timer = idm::withdraw<lv2_obj, lv2_timer>(timer_id, [&](lv2_timer& timer) -> CellError
|
||||
{
|
||||
if (reader_lock lock(timer.mutex); lv2_obj::check(timer.port))
|
||||
{
|
||||
return CELL_EISCONN;
|
||||
}
|
||||
|
||||
timer = thread_state::aborting;
|
||||
timer.exists--;
|
||||
return {};
|
||||
});
|
||||
|
||||
@ -103,6 +152,9 @@ error_code sys_timer_destroy(ppu_thread& ppu, u32 timer_id)
|
||||
return timer.ret;
|
||||
}
|
||||
|
||||
auto& thread = g_fxo->get<named_thread<lv2_timer_thread>>();
|
||||
std::lock_guard lock(thread.mutex);
|
||||
lv2_obj::unqueue(thread.timers, std::move(timer.ptr));
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -144,7 +196,7 @@ error_code _sys_timer_start(ppu_thread& ppu, u32 timer_id, u64 base_time, u64 pe
|
||||
|
||||
const auto timer = idm::check<lv2_obj, lv2_timer>(timer_id, [&](lv2_timer& timer) -> CellError
|
||||
{
|
||||
std::unique_lock lock(timer.mutex);
|
||||
std::lock_guard lock(timer.mutex);
|
||||
|
||||
if (!lv2_obj::check(timer.port))
|
||||
{
|
||||
@ -167,9 +219,6 @@ error_code _sys_timer_start(ppu_thread& ppu, u32 timer_id, u64 base_time, u64 pe
|
||||
timer.expire = expire > start_time ? expire : umax;
|
||||
timer.period = period;
|
||||
timer.state = SYS_TIMER_STATE_RUN;
|
||||
|
||||
lock.unlock();
|
||||
timer.state.notify_one();
|
||||
return {};
|
||||
});
|
||||
|
||||
@ -188,6 +237,8 @@ error_code _sys_timer_start(ppu_thread& ppu, u32 timer_id, u64 base_time, u64 pe
|
||||
return timer.ret;
|
||||
}
|
||||
|
||||
g_fxo->get<named_thread<lv2_timer_thread>>()([]{});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -21,12 +21,10 @@ struct sys_timer_information_t
|
||||
be_t<u32> pad;
|
||||
};
|
||||
|
||||
struct lv2_timer_context : lv2_obj
|
||||
struct lv2_timer : lv2_obj
|
||||
{
|
||||
static const u32 id_base = 0x11000000;
|
||||
|
||||
void operator()();
|
||||
|
||||
shared_mutex mutex;
|
||||
atomic_t<u32> state{SYS_TIMER_STATE_STOP};
|
||||
|
||||
@ -38,6 +36,13 @@ struct lv2_timer_context : lv2_obj
|
||||
atomic_t<u64> expire{0}; // Next expiration time
|
||||
atomic_t<u64> period{0}; // Period (oneshot if 0)
|
||||
|
||||
u64 check();
|
||||
|
||||
lv2_timer() noexcept
|
||||
: lv2_obj{1}
|
||||
{
|
||||
}
|
||||
|
||||
void get_information(sys_timer_information_t& info)
|
||||
{
|
||||
reader_lock lock(mutex);
|
||||
@ -57,8 +62,6 @@ struct lv2_timer_context : lv2_obj
|
||||
}
|
||||
};
|
||||
|
||||
using lv2_timer = named_thread<lv2_timer_context>;
|
||||
|
||||
class ppu_thread;
|
||||
|
||||
// Syscalls
|
||||
|
Loading…
x
Reference in New Issue
Block a user