1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-26 12:42:41 +01:00

Timers scaling and fixes

This commit is contained in:
Eladash 2019-07-14 06:55:11 +03:00 committed by Ani
parent d17be2c2ec
commit 85b1152e29
27 changed files with 160 additions and 162 deletions

View File

@ -1259,7 +1259,7 @@ void camera_context::operator()()
continue; continue;
} }
const u64 frame_start = get_system_time(); const u64 frame_start = get_guest_system_time();
std::unique_lock lock(mutex_notify_data_map); std::unique_lock lock(mutex_notify_data_map);
@ -1304,7 +1304,7 @@ void camera_context::operator()()
for (const u64 frame_target_time = 1000000u / fps;;) 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) if (time_passed >= frame_target_time)
break; break;

View File

@ -38,7 +38,7 @@ void mic_context::operator()()
continue; 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 time_pos = stamp0 - start_time - Emu.GetPauseTime();
const u64 expected_time = m_counter * 256 * 1000000 / 48000; const u64 expected_time = m_counter * 256 * 1000000 / 48000;

View File

@ -254,7 +254,7 @@ public:
std::unordered_map<u8, microphone_device> mic_list; std::unordered_map<u8, microphone_device> mic_list;
protected: protected:
const u64 start_time = get_system_time(); const u64 start_time = get_guest_system_time();
u64 m_counter = 0; u64 m_counter = 0;
// u32 signalStateLocalTalk = 9; // value is in range 0-10. 10 indicates talking, 0 indicating none. // u32 signalStateLocalTalk = 9; // value is in range 0-10. 10 indicates talking, 0 indicating none.

View File

