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:
parent
d17be2c2ec
commit
85b1152e29
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user