From f4e85af53c12da2579561824f23cff57eb3b7de6 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 30 May 2022 22:24:25 +0200 Subject: [PATCH] sceNpUtil: implement skeleton bandwidth test --- rpcs3/Emu/Cell/Modules/sceNpUtil.cpp | 124 +++++++++++++++++++++++---- rpcs3/Emu/Cell/Modules/sceNpUtil.h | 8 +- 2 files changed, 106 insertions(+), 26 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp b/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp index 2370a63cfe..7b2359b946 100644 --- a/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp @@ -7,46 +7,125 @@ LOG_CHANNEL(sceNpUtil); -error_code sceNpUtilBandwidthTestInitStart(u32 prio, u64 stack) +struct bandwidth_test +{ + atomic_t status = SCE_NP_UTIL_BANDWIDTH_TEST_STATUS_NONE; + atomic_t abort = false; + atomic_t shutdown = false; + atomic_t finished = false; + SceNpUtilBandwidthTestResult test_result{}; + + static constexpr auto thread_name = "HLE SceNpBandwidthTest"sv; + + void operator()() + { + status = SCE_NP_UTIL_BANDWIDTH_TEST_STATUS_RUNNING; + u32 fake_sleep_count = 0; + + while (thread_ctrl::state() != thread_state::aborting) + { + if (abort || shutdown) + { + break; + } + + // TODO: run proper bandwidth test, probably with cellHttp + + thread_ctrl::wait_for(1000); // wait 1ms + + if (fake_sleep_count++ > 100) // end fake bandwidth test after 100 ms + { + break; + } + } + + test_result.upload_bps = 16000.0; + test_result.download_bps = 16000.0; + test_result.result = CELL_OK; + status = SCE_NP_UTIL_BANDWIDTH_TEST_STATUS_FINISHED; + finished = true; + } +}; + +struct sce_np_util_manager +{ + shared_mutex mtx{}; + std::unique_ptr> bandwidth_test_thread; + + ~sce_np_util_manager() + { + join_thread(); + } + + void join_thread() + { + if (bandwidth_test_thread) + { + auto& thread = *bandwidth_test_thread; + thread = thread_state::aborting; + thread(); + bandwidth_test_thread.reset(); + } + } +}; + +error_code sceNpUtilBandwidthTestInitStart(ppu_thread& ppu, u32 prio, u32 stack) { sceNpUtil.todo("sceNpUtilBandwidthTestInitStart(prio=%d, stack=%d)", prio, stack); auto& util_manager = g_fxo->get(); + std::lock_guard lock(util_manager.mtx); - if (util_manager.is_initialized) + if (util_manager.bandwidth_test_thread) { return SCE_NP_ERROR_ALREADY_INITIALIZED; } - util_manager.is_initialized = true; + util_manager.bandwidth_test_thread = std::make_unique>(); return CELL_OK; } error_code sceNpUtilBandwidthTestGetStatus() { - sceNpUtil.todo("sceNpUtilBandwidthTestGetStatus()"); - - if (!g_fxo->get().is_initialized) - { - return SCE_NP_ERROR_NOT_INITIALIZED; - } - - return not_an_error(SCE_NP_UTIL_BANDWIDTH_TEST_STATUS_FINISHED); -} - -error_code sceNpUtilBandwidthTestShutdown(vm::ptr result) -{ - sceNpUtil.todo("sceNpUtilBandwidthTestShutdown(result=*0x%x)", result); + sceNpUtil.notice("sceNpUtilBandwidthTestGetStatus()"); auto& util_manager = g_fxo->get(); + std::lock_guard lock(util_manager.mtx); - if (!util_manager.is_initialized) + if (!util_manager.bandwidth_test_thread) { return SCE_NP_ERROR_NOT_INITIALIZED; } - util_manager.is_initialized = false; + return not_an_error(util_manager.bandwidth_test_thread->status); +} + +error_code sceNpUtilBandwidthTestShutdown(ppu_thread& ppu, vm::ptr result) +{ + sceNpUtil.warning("sceNpUtilBandwidthTestShutdown(result=*0x%x)", result); + + auto& util_manager = g_fxo->get(); + std::lock_guard lock(util_manager.mtx); + + if (!util_manager.bandwidth_test_thread) + { + return SCE_NP_ERROR_NOT_INITIALIZED; + } + + util_manager.bandwidth_test_thread->shutdown = true; + + while (!util_manager.bandwidth_test_thread->finished) + { + thread_ctrl::wait_for(1000); + } + + if (result) // TODO: what happens when this is null ? + { + *result = util_manager.bandwidth_test_thread->test_result; + } + + util_manager.join_thread(); return CELL_OK; } @@ -55,11 +134,18 @@ error_code sceNpUtilBandwidthTestAbort() { sceNpUtil.todo("sceNpUtilBandwidthTestAbort()"); - if (!g_fxo->get().is_initialized) + auto& util_manager = g_fxo->get(); + std::lock_guard lock(util_manager.mtx); + + if (!util_manager.bandwidth_test_thread) { return SCE_NP_ERROR_NOT_INITIALIZED; } + // TODO: cellHttpTransactionAbortConnection(); + + util_manager.bandwidth_test_thread->abort = true; + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/sceNpUtil.h b/rpcs3/Emu/Cell/Modules/sceNpUtil.h index b81ab5d7ac..290b9d1a3d 100644 --- a/rpcs3/Emu/Cell/Modules/sceNpUtil.h +++ b/rpcs3/Emu/Cell/Modules/sceNpUtil.h @@ -12,11 +12,5 @@ struct SceNpUtilBandwidthTestResult be_t upload_bps; be_t download_bps; be_t result; -}; - -// fxm objects - -struct sce_np_util_manager -{ - atomic_t is_initialized = false; + s8 padding[4]; };