From 267cd4ee2098b40a126522478a1f7c870b6d1ff0 Mon Sep 17 00:00:00 2001 From: Eladash Date: Sat, 26 Nov 2022 12:01:55 +0200 Subject: [PATCH] Improve error_code, make HDD1 errors be warnings --- Utilities/Thread.cpp | 2 +- rpcs3/Emu/Cell/ErrorCodes.h | 37 +++++++++++++++++++--------- rpcs3/Emu/Cell/lv2/sys_fs.cpp | 31 +++++++++++++++++------- rpcs3/Emu/System.cpp | 45 +++++++++++++++++++++++++++-------- 4 files changed, 85 insertions(+), 30 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index bd7e2650419a..980e798484bf 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -2065,7 +2065,7 @@ void thread_base::set_name(std::string name) u64 thread_base::finalize(thread_state result_state) noexcept { // Report pending errors - error_code::error_report(0, 0, 0, 0); + error_code::make_report(0, false, 0, 0, 0); #ifdef _WIN32 static thread_local ULONG64 tls_cycles{}; diff --git a/rpcs3/Emu/Cell/ErrorCodes.h b/rpcs3/Emu/Cell/ErrorCodes.h index 15e8a1fc3e3d..9d70e81e4008 100644 --- a/rpcs3/Emu/Cell/ErrorCodes.h +++ b/rpcs3/Emu/Cell/ErrorCodes.h @@ -3,6 +3,11 @@ #include "util/types.hpp" #include "Utilities/StrFmt.h" +struct error_is_warning +{ + bool value = true; +}; + // Error code type (return type), implements error reporting. class error_code { @@ -12,26 +17,35 @@ class error_code error_code() = default; // Implementation must be provided independently - static s32 error_report(s32 result, const char* fmt, const fmt_type_info* sup, const u64* args); + static s32 make_report(s32 result, bool is_warning, const char* fmt, const fmt_type_info* sup, const u64* args); + static void log_report(); + bool silence_report(); // Common constructor - template - error_code(const ET& value) - : value(error_report(static_cast(value), " : %s", fmt::type_info_v, fmt_args_t{fmt_unveil::get(value)})) + template requires requires (ET v) { static_cast(v); } + error_code(error_is_warning is_warning, const ET& value) noexcept + : value(make_report(static_cast(value), is_warning.value, " : %s", fmt::type_info_v, fmt_args_t{fmt_unveil::get(value)})) { } // Error constructor (2 args) - template - error_code(const ET& value, const T& arg) - : value(error_report(static_cast(value), " : %s, %s", fmt::type_info_v, fmt_args_t{fmt_unveil::get(value), fmt_unveil::get(arg)})) + template requires requires (ET v) { static_cast(v); } + error_code(error_is_warning is_warning, const ET& value, const T& arg) noexcept + : value(make_report(static_cast(value), is_warning.value, " : %s, %s", fmt::type_info_v, fmt_args_t{fmt_unveil::get(value), fmt_unveil::get(std::forward(arg))})) { } // Formatting constructor (error, format string, variadic list) - template requires (sizeof...(Args) > 0) - error_code(const ET& value, const const_str& fmt, const Args&... args) - : value(error_report(static_cast(value), fmt, fmt::type_info_v, fmt_args_t{fmt_unveil::get(args)...})) + template requires (sizeof...(Args) > 0) && (requires (ET v) { static_cast(v); }) + error_code(error_is_warning is_warning, const ET& value, const const_str& fmt, const Args&... args) noexcept + : value(make_report(static_cast(value), is_warning.value, fmt, fmt::type_info_v, fmt_args_t{fmt_unveil::get(std::forward(args))...})) + { + } + + // Not a warning constructor + template requires (!(std::is_same_v, error_is_warning> || ...)) + error_code(Args&&... args) noexcept + : error_code({false}, std::forward(args)...) { } @@ -51,7 +65,7 @@ enum CellNotAnError : s32 // Constructor specialization that doesn't trigger reporting template <> -constexpr FORCE_INLINE error_code::error_code(const CellNotAnError& value) +constexpr FORCE_INLINE error_code::error_code(CellNotAnError&& value) : value(value) { } @@ -71,6 +85,7 @@ struct ppu_gpr_cast_impl { static inline u64 to(const error_code& code) { + error_code::log_report(); return code; } diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index ff533d5cb0eb..b3b63faadca1 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -945,7 +945,7 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr path, s32 flags, vm::ptr< return not_an_error(CELL_EEXIST); } - return {error, path}; + return {error_is_warning{lv2_fs_object::get_mp(vpath) == &g_mp_sys_dev_hdd1}, error, path}; } if (const u32 id = idm::import([&ppath = ppath, &file = file, mode, flags, &real = real, &type = type]() -> std::shared_ptr @@ -1246,7 +1246,7 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr path, vm::ptr fd) { if (ext.empty()) { - return {CELL_ENOENT, path}; + return {error_is_warning{mp == &g_mp_sys_dev_hdd1}, CELL_ENOENT, path}; } break; @@ -1435,7 +1435,7 @@ error_code sys_fs_stat(ppu_thread& ppu, vm::cptr path, vm::ptr break; } - return {CELL_ENOENT, path}; + return {error_is_warning{mp == &g_mp_sys_dev_hdd1}, CELL_ENOENT, path}; } default: { @@ -1563,8 +1563,14 @@ error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr path, s32 mode) { switch (auto error = fs::g_tls_error) { - case fs::error::noent: return {CELL_ENOENT, path}; - case fs::error::exist: return {CELL_EEXIST, path}; + case fs::error::noent: + { + return {error_is_warning{mp == &g_mp_sys_dev_hdd1}, CELL_ENOENT, path}; + } + case fs::error::exist: + { + return {error_is_warning{}, CELL_EEXIST, path}; + } default: sys_fs.error("sys_fs_mkdir(): unknown error %s", error); } @@ -1737,7 +1743,10 @@ error_code sys_fs_unlink(ppu_thread& ppu, vm::cptr path) { switch (auto error = fs::g_tls_error) { - case fs::error::noent: return {CELL_ENOENT, path}; + case fs::error::noent: + { + return {error_is_warning{mp == &g_mp_sys_dev_hdd1}, CELL_ENOENT, path}; + } default: sys_fs.error("sys_fs_unlink(): unknown error %s", error); } @@ -2690,7 +2699,10 @@ error_code sys_fs_truncate(ppu_thread& ppu, vm::cptr path, u64 size) { switch (auto error = fs::g_tls_error) { - case fs::error::noent: return {CELL_ENOENT, path}; + case fs::error::noent: + { + return {error_is_warning{mp == &g_mp_sys_dev_hdd1}, CELL_ENOENT, path}; + } default: sys_fs.error("sys_fs_truncate(): unknown error %s", error); } @@ -2890,7 +2902,10 @@ error_code sys_fs_utime(ppu_thread& ppu, vm::cptr path, vm::cptr g_tls_error_stats; - static thread_local std::string g_tls_error_str; +static thread_local std::string g_tls_error_str; +static thread_local std::unordered_map g_tls_error_stats; +static thread_local bool g_tls_is_error_a_warning; +s32 error_code::make_report(s32 result, bool is_warning, const char* fmt, const fmt_type_info* sup, const u64* args) +{ if (!sup && !args) { if (!fmt) @@ -2776,7 +2777,6 @@ s32 error_code::error_report(s32 result, const char* fmt, const fmt_type_info* s ensure(fmt); - logs::channel* channel = &sys_log; const char* func = "Unknown function"; if (auto ppu = get_current_cpu_thread()) @@ -2789,6 +2789,7 @@ s32 error_code::error_report(s32 result, const char* fmt, const fmt_type_info* s // Format log message (use preallocated buffer) g_tls_error_str.clear(); + g_tls_is_error_a_warning = is_warning; fmt::append(g_tls_error_str, "'%s' failed with 0x%08x", func, result); // Add spacer between error and fmt if necessary @@ -2804,24 +2805,48 @@ s32 error_code::error_report(s32 result, const char* fmt, const fmt_type_info* s if (!g_tls_error_stats.empty()) { // Report and clean error state - error_report(0, nullptr, nullptr, nullptr); + make_report(0, false, nullptr, nullptr, nullptr); } - - channel->error("%s", g_tls_error_str); } else { const auto stat = ++g_tls_error_stats[g_tls_error_str]; - if (stat <= 3) + if (stat > 3) { - channel->error("%s [%u]", g_tls_error_str, stat); + g_tls_error_str.clear(); } } return result; } +void error_code::log_report() +{ + const bool is_warning = std::exchange(g_tls_is_error_a_warning, false); + + if (g_tls_error_str.empty()) + { + // No error + return; + } + + (is_warning ? sys_log.warning : sys_log.error)("%s", g_tls_error_str); + g_tls_error_str.clear(); +} + +bool error_code::silence_report() +{ + if (!g_tls_error_str.empty() && g_tls_error_str.ends_with(fmt::format("0x%08x", value))) + { + g_tls_error_str.clear(); + g_tls_is_error_a_warning = false; + return true; + } + + return false; +} + void Emulator::ConfigurePPUCache() const { auto& _main = g_fxo->get();