From e551e2bc5d0970eef6e90bb4d9b6af835fae27e9 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 21 Aug 2015 14:07:31 +0300 Subject: [PATCH] Bugfix --- Utilities/GNU.h | 4 +--- Utilities/StrFmt.h | 14 ++++++----- Utilities/Thread.cpp | 13 ++++++++--- Utilities/Thread.h | 17 ++++++++++++-- rpcs3/Emu/Cell/PPUThread.cpp | 20 ++++++++++------ rpcs3/Emu/SysCalls/Modules/cellFs.cpp | 12 +++++++++- rpcs3/Emu/SysCalls/Modules/cellGame.cpp | 4 ++-- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 6 ++--- rpcs3/Emu/SysCalls/Modules/sys_net.cpp | 11 +++++++-- rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp | 12 +++++----- rpcs3/Loader/ELF64.cpp | 4 ++-- rpcs3/stdafx.h | 27 ++++++++++++++++++++++ 12 files changed, 107 insertions(+), 37 deletions(-) diff --git a/Utilities/GNU.h b/Utilities/GNU.h index 2e79a8dd8ab5..d6e21fdf20d7 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -28,8 +28,6 @@ #if defined(_MSC_VER) && _MSC_VER <= 1800 #define alignas(x) _CRT_ALIGN(x) -#elif defined(__GNUG__) -#define ALIGN(x) __attribute__((aligned(x))) // not used #endif #if defined(__GNUG__) @@ -83,7 +81,7 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp); #endif /* __GNUG__ */ #if defined(_MSC_VER) -// Unsigned 128-bit number implementation +// Unsigned 128-bit integer implementation struct alignas(16) uint128_t { uint64_t lo, hi; diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 153b345f854d..541f1007f506 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -248,7 +248,7 @@ namespace fmt // pointer to the current buffer char* buf_addr = fixed_buf.data(); - for (std::size_t buf_size = fixed_buf.size();; buf_size *= 2, buf.reset(buf_addr = new char[buf_size])) + for (std::size_t buf_size = fixed_buf.size();; buf.reset(buf_addr = new char[buf_size])) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-security" @@ -256,10 +256,17 @@ namespace fmt #pragma GCC diagnostic pop + if (len > INT_MAX) + { + throw std::runtime_error("std::snprintf() failed"); + } + if (len <= buf_size) { return{ buf_addr, len }; } + + buf_size = len; } } @@ -285,11 +292,6 @@ namespace fmt std::memcpy(message.get(), other, size + 1); } - exception(exception&& other) - { - message = std::move(other.message); - } - operator const char*() const { return message.get(); diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 5c6757c131d8..bdc740374abf 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1196,7 +1196,7 @@ const thread_ctrl_t* get_current_thread_ctrl() std::string thread_ctrl_t::get_name() const { - return name(); + return m_name(); } named_thread_t::named_thread_t(std::function name, std::function func) @@ -1220,12 +1220,12 @@ std::string named_thread_t::get_name() const throw EXCEPTION("Invalid thread"); } - if (!m_thread->name) + if (!m_thread->m_name) { throw EXCEPTION("Invalid name getter"); } - return m_thread->name(); + return m_thread->m_name(); } std::atomic g_thread_count{ 0 }; @@ -1296,6 +1296,13 @@ void named_thread_t::start(std::function name, std::functionm_atexit) + { + func(); + + func = nullptr; + } + vm::reservation_free(); g_thread_count--; diff --git a/Utilities/Thread.h b/Utilities/Thread.h index 6b21b86bb4c7..a2df0e3cf846 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -7,15 +7,20 @@ class thread_ctrl_t final { friend class named_thread_t; + template friend void current_thread_register_atexit(T); + // thread handler std::thread m_thread; // name getter - const std::function name; + const std::function m_name; + + // functions executed at thread exit (temporarily) + std::vector> m_atexit; public: thread_ctrl_t(std::function name) - : name(std::move(name)) + : m_name(std::move(name)) { } @@ -23,6 +28,14 @@ class thread_ctrl_t final std::string get_name() const; }; +// register function at thread exit (temporarily) +template void current_thread_register_atexit(T func) +{ + extern thread_local thread_ctrl_t* g_tls_this_thread; + + g_tls_this_thread->m_atexit.emplace_back(func); +} + class named_thread_t { // pointer to managed resource (shared with actual thread) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index a8a98abf9870..cf2d6cf8c6ca 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -25,7 +25,8 @@ u64 rotate_mask[64][64]; extern u32 ppu_get_tls(u32 thread); extern void ppu_free_tls(u32 thread); -thread_local const std::weak_ptr g_tls_ppu_decoder_cache = fxm::get(); +//thread_local const std::weak_ptr g_tls_ppu_decoder_cache = fxm::get(); +thread_local const ppu_decoder_cache_t* g_tls_ppu_decoder_cache = nullptr; // temporarily, because thread_local is not fully available ppu_decoder_cache_t::ppu_decoder_cache_t() #ifdef _WIN32 @@ -285,14 +286,19 @@ void PPUThread::task() return custom_task(*this); } - const auto decoder_cache = g_tls_ppu_decoder_cache.lock(); - - if (!decoder_cache) + if (!g_tls_ppu_decoder_cache) { - throw EXCEPTION("PPU Decoder Cache not initialized"); - } + const auto decoder_cache = fxm::get(); + + if (!decoder_cache) + { + throw EXCEPTION("PPU Decoder Cache not initialized"); + } - const auto exec_map = decoder_cache->pointer; + g_tls_ppu_decoder_cache = decoder_cache.get(); // unsafe (TODO) + } + + const auto exec_map = g_tls_ppu_decoder_cache->pointer; if (m_dec) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellFs.cpp b/rpcs3/Emu/SysCalls/Modules/cellFs.cpp index 51502a74ddad..02a887dce459 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellFs.cpp @@ -833,7 +833,17 @@ s32 cellFsSdataOpen(PPUThread& ppu, vm::cptr path, s32 flags, vm::ptr return CELL_FS_EINVAL; } - return cellFsOpen(path, CELL_FS_O_RDONLY, fd, vm::var(ppu), 8); + struct _arg_t + { + be_t a, b; + }; + + const vm::var<_arg_t> _arg(ppu); + + _arg->a = 0x180; + _arg->b = 0x10; + + return cellFsOpen(path, CELL_FS_O_RDONLY, fd, _arg, 8); // Don't implement sdata decryption in this function, it should be done in sys_fs_open() syscall or somewhere else diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index 692a2d7055fe..d91992c1d1ba 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -314,7 +314,7 @@ s32 cellGameDataCheck(u32 type, vm::cptr dirName, vm::ptr dirName // TODO: output errors (errDialog) - const std::string dir = std::string("/dev_hdd0/game/") + dirName.get_ptr(); + const std::string dir = "/dev_hdd0/game/"s + dirName.get_ptr(); if (!Emu.GetVFS().ExistsDir(dir)) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index c5bb50ec3208..bfd41f5d7d26 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -212,7 +212,7 @@ s32 cellSysCacheClear(void) } std::string localPath; - Emu.GetVFS().GetDevice(std::string("/dev_hdd1/cache/"), localPath); + Emu.GetVFS().GetDevice("/dev_hdd1/cache/", localPath); // TODO: Write tests to figure out, what is deleted. @@ -226,9 +226,9 @@ s32 cellSysCacheMount(vm::ptr param) // TODO: implement char id[CELL_SYSCACHE_ID_SIZE]; strncpy(id, param->cacheId, CELL_SYSCACHE_ID_SIZE); - strncpy(param->getCachePath, ("/dev_hdd1/cache/" + std::string(id) + "/").c_str(), CELL_SYSCACHE_PATH_MAX); + strncpy(param->getCachePath, ("/dev_hdd1/cache/"s + id + "/").c_str(), CELL_SYSCACHE_PATH_MAX); param->getCachePath[CELL_SYSCACHE_PATH_MAX - 1] = '\0'; - Emu.GetVFS().CreateDir(std::string(param->getCachePath)); + Emu.GetVFS().CreateDir(param->getCachePath); g_sysutil->cacheMounted.exchange(true); return CELL_SYSCACHE_RET_OK_RELAYED; diff --git a/rpcs3/Emu/SysCalls/Modules/sys_net.cpp b/rpcs3/Emu/SysCalls/Modules/sys_net.cpp index bad9b5a4ac57..034381eb657f 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_net.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_net.cpp @@ -118,13 +118,20 @@ namespace sys_net be_t _h_errno; }; - thread_local vm::var<_tls_data_t, vm::page_alloc_t> g_tls_net_data; + // TODO + thread_local vm::ptr<_tls_data_t> g_tls_net_data{}; inline void initialize_tls() { + // allocate if not initialized if (!g_tls_net_data) { - g_tls_net_data = { vm::main }; // allocate if not initialized + g_tls_net_data.set(vm::alloc(sizeof(decltype(g_tls_net_data)::type), vm::main)); + + current_thread_register_atexit([addr = g_tls_net_data.addr()] + { + vm::dealloc_verbose_nothrow(addr, vm::main); + }); } } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp index bd21fd963920..65d757a8e5ff 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp @@ -40,9 +40,9 @@ s32 sys_mmapper_allocate_address(u64 size, u64 flags, u64 alignment, vm::ptr(alignment)) + for (u64 addr = ::align(0x30000000, alignment); addr < 0xC0000000; addr += alignment) { - if (const auto area = vm::map(addr, static_cast(size), flags)) + if (const auto area = vm::map(static_cast(addr), static_cast(size), flags)) { *alloc_addr = addr; @@ -273,9 +273,9 @@ s32 sys_mmapper_map_memory(u32 addr, u32 mem_id, u64 flags) return CELL_EALIGN; } - if (mem->addr) + if (const u32 old_addr = mem->addr.load()) { - throw EXCEPTION("Already mapped (mem_id=0x%x, addr=0x%x)", mem_id, mem->addr.load()); + throw EXCEPTION("Already mapped (mem_id=0x%x, addr=0x%x)", mem_id, old_addr); } if (!area->falloc(addr, mem->size)) @@ -322,7 +322,7 @@ s32 sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, vm::ptr mem_id) { - sys_mmapper.Todo("sys_mmapper_unmap_memory(addr=0x%x, mem_id=*0x%x)", addr, mem_id); + sys_mmapper.Error("sys_mmapper_unmap_memory(addr=0x%x, mem_id=*0x%x)", addr, mem_id); LV2_LOCK; @@ -339,7 +339,7 @@ s32 sys_mmapper_unmap_memory(u32 addr, vm::ptr mem_id) { if (!area->dealloc(addr)) { - throw EXCEPTION("Not mapped (mem_id=0x%x, addr=0x%x)", mem->id, addr); + throw EXCEPTION("Deallocation failed (mem_id=0x%x, addr=0x%x)", mem->id, addr); } mem->addr = 0; diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index 02058aa8fe24..b656f28b6688 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -148,7 +148,7 @@ namespace loader char name[27]; m_stream->Seek(handler::get_stream_offset() + phdr.p_offset + lib.name_addr); m_stream->Read(name, sizeof(name)); - modulename = std::string(name); + modulename = name; LOG_WARNING(LOADER, "**** Exported: %s", name); } @@ -185,7 +185,7 @@ namespace loader char name[27]; m_stream->Seek(handler::get_stream_offset() + phdr.p_offset + lib.name_addr); m_stream->Read(name, sizeof(name)); - modulename = std::string(name); + modulename = name; LOG_WARNING(LOADER, "**** Imported: %s", name); } diff --git a/rpcs3/stdafx.h b/rpcs3/stdafx.h index 69d8849fd9f9..ee829d5339fb 100644 --- a/rpcs3/stdafx.h +++ b/rpcs3/stdafx.h @@ -41,12 +41,15 @@ #include #include +using namespace std::string_literals; + #include "Utilities/GNU.h" #define CHECK_SIZE(type, size) static_assert(sizeof(type) == size, "Invalid " #type " type size") #define CHECK_ALIGN(type, align) static_assert(__alignof(type) == align, "Invalid " #type " type alignment") #define CHECK_MAX_SIZE(type, size) static_assert(sizeof(type) <= size, #type " type size is too big") #define CHECK_SIZE_ALIGN(type, size, align) CHECK_SIZE(type, size); CHECK_ALIGN(type, align) +#define CHECK_ASCENDING(constexpr_array) static_assert(::is_ascending(constexpr_array), #constexpr_array " is not sorted in ascending order") using uint = unsigned int; @@ -107,6 +110,18 @@ template inline void strcpy_trunc(char(&dst)[N], dst[count] = '\0'; } +// returns true if all array elements are unique and sorted in ascending order +template constexpr bool is_ascending(const T(&array)[N], std::size_t from = 0) +{ + return from >= N - 1 ? true : array[from] < array[from + 1] ? is_ascending(array, from + 1) : false; +} + +// get (first) array element equal to `value` or nullptr if not found +template constexpr const T* static_search(const T(&array)[N], const T2& value, std::size_t from = 0) +{ + return from >= N ? nullptr : array[from] == value ? array + from : static_search(array, value, from + 1); +} + // bool wrapper for restricting bool result conversions struct explicit_bool_t { @@ -123,6 +138,18 @@ struct explicit_bool_t } }; +template struct triplet_t +{ + T1 first; + T2 second; + T3 third; + + constexpr bool operator ==(const T1& right) const + { + return first == right; + } +}; + // return 32 bit sizeof() to avoid widening/narrowing conversions with size_t #define sizeof32(type) static_cast(sizeof(type))