diff --git a/rpcs3/Emu/Cell/Modules/cellCamera.cpp b/rpcs3/Emu/Cell/Modules/cellCamera.cpp index e66daab4ca..bf1f94d6bf 100644 --- a/rpcs3/Emu/Cell/Modules/cellCamera.cpp +++ b/rpcs3/Emu/Cell/Modules/cellCamera.cpp @@ -1259,7 +1259,7 @@ void camera_context::operator()() continue; } - const u64 frame_start = get_system_time(); + const u64 frame_start = get_guest_system_time(); std::unique_lock lock(mutex_notify_data_map); @@ -1304,7 +1304,7 @@ void camera_context::operator()() for (const u64 frame_target_time = 1000000u / fps;;) { - const u64 time_passed = get_system_time() - frame_start; + const u64 time_passed = get_guest_system_time() - frame_start; if (time_passed >= frame_target_time) break; diff --git a/rpcs3/Emu/Cell/Modules/cellMic.cpp b/rpcs3/Emu/Cell/Modules/cellMic.cpp index cc5effba99..769f5cb4c8 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMic.cpp @@ -38,7 +38,7 @@ void mic_context::operator()() continue; } - const u64 stamp0 = get_system_time(); + const u64 stamp0 = get_guest_system_time(); const u64 time_pos = stamp0 - start_time - Emu.GetPauseTime(); const u64 expected_time = m_counter * 256 * 1000000 / 48000; diff --git a/rpcs3/Emu/Cell/Modules/cellMic.h b/rpcs3/Emu/Cell/Modules/cellMic.h index 87b477bf6c..aab3a25da2 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.h +++ b/rpcs3/Emu/Cell/Modules/cellMic.h @@ -254,7 +254,7 @@ public: std::unordered_map mic_list; protected: - const u64 start_time = get_system_time(); + const u64 start_time = get_guest_system_time(); u64 m_counter = 0; // u32 signalStateLocalTalk = 9; // value is in range 0-10. 10 indicates talking, 0 indicating none. diff --git a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp index df2192e2cd..c28004631d 100644 --- a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp @@ -332,8 +332,8 @@ error_code cellMsgDialogClose(f32 delay) { cellSysutil.warning("cellMsgDialogClose(delay=%f)", delay); - extern u64 get_system_time(); - const u64 wait_until = get_system_time() + static_cast(std::max(delay, 0.0f) * 1000); + extern u64 get_guest_system_time(); + const u64 wait_until = get_guest_system_time() + static_cast(std::max(delay, 0.0f) * 1000); if (auto manager = fxm::get()) { @@ -341,7 +341,7 @@ error_code cellMsgDialogClose(f32 delay) { thread_ctrl::spawn("cellMsgDialogClose() Thread", [=] { - while (get_system_time() < wait_until) + while (get_guest_system_time() < wait_until) { if (Emu.IsStopped()) return; @@ -368,7 +368,7 @@ error_code cellMsgDialogClose(f32 delay) thread_ctrl::spawn("cellMsgDialogClose() Thread", [=]() { - while (dlg->state == MsgDialogState::Open && get_system_time() < wait_until) + while (dlg->state == MsgDialogState::Open && get_guest_system_time() < wait_until) { if (Emu.IsStopped()) return; diff --git a/rpcs3/Emu/Cell/Modules/cellVpost.cpp b/rpcs3/Emu/Cell/Modules/cellVpost.cpp index 6110b84d7b..9bd40294bb 100644 --- a/rpcs3/Emu/Cell/Modules/cellVpost.cpp +++ b/rpcs3/Emu/Cell/Modules/cellVpost.cpp @@ -113,16 +113,16 @@ s32 cellVpostExec(u32 handle, vm::cptr inPicBuff, vm::cptrreserved1 = 0; picInfo->reserved2 = 0; - //u64 stamp0 = get_system_time(); + //u64 stamp0 = get_guest_system_time(); std::unique_ptr pA(new u8[w*h]); memset(pA.get(), ctrlParam->outAlpha, w*h); - //u64 stamp1 = get_system_time(); + //u64 stamp1 = get_guest_system_time(); vpost->sws = sws_getCachedContext(vpost->sws, w, h, AV_PIX_FMT_YUVA420P, ow, oh, AV_PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL); - //u64 stamp2 = get_system_time(); + //u64 stamp2 = get_guest_system_time(); const u8* in_data[4] = { &inPicBuff[0], &inPicBuff[w * h], &inPicBuff[w * h * 5 / 4], pA.get() }; int in_line[4] = { w, w/2, w/2, w }; @@ -132,7 +132,7 @@ s32 cellVpostExec(u32 handle, vm::cptr inPicBuff, vm::cptrsws, in_data, in_line, 0, h, out_data, out_line); //ConLog.Write("cellVpostExec() perf (access=%d, getContext=%d, scale=%d, finalize=%d)", - //stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3); + //stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_guest_system_time() - stamp3); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/libmixer.cpp b/rpcs3/Emu/Cell/Modules/libmixer.cpp index 4ba14bbe3f..9ef87380a6 100644 --- a/rpcs3/Emu/Cell/Modules/libmixer.cpp +++ b/rpcs3/Emu/Cell/Modules/libmixer.cpp @@ -346,7 +346,7 @@ struct surmixer_thread : ppu_thread if (port.state == audio_port_state::started) { - //u64 stamp0 = get_system_time(); + //u64 stamp0 = get_guest_system_time(); memset(g_surmx.mixdata, 0, sizeof(g_surmx.mixdata)); if (g_surmx.cb) @@ -355,7 +355,7 @@ struct surmixer_thread : ppu_thread lv2_obj::sleep(*this); } - //u64 stamp1 = get_system_time(); + //u64 stamp1 = get_guest_system_time(); { std::lock_guard lock(g_surmx.mutex); @@ -434,7 +434,7 @@ struct surmixer_thread : ppu_thread } } - //u64 stamp2 = get_system_time(); + //u64 stamp2 = get_guest_system_time(); auto buf = vm::_ptr(port.addr.addr() + (g_surmx.mixcount % port.num_blocks) * port.num_channels * AUDIO_BUFFER_SAMPLES * sizeof(float)); @@ -444,7 +444,7 @@ struct surmixer_thread : ppu_thread *buf++ = mixdata; } - //u64 stamp3 = get_system_time(); + //u64 stamp3 = get_guest_system_time(); //ConLog.Write("Libmixer perf: start=%lld (cb=%lld, ssp=%lld, finalize=%lld)", stamp0 - m_config.start_time, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2); } diff --git a/rpcs3/Emu/Cell/Modules/sysPrxForUser.cpp b/rpcs3/Emu/Cell/Modules/sysPrxForUser.cpp index 172a3bda92..c12ec6e4dc 100644 --- a/rpcs3/Emu/Cell/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/Cell/Modules/sysPrxForUser.cpp @@ -11,7 +11,7 @@ LOG_CHANNEL(sysPrxForUser); -extern u64 get_system_time(); +extern u64 get_guest_system_time(); vm::gvar sys_prx_version; // ??? vm::gvar> g_ppu_atexitspawn; @@ -22,7 +22,7 @@ s64 sys_time_get_system_time() { sysPrxForUser.trace("sys_time_get_system_time()"); - return get_system_time(); + return get_guest_system_time(); } void sys_process_exit(ppu_thread& ppu, s32 status) diff --git a/rpcs3/Emu/Cell/Modules/sys_lwmutex_.cpp b/rpcs3/Emu/Cell/Modules/sys_lwmutex_.cpp index f3f1811897..8a8999f788 100644 --- a/rpcs3/Emu/Cell/Modules/sys_lwmutex_.cpp +++ b/rpcs3/Emu/Cell/Modules/sys_lwmutex_.cpp @@ -214,7 +214,7 @@ error_code sys_lwmutex_lock(ppu_thread& ppu, vm::ptr lwmutex, u64 return CELL_OK; } - const u64 time0 = timeout ? get_system_time() : 0; + const u64 time0 = timeout ? get_guest_system_time() : 0; const error_code res_ = _sys_lwmutex_lock(ppu, lwmutex->sleep_queue, timeout); @@ -229,7 +229,7 @@ error_code sys_lwmutex_lock(ppu_thread& ppu, vm::ptr lwmutex, u64 } else if (timeout && res_ != CELL_ETIMEDOUT) { - const u64 time_diff = get_system_time() - time0; + const u64 time_diff = get_guest_system_time() - time0; if (timeout <= time_diff) { diff --git a/rpcs3/Emu/Cell/Modules/sys_spu_.cpp b/rpcs3/Emu/Cell/Modules/sys_spu_.cpp index 2920522b6b..9c01ca8404 100644 --- a/rpcs3/Emu/Cell/Modules/sys_spu_.cpp +++ b/rpcs3/Emu/Cell/Modules/sys_spu_.cpp @@ -10,8 +10,6 @@ extern logs::channel sysPrxForUser; -extern u64 get_system_time(); - spu_printf_cb_t g_spu_printf_agcb; spu_printf_cb_t g_spu_printf_dgcb; spu_printf_cb_t g_spu_printf_atcb; diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 384664a2b0..7fc6e0b0c5 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -64,7 +64,7 @@ const bool s_use_ssse3 = #define _mm_shuffle_epi8 #endif -extern u64 get_system_time(); +extern u64 get_guest_system_time(); extern atomic_t g_progr; extern atomic_t g_progr_ptotal; @@ -469,7 +469,7 @@ std::string ppu_thread::dump() const if (const auto _time = start_time) { - fmt::append(ret, "Waiting: %fs\n", (get_system_time() - _time) / 1000000.); + fmt::append(ret, "Waiting: %fs\n", (get_guest_system_time() - _time) / 1000000.); } else { @@ -721,7 +721,7 @@ ppu_thread::ppu_thread(const ppu_thread_params& param, std::string_view name, u3 , prio(prio) , stack_size(param.stack_size) , stack_addr(param.stack_addr) - , start_time(get_system_time()) + , start_time(get_guest_system_time()) , joiner(-!!detached) , ppu_name(name) { @@ -846,7 +846,7 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc) { if (start_time) { - LOG_WARNING(PPU, "'%s' aborted (%fs)", current_function, (get_system_time() - start_time) / 1000000.); + LOG_WARNING(PPU, "'%s' aborted (%fs)", current_function, (get_guest_system_time() - start_time) / 1000000.); } else { diff --git a/rpcs3/Emu/Cell/lv2/lv2.cpp b/rpcs3/Emu/Cell/lv2/lv2.cpp index 06648146b6..762f88eab6 100644 --- a/rpcs3/Emu/Cell/lv2/lv2.cpp +++ b/rpcs3/Emu/Cell/lv2/lv2.cpp @@ -999,7 +999,7 @@ extern ppu_function_t ppu_get_syscall(u64 code) return nullptr; } -extern u64 get_system_time(); +extern u64 get_guest_system_time(); DECLARE(lv2_obj::g_mutex); DECLARE(lv2_obj::g_ppu); @@ -1010,7 +1010,7 @@ void lv2_obj::sleep_timeout(cpu_thread& thread, u64 timeout) { std::lock_guard lock(g_mutex); - const u64 start_time = get_system_time(); + const u64 start_time = get_guest_system_time(); if (auto ppu = static_cast(thread.id_type() == 1 ? &thread : nullptr)) { @@ -1040,7 +1040,7 @@ void lv2_obj::sleep_timeout(cpu_thread& thread, u64 timeout) ppu->start_time = start_time; } - if (timeout) + if (timeout && g_cfg.core.sleep_timers_accuracy != sleep_timers_accuracy_level::_all_timers) { const u64 wait_until = start_time + timeout; @@ -1078,7 +1078,7 @@ void lv2_obj::awake(cpu_thread& cpu, u32 prio) else if (prio == -4) { // Yield command - const u64 start_time = get_system_time(); + const u64 start_time = get_guest_system_time(); for (std::size_t i = 0, pos = -1; i < g_ppu.size(); i++) { @@ -1184,7 +1184,7 @@ void lv2_obj::schedule_all() { auto& pair = g_waiting.front(); - if (pair.first <= get_system_time()) + if (pair.first <= get_guest_system_time()) { pair.second->notify(); g_waiting.pop_front(); diff --git a/rpcs3/Emu/Cell/lv2/sys_cond.cpp b/rpcs3/Emu/Cell/lv2/sys_cond.cpp index dc86ebfe5c..6f63ffa9f6 100644 --- a/rpcs3/Emu/Cell/lv2/sys_cond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_cond.cpp @@ -12,8 +12,6 @@ LOG_CHANNEL(sys_cond); template<> DECLARE(ipc_manager::g_ipc) {}; -extern u64 get_system_time(); - error_code sys_cond_create(ppu_thread& ppu, vm::ptr cond_id, u32 mutex_id, vm::ptr attr) { vm::temporary_unlock(ppu); @@ -262,9 +260,7 @@ error_code sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout) if (timeout) { - const u64 passed = get_system_time() - ppu.start_time; - - if (passed >= timeout) + if (lv2_obj::wait_timeout(timeout, &ppu)) { std::lock_guard lock(cond->mutex->mutex); @@ -285,8 +281,6 @@ error_code sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout) timeout = 0; continue; } - - thread_ctrl::wait_for(timeout - passed); } else { diff --git a/rpcs3/Emu/Cell/lv2/sys_event.cpp b/rpcs3/Emu/Cell/lv2/sys_event.cpp index 04825f84f2..610976b49d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event.cpp @@ -14,8 +14,6 @@ LOG_CHANNEL(sys_event); template<> DECLARE(ipc_manager::g_ipc) {}; -extern u64 get_system_time(); - std::shared_ptr lv2_event_queue::find(u64 ipc_key) { if (ipc_key == SYS_EVENT_QUEUE_LOCAL) @@ -284,9 +282,7 @@ error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr= timeout) + if (lv2_obj::wait_timeout(timeout, &ppu)) { std::lock_guard lock(queue->mutex); @@ -299,8 +295,6 @@ error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr DECLARE(ipc_manager::g_ipc) {}; -extern u64 get_system_time(); - error_code sys_event_flag_create(ppu_thread& ppu, vm::ptr id, vm::ptr attr, u64 init) { vm::temporary_unlock(ppu); @@ -171,9 +169,7 @@ error_code sys_event_flag_wait(ppu_thread& ppu, u32 id, u64 bitptn, u32 mode, vm if (timeout) { - const u64 passed = get_system_time() - ppu.start_time; - - if (passed >= timeout) + if (lv2_obj::wait_timeout(timeout, &ppu)) { std::lock_guard lock(flag->mutex); @@ -188,8 +184,6 @@ error_code sys_event_flag_wait(ppu_thread& ppu, u32 id, u64 bitptn, u32 mode, vm ppu.gpr[6] = flag->pattern; break; } - - thread_ctrl::wait_for(timeout - passed); } else { diff --git a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp index f477b00ca5..1178466114 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp @@ -10,8 +10,6 @@ LOG_CHANNEL(sys_lwcond); -extern u64 get_system_time(); - error_code _sys_lwcond_create(ppu_thread& ppu, vm::ptr lwcond_id, u32 lwmutex_id, vm::ptr control, u64 name, u32 arg5) { vm::temporary_unlock(ppu); @@ -313,9 +311,7 @@ error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id if (timeout) { - const u64 passed = get_system_time() - ppu.start_time; - - if (passed >= timeout) + if (lv2_obj::wait_timeout(timeout, &ppu)) { std::lock_guard lock(cond->mutex); @@ -330,8 +326,6 @@ error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id ppu.gpr[3] = CELL_ETIMEDOUT; break; } - - thread_ctrl::wait_for(timeout - passed); } else { diff --git a/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp b/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp index 438a7c6642..21722cb7ae 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp @@ -9,8 +9,6 @@ LOG_CHANNEL(sys_lwmutex); -extern u64 get_system_time(); - error_code _sys_lwmutex_create(ppu_thread& ppu, vm::ptr lwmutex_id, u32 protocol, vm::ptr control, s32 has_name, u64 name) { vm::temporary_unlock(ppu); @@ -130,9 +128,7 @@ error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout) if (timeout) { - const u64 passed = get_system_time() - ppu.start_time; - - if (passed >= timeout) + if (lv2_obj::wait_timeout(timeout, &ppu)) { std::lock_guard lock(mutex->mutex); @@ -145,8 +141,6 @@ error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout) ppu.gpr[3] = CELL_ETIMEDOUT; break; } - - thread_ctrl::wait_for(timeout - passed); } else { diff --git a/rpcs3/Emu/Cell/lv2/sys_mutex.cpp b/rpcs3/Emu/Cell/lv2/sys_mutex.cpp index 5f7fb5843c..0772f695bc 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mutex.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mutex.cpp @@ -12,8 +12,6 @@ LOG_CHANNEL(sys_mutex); template<> DECLARE(ipc_manager::g_ipc) {}; -extern u64 get_system_time(); - error_code sys_mutex_create(ppu_thread& ppu, vm::ptr mutex_id, vm::ptr attr) { vm::temporary_unlock(ppu); @@ -165,9 +163,7 @@ error_code sys_mutex_lock(ppu_thread& ppu, u32 mutex_id, u64 timeout) if (timeout) { - const u64 passed = get_system_time() - ppu.start_time; - - if (passed >= timeout) + if (lv2_obj::wait_timeout(timeout, &ppu)) { std::lock_guard lock(mutex->mutex); @@ -180,8 +176,6 @@ error_code sys_mutex_lock(ppu_thread& ppu, u32 mutex_id, u64 timeout) ppu.gpr[3] = CELL_ETIMEDOUT; break; } - - thread_ctrl::wait_for(timeout - passed); } else { diff --git a/rpcs3/Emu/Cell/lv2/sys_net.cpp b/rpcs3/Emu/Cell/lv2/sys_net.cpp index 9b9b49f801..2abbc6a3a8 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net.cpp @@ -30,8 +30,6 @@ static std::vector s_to_awake; static shared_mutex s_nw_mutex; -extern u64 get_system_time(); - // Error helper functions static s32 get_last_error(bool is_blocking, int native_error = 0) { @@ -1613,9 +1611,7 @@ s32 sys_net_bnet_poll(ppu_thread& ppu, vm::ptr fds, s32 nfds, s3 if (timeout) { - const u64 passed = get_system_time() - ppu.start_time; - - if (passed >= timeout) + if (lv2_obj::wait_timeout(timeout, &ppu)) { std::lock_guard nw_lock(s_nw_mutex); @@ -1628,8 +1624,6 @@ s32 sys_net_bnet_poll(ppu_thread& ppu, vm::ptr fds, s32 nfds, s3 network_clear_queue(ppu); break; } - - thread_ctrl::wait_for(timeout - passed); } else { @@ -1814,9 +1808,7 @@ s32 sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr readf if (timeout) { - const u64 passed = get_system_time() - ppu.start_time; - - if (passed >= timeout) + if (lv2_obj::wait_timeout(timeout, &ppu)) { std::lock_guard nw_lock(s_nw_mutex); @@ -1829,8 +1821,6 @@ s32 sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr readf network_clear_queue(ppu); break; } - - thread_ctrl::wait_for(timeout - passed); } else { diff --git a/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp b/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp index 5f6a76ec5c..05d3eca652 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp @@ -12,8 +12,6 @@ LOG_CHANNEL(sys_rwlock); template<> DECLARE(ipc_manager::g_ipc) {}; -extern u64 get_system_time(); - error_code sys_rwlock_create(ppu_thread& ppu, vm::ptr rw_lock_id, vm::ptr attr) { vm::temporary_unlock(ppu); @@ -140,9 +138,7 @@ error_code sys_rwlock_rlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout) if (timeout) { - const u64 passed = get_system_time() - ppu.start_time; - - if (passed >= timeout) + if (lv2_obj::wait_timeout(timeout, &ppu)) { std::lock_guard lock(rwlock->mutex); @@ -155,8 +151,6 @@ error_code sys_rwlock_rlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout) ppu.gpr[3] = CELL_ETIMEDOUT; break; } - - thread_ctrl::wait_for(timeout - passed); } else { @@ -341,9 +335,7 @@ error_code sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout) if (timeout) { - const u64 passed = get_system_time() - ppu.start_time; - - if (passed >= timeout) + if (lv2_obj::wait_timeout(timeout, &ppu)) { std::lock_guard lock(rwlock->mutex); @@ -371,8 +363,6 @@ error_code sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout) ppu.gpr[3] = CELL_ETIMEDOUT; break; } - - thread_ctrl::wait_for(timeout - passed); } else { diff --git a/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp b/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp index 74c2803360..3bfaddbc67 100644 --- a/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp @@ -12,8 +12,6 @@ LOG_CHANNEL(sys_semaphore); template<> DECLARE(ipc_manager::g_ipc) {}; -extern u64 get_system_time(); - error_code sys_semaphore_create(ppu_thread& ppu, vm::ptr sem_id, vm::ptr attr, s32 initial_val, s32 max_val) { vm::temporary_unlock(ppu); @@ -134,9 +132,7 @@ error_code sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout) if (timeout) { - const u64 passed = get_system_time() - ppu.start_time; - - if (passed >= timeout) + if (lv2_obj::wait_timeout(timeout, &ppu)) { std::lock_guard lock(sem->mutex); @@ -157,8 +153,6 @@ error_code sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout) ppu.gpr[3] = CELL_ETIMEDOUT; break; } - - thread_ctrl::wait_for(timeout - passed); } else { diff --git a/rpcs3/Emu/Cell/lv2/sys_sync.h b/rpcs3/Emu/Cell/lv2/sys_sync.h index 960fab7fe0..599747a727 100644 --- a/rpcs3/Emu/Cell/lv2/sys_sync.h +++ b/rpcs3/Emu/Cell/lv2/sys_sync.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "Utilities/mutex.h" #include "Utilities/sema.h" @@ -9,8 +9,10 @@ #include "Emu/Cell/ErrorCodes.h" #include "Emu/IdManager.h" #include "Emu/IPC.h" +#include "Emu/System.h" #include +#include // attr_protocol (waiting scheduling policy) enum @@ -213,6 +215,68 @@ struct lv2_obj } } + template + static bool wait_timeout(u64 usec, cpu_thread* const cpu = nullptr) + { + usec = (usec * g_cfg.core.clocks_scale) / 100; + +#ifdef __linux__ + // TODO: Confirm whether Apple or any BSD can benefit from this as well + constexpr u32 host_min_quantum = 50; +#else + // Host scheduler quantum for windows (worst case) + // NOTE: On ps3 this function has very high accuracy + constexpr u32 host_min_quantum = 500; +#endif + extern u64 get_system_time(); + + u64 passed = 0; + u64 remaining; + + const u64 start_time = get_system_time(); + while (usec >= passed) + { + remaining = usec - passed; + + if (g_cfg.core.sleep_timers_accuracy < (is_usleep ? sleep_timers_accuracy_level::_usleep : sleep_timers_accuracy_level::_all_timers)) + { + thread_ctrl::wait_for(remaining); + } + else + { + if (remaining > host_min_quantum) + { +#ifdef __linux__ + // Do not wait for the last quantum to avoid loss of accuracy + thread_ctrl::wait_for(remaining - ((remaining % host_min_quantum) + host_min_quantum)); +#else + // Wait on multiple of min quantum for large durations to avoid overloading low thread cpus + thread_ctrl::wait_for(remaining - (remaining % host_min_quantum)); +#endif + } + else + { + // Try yielding. May cause long wake latency but helps weaker CPUs a lot by alleviating resource pressure + std::this_thread::yield(); + } + } + + if (Emu.IsStopped()) + { + return false; + } + + if (cpu && cpu->state & cpu_flag::signal) + { + return false; + } + + passed = get_system_time() - start_time; + } + + return true; + } + private: // Scheduler mutex static shared_mutex g_mutex; diff --git a/rpcs3/Emu/Cell/lv2/sys_time.cpp b/rpcs3/Emu/Cell/lv2/sys_time.cpp index b166578e5a..01eb623215 100644 --- a/rpcs3/Emu/Cell/lv2/sys_time.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_time.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "stdafx.h" #include "sys_time.h" #include "Emu/System.h" @@ -102,11 +102,9 @@ static int clock_gettime(int clk_id, struct timespec* tp) #endif - - LOG_CHANNEL(sys_time); -static const u64 g_timebase_freq = /*79800000*/ 80000000; // 80 Mhz +static constexpr u64 g_timebase_freq = /*79800000*/ 80000000ull; // 80 Mhz // Auxiliary functions u64 get_timebased_time() @@ -118,12 +116,12 @@ u64 get_timebased_time() const u64 time = count.QuadPart; const u64 freq = s_time_aux_info.perf_freq; - return time / freq * g_timebase_freq + time % freq * g_timebase_freq / freq; + return (time / freq * g_timebase_freq + time % freq * g_timebase_freq / freq) * g_cfg.core.clocks_scale / 100u; #else struct timespec ts; verify(HERE), ::clock_gettime(CLOCK_MONOTONIC, &ts) == 0; - return static_cast(ts.tv_sec) * g_timebase_freq + static_cast(ts.tv_nsec) * g_timebase_freq / 1000000000u; + return (static_cast(ts.tv_sec) * g_timebase_freq + static_cast(ts.tv_nsec) * g_timebase_freq / 1000000000ull) * g_cfg.core.clocks_scale / 100u; #endif } @@ -139,18 +137,24 @@ u64 get_system_time() const u64 time = count.QuadPart; const u64 freq = s_time_aux_info.perf_freq; - const u64 result = time / freq * 1000000u + (time % freq) * 1000000u / freq; + const u64 result = time / freq * 1000000ull + (time % freq) * 1000000ull / freq; #else struct timespec ts; verify(HERE), ::clock_gettime(CLOCK_MONOTONIC, &ts) == 0; - const u64 result = static_cast(ts.tv_sec) * 1000000u + static_cast(ts.tv_nsec) / 1000u; + const u64 result = static_cast(ts.tv_sec) * 1000000ull + static_cast(ts.tv_nsec) / 1000u; #endif if (result) return result; } } +// As get_system_time but obeys Clocks scaling setting +u64 get_guest_system_time() +{ + return get_system_time() * g_cfg.core.clocks_scale / 100; +} + // Functions s32 sys_time_get_timezone(vm::ptr timezone, vm::ptr summertime) { @@ -171,24 +175,24 @@ s32 sys_time_get_current_time(vm::ptr sec, vm::ptr nsec) verify(HERE), QueryPerformanceCounter(&count); // get time difference in nanoseconds - const u64 diff = (count.QuadPart - s_time_aux_info.start_time) * 1000000000u / s_time_aux_info.perf_freq; + const u64 diff = (count.QuadPart - s_time_aux_info.start_time) * 1000000000ull / s_time_aux_info.perf_freq; // get time since Epoch in nanoseconds - const u64 time = s_time_aux_info.start_ftime * 100u + diff; + const u64 time = (s_time_aux_info.start_ftime * 100u + diff) * g_cfg.core.clocks_scale / 100u; if (!sec) { return CELL_EFAULT; } - *sec = time / 1000000000u; + *sec = time / 1000000000ull; if (!nsec) { return CELL_EFAULT; } - *nsec = time % 1000000000u; + *nsec = time % 1000000000ull; #else struct timespec ts; verify(HERE), ::clock_gettime(CLOCK_REALTIME, &ts) == 0; @@ -198,14 +202,14 @@ s32 sys_time_get_current_time(vm::ptr sec, vm::ptr nsec) return CELL_EFAULT; } - *sec = ts.tv_sec; + *sec = (ts.tv_sec * g_cfg.core.clocks_scale / 100u) + (ts.tv_nsec * g_cfg.core.clocks_scale / (1000000000ull * 100)); if (!nsec) { return CELL_EFAULT; } - *nsec = ts.tv_nsec; + *nsec = (ts.tv_nsec * g_cfg.core.clocks_scale / 100u) % 1000000000ull; #endif return CELL_OK; diff --git a/rpcs3/Emu/Cell/lv2/sys_timer.cpp b/rpcs3/Emu/Cell/lv2/sys_timer.cpp index f11cd262a1..5a6b5f0246 100644 --- a/rpcs3/Emu/Cell/lv2/sys_timer.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_timer.cpp @@ -13,7 +13,7 @@ LOG_CHANNEL(sys_timer); -extern u64 get_system_time(); +extern u64 get_guest_system_time(); void lv2_timer_context::operator()() { @@ -23,7 +23,7 @@ void lv2_timer_context::operator()() if (_state == SYS_TIMER_STATE_RUN) { - const u64 _now = get_system_time(); + const u64 _now = get_guest_system_time(); const u64 next = expire; if (_now >= next) @@ -48,7 +48,7 @@ void lv2_timer_context::operator()() } // TODO: use single global dedicated thread for busy waiting, no timer threads - thread_ctrl::wait_for(next - _now); + lv2_obj::wait_timeout(next - _now); } else if (_state == SYS_TIMER_STATE_STOP) { @@ -142,7 +142,7 @@ error_code _sys_timer_start(ppu_thread& ppu, u32 timer_id, u64 base_time, u64 pe sys_timer.trace("_sys_timer_start(timer_id=0x%x, base_time=0x%llx, period=0x%llx)", timer_id, base_time, period); - const u64 start_time = get_system_time(); + const u64 start_time = get_guest_system_time(); if (!period && start_time >= base_time) { @@ -307,46 +307,13 @@ error_code sys_timer_usleep(ppu_thread& ppu, u64 sleep_time) if (sleep_time) { -#ifdef __linux__ - // TODO: Confirm whether Apple or any BSD can benefit from this as well - constexpr u32 host_min_quantum = 50; -#else - // Host scheduler quantum for windows (worst case) - // NOTE: On ps3 this function has very high accuracy - constexpr u32 host_min_quantum = 500; -#endif + lv2_obj::sleep(ppu, 0); - u64 passed = 0; - u64 remaining; + lv2_obj::wait_timeout(sleep_time); - lv2_obj::sleep(ppu, sleep_time); - - while (sleep_time >= passed) + if (ppu.is_stopped()) { - if (ppu.is_stopped()) - { - return 0; - } - - remaining = sleep_time - passed; - - if (remaining > host_min_quantum) - { -#ifdef __linux__ - // Do not wait for the last quantum to avoid loss of accuracy - thread_ctrl::wait_for(remaining - ((remaining % host_min_quantum) + host_min_quantum)); -#else - // Wait on multiple of min quantum for large durations to avoid overloading low thread cpus - thread_ctrl::wait_for(remaining - (remaining % host_min_quantum)); -#endif - } - else - { - // Try yielding. May cause long wake latency but helps weaker CPUs a lot by alleviating resource pressure - std::this_thread::yield(); - } - - passed = (get_system_time() - ppu.start_time); + return 0; } } else diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 30dfbdea7d..eee3b52ccd 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -799,7 +799,7 @@ namespace rsx u64 thread::timestamp() { // Get timestamp, and convert it from microseconds to nanoseconds - const u64 t = get_system_time() * 1000; + const u64 t = get_guest_system_time() * 1000; if (t != timestamp_ctrl) { timestamp_ctrl = t; diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index a448af475a..565aad16dc 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -20,6 +20,7 @@ #include "Emu/Cell/lv2/sys_rsx.h" +extern u64 get_guest_system_time(); extern u64 get_system_time(); struct RSXIOTable diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 1d68c4db70..dd5298105d 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -275,6 +275,22 @@ void fmt_class_string::format(std::string& out, u64 arg) }); } +template <> +void fmt_class_string::format(std::string& out, u64 arg) +{ + format_enum(out, arg, [](sleep_timers_accuracy_level value) + { + switch (value) + { + case sleep_timers_accuracy_level::_as_host: return "Host"; + case sleep_timers_accuracy_level::_usleep: return "Usleep"; + case sleep_timers_accuracy_level::_all_timers: return "All"; + } + + return unknown; + }); +} + template <> void fmt_class_string::format(std::string& out, u64 arg) { diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index ab3823c065..4487306eb1 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -8,6 +8,7 @@ #include u64 get_system_time(); +u64 get_guest_system_time(); enum class system_state { @@ -47,6 +48,13 @@ enum class lib_loading_type liblv2only }; +enum sleep_timers_accuracy_level : u32 +{ + _as_host = 0, + _usleep, + _all_timers, +}; + enum class keyboard_handler { null, @@ -406,6 +414,8 @@ struct cfg_root : cfg::node cfg::set_entry load_libraries{this, "Load libraries"}; cfg::_bool hle_lwmutex{this, "HLE lwmutex"}; // Force alternative lwmutex/lwcond implementation + cfg::_int<10, 1000> clocks_scale{this, "Clocks scale", 100}; // Changing this from 100 (percentage) may affect game speed in unexpected ways + cfg::_enum sleep_timers_accuracy{this, "Sleep timers accuracy", sleep_timers_accuracy_level::_as_host}; // Affects sleep timers accuracy (to fix host's sleep accuracy) } core{this}; struct node_vfs : cfg::node @@ -477,7 +487,7 @@ struct cfg_root : cfg::node cfg::_int<0, 16> anisotropic_level_override{this, "Anisotropic Filter Override", 0}; cfg::_int<1, 1024> min_scalable_dimension{this, "Minimum Scalable Dimension", 16}; cfg::_int<0, 30000000> driver_recovery_timeout{this, "Driver Recovery Timeout", 1000000}; - cfg::_int<1, 500> vblank_rate{this, "Vblank Rate", 60}; // Changing this from 60 may affect game speed unexpected ways + cfg::_int<1, 500> vblank_rate{this, "Vblank Rate", 60}; // Changing this from 60 may affect game speed in unexpected ways struct node_d3d12 : cfg::node {