@ -332,8 +332,8 @@ error_code cellMsgDialogClose(f32 delay)
{ {
cellSysutil.warning("cellMsgDialogClose(delay=%f)", delay); cellSysutil.warning("cellMsgDialogClose(delay=%f)", delay);
extern u64 get_system_time(); extern u64 get_guest_system_time();
const u64 wait_until = get_system_time() + static_cast<s64>(std::max<float>(delay, 0.0f) * 1000); const u64 wait_until = get_guest_system_time() + static_cast<s64>(std::max<float>(delay, 0.0f) * 1000);
if (auto manager = fxm::get<rsx::overlays::display_manager>()) if (auto manager = fxm::get<rsx::overlays::display_manager>())
{ {
@ -341,7 +341,7 @@ error_code cellMsgDialogClose(f32 delay)
{ {
thread_ctrl::spawn("cellMsgDialogClose() Thread", [=] thread_ctrl::spawn("cellMsgDialogClose() Thread", [=]
{ {
while (get_system_time() < wait_until) while (get_guest_system_time() < wait_until)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
return; return;
@ -368,7 +368,7 @@ error_code cellMsgDialogClose(f32 delay)
thread_ctrl::spawn("cellMsgDialogClose() Thread", [=]() 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; if (Emu.IsStopped()) return;

View File

@ -113,16 +113,16 @@ s32 cellVpostExec(u32 handle, vm::cptr<u8> inPicBuff, vm::cptr<CellVpostCtrlPara
picInfo->reserved1 = 0; picInfo->reserved1 = 0;
picInfo->reserved2 = 0; picInfo->reserved2 = 0;
//u64 stamp0 = get_system_time(); //u64 stamp0 = get_guest_system_time();
std::unique_ptr<u8[]> pA(new u8[w*h]); std::unique_ptr<u8[]> pA(new u8[w*h]);
memset(pA.get(), ctrlParam->outAlpha, 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); 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() }; 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 }; int in_line[4] = { w, w/2, w/2, w };
@ -132,7 +132,7 @@ s32 cellVpostExec(u32 handle, vm::cptr<u8> inPicBuff, vm::cptr<CellVpostCtrlPara
sws_scale(vpost->sws, in_data, in_line, 0, h, out_data, out_line); sws_scale(vpost->sws, in_data, in_line, 0, h, out_data, out_line);
//ConLog.Write("cellVpostExec() perf (access=%d, getContext=%d, scale=%d, finalize=%d)", //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; return CELL_OK;
} }

View File

@ -346,7 +346,7 @@ struct surmixer_thread : ppu_thread
if (port.state == audio_port_state::started) 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)); memset(g_surmx.mixdata, 0, sizeof(g_surmx.mixdata));
if (g_surmx.cb) if (g_surmx.cb)
@ -355,7 +355,7 @@ struct surmixer_thread : ppu_thread
lv2_obj::sleep(*this); lv2_obj::sleep(*this);
} }
//u64 stamp1 = get_system_time(); //u64 stamp1 = get_guest_system_time();
{ {
std::lock_guard lock(g_surmx.mutex); 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<f32>(port.addr.addr() + (g_surmx.mixcount % port.num_blocks) * port.num_channels * AUDIO_BUFFER_SAMPLES * sizeof(float)); auto buf = vm::_ptr<f32>(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; *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); //ConLog.Write("Libmixer perf: start=%lld (cb=%lld, ssp=%lld, finalize=%lld)", stamp0 - m_config.start_time, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2);
} }

View File

@ -11,7 +11,7 @@
LOG_CHANNEL(sysPrxForUser); LOG_CHANNEL(sysPrxForUser);
extern u64 get_system_time(); extern u64 get_guest_system_time();
vm::gvar<s32> sys_prx_version; // ??? vm::gvar<s32> sys_prx_version; // ???
vm::gvar<vm::ptr<void()>> g_ppu_atexitspawn; vm::gvar<vm::ptr<void()>> g_ppu_atexitspawn;
@ -22,7 +22,7 @@ s64 sys_time_get_system_time()
{ {
sysPrxForUser.trace("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) void sys_process_exit(ppu_thread& ppu, s32 status)

View File

@ -214,7 +214,7 @@ error_code sys_lwmutex_lock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex, u64
return CELL_OK; 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); 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<sys_lwmutex_t> lwmutex, u64
} }
else if (timeout && res_ != CELL_ETIMEDOUT) 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) if (timeout <= time_diff)
{ {

View File

@ -10,8 +10,6 @@
extern logs::channel sysPrxForUser; extern logs::channel sysPrxForUser;
extern u64 get_system_time();
spu_printf_cb_t g_spu_printf_agcb; spu_printf_cb_t g_spu_printf_agcb;
spu_printf_cb_t g_spu_printf_dgcb; spu_printf_cb_t g_spu_printf_dgcb;
spu_printf_cb_t g_spu_printf_atcb; spu_printf_cb_t g_spu_printf_atcb;

View File

@ -64,7 +64,7 @@ const bool s_use_ssse3 =
#define _mm_shuffle_epi8 #define _mm_shuffle_epi8
#endif #endif
extern u64 get_system_time(); extern u64 get_guest_system_time();
extern atomic_t<const char*> g_progr; extern atomic_t<const char*> g_progr;
extern atomic_t<u64> g_progr_ptotal; extern atomic_t<u64> g_progr_ptotal;
@ -469,7 +469,7 @@ std::string ppu_thread::dump() const
if (const auto _time = start_time) 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 else
{ {
@ -721,7 +721,7 @@ ppu_thread::ppu_thread(const ppu_thread_params& param, std::string_view name, u3
, prio(prio) , prio(prio)
, stack_size(param.stack_size) , stack_size(param.stack_size)
, stack_addr(param.stack_addr) , stack_addr(param.stack_addr)
, start_time(get_system_time()) , start_time(get_guest_system_time())
, joiner(-!!detached) , joiner(-!!detached)
, ppu_name(name) , ppu_name(name)
{ {
@ -846,7 +846,7 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc)
{ {
if (start_time) 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 else
{ {

View File

@ -999,7 +999,7 @@ extern ppu_function_t ppu_get_syscall(u64 code)
return nullptr; return nullptr;
} }
extern u64 get_system_time(); extern u64 get_guest_system_time();
DECLARE(lv2_obj::g_mutex); DECLARE(lv2_obj::g_mutex);
DECLARE(lv2_obj::g_ppu); 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); 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<ppu_thread*>(thread.id_type() == 1 ? &thread : nullptr)) if (auto ppu = static_cast<ppu_thread*>(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; 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; const u64 wait_until = start_time + timeout;
@ -1078,7 +1078,7 @@ void lv2_obj::awake(cpu_thread& cpu, u32 prio)
else if (prio == -4) else if (prio == -4)
{ {
// Yield command // 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++) 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(); auto& pair = g_waiting.front();
if (pair.first <= get_system_time()) if (pair.first <= get_guest_system_time())
{ {
pair.second->notify(); pair.second->notify();
g_waiting.pop_front(); g_waiting.pop_front();

View File

@ -12,8 +12,6 @@ LOG_CHANNEL(sys_cond);
template<> DECLARE(ipc_manager<lv2_cond, u64>::g_ipc) {}; template<> DECLARE(ipc_manager<lv2_cond, u64>::g_ipc) {};
extern u64 get_system_time();
error_code sys_cond_create(ppu_thread& ppu, vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribute_t> attr) error_code sys_cond_create(ppu_thread& ppu, vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribute_t> attr)
{ {
vm::temporary_unlock(ppu); vm::temporary_unlock(ppu);
@ -262,9 +260,7 @@ error_code sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout)
if (timeout) if (timeout)
{ {
const u64 passed = get_system_time() - ppu.start_time; if (lv2_obj::wait_timeout(timeout, &ppu))
if (passed >= timeout)
{ {
std::lock_guard lock(cond->mutex->mutex); 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; timeout = 0;
continue; continue;
} }
thread_ctrl::wait_for(timeout - passed);
} }
else else
{ {

View File

@ -14,8 +14,6 @@ LOG_CHANNEL(sys_event);
template<> DECLARE(ipc_manager<lv2_event_queue, u64>::g_ipc) {}; template<> DECLARE(ipc_manager<lv2_event_queue, u64>::g_ipc) {};
extern u64 get_system_time();
std::shared_ptr<lv2_event_queue> lv2_event_queue::find(u64 ipc_key) std::shared_ptr<lv2_event_queue> lv2_event_queue::find(u64 ipc_key)
{ {
if (ipc_key == SYS_EVENT_QUEUE_LOCAL) 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<sys_e
if (timeout) if (timeout)
{ {
const u64 passed = get_system_time() - ppu.start_time; if (lv2_obj::wait_timeout(timeout, &ppu))
if (passed >= timeout)
{ {
std::lock_guard lock(queue->mutex); std::lock_guard lock(queue->mutex);
@ -299,8 +295,6 @@ error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sys_e
ppu.gpr[3] = CELL_ETIMEDOUT; ppu.gpr[3] = CELL_ETIMEDOUT;
break; break;
} }
thread_ctrl::wait_for(timeout - passed);
} }
else else
{ {

View File

@ -14,8 +14,6 @@ LOG_CHANNEL(sys_event_flag);
template<> DECLARE(ipc_manager<lv2_event_flag, u64>::g_ipc) {}; template<> DECLARE(ipc_manager<lv2_event_flag, u64>::g_ipc) {};
extern u64 get_system_time();
error_code sys_event_flag_create(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<sys_event_flag_attribute_t> attr, u64 init) error_code sys_event_flag_create(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<sys_event_flag_attribute_t> attr, u64 init)
{ {
vm::temporary_unlock(ppu); 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) if (timeout)
{ {
const u64 passed = get_system_time() - ppu.start_time; if (lv2_obj::wait_timeout(timeout, &ppu))
if (passed >= timeout)
{ {
std::lock_guard lock(flag->mutex); 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; ppu.gpr[6] = flag->pattern;
break; break;
} }
thread_ctrl::wait_for(timeout - passed);
} }
else else
{ {

View File

@ -10,8 +10,6 @@
LOG_CHANNEL(sys_lwcond); LOG_CHANNEL(sys_lwcond);
extern u64 get_system_time();
error_code _sys_lwcond_create(ppu_thread& ppu, vm::ptr<u32> lwcond_id, u32 lwmutex_id, vm::ptr<sys_lwcond_t> control, u64 name, u32 arg5) error_code _sys_lwcond_create(ppu_thread& ppu, vm::ptr<u32> lwcond_id, u32 lwmutex_id, vm::ptr<sys_lwcond_t> control, u64 name, u32 arg5)
{ {
vm::temporary_unlock(ppu); 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) if (timeout)
{ {
const u64 passed = get_system_time() - ppu.start_time; if (lv2_obj::wait_timeout(timeout, &ppu))
if (passed >= timeout)
{ {
std::lock_guard lock(cond->mutex); 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; ppu.gpr[3] = CELL_ETIMEDOUT;
break; break;
} }
thread_ctrl::wait_for(timeout - passed);
} }
else else
{ {

View File

@ -9,8 +9,6 @@
LOG_CHANNEL(sys_lwmutex); LOG_CHANNEL(sys_lwmutex);
extern u64 get_system_time();
error_code _sys_lwmutex_create(ppu_thread& ppu, vm::ptr<u32> lwmutex_id, u32 protocol, vm::ptr<sys_lwmutex_t> control, s32 has_name, u64 name) error_code _sys_lwmutex_create(ppu_thread& ppu, vm::ptr<u32> lwmutex_id, u32 protocol, vm::ptr<sys_lwmutex_t> control, s32 has_name, u64 name)
{ {
vm::temporary_unlock(ppu); vm::temporary_unlock(ppu);
@ -130,9 +128,7 @@ error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout)
if (timeout) if (timeout)
{ {
const u64 passed = get_system_time() - ppu.start_time; if (lv2_obj::wait_timeout(timeout, &ppu))
if (passed >= timeout)
{ {
std::lock_guard lock(mutex->mutex); 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; ppu.gpr[3] = CELL_ETIMEDOUT;
break; break;
} }
thread_ctrl::wait_for(timeout - passed);
} }
else else
{ {

View File

@ -12,8 +12,6 @@ LOG_CHANNEL(sys_mutex);
template<> DECLARE(ipc_manager<lv2_mutex, u64>::g_ipc) {}; template<> DECLARE(ipc_manager<lv2_mutex, u64>::g_ipc) {};
extern u64 get_system_time();
error_code sys_mutex_create(ppu_thread& ppu, vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr) error_code sys_mutex_create(ppu_thread& ppu, vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr)
{ {
vm::temporary_unlock(ppu); vm::temporary_unlock(ppu);
@ -165,9 +163,7 @@ error_code sys_mutex_lock(ppu_thread& ppu, u32 mutex_id, u64 timeout)
if (timeout) if (timeout)
{ {
const u64 passed = get_system_time() - ppu.start_time; if (lv2_obj::wait_timeout(timeout, &ppu))
if (passed >= timeout)
{ {
std::lock_guard lock(mutex->mutex); 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; ppu.gpr[3] = CELL_ETIMEDOUT;
break; break;
} }
thread_ctrl::wait_for(timeout - passed);
} }
else else
{ {

View File

@ -30,8 +30,6 @@ static std::vector<ppu_thread*> s_to_awake;
static shared_mutex s_nw_mutex; static shared_mutex s_nw_mutex;
extern u64 get_system_time();
// Error helper functions // Error helper functions
static s32 get_last_error(bool is_blocking, int native_error = 0) 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<sys_net_pollfd> fds, s32 nfds, s3
if (timeout) if (timeout)
{ {
const u64 passed = get_system_time() - ppu.start_time; if (lv2_obj::wait_timeout(timeout, &ppu))
if (passed >= timeout)
{ {
std::lock_guard nw_lock(s_nw_mutex); std::lock_guard nw_lock(s_nw_mutex);
@ -1628,8 +1624,6 @@ s32 sys_net_bnet_poll(ppu_thread& ppu, vm::ptr<sys_net_pollfd> fds, s32 nfds, s3
network_clear_queue(ppu); network_clear_queue(ppu);
break; break;
} }
thread_ctrl::wait_for(timeout - passed);
} }
else else
{ {
@ -1814,9 +1808,7 @@ s32 sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr<sys_net_fd_set> readf
if (timeout) if (timeout)
{ {
const u64 passed = get_system_time() - ppu.start_time; if (lv2_obj::wait_timeout(timeout, &ppu))
if (passed >= timeout)
{ {
std::lock_guard nw_lock(s_nw_mutex); std::lock_guard nw_lock(s_nw_mutex);
@ -1829,8 +1821,6 @@ s32 sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr<sys_net_fd_set> readf
network_clear_queue(ppu); network_clear_queue(ppu);
break; break;
} }
thread_ctrl::wait_for(timeout - passed);
} }
else else
{ {

View File

@ -12,8 +12,6 @@ LOG_CHANNEL(sys_rwlock);
template<> DECLARE(ipc_manager<lv2_rwlock, u64>::g_ipc) {}; template<> DECLARE(ipc_manager<lv2_rwlock, u64>::g_ipc) {};
extern u64 get_system_time();
error_code sys_rwlock_create(ppu_thread& ppu, vm::ptr<u32> rw_lock_id, vm::ptr<sys_rwlock_attribute_t> attr) error_code sys_rwlock_create(ppu_thread& ppu, vm::ptr<u32> rw_lock_id, vm::ptr<sys_rwlock_attribute_t> attr)
{ {
vm::temporary_unlock(ppu); vm::temporary_unlock(ppu);
@ -140,9 +138,7 @@ error_code sys_rwlock_rlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout)
if (timeout) if (timeout)
{ {
const u64 passed = get_system_time() - ppu.start_time; if (lv2_obj::wait_timeout(timeout, &ppu))
if (passed >= timeout)
{ {
std::lock_guard lock(rwlock->mutex); 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; ppu.gpr[3] = CELL_ETIMEDOUT;
break; break;
} }
thread_ctrl::wait_for(timeout - passed);
} }
else else
{ {
@ -341,9 +335,7 @@ error_code sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout)
if (timeout) if (timeout)
{ {
const u64 passed = get_system_time() - ppu.start_time; if (lv2_obj::wait_timeout(timeout, &ppu))
if (passed >= timeout)
{ {
std::lock_guard lock(rwlock->mutex); 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; ppu.gpr[3] = CELL_ETIMEDOUT;
break; break;
} }
thread_ctrl::wait_for(timeout - passed);
} }
else else
{ {

View File

@ -12,8 +12,6 @@ LOG_CHANNEL(sys_semaphore);
template<> DECLARE(ipc_manager<lv2_sema, u64>::g_ipc) {}; template<> DECLARE(ipc_manager<lv2_sema, u64>::g_ipc) {};
extern u64 get_system_time();
error_code sys_semaphore_create(ppu_thread& ppu, vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val) error_code sys_semaphore_create(ppu_thread& ppu, vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val)
{ {
vm::temporary_unlock(ppu); vm::temporary_unlock(ppu);
@ -134,9 +132,7 @@ error_code sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout)
if (timeout) if (timeout)
{ {
const u64 passed = get_system_time() - ppu.start_time; if (lv2_obj::wait_timeout(timeout, &ppu))
if (passed >= timeout)
{ {
std::lock_guard lock(sem->mutex); 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; ppu.gpr[3] = CELL_ETIMEDOUT;
break; break;
} }
thread_ctrl::wait_for(timeout - passed);
} }
else else
{ {

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "Utilities/mutex.h" #include "Utilities/mutex.h"
#include "Utilities/sema.h" #include "Utilities/sema.h"
@ -9,8 +9,10 @@
#include "Emu/Cell/ErrorCodes.h" #include "Emu/Cell/ErrorCodes.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/IPC.h" #include "Emu/IPC.h"
#include "Emu/System.h"
#include <deque> #include <deque>
#include <thread>
// attr_protocol (waiting scheduling policy) // attr_protocol (waiting scheduling policy)
enum enum
@ -213,6 +215,68 @@ struct lv2_obj
} }
} }
template<bool is_usleep = false>
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: private:
// Scheduler mutex // Scheduler mutex
static shared_mutex g_mutex; static shared_mutex g_mutex;

View File

@ -1,4 +1,4 @@
#include "stdafx.h" #include "stdafx.h"
#include "sys_time.h" #include "sys_time.h"
#include "Emu/System.h" #include "Emu/System.h"
@ -102,11 +102,9 @@ static int clock_gettime(int clk_id, struct timespec* tp)
#endif #endif
LOG_CHANNEL(sys_time); 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 // Auxiliary functions
u64 get_timebased_time() u64 get_timebased_time()
@ -118,12 +116,12 @@ u64 get_timebased_time()
const u64 time = count.QuadPart; const u64 time = count.QuadPart;
const u64 freq = s_time_aux_info.perf_freq; 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 #else
struct timespec ts; struct timespec ts;
verify(HERE), ::clock_gettime(CLOCK_MONOTONIC, &ts) == 0; verify(HERE), ::clock_gettime(CLOCK_MONOTONIC, &ts) == 0;
return static_cast<u64>(ts.tv_sec) * g_timebase_freq + static_cast<u64>(ts.tv_nsec) * g_timebase_freq / 1000000000u; return (static_cast<u64>(ts.tv_sec) * g_timebase_freq + static_cast<u64>(ts.tv_nsec) * g_timebase_freq / 1000000000ull) * g_cfg.core.clocks_scale / 100u;
#endif #endif
} }
@ -139,18 +137,24 @@ u64 get_system_time()
const u64 time = count.QuadPart; const u64 time = count.QuadPart;
const u64 freq = s_time_aux_info.perf_freq; 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 #else
struct timespec ts; struct timespec ts;
verify(HERE), ::clock_gettime(CLOCK_MONOTONIC, &ts) == 0; verify(HERE), ::clock_gettime(CLOCK_MONOTONIC, &ts) == 0;
const u64 result = static_cast<u64>(ts.tv_sec) * 1000000u + static_cast<u64>(ts.tv_nsec) / 1000u; const u64 result = static_cast<u64>(ts.tv_sec) * 1000000ull + static_cast<u64>(ts.tv_nsec) / 1000u;
#endif #endif
if (result) return result; 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 // Functions
s32 sys_time_get_timezone(vm::ptr<s32> timezone, vm::ptr<s32> summertime) s32 sys_time_get_timezone(vm::ptr<s32> timezone, vm::ptr<s32> summertime)
{ {
@ -171,24 +175,24 @@ s32 sys_time_get_current_time(vm::ptr<s64> sec, vm::ptr<s64> nsec)
verify(HERE), QueryPerformanceCounter(&count); verify(HERE), QueryPerformanceCounter(&count);
// get time difference in nanoseconds // 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 // 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) if (!sec)
{ {
return CELL_EFAULT; return CELL_EFAULT;
} }
*sec = time / 1000000000u; *sec = time / 1000000000ull;
if (!nsec) if (!nsec)
{ {
return CELL_EFAULT; return CELL_EFAULT;
} }
*nsec = time % 1000000000u; *nsec = time % 1000000000ull;
#else #else
struct timespec ts; struct timespec ts;
verify(HERE), ::clock_gettime(CLOCK_REALTIME, &ts) == 0; verify(HERE), ::clock_gettime(CLOCK_REALTIME, &ts) == 0;
@ -198,14 +202,14 @@ s32 sys_time_get_current_time(vm::ptr<s64> sec, vm::ptr<s64> nsec)
return CELL_EFAULT; 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) if (!nsec)
{ {
return CELL_EFAULT; return CELL_EFAULT;
} }
*nsec = ts.tv_nsec; *nsec = (ts.tv_nsec * g_cfg.core.clocks_scale / 100u) % 1000000000ull;
#endif #endif
return CELL_OK; return CELL_OK;

View File

@ -13,7 +13,7 @@
LOG_CHANNEL(sys_timer); LOG_CHANNEL(sys_timer);
extern u64 get_system_time(); extern u64 get_guest_system_time();
void lv2_timer_context::operator()() void lv2_timer_context::operator()()
{ {
@ -23,7 +23,7 @@ void lv2_timer_context::operator()()
if (_state == SYS_TIMER_STATE_RUN) if (_state == SYS_TIMER_STATE_RUN)
{ {
const u64 _now = get_system_time(); const u64 _now = get_guest_system_time();
const u64 next = expire; const u64 next = expire;
if (_now >= next) if (_now >= next)
@ -48,7 +48,7 @@ void lv2_timer_context::operator()()
} }
// TODO: use single global dedicated thread for busy waiting, no timer threads // 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) 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); 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) if (!period && start_time >= base_time)
{ {
@ -307,46 +307,13 @@ error_code sys_timer_usleep(ppu_thread& ppu, u64 sleep_time)
if (sleep_time) if (sleep_time)
{ {
#ifdef __linux__ lv2_obj::sleep(ppu, 0);
// 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
u64 passed = 0; lv2_obj::wait_timeout<true>(sleep_time);
u64 remaining;
lv2_obj::sleep(ppu, sleep_time); if (ppu.is_stopped())
while (sleep_time >= passed)
{ {
if (ppu.is_stopped()) return 0;
{
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);
} }
} }
else else

View File

@ -799,7 +799,7 @@ namespace rsx
u64 thread::timestamp() u64 thread::timestamp()
{ {
// Get timestamp, and convert it from microseconds to nanoseconds // 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) if (t != timestamp_ctrl)
{ {
timestamp_ctrl = t; timestamp_ctrl = t;

View File

@ -20,6 +20,7 @@
#include "Emu/Cell/lv2/sys_rsx.h" #include "Emu/Cell/lv2/sys_rsx.h"
extern u64 get_guest_system_time();
extern u64 get_system_time(); extern u64 get_system_time();
struct RSXIOTable struct RSXIOTable

View File

@ -275,6 +275,22 @@ void fmt_class_string<tsx_usage>::format(std::string& out, u64 arg)
}); });
} }
template <>
void fmt_class_string<sleep_timers_accuracy_level>::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 <> template <>
void fmt_class_string<enter_button_assign>::format(std::string& out, u64 arg) void fmt_class_string<enter_button_assign>::format(std::string& out, u64 arg)
{ {

View File

@ -8,6 +8,7 @@
#include <string> #include <string>
u64 get_system_time(); u64 get_system_time();
u64 get_guest_system_time();
enum class system_state enum class system_state
{ {
@ -47,6 +48,13 @@ enum class lib_loading_type
liblv2only liblv2only
}; };
enum sleep_timers_accuracy_level : u32
{
_as_host = 0,
_usleep,
_all_timers,
};
enum class keyboard_handler enum class keyboard_handler
{ {
null, null,
@ -406,6 +414,8 @@ struct cfg_root : cfg::node
cfg::set_entry load_libraries{this, "Load libraries"}; cfg::set_entry load_libraries{this, "Load libraries"};
cfg::_bool hle_lwmutex{this, "HLE lwmutex"}; // Force alternative lwmutex/lwcond implementation 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_level> 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}; } core{this};
struct node_vfs : cfg::node 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<0, 16> anisotropic_level_override{this, "Anisotropic Filter Override", 0};
cfg::_int<1, 1024> min_scalable_dimension{this, "Minimum Scalable Dimension", 16}; 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<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 struct node_d3d12 : cfg::node
{ {