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:
Vladislav Mikhalin 2026-04-18 16:17:48 +03:00 committed by GitHub
parent 685d5f9df9
commit beba435a09
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 56 additions and 39 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View 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

View File

@ -147,7 +147,6 @@ void Linker::Execute(const std::vector<std::string>& args) {
}
}
params.entry_addr = module->GetEntryAddress();
Libraries::Kernel::ClearStack();
RunMainEntry(&params);
});
}

View File

@ -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
}

View File

@ -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;
};