diff --git a/src/core/libraries/avplayer/avplayer_impl.cpp b/src/core/libraries/avplayer/avplayer_impl.cpp index 138747da4..db32862ad 100644 --- a/src/core/libraries/avplayer/avplayer_impl.cpp +++ b/src/core/libraries/avplayer/avplayer_impl.cpp @@ -12,28 +12,28 @@ void* PS4_SYSV_ABI AvPlayer::Allocate(void* handle, u32 alignment, u32 size) { const auto* const self = reinterpret_cast(handle); const auto allocate = self->m_init_data_original.memory_replacement.allocate; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - return Core::ExecuteGuest(allocate, ptr, alignment, size); + return allocate(ptr, alignment, size); } void PS4_SYSV_ABI AvPlayer::Deallocate(void* handle, void* memory) { const auto* const self = reinterpret_cast(handle); const auto deallocate = self->m_init_data_original.memory_replacement.deallocate; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - return Core::ExecuteGuest(deallocate, ptr, memory); + return deallocate(ptr, memory); } void* PS4_SYSV_ABI AvPlayer::AllocateTexture(void* handle, u32 alignment, u32 size) { const auto* const self = reinterpret_cast(handle); const auto allocate = self->m_init_data_original.memory_replacement.allocate_texture; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - return Core::ExecuteGuest(allocate, ptr, alignment, size); + return allocate(ptr, alignment, size); } void PS4_SYSV_ABI AvPlayer::DeallocateTexture(void* handle, void* memory) { const auto* const self = reinterpret_cast(handle); const auto deallocate = self->m_init_data_original.memory_replacement.deallocate_texture; const auto ptr = self->m_init_data_original.memory_replacement.object_ptr; - return Core::ExecuteGuest(deallocate, ptr, memory); + return deallocate(ptr, memory); } int PS4_SYSV_ABI AvPlayer::OpenFile(void* handle, const char* filename) { @@ -42,7 +42,7 @@ int PS4_SYSV_ABI AvPlayer::OpenFile(void* handle, const char* filename) { const auto open = self->m_init_data_original.file_replacement.open; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - return Core::ExecuteGuest(open, ptr, filename); + return open(ptr, filename); } int PS4_SYSV_ABI AvPlayer::CloseFile(void* handle) { @@ -51,7 +51,7 @@ int PS4_SYSV_ABI AvPlayer::CloseFile(void* handle) { const auto close = self->m_init_data_original.file_replacement.close; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - return Core::ExecuteGuest(close, ptr); + return close(ptr); } int PS4_SYSV_ABI AvPlayer::ReadOffsetFile(void* handle, u8* buffer, u64 position, u32 length) { @@ -60,7 +60,7 @@ int PS4_SYSV_ABI AvPlayer::ReadOffsetFile(void* handle, u8* buffer, u64 position const auto read_offset = self->m_init_data_original.file_replacement.read_offset; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - return Core::ExecuteGuest(read_offset, ptr, buffer, position, length); + return read_offset(ptr, buffer, position, length); } u64 PS4_SYSV_ABI AvPlayer::SizeFile(void* handle) { @@ -69,7 +69,7 @@ u64 PS4_SYSV_ABI AvPlayer::SizeFile(void* handle) { const auto size = self->m_init_data_original.file_replacement.size; const auto ptr = self->m_init_data_original.file_replacement.object_ptr; - return Core::ExecuteGuest(size, ptr); + return size(ptr); } AvPlayerInitData AvPlayer::StubInitData(const AvPlayerInitData& data) { diff --git a/src/core/libraries/avplayer/avplayer_state.cpp b/src/core/libraries/avplayer/avplayer_state.cpp index e1b11840e..dbaa36d18 100644 --- a/src/core/libraries/avplayer/avplayer_state.cpp +++ b/src/core/libraries/avplayer/avplayer_state.cpp @@ -92,7 +92,7 @@ void AvPlayerState::DefaultEventCallback(void* opaque, AvPlayerEvents event_id, const auto callback = self->m_event_replacement.event_callback; const auto ptr = self->m_event_replacement.object_ptr; if (callback != nullptr) { - Core::ExecuteGuest(callback, ptr, event_id, 0, event_data); + callback(ptr, event_id, 0, event_data); } } diff --git a/src/core/libraries/ime/ime.cpp b/src/core/libraries/ime/ime.cpp index 258cc61e1..96ae446fa 100644 --- a/src/core/libraries/ime/ime.cpp +++ b/src/core/libraries/ime/ime.cpp @@ -99,16 +99,16 @@ public: if (m_ime_mode) { OrbisImeParam param = m_param.ime; if (use_param_handler) { - Core::ExecuteGuest(param.handler, param.arg, event); + param.handler(param.arg, event); } else { - Core::ExecuteGuest(handler, param.arg, event); + handler(param.arg, event); } } else { OrbisImeKeyboardParam param = m_param.key; if (use_param_handler) { - Core::ExecuteGuest(param.handler, param.arg, event); + param.handler(param.arg, event); } else { - Core::ExecuteGuest(handler, param.arg, event); + handler(param.arg, event); } } } diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index 4a95c60c9..9611e7c49 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -131,8 +131,7 @@ bool ImeDialogState::CallTextFilter() { return false; } - int ret = - Core::ExecuteGuest(text_filter, out_text, &out_text_length, src_text, src_text_length); + int ret = text_filter(out_text, &out_text_length, src_text, src_text_length); if (ret != 0) { return false; @@ -153,7 +152,7 @@ bool ImeDialogState::CallKeyboardFilter(const OrbisImeKeycode* src_keycode, u16* return true; } - int ret = Core::ExecuteGuest(keyboard_filter, src_keycode, out_keycode, out_status, nullptr); + int ret = keyboard_filter(src_keycode, out_keycode, out_status, nullptr); return ret == 0; } diff --git a/src/core/libraries/kernel/threads.cpp b/src/core/libraries/kernel/threads.cpp index 082a52b67..083dc8ee1 100644 --- a/src/core/libraries/kernel/threads.cpp +++ b/src/core/libraries/kernel/threads.cpp @@ -7,6 +7,17 @@ namespace Libraries::Kernel { +void PS4_SYSV_ABI ClearStack() { + void* const stackaddr_attr = Libraries::Kernel::g_curthread->attr.stackaddr_attr; + void* volatile sp; + asm("mov %%rsp, %0" : "=rm"(sp)); + // leave a safety net of 64 bytes for memset + const size_t size = ((uintptr_t)sp - (uintptr_t)stackaddr_attr) - 64; + void* volatile buf = alloca(size); + memset(buf, 0, size); + sp = nullptr; +} + void RegisterThreads(Core::Loader::SymbolsResolver* sym) { RegisterMutex(sym); RegisterCond(sym); diff --git a/src/core/libraries/kernel/threads.h b/src/core/libraries/kernel/threads.h index 42ab0b13f..81535352c 100644 --- a/src/core/libraries/kernel/threads.h +++ b/src/core/libraries/kernel/threads.h @@ -27,6 +27,7 @@ int PS4_SYSV_ABI posix_pthread_create(PthreadT* thread, const PthreadAttrT* attr PthreadEntryFunc start_routine, void* arg); int PS4_SYSV_ABI posix_pthread_join(PthreadT pthread, void** thread_return); +int PS4_SYSV_ABI posix_pthread_detach(PthreadT pthread); int PS4_SYSV_ABI posix_pthread_mutexattr_init(PthreadMutexAttrT* attr); int PS4_SYSV_ABI posix_pthread_mutexattr_settype(PthreadMutexAttrT* attr, PthreadMutexType type); @@ -40,6 +41,8 @@ int PS4_SYSV_ABI posix_pthread_mutex_destroy(PthreadMutexT* mutex); void RegisterThreads(Core::Loader::SymbolsResolver* sym); +void PS4_SYSV_ABI ClearStack(); + class Thread { public: explicit Thread() = default; diff --git a/src/core/libraries/kernel/threads/exception.cpp b/src/core/libraries/kernel/threads/exception.cpp index 0b27f2bd8..cf36da0cc 100644 --- a/src/core/libraries/kernel/threads/exception.cpp +++ b/src/core/libraries/kernel/threads/exception.cpp @@ -317,7 +317,7 @@ int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) { u64 res = NtQueueApcThreadEx(reinterpret_cast(thread->native_thr.GetHandle()), option, ExceptionHandler, (void*)thread->name.c_str(), - (void*)native_signum, nullptr); + (void*)(s64)native_signum, nullptr); ASSERT(res == 0); #endif return ORBIS_OK; diff --git a/src/core/libraries/kernel/threads/pthread.cpp b/src/core/libraries/kernel/threads/pthread.cpp index 20bd20f4b..da9e1600f 100644 --- a/src/core/libraries/kernel/threads/pthread.cpp +++ b/src/core/libraries/kernel/threads/pthread.cpp @@ -199,10 +199,17 @@ static void RunThread(void* arg) { g_curthread = curthread; Common::SetCurrentThreadName(curthread->name.c_str()); DebugState.AddCurrentThreadToGuestList(); + Core::InitializeTLS(); + + curthread->native_thr.Initialize(); + + // Clear the stack before running the guest thread + if (False(g_curthread->attr.flags & PthreadAttrFlags::StackUser)) { + ClearStack(); + } /* Run the current thread's start routine with argument: */ - curthread->native_thr.Initialize(); - void* ret = Core::ExecuteGuest(curthread->start_routine, curthread->arg); + void* ret = curthread->start_routine(curthread->arg); /* Remove thread from tracking */ DebugState.RemoveCurrentThreadFromGuestList(); diff --git a/src/core/libraries/kernel/threads/pthread_spec.cpp b/src/core/libraries/kernel/threads/pthread_spec.cpp index 094866a5a..38032f174 100644 --- a/src/core/libraries/kernel/threads/pthread_spec.cpp +++ b/src/core/libraries/kernel/threads/pthread_spec.cpp @@ -84,7 +84,7 @@ void _thread_cleanupspecific() { * destructor: */ lk.unlock(); - Core::ExecuteGuest(destructor, data); + destructor(data); lk.lock(); } } diff --git a/src/core/libraries/network/net_ctl_obj.cpp b/src/core/libraries/network/net_ctl_obj.cpp index a295477b6..a4081cd11 100644 --- a/src/core/libraries/network/net_ctl_obj.cpp +++ b/src/core/libraries/network/net_ctl_obj.cpp @@ -50,7 +50,7 @@ void NetCtlInternal::CheckCallback() { : ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED; for (const auto [func, arg] : callbacks) { if (func != nullptr) { - Core::ExecuteGuest(func, event, arg); + func(event, arg); } } } @@ -61,7 +61,7 @@ void NetCtlInternal::CheckNpToolkitCallback() { : ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED; for (const auto [func, arg] : nptool_callbacks) { if (func != nullptr) { - Core::ExecuteGuest(func, event, arg); + func(event, arg); } } } diff --git a/src/core/libraries/ngs2/ngs2.cpp b/src/core/libraries/ngs2/ngs2.cpp index 2f785f9a0..97d19c352 100644 --- a/src/core/libraries/ngs2/ngs2.cpp +++ b/src/core/libraries/ngs2/ngs2.cpp @@ -160,13 +160,13 @@ s32 PS4_SYSV_ABI sceNgs2SystemCreateWithAllocator(const OrbisNgs2SystemOption* o result = SystemSetup(option, &bufferInfo, 0, 0); if (result >= 0) { uintptr_t sysUserData = allocator->userData; - result = Core::ExecuteGuest(hostAlloc, &bufferInfo); + result = hostAlloc(&bufferInfo); if (result >= 0) { OrbisNgs2Handle* handleCopy = outHandle; result = SystemSetup(option, &bufferInfo, hostFree, handleCopy); if (result < 0) { if (hostFree) { - Core::ExecuteGuest(hostFree, &bufferInfo); + hostFree(&bufferInfo); } } } diff --git a/src/core/libraries/usbd/emulated/dimensions.cpp b/src/core/libraries/usbd/emulated/dimensions.cpp index 272f2f649..452968840 100644 --- a/src/core/libraries/usbd/emulated/dimensions.cpp +++ b/src/core/libraries/usbd/emulated/dimensions.cpp @@ -3,6 +3,9 @@ #include "dimensions.h" +#include "core/libraries/kernel/threads.h" +#include "core/tls.h" + #include #include @@ -619,22 +622,46 @@ libusb_transfer_status DimensionsBackend::HandleAsyncTransfer(libusb_transfer* t return LIBUSB_TRANSFER_COMPLETED; } +struct WriteThreadArgs { + DimensionsBackend* self; + libusb_transfer* transfer; +}; + +void* PS4_SYSV_ABI DimensionsBackend::WriteThread(void* arg) { + auto* args = reinterpret_cast(arg); + + auto* self = args->self; + auto* transfer = args->transfer; + + self->HandleAsyncTransfer(transfer); + + const u8 flags = transfer->flags; + transfer->status = LIBUSB_TRANSFER_COMPLETED; + transfer->actual_length = transfer->length; + if (transfer->callback) { + transfer->callback(transfer); + } + if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) { + libusb_free_transfer(transfer); + } + delete args; + return nullptr; +} + s32 DimensionsBackend::SubmitTransfer(libusb_transfer* transfer) { if (transfer->endpoint == 0x01) { - std::thread write_thread([this, transfer] { - HandleAsyncTransfer(transfer); + using namespace Libraries::Kernel; + + PthreadAttrT attr{}; + posix_pthread_attr_init(&attr); + PthreadT thread{}; + auto* args = new WriteThreadArgs(); + args->self = this; + args->transfer = transfer; + posix_pthread_create(&thread, &attr, HOST_CALL(DimensionsBackend::WriteThread), args); + posix_pthread_attr_destroy(&attr); + posix_pthread_detach(thread); - const u8 flags = transfer->flags; - transfer->status = LIBUSB_TRANSFER_COMPLETED; - transfer->actual_length = transfer->length; - if (transfer->callback) { - transfer->callback(transfer); - } - if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) { - libusb_free_transfer(transfer); - } - }); - write_thread.detach(); return LIBUSB_SUCCESS; } diff --git a/src/core/libraries/usbd/emulated/dimensions.h b/src/core/libraries/usbd/emulated/dimensions.h index d9573b5f4..bc409f7c3 100644 --- a/src/core/libraries/usbd/emulated/dimensions.h +++ b/src/core/libraries/usbd/emulated/dimensions.h @@ -103,6 +103,8 @@ protected: std::queue> m_queries; private: + static void* PS4_SYSV_ABI WriteThread(void* arg); + std::shared_ptr m_dimensions_toypad = std::make_shared(); std::array m_endpoint_out_extra = {0x09, 0x21, 0x11, 0x01, 0x00, 0x01, 0x22, 0x1d, 0x00}; diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 7a0653e9f..0b80ecacc 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -135,7 +135,8 @@ void Linker::Execute(const std::vector& args) { } } params.entry_addr = module->GetEntryAddress(); - ExecuteGuest(RunMainEntry, ¶ms); + Libraries::Kernel::ClearStack(); + RunMainEntry(¶ms); }); } @@ -379,8 +380,7 @@ void* Linker::TlsGetAddr(u64 module_index, u64 offset) { if (!addr) { // Module was just loaded by above code. Allocate TLS block for it. const u32 init_image_size = module->tls.init_image_size; - u8* dest = reinterpret_cast( - Core::ExecuteGuest(heap_api->heap_malloc, module->tls.image_size)); + u8* dest = reinterpret_cast(heap_api->heap_malloc(module->tls.image_size)); const u8* src = reinterpret_cast(module->tls.image_virtual_addr); std::memcpy(dest, src, init_image_size); std::memset(dest + init_image_size, 0, module->tls.image_size - init_image_size); @@ -412,7 +412,7 @@ void* Linker::AllocateTlsForThread(bool is_primary) { ASSERT_MSG(ret == 0, "Unable to allocate TLS+TCB for the primary thread"); } else { if (heap_api) { - addr_out = Core::ExecuteGuest(heap_api->heap_malloc, total_tls_size); + addr_out = heap_api->heap_malloc(total_tls_size); } else { addr_out = std::malloc(total_tls_size); } @@ -422,7 +422,7 @@ void* Linker::AllocateTlsForThread(bool is_primary) { void Linker::FreeTlsForNonPrimaryThread(void* pointer) { if (heap_api) { - Core::ExecuteGuest(heap_api->heap_free, pointer); + heap_api->heap_free(pointer); } else { std::free(pointer); } diff --git a/src/core/module.cpp b/src/core/module.cpp index 127e74293..7e9d74a09 100644 --- a/src/core/module.cpp +++ b/src/core/module.cpp @@ -97,7 +97,7 @@ Module::~Module() = default; s32 Module::Start(u64 args, const void* argp, void* param) { LOG_INFO(Core_Linker, "Module started : {}", name); const VAddr addr = dynamic_info.init_virtual_addr + GetBaseAddress(); - return ExecuteGuest(reinterpret_cast(addr), args, argp, param); + return reinterpret_cast(addr)(args, argp, param); } void Module::LoadModuleToMemory(u32& max_tls_index) { diff --git a/src/core/tls.cpp b/src/core/tls.cpp index 57ed20f38..8b926cb39 100644 --- a/src/core/tls.cpp +++ b/src/core/tls.cpp @@ -198,7 +198,7 @@ Tcb* GetTcbBase() { thread_local std::once_flag init_tls_flag; -void EnsureThreadInitialized() { +void InitializeTLS() { std::call_once(init_tls_flag, [] { SetTcbBase(Libraries::Kernel::g_curthread->tcb); }); } diff --git a/src/core/tls.h b/src/core/tls.h index 27de518ea..2d94488f7 100644 --- a/src/core/tls.h +++ b/src/core/tls.h @@ -43,30 +43,7 @@ void SetTcbBase(void* image_address); Tcb* GetTcbBase(); /// Makes sure TLS is initialized for the thread before entering guest. -void EnsureThreadInitialized(); - -template -#ifdef __clang__ -__attribute__((optnone)) -#else -__attribute__((optimize("O0"))) -#endif -void ClearStack() { - volatile void* buf = alloca(size); - memset(const_cast(buf), 0, size); - buf = nullptr; -} - -template -ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), CallArgs&&... args) { - EnsureThreadInitialized(); - // clear stack to avoid trash from EnsureThreadInitialized - auto* tcb = GetTcbBase(); - if (tcb != nullptr && tcb->tcb_fiber == nullptr) { - ClearStack<12_KB>(); - } - return func(std::forward(args)...); -} +void InitializeTLS(); template struct HostCallWrapperImpl;