mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-29 23:41:19 -06:00
separate thread init and run stacks (#4274)
* separate thread init and run stacks * copyrights * remove TEB setting * revert fibers * fix linux * remove unused variables
This commit is contained in:
parent
685d5f9df9
commit
beba435a09
@ -327,6 +327,7 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
|
||||
src/core/libraries/kernel/threads/sleepq.cpp
|
||||
src/core/libraries/kernel/threads/sleepq.h
|
||||
src/core/libraries/kernel/threads/stack.cpp
|
||||
src/core/libraries/kernel/threads/stack.s
|
||||
src/core/libraries/kernel/threads/tcb.cpp
|
||||
src/core/libraries/kernel/threads/pthread.h
|
||||
src/core/libraries/kernel/threads/thread_state.cpp
|
||||
@ -353,6 +354,8 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
|
||||
src/core/libraries/kernel/aio.h
|
||||
)
|
||||
|
||||
set_source_files_properties(src/core/libraries/kernel/threads/stack.s PROPERTIES COMPILE_OPTIONS -Wno-unused-command-line-argument)
|
||||
|
||||
set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
||||
src/core/libraries/network/http.h
|
||||
src/core/libraries/network/http_error.h
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/libraries/kernel/kernel.h"
|
||||
@ -7,17 +7,6 @@
|
||||
|
||||
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);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
@ -41,8 +41,6 @@ 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;
|
||||
|
||||
@ -12,6 +12,9 @@
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
extern "C" void* PS4_SYSV_ABI _runOnAnotherStack(void* arg, void* func,
|
||||
void* stackb) asm("_runOnAnotherStack");
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
||||
extern PthreadAttr PthreadAttrDefault;
|
||||
@ -203,13 +206,10 @@ static void RunThread(void* arg) {
|
||||
|
||||
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: */
|
||||
void* ret = curthread->start_routine(curthread->arg);
|
||||
auto* const stack =
|
||||
(void*)((size_t)curthread->attr.stackaddr_attr + curthread->attr.stacksize_attr);
|
||||
void* ret = _runOnAnotherStack(curthread->arg, (void*)curthread->start_routine, stack);
|
||||
|
||||
/* Remove thread from tracking */
|
||||
DebugState.RemoveCurrentThreadFromGuestList();
|
||||
@ -290,7 +290,7 @@ int PS4_SYSV_ABI posix_pthread_create_name_np(PthreadT* thread, const PthreadAtt
|
||||
|
||||
/* Create thread */
|
||||
new_thread->native_thr = Core::NativeThread();
|
||||
int ret = new_thread->native_thr.Create(RunThread, new_thread, &new_thread->attr);
|
||||
int ret = new_thread->native_thr.Create(RunThread, new_thread);
|
||||
|
||||
ASSERT_MSG(ret == 0, "Failed to create thread with error {}", ret);
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/assert.h"
|
||||
@ -70,6 +70,7 @@ int ThreadState::CreateStack(PthreadAttr* attr) {
|
||||
|
||||
/* A cached stack was found. Release the lock. */
|
||||
if (attr->stackaddr_attr != nullptr) {
|
||||
std::memset(attr->stackaddr_attr, 0, stacksize);
|
||||
thread_list_lock.unlock();
|
||||
return 0;
|
||||
}
|
||||
@ -112,6 +113,7 @@ int ThreadState::CreateStack(PthreadAttr* attr) {
|
||||
attr->stackaddr_attr = (void*)stackaddr;
|
||||
|
||||
if (attr->stackaddr_attr != nullptr) {
|
||||
std::memset(attr->stackaddr_attr, 0, stacksize);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
|
||||
17
src/core/libraries/kernel/threads/stack.s
Normal file
17
src/core/libraries/kernel/threads/stack.s
Normal file
@ -0,0 +1,17 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
.global _runOnAnotherStack
|
||||
_runOnAnotherStack:
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
movq %rsp, %r12
|
||||
movq %rbp, %r13
|
||||
movq %rdx, %rsp
|
||||
movq %rdx, %rbp
|
||||
callq *%rsi
|
||||
movq %r13, %rbp
|
||||
movq %r12, %rsp
|
||||
popq %r13
|
||||
popq %r12
|
||||
ret
|
||||
@ -147,7 +147,6 @@ void Linker::Execute(const std::vector<std::string>& args) {
|
||||
}
|
||||
}
|
||||
params.entry_addr = module->GetEntryAddress();
|
||||
Libraries::Kernel::ClearStack();
|
||||
RunMainEntry(¶ms);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/alignment.h"
|
||||
@ -26,17 +26,17 @@ static constexpr u32 ORBIS_FPUCW = 0x037f;
|
||||
#define RPL_MASK (0x03)
|
||||
#define EFLAGS_INTERRUPT_MASK (0x200)
|
||||
|
||||
void InitializeTeb(INITIAL_TEB* teb, const ::Libraries::Kernel::PthreadAttr* attr) {
|
||||
teb->StackBase = (void*)((u64)attr->stackaddr_attr + attr->stacksize_attr);
|
||||
void InitializeTeb(INITIAL_TEB* teb, void* stackaddr, size_t stacksize) {
|
||||
teb->StackBase = (void*)((u64)stackaddr + stacksize);
|
||||
teb->StackLimit = nullptr;
|
||||
teb->StackAllocationBase = attr->stackaddr_attr;
|
||||
teb->StackAllocationBase = stackaddr;
|
||||
}
|
||||
|
||||
void InitializeContext(CONTEXT* ctx, ThreadFunc func, void* arg,
|
||||
const ::Libraries::Kernel::PthreadAttr* attr) {
|
||||
void InitializeContext(CONTEXT* ctx, ThreadFunc func, void* arg, void* stackaddr,
|
||||
size_t stacksize) {
|
||||
/* Note: The stack has to be reversed */
|
||||
ctx->Rsp = (u64)attr->stackaddr_attr + attr->stacksize_attr;
|
||||
ctx->Rbp = (u64)attr->stackaddr_attr + attr->stacksize_attr;
|
||||
ctx->Rsp = (u64)stackaddr + stacksize;
|
||||
ctx->Rbp = (u64)stackaddr + stacksize;
|
||||
ctx->Rcx = (u64)arg;
|
||||
ctx->Rip = (u64)func;
|
||||
|
||||
@ -58,12 +58,14 @@ NativeThread::NativeThread() : native_handle{0} {}
|
||||
|
||||
NativeThread::~NativeThread() {}
|
||||
|
||||
int NativeThread::Create(ThreadFunc func, void* arg, const ::Libraries::Kernel::PthreadAttr* attr) {
|
||||
int NativeThread::Create(ThreadFunc func, void* arg) {
|
||||
constexpr size_t stacksize = 8_KB;
|
||||
init_stack_ptr = malloc(stacksize);
|
||||
#ifndef _WIN64
|
||||
pthread_t* pthr = reinterpret_cast<pthread_t*>(&native_handle);
|
||||
pthread_attr_t pattr;
|
||||
pthread_attr_init(&pattr);
|
||||
pthread_attr_setstack(&pattr, attr->stackaddr_attr, attr->stacksize_attr);
|
||||
pthread_attr_setstack(&pattr, init_stack_ptr, stacksize);
|
||||
return pthread_create(pthr, &pattr, (PthreadFunc)func, arg);
|
||||
#else
|
||||
CLIENT_ID clientId{};
|
||||
@ -73,8 +75,8 @@ int NativeThread::Create(ThreadFunc func, void* arg, const ::Libraries::Kernel::
|
||||
clientId.UniqueProcess = GetCurrentProcess();
|
||||
clientId.UniqueThread = GetCurrentThread();
|
||||
|
||||
InitializeTeb(&teb, attr);
|
||||
InitializeContext(&ctx, func, arg, attr);
|
||||
InitializeTeb(&teb, init_stack_ptr, stacksize);
|
||||
InitializeContext(&ctx, func, arg, init_stack_ptr, stacksize);
|
||||
|
||||
return NtCreateThread(&native_handle, THREAD_ALL_ACCESS, nullptr, GetCurrentProcess(),
|
||||
&clientId, &ctx, &teb, false);
|
||||
@ -107,6 +109,9 @@ void NativeThread::Exit() {
|
||||
auto* teb = reinterpret_cast<TEB*>(NtCurrentTeb());
|
||||
teb->DeallocationStack = nullptr;
|
||||
|
||||
if (init_stack_ptr != nullptr) {
|
||||
free(init_stack_ptr);
|
||||
}
|
||||
NtTerminateThread(nullptr, 0);
|
||||
#else
|
||||
// Disable and free the signal stack.
|
||||
@ -120,6 +125,9 @@ void NativeThread::Exit() {
|
||||
sig_stack_ptr = nullptr;
|
||||
}
|
||||
|
||||
if (init_stack_ptr != nullptr) {
|
||||
free(init_stack_ptr);
|
||||
}
|
||||
pthread_exit(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
@ -19,7 +19,7 @@ public:
|
||||
NativeThread();
|
||||
~NativeThread();
|
||||
|
||||
int Create(ThreadFunc func, void* arg, const ::Libraries::Kernel::PthreadAttr* attr);
|
||||
int Create(ThreadFunc func, void* arg);
|
||||
void Exit();
|
||||
|
||||
void Initialize();
|
||||
@ -37,8 +37,9 @@ private:
|
||||
void* native_handle;
|
||||
#else
|
||||
uintptr_t native_handle;
|
||||
void* sig_stack_ptr;
|
||||
void* sig_stack_ptr = nullptr;
|
||||
#endif
|
||||
void* init_stack_ptr = nullptr;
|
||||
u64 tid;
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user