mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-01 12:15:43 -06:00
threads: remove low level threads on windows (#4277)
This commit is contained in:
parent
9141c19302
commit
9ec75c32ad
@ -197,7 +197,11 @@ int PS4_SYSV_ABI posix_pthread_detach(PthreadT pthread) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RunThread(void* arg) {
|
#ifdef WIN32
|
||||||
|
static DWORD RunThread(void* arg) {
|
||||||
|
#else
|
||||||
|
static void* RunThread(void* arg) {
|
||||||
|
#endif
|
||||||
auto* curthread = static_cast<Pthread*>(arg);
|
auto* curthread = static_cast<Pthread*>(arg);
|
||||||
g_curthread = curthread;
|
g_curthread = curthread;
|
||||||
Common::SetCurrentThreadName(curthread->name.c_str());
|
Common::SetCurrentThreadName(curthread->name.c_str());
|
||||||
@ -214,6 +218,11 @@ static void RunThread(void* arg) {
|
|||||||
/* Remove thread from tracking */
|
/* Remove thread from tracking */
|
||||||
DebugState.RemoveCurrentThreadFromGuestList();
|
DebugState.RemoveCurrentThreadFromGuestList();
|
||||||
posix_pthread_exit(ret);
|
posix_pthread_exit(ret);
|
||||||
|
#ifdef WIN32
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_create_name_np(PthreadT* thread, const PthreadAttrT* attr,
|
int PS4_SYSV_ABI posix_pthread_create_name_np(PthreadT* thread, const PthreadAttrT* attr,
|
||||||
|
|||||||
@ -5,6 +5,19 @@
|
|||||||
_runOnAnotherStack:
|
_runOnAnotherStack:
|
||||||
pushq %r12
|
pushq %r12
|
||||||
pushq %r13
|
pushq %r13
|
||||||
|
#ifdef WIN32
|
||||||
|
pushq %r14
|
||||||
|
pushq %r15
|
||||||
|
|
||||||
|
# save stack check registers
|
||||||
|
movq %gs:0x08, %r14 # teb->stack_bottom
|
||||||
|
movq %gs:0x10, %r15 # teb->stack_top
|
||||||
|
|
||||||
|
# disable stack checks
|
||||||
|
xorq %rcx, %rcx
|
||||||
|
movq %rcx, %gs:0x08 # teb->stack_bottom = 0
|
||||||
|
movq %rcx, %gs:0x10 # teb->stack_top = 0
|
||||||
|
#endif
|
||||||
movq %rsp, %r12
|
movq %rsp, %r12
|
||||||
movq %rbp, %r13
|
movq %rbp, %r13
|
||||||
movq %rdx, %rsp
|
movq %rdx, %rsp
|
||||||
@ -12,6 +25,13 @@ _runOnAnotherStack:
|
|||||||
callq *%rsi
|
callq *%rsi
|
||||||
movq %r13, %rbp
|
movq %r13, %rbp
|
||||||
movq %r12, %rsp
|
movq %r12, %rsp
|
||||||
|
#ifdef WIN32
|
||||||
|
# restore stack check registers
|
||||||
|
movq %r14, %gs:0x08 # teb->stack_bottom
|
||||||
|
movq %r15, %gs:0x10 # teb->stack_top
|
||||||
|
popq %r15
|
||||||
|
popq %r14
|
||||||
|
#endif
|
||||||
popq %r13
|
popq %r13
|
||||||
popq %r12
|
popq %r12
|
||||||
ret
|
ret
|
||||||
|
|||||||
@ -19,67 +19,20 @@ namespace Core {
|
|||||||
static constexpr u32 ORBIS_MXCSR = 0x9fc0;
|
static constexpr u32 ORBIS_MXCSR = 0x9fc0;
|
||||||
static constexpr u32 ORBIS_FPUCW = 0x037f;
|
static constexpr u32 ORBIS_FPUCW = 0x037f;
|
||||||
|
|
||||||
#ifdef _WIN64
|
|
||||||
#define KGDT64_R3_DATA (0x28)
|
|
||||||
#define KGDT64_R3_CODE (0x30)
|
|
||||||
#define KGDT64_R3_CMTEB (0x50)
|
|
||||||
#define RPL_MASK (0x03)
|
|
||||||
#define EFLAGS_INTERRUPT_MASK (0x200)
|
|
||||||
|
|
||||||
void InitializeTeb(INITIAL_TEB* teb, void* stackaddr, size_t stacksize) {
|
|
||||||
teb->StackBase = (void*)((u64)stackaddr + stacksize);
|
|
||||||
teb->StackLimit = nullptr;
|
|
||||||
teb->StackAllocationBase = stackaddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeContext(CONTEXT* ctx, ThreadFunc func, void* arg, void* stackaddr,
|
|
||||||
size_t stacksize) {
|
|
||||||
/* Note: The stack has to be reversed */
|
|
||||||
ctx->Rsp = (u64)stackaddr + stacksize;
|
|
||||||
ctx->Rbp = (u64)stackaddr + stacksize;
|
|
||||||
ctx->Rcx = (u64)arg;
|
|
||||||
ctx->Rip = (u64)func;
|
|
||||||
|
|
||||||
ctx->SegGs = KGDT64_R3_DATA | RPL_MASK;
|
|
||||||
ctx->SegEs = KGDT64_R3_DATA | RPL_MASK;
|
|
||||||
ctx->SegDs = KGDT64_R3_DATA | RPL_MASK;
|
|
||||||
ctx->SegCs = KGDT64_R3_CODE | RPL_MASK;
|
|
||||||
ctx->SegSs = KGDT64_R3_DATA | RPL_MASK;
|
|
||||||
ctx->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
|
|
||||||
|
|
||||||
ctx->EFlags = 0x3000 | EFLAGS_INTERRUPT_MASK;
|
|
||||||
|
|
||||||
ctx->ContextFlags =
|
|
||||||
CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NativeThread::NativeThread() : native_handle{0} {}
|
NativeThread::NativeThread() : native_handle{0} {}
|
||||||
|
|
||||||
NativeThread::~NativeThread() {}
|
NativeThread::~NativeThread() {}
|
||||||
|
|
||||||
int NativeThread::Create(ThreadFunc func, void* arg) {
|
int NativeThread::Create(ThreadFunc func, void* arg) {
|
||||||
constexpr size_t stacksize = 8_KB;
|
|
||||||
init_stack_ptr = malloc(stacksize);
|
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
pthread_t* pthr = reinterpret_cast<pthread_t*>(&native_handle);
|
pthread_t* pthr = reinterpret_cast<pthread_t*>(&native_handle);
|
||||||
pthread_attr_t pattr;
|
return pthread_create(pthr, nullptr, func, arg);
|
||||||
pthread_attr_init(&pattr);
|
|
||||||
pthread_attr_setstack(&pattr, init_stack_ptr, stacksize);
|
|
||||||
return pthread_create(pthr, &pattr, (PthreadFunc)func, arg);
|
|
||||||
#else
|
#else
|
||||||
CLIENT_ID clientId{};
|
native_handle = CreateThread(nullptr, 0, func, arg, 0, nullptr);
|
||||||
INITIAL_TEB teb{};
|
if (native_handle == nullptr) {
|
||||||
CONTEXT ctx{};
|
return GetLastError();
|
||||||
|
}
|
||||||
clientId.UniqueProcess = GetCurrentProcess();
|
return 0;
|
||||||
clientId.UniqueThread = GetCurrentThread();
|
|
||||||
|
|
||||||
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);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,28 +44,8 @@ void NativeThread::Exit() {
|
|||||||
tid = 0;
|
tid = 0;
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
NtClose(native_handle);
|
|
||||||
native_handle = nullptr;
|
native_handle = nullptr;
|
||||||
|
ExitThread(0);
|
||||||
/* The Windows kernel will free the stack
|
|
||||||
given at thread creation via INITIAL_TEB
|
|
||||||
(StackAllocationBase) upon thread termination.
|
|
||||||
|
|
||||||
In earlier Windows versions (NT4 to Windows Server 2003),
|
|
||||||
you could get around this via disabling FreeStackOnTermination
|
|
||||||
on the TEB. This has been removed since then.
|
|
||||||
|
|
||||||
To avoid this, we must forcefully set the TEB
|
|
||||||
deallocation stack pointer to NULL so ZwFreeVirtualMemory fails
|
|
||||||
in the kernel and our stack is not freed.
|
|
||||||
*/
|
|
||||||
auto* teb = reinterpret_cast<TEB*>(NtCurrentTeb());
|
|
||||||
teb->DeallocationStack = nullptr;
|
|
||||||
|
|
||||||
if (init_stack_ptr != nullptr) {
|
|
||||||
free(init_stack_ptr);
|
|
||||||
}
|
|
||||||
NtTerminateThread(nullptr, 0);
|
|
||||||
#else
|
#else
|
||||||
// Disable and free the signal stack.
|
// Disable and free the signal stack.
|
||||||
constexpr stack_t sig_stack = {
|
constexpr stack_t sig_stack = {
|
||||||
@ -124,10 +57,6 @@ void NativeThread::Exit() {
|
|||||||
free(sig_stack_ptr);
|
free(sig_stack_ptr);
|
||||||
sig_stack_ptr = nullptr;
|
sig_stack_ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_stack_ptr != nullptr) {
|
|
||||||
free(init_stack_ptr);
|
|
||||||
}
|
|
||||||
pthread_exit(nullptr);
|
pthread_exit(nullptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,9 +10,11 @@ struct PthreadAttr;
|
|||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
#ifdef WIN32
|
||||||
using ThreadFunc = void (*)(void*);
|
using ThreadFunc = DWORD (*)(void*);
|
||||||
using PthreadFunc = void* (*)(void*);
|
#else
|
||||||
|
using ThreadFunc = void* (*)(void*);
|
||||||
|
#endif
|
||||||
|
|
||||||
class NativeThread {
|
class NativeThread {
|
||||||
public:
|
public:
|
||||||
@ -39,7 +41,6 @@ private:
|
|||||||
uintptr_t native_handle;
|
uintptr_t native_handle;
|
||||||
void* sig_stack_ptr = nullptr;
|
void* sig_stack_ptr = nullptr;
|
||||||
#endif
|
#endif
|
||||||
void* init_stack_ptr = nullptr;
|
|
||||||
u64 tid;
|
u64 tid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user