mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-29 23:41:19 -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;
|
||||
}
|
||||
|
||||
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);
|
||||
g_curthread = curthread;
|
||||
Common::SetCurrentThreadName(curthread->name.c_str());
|
||||
@ -214,6 +218,11 @@ static void RunThread(void* arg) {
|
||||
/* Remove thread from tracking */
|
||||
DebugState.RemoveCurrentThreadFromGuestList();
|
||||
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,
|
||||
|
||||
@ -5,6 +5,19 @@
|
||||
_runOnAnotherStack:
|
||||
pushq %r12
|
||||
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 %rbp, %r13
|
||||
movq %rdx, %rsp
|
||||
@ -12,6 +25,13 @@ _runOnAnotherStack:
|
||||
callq *%rsi
|
||||
movq %r13, %rbp
|
||||
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 %r12
|
||||
ret
|
||||
|
||||
@ -19,67 +19,20 @@ namespace Core {
|
||||
static constexpr u32 ORBIS_MXCSR = 0x9fc0;
|
||||
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() {}
|
||||
|
||||
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, init_stack_ptr, stacksize);
|
||||
return pthread_create(pthr, &pattr, (PthreadFunc)func, arg);
|
||||
return pthread_create(pthr, nullptr, func, arg);
|
||||
#else
|
||||
CLIENT_ID clientId{};
|
||||
INITIAL_TEB teb{};
|
||||
CONTEXT ctx{};
|
||||
|
||||
clientId.UniqueProcess = GetCurrentProcess();
|
||||
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);
|
||||
native_handle = CreateThread(nullptr, 0, func, arg, 0, nullptr);
|
||||
if (native_handle == nullptr) {
|
||||
return GetLastError();
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -91,28 +44,8 @@ void NativeThread::Exit() {
|
||||
tid = 0;
|
||||
|
||||
#ifdef _WIN64
|
||||
NtClose(native_handle);
|
||||
native_handle = nullptr;
|
||||
|
||||
/* 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);
|
||||
ExitThread(0);
|
||||
#else
|
||||
// Disable and free the signal stack.
|
||||
constexpr stack_t sig_stack = {
|
||||
@ -124,10 +57,6 @@ void NativeThread::Exit() {
|
||||
free(sig_stack_ptr);
|
||||
sig_stack_ptr = nullptr;
|
||||
}
|
||||
|
||||
if (init_stack_ptr != nullptr) {
|
||||
free(init_stack_ptr);
|
||||
}
|
||||
pthread_exit(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -10,9 +10,11 @@ struct PthreadAttr;
|
||||
} // namespace Libraries::Kernel
|
||||
|
||||
namespace Core {
|
||||
|
||||
using ThreadFunc = void (*)(void*);
|
||||
using PthreadFunc = void* (*)(void*);
|
||||
#ifdef WIN32
|
||||
using ThreadFunc = DWORD (*)(void*);
|
||||
#else
|
||||
using ThreadFunc = void* (*)(void*);
|
||||
#endif
|
||||
|
||||
class NativeThread {
|
||||
public:
|
||||
@ -39,7 +41,6 @@ private:
|
||||
uintptr_t native_handle;
|
||||
void* sig_stack_ptr = nullptr;
|
||||
#endif
|
||||
void* init_stack_ptr = nullptr;
|
||||
u64 tid;
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user