diff --git a/rpcs3/Emu/Cell/lv2/sys_sync.h b/rpcs3/Emu/Cell/lv2/sys_sync.h index 61fba830bb..7585583937 100644 --- a/rpcs3/Emu/Cell/lv2/sys_sync.h +++ b/rpcs3/Emu/Cell/lv2/sys_sync.h @@ -122,6 +122,12 @@ struct lv2_obj sleep_timeout(thread, timeout); } + static void yield(cpu_thread& thread) + { + vm::temporary_unlock(thread); + awake(thread, -4); + } + // Schedule the thread static void awake(cpu_thread&, u32 prio); diff --git a/rpcs3/Emu/Cell/lv2/sys_timer.cpp b/rpcs3/Emu/Cell/lv2/sys_timer.cpp index bcd81a99d7..bf3103b03f 100644 --- a/rpcs3/Emu/Cell/lv2/sys_timer.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_timer.cpp @@ -294,14 +294,28 @@ error_code sys_timer_usleep(ppu_thread& ppu, u64 sleep_time) sys_timer.trace("sys_timer_usleep(sleep_time=0x%llx)", sleep_time); - u64 passed = 0; - - lv2_obj::sleep(ppu, std::max(1, sleep_time)); - - while (sleep_time >= passed) + if (sleep_time) { - thread_ctrl::wait_for(std::max(1, sleep_time - passed)); - passed = get_system_time() - ppu.start_time; + u64 passed = 0; + u64 remaining; + + lv2_obj::sleep(ppu, sleep_time); + + while (sleep_time > passed) + { + remaining = sleep_time - passed; + + if (remaining > 500) + thread_ctrl::wait_for(remaining - (remaining % 500)); + else + busy_wait(4000); + + passed = (get_system_time() - ppu.start_time); + } + } + else + { + lv2_obj::yield(ppu); } return CELL_OK;