Make Ps functions use Ob to create thread handles
This commit is contained in:
parent
484a2c3f47
commit
9082891903
|
@ -34,6 +34,7 @@
|
|||
#include "Timer.h"
|
||||
#include "common\util\CxbxUtil.h"
|
||||
#include "core\kernel\init\CxbxKrnl.h"
|
||||
#include "core\kernel\support\EmuFS.h"
|
||||
#ifdef __linux__
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
@ -142,6 +143,7 @@ void ClockThread(TimerObject* Timer)
|
|||
if (GetTime_NS(Timer) > NewExpireTime) {
|
||||
if (Timer->Exit.load()) {
|
||||
Timer_Destroy(Timer);
|
||||
EmuKeFreeThread();
|
||||
return;
|
||||
}
|
||||
Timer->Callback(Timer->Opaque);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "CxbxVersion.h"
|
||||
#include "core\kernel\init\CxbxKrnl.h"
|
||||
#include "core\kernel\support\Emu.h"
|
||||
#include "core\kernel\support\EmuFS.h"
|
||||
#include "EmuShared.h"
|
||||
#include "..\FixedFunctionState.h"
|
||||
#include "core\hle\D3D8\ResourceTracker.h"
|
||||
|
@ -632,9 +633,6 @@ void CxbxInitWindow(bool bFullInit)
|
|||
// We set the priority of this thread a bit higher, to assure reliable timing :
|
||||
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
g_AffinityPolicy->SetAffinityOther(hThread);
|
||||
|
||||
CxbxKrnlRegisterThread(hThread);
|
||||
CloseHandle(hThread); // CxbxKrnlRegisterThread duplicates the handle so we can close this one
|
||||
}
|
||||
|
||||
/* TODO : Port this Dxbx code :
|
||||
|
@ -2173,6 +2171,7 @@ static DWORD WINAPI EmuUpdateTickCount(LPVOID)
|
|||
|
||||
// We check for LLE flag as NV2A handles it's own VBLANK if LLE is enabled!
|
||||
if (bLLE_GPU) {
|
||||
EmuKeFreeThread();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace xbox
|
|||
XBSYSAPI EXPORTNUM(254) ntstatus_xt NTAPI PsCreateSystemThread
|
||||
(
|
||||
OUT PHANDLE ThreadHandle,
|
||||
OUT PDWORD ThreadId OPTIONAL,
|
||||
OUT PHANDLE ThreadId OPTIONAL,
|
||||
IN PKSTART_ROUTINE StartRoutine,
|
||||
IN PVOID StartContext,
|
||||
IN boolean_xt DebuggerThread
|
||||
|
@ -40,7 +40,7 @@ XBSYSAPI EXPORTNUM(255) ntstatus_xt NTAPI PsCreateSystemThreadEx
|
|||
IN ulong_xt ThreadExtensionSize,
|
||||
IN ulong_xt KernelStackSize,
|
||||
IN ulong_xt TlsDataSize,
|
||||
OUT PDWORD ThreadId OPTIONAL,
|
||||
OUT PHANDLE ThreadId OPTIONAL,
|
||||
IN PKSTART_ROUTINE StartRoutine,
|
||||
IN PVOID StartContext,
|
||||
IN boolean_xt CreateSuspended,
|
||||
|
@ -69,7 +69,9 @@ XBSYSAPI EXPORTNUM(257) ntstatus_xt NTAPI PsSetCreateThreadNotifyRoutine
|
|||
// ******************************************************************
|
||||
XBSYSAPI EXPORTNUM(258) void_xt NTAPI PsTerminateSystemThread(IN ntstatus_xt ExitStatus);
|
||||
|
||||
XBSYSAPI EXPORTNUM(259) volatile OBJECT_TYPE PsThreadObjectType;
|
||||
XBSYSAPI EXPORTNUM(259) OBJECT_TYPE PsThreadObjectType;
|
||||
|
||||
PETHREAD PspGetCurrentThread();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ typedef void* LPSECURITY_ATTRIBUTES;
|
|||
#define X_STATUS_UNRECOGNIZED_MEDIA 0xC0000014L
|
||||
#define X_STATUS_NO_MEMORY 0xC0000017L
|
||||
#define X_STATUS_BUFFER_TOO_SMALL 0xC0000023L
|
||||
#define X_STATUS_INVALID_PARAMETER 0xC000000DL
|
||||
#define X_STATUS_INVALID_PARAMETER_2 0xC00000F0L
|
||||
#define X_STATUS_ALERTED 0x00000101L
|
||||
#define X_STATUS_USER_APC 0x000000C0L
|
||||
|
@ -1916,7 +1917,7 @@ typedef struct _ETHREAD
|
|||
{
|
||||
struct _KTHREAD Tcb;
|
||||
uchar_xt UnknownA[0x1C]; // 0x110
|
||||
dword_xt UniqueThread; // 0x12C
|
||||
HANDLE UniqueThread; // 0x12C
|
||||
}
|
||||
ETHREAD, *PETHREAD;
|
||||
|
||||
|
|
|
@ -140,11 +140,9 @@ xbox::KPCR* WINAPI KeGetPcr()
|
|||
Pcr = (xbox::PKPCR)__readfsdword(TIB_ArbitraryDataSlot);
|
||||
|
||||
if (Pcr == nullptr) {
|
||||
EmuLog(LOG_LEVEL::WARNING, "KeGetPCR returned nullptr: Was this called from a non-xbox thread?");
|
||||
// Attempt to salvage the situation by calling InitXboxThread to setup KPCR in place
|
||||
InitXboxThread();
|
||||
g_AffinityPolicy->SetAffinityXbox();
|
||||
Pcr = (xbox::PKPCR)__readfsdword(TIB_ArbitraryDataSlot);
|
||||
// If we reach here, it's a bug: it means we are executing xbox code from a host thread, and we have forgotten to intialize
|
||||
// the xbox thread first
|
||||
CxbxrKrnlAbort("KeGetPCR returned nullptr: Was this called from a non-xbox thread?");
|
||||
}
|
||||
|
||||
return Pcr;
|
||||
|
|
|
@ -88,6 +88,7 @@ the said software).
|
|||
|
||||
#define ASSERT_TIMER_LOCKED assert(KiTimerMtx.Acquired > 0)
|
||||
|
||||
xbox::KPROCESS KiUniqueProcess;
|
||||
const xbox::ulong_xt CLOCK_TIME_INCREMENT = 0x2710;
|
||||
xbox::KDPC KiTimerExpireDpc;
|
||||
xbox::KI_TIMER_LOCK KiTimerMtx;
|
||||
|
@ -97,13 +98,13 @@ xbox::LIST_ENTRY KiWaitInListHead;
|
|||
|
||||
xbox::void_xt xbox::KiInitSystem()
|
||||
{
|
||||
unsigned int i;
|
||||
KiUniqueProcess.StackCount = 0;
|
||||
|
||||
InitializeListHead(&KiWaitInListHead);
|
||||
|
||||
KiTimerMtx.Acquired = 0;
|
||||
KeInitializeDpc(&KiTimerExpireDpc, KiTimerExpiration, NULL);
|
||||
for (i = 0; i < TIMER_TABLE_SIZE; i++) {
|
||||
for (unsigned i = 0; i < TIMER_TABLE_SIZE; i++) {
|
||||
InitializeListHead(&KiTimerTableListHead[i].Entry);
|
||||
KiTimerTableListHead[i].Time.u.HighPart = 0xFFFFFFFF;
|
||||
KiTimerTableListHead[i].Time.u.LowPart = 0;
|
||||
|
|
|
@ -136,6 +136,7 @@ namespace xbox
|
|||
);
|
||||
};
|
||||
|
||||
extern xbox::KPROCESS KiUniqueProcess;
|
||||
extern const xbox::ulong_xt CLOCK_TIME_INCREMENT;
|
||||
extern xbox::LIST_ENTRY KiWaitInListHead;
|
||||
extern xbox::KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE];
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
|
||||
#include <core\kernel\exports\xboxkrnl.h> // For PsCreateSystemThreadEx, etc.
|
||||
#include "core\kernel\exports\EmuKrnlKi.h"
|
||||
#include <process.h> // For __beginthreadex(), etc.
|
||||
#include <float.h> // For _controlfp constants
|
||||
|
||||
|
@ -39,6 +40,7 @@
|
|||
#include "core\kernel\init\CxbxKrnl.h" // For CxbxKrnl_TLS
|
||||
#include "core\kernel\support\Emu.h" // For EmuLog(LOG_LEVEL::WARNING, )
|
||||
#include "core\kernel\support\EmuFS.h" // For EmuGenerateFS
|
||||
#include "core\kernel\support\NativeHandle.h"
|
||||
|
||||
// prevent name collisions
|
||||
namespace NtDll
|
||||
|
@ -51,9 +53,10 @@ namespace NtDll
|
|||
// PsCreateSystemThread proxy parameters
|
||||
typedef struct _PCSTProxyParam
|
||||
{
|
||||
IN PVOID StartRoutine;
|
||||
IN PVOID StartContext;
|
||||
IN PVOID SystemRoutine;
|
||||
IN xbox::PVOID StartRoutine;
|
||||
IN xbox::PVOID StartContext;
|
||||
IN xbox::PVOID SystemRoutine;
|
||||
IN xbox::PVOID Ethread;
|
||||
}
|
||||
PCSTProxyParam;
|
||||
|
||||
|
@ -64,23 +67,25 @@ extern int g_iThreadNotificationCount = 0;
|
|||
// Separate function for logging, otherwise in PCSTProxy __try wont work (Compiler Error C2712)
|
||||
void LOG_PCSTProxy
|
||||
(
|
||||
PVOID StartRoutine,
|
||||
PVOID StartContext,
|
||||
PVOID SystemRoutine
|
||||
xbox::PVOID StartRoutine,
|
||||
xbox::PVOID StartContext,
|
||||
xbox::PVOID SystemRoutine,
|
||||
xbox::PVOID Ethread
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(StartRoutine)
|
||||
LOG_FUNC_ARG(StartContext)
|
||||
LOG_FUNC_ARG(SystemRoutine)
|
||||
LOG_FUNC_ARG(Ethread)
|
||||
LOG_FUNC_END;
|
||||
}
|
||||
|
||||
// Overload which doesn't change affinity
|
||||
void InitXboxThread()
|
||||
void InitXboxThread(xbox::PVOID Ethread)
|
||||
{
|
||||
// initialize FS segment selector
|
||||
EmuGenerateFS(CxbxKrnl_TLS, CxbxKrnl_TLSData);
|
||||
EmuGenerateFS(CxbxKrnl_TLS, CxbxKrnl_TLSData, Ethread);
|
||||
|
||||
_controlfp(_PC_53, _MCW_PC); // Set Precision control to 53 bits (verified setting)
|
||||
_controlfp(_RC_NEAR, _MCW_RC); // Set Rounding control to near (unsure about this)
|
||||
|
@ -104,11 +109,12 @@ static unsigned int WINAPI PCSTProxy
|
|||
LOG_PCSTProxy(
|
||||
params.StartRoutine,
|
||||
params.StartContext,
|
||||
params.SystemRoutine);
|
||||
params.SystemRoutine,
|
||||
params.Ethread);
|
||||
|
||||
|
||||
// Do minimal thread initialization
|
||||
InitXboxThread();
|
||||
InitXboxThread(params.Ethread);
|
||||
|
||||
auto routine = (xbox::PKSYSTEM_ROUTINE)params.SystemRoutine;
|
||||
// Debugging notice : When the below line shows up with an Exception dialog and a
|
||||
|
@ -137,13 +143,19 @@ void PspSystemThreadStartup
|
|||
xbox::PsTerminateSystemThread(X_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
xbox::PETHREAD xbox::PspGetCurrentThread()
|
||||
{
|
||||
// This works because we assign ethread to Prcb->CurrentThread
|
||||
return reinterpret_cast<PETHREAD>(KeGetCurrentThread());
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * 0x00FE - PsCreateSystemThread()
|
||||
// ******************************************************************
|
||||
XBSYSAPI EXPORTNUM(254) xbox::ntstatus_xt NTAPI xbox::PsCreateSystemThread
|
||||
(
|
||||
OUT PHANDLE ThreadHandle,
|
||||
OUT PDWORD ThreadId OPTIONAL,
|
||||
OUT PHANDLE ThreadId OPTIONAL,
|
||||
IN PKSTART_ROUTINE StartRoutine,
|
||||
IN PVOID StartContext,
|
||||
IN boolean_xt DebuggerThread
|
||||
|
@ -187,7 +199,7 @@ XBSYSAPI EXPORTNUM(255) xbox::ntstatus_xt NTAPI xbox::PsCreateSystemThreadEx
|
|||
IN ulong_xt ThreadExtensionSize,
|
||||
IN ulong_xt KernelStackSize,
|
||||
IN ulong_xt TlsDataSize,
|
||||
OUT PDWORD ThreadId OPTIONAL,
|
||||
OUT PHANDLE ThreadId OPTIONAL,
|
||||
IN PKSTART_ROUTINE StartRoutine,
|
||||
IN PVOID StartContext,
|
||||
IN boolean_xt CreateSuspended,
|
||||
|
@ -222,7 +234,31 @@ XBSYSAPI EXPORTNUM(255) xbox::ntstatus_xt NTAPI xbox::PsCreateSystemThreadEx
|
|||
|
||||
// create thread, using our special proxy technique
|
||||
{
|
||||
DWORD dwThreadId = 0;
|
||||
PETHREAD eThread;
|
||||
ntstatus_xt result = ObCreateObject(&PsThreadObjectType, zeroptr, sizeof(ETHREAD) + ThreadExtensionSize, reinterpret_cast<PVOID *>(&eThread));
|
||||
if (!X_NT_SUCCESS(result)) {
|
||||
RETURN(result);
|
||||
}
|
||||
|
||||
std::memset(eThread, 0, sizeof(ETHREAD) + ThreadExtensionSize);
|
||||
|
||||
// The ob handle of the ethread obj is the thread id we return to the title
|
||||
result = ObInsertObject(eThread, zeroptr, 0, &eThread->UniqueThread);
|
||||
if (!X_NT_SUCCESS(result)) {
|
||||
ObfDereferenceObject(eThread);
|
||||
RETURN(result);
|
||||
}
|
||||
|
||||
// Create another handle to pass back to the title in the ThreadHandle argument
|
||||
result = ObOpenObjectByPointer(eThread, &PsThreadObjectType, ThreadHandle);
|
||||
if (!X_NT_SUCCESS(result)) {
|
||||
ObfDereferenceObject(eThread);
|
||||
RETURN(result);
|
||||
}
|
||||
|
||||
if (ThreadId != zeroptr) {
|
||||
*ThreadId = eThread->UniqueThread;
|
||||
}
|
||||
|
||||
// PCSTProxy is responsible for cleaning up this pointer
|
||||
PCSTProxyParam *iPCSTProxyParam = new PCSTProxyParam;
|
||||
|
@ -230,6 +266,7 @@ XBSYSAPI EXPORTNUM(255) xbox::ntstatus_xt NTAPI xbox::PsCreateSystemThreadEx
|
|||
iPCSTProxyParam->StartRoutine = (PVOID)StartRoutine;
|
||||
iPCSTProxyParam->StartContext = StartContext;
|
||||
iPCSTProxyParam->SystemRoutine = (PVOID)SystemRoutine; // NULL, XapiThreadStartup or unknown?
|
||||
iPCSTProxyParam->Ethread = eThread;
|
||||
|
||||
/*
|
||||
// call thread notification routine(s)
|
||||
|
@ -253,27 +290,27 @@ XBSYSAPI EXPORTNUM(255) xbox::ntstatus_xt NTAPI xbox::PsCreateSystemThreadEx
|
|||
}
|
||||
}*/
|
||||
|
||||
HANDLE handle = reinterpret_cast<HANDLE>(_beginthreadex(NULL, KernelStackSize, PCSTProxy, iPCSTProxyParam, CREATE_SUSPENDED, reinterpret_cast<unsigned int*>(&dwThreadId)));
|
||||
HANDLE handle = reinterpret_cast<HANDLE>(_beginthreadex(NULL, KernelStackSize, PCSTProxy, iPCSTProxyParam, CREATE_SUSPENDED, nullptr));
|
||||
if (handle == NULL) {
|
||||
delete iPCSTProxyParam;
|
||||
ObpClose(eThread->UniqueThread);
|
||||
ObfDereferenceObject(eThread);
|
||||
RETURN(X_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
*ThreadHandle = handle;
|
||||
if (ThreadId != NULL)
|
||||
*ThreadId = dwThreadId;
|
||||
|
||||
KiUniqueProcess.StackCount++;
|
||||
RegisterXboxHandle(ThreadHandle, handle);
|
||||
RegisterXboxHandle(eThread->UniqueThread, handle);
|
||||
|
||||
g_AffinityPolicy->SetAffinityXbox(handle);
|
||||
CxbxKrnlRegisterThread(handle);
|
||||
|
||||
// Now that ThreadId is populated and affinity is changed, resume the thread (unless the guest passed CREATE_SUSPENDED)
|
||||
if (!CreateSuspended) {
|
||||
ResumeThread(handle);
|
||||
}
|
||||
|
||||
// Note : DO NOT use iPCSTProxyParam anymore, since ownership is transferred to the proxy (which frees it too)
|
||||
|
||||
// Log ThreadID identical to how GetCurrentThreadID() is rendered :
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Created Xbox proxy thread. Handle : 0x%X, ThreadId : [0x%.4X]", handle, dwThreadId);
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Created Xbox proxy thread. Handle : 0x%X, ThreadId : [0x%.4X]", *ThreadHandle, eThread->UniqueThread);
|
||||
}
|
||||
|
||||
RETURN(X_STATUS_SUCCESS);
|
||||
|
@ -289,14 +326,13 @@ XBSYSAPI EXPORTNUM(256) xbox::ntstatus_xt NTAPI xbox::PsQueryStatistics
|
|||
{
|
||||
LOG_FUNC_ONE_ARG_OUT(ProcessStatistics);
|
||||
|
||||
NTSTATUS ret = X_STATUS_SUCCESS;
|
||||
ntstatus_xt ret = X_STATUS_SUCCESS;
|
||||
|
||||
if (ProcessStatistics->Length == sizeof(PS_STATISTICS)) {
|
||||
LOG_INCOMPLETE(); // TODO : Return number of threads and handles that currently exist
|
||||
ProcessStatistics->ThreadCount = 1;
|
||||
ProcessStatistics->HandleCount = 1;
|
||||
ProcessStatistics->ThreadCount = KiUniqueProcess.StackCount;
|
||||
ProcessStatistics->HandleCount = ObpObjectHandleTable.HandleCount; // This currently doesn't count native handles that we use as xbox handles
|
||||
} else {
|
||||
ret = STATUS_INVALID_PARAMETER;
|
||||
ret = X_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
RETURN(ret);
|
||||
|
@ -368,7 +404,9 @@ XBSYSAPI EXPORTNUM(258) xbox::void_xt NTAPI xbox::PsTerminateSystemThread
|
|||
}
|
||||
}*/
|
||||
|
||||
EmuKeFreePcr();
|
||||
EmuKeFreeThread();
|
||||
KiUniqueProcess.StackCount--;
|
||||
|
||||
_endthreadex(ExitStatus);
|
||||
// ExitThread(ExitStatus);
|
||||
// CxbxKrnlTerminateThread();
|
||||
|
@ -377,7 +415,7 @@ XBSYSAPI EXPORTNUM(258) xbox::void_xt NTAPI xbox::PsTerminateSystemThread
|
|||
// ******************************************************************
|
||||
// * 0x0103 - PsThreadObjectType
|
||||
// ******************************************************************
|
||||
XBSYSAPI EXPORTNUM(259) xbox::OBJECT_TYPE VOLATILE xbox::PsThreadObjectType =
|
||||
XBSYSAPI EXPORTNUM(259) xbox::OBJECT_TYPE xbox::PsThreadObjectType =
|
||||
{
|
||||
xbox::ExAllocatePoolWithTag,
|
||||
xbox::ExFreePool,
|
||||
|
|
|
@ -93,9 +93,6 @@ DebugMode CxbxrKrnl_DebugMode = DebugMode::DM_NONE;
|
|||
std::string CxbxrKrnl_DebugFileName = "";
|
||||
Xbe::Certificate *g_pCertificate = NULL;
|
||||
|
||||
/*! thread handles */
|
||||
static std::vector<HANDLE> g_hThreads;
|
||||
|
||||
char szFilePath_CxbxReloaded_Exe[MAX_PATH] = { 0 };
|
||||
std::string g_DataFilePath;
|
||||
char szFilePath_EEPROM_bin[MAX_PATH] = { 0 };
|
||||
|
@ -364,6 +361,8 @@ static unsigned int WINAPI CxbxKrnlInterruptThread(PVOID param)
|
|||
Sleep(1);
|
||||
}
|
||||
|
||||
EmuKeFreeThread();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1405,8 +1404,6 @@ static void CxbxrKrnlInitHacks()
|
|||
|
||||
CxbxrLogDumpXbeInfo(pLibraryVersion);
|
||||
|
||||
CxbxKrnlRegisterThread(GetCurrentThread());
|
||||
|
||||
// Make sure the Xbox1 code runs on one core (as the box itself has only 1 CPU,
|
||||
// this will better aproximate the environment with regard to multi-threading) :
|
||||
EmuLogInit(LOG_LEVEL::DEBUG, "Determining CPU affinity.");
|
||||
|
@ -1511,12 +1508,14 @@ static void CxbxrKrnlInitHacks()
|
|||
DWORD dwThreadId;
|
||||
HANDLE hThread = (HANDLE)_beginthreadex(NULL, NULL, CxbxKrnlInterruptThread, NULL, NULL, (unsigned int*)&dwThreadId);
|
||||
// Start the kernel clock thread
|
||||
TimerObject* KernelClockThr = Timer_Create(CxbxKrnlClockThread, nullptr, "Kernel clock thread", false);
|
||||
TimerObject* KernelClockThr = Timer_Create(CxbxKrnlClockThread, nullptr, "Kernel clock thread", true);
|
||||
Timer_Start(KernelClockThr, SCALE_MS_IN_NS);
|
||||
|
||||
EmuLogInit(LOG_LEVEL::DEBUG, "Calling XBE entry point...");
|
||||
CxbxLaunchXbe(Entry);
|
||||
|
||||
EmuKeFreeThread();
|
||||
|
||||
// FIXME: Wait for Cxbx to exit or error fatally
|
||||
Sleep(INFINITE);
|
||||
|
||||
|
@ -1544,8 +1543,6 @@ static void CxbxrKrnlInitHacks()
|
|||
{
|
||||
g_bEmuException = true;
|
||||
|
||||
CxbxKrnlResume();
|
||||
|
||||
// print out error message (if exists)
|
||||
if(szErrorMessage != NULL)
|
||||
{
|
||||
|
@ -1575,67 +1572,6 @@ static void CxbxrKrnlInitHacks()
|
|||
CxbxKrnlShutDown();
|
||||
}
|
||||
|
||||
void CxbxKrnlRegisterThread(HANDLE hThread)
|
||||
{
|
||||
// we must duplicate this handle in order to retain Suspend/Resume thread rights from a remote thread
|
||||
{
|
||||
HANDLE hDupHandle = NULL;
|
||||
|
||||
if (DuplicateHandle(g_CurrentProcessHandle, hThread, g_CurrentProcessHandle, &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
|
||||
hThread = hDupHandle; // Thread handle was duplicated, continue registration with the duplicate
|
||||
}
|
||||
else {
|
||||
auto message = CxbxGetLastErrorString("DuplicateHandle");
|
||||
EmuLog(LOG_LEVEL::WARNING, message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
g_hThreads.push_back(hThread);
|
||||
}
|
||||
|
||||
void CxbxKrnlSuspend()
|
||||
{
|
||||
if(g_bEmuSuspended || g_bEmuException)
|
||||
return;
|
||||
|
||||
for (auto it = g_hThreads.begin(); it != g_hThreads.end(); ++it)
|
||||
{
|
||||
DWORD dwExitCode;
|
||||
|
||||
if(GetExitCodeThread(*it, &dwExitCode) && dwExitCode == STILL_ACTIVE) {
|
||||
// suspend thread if it is active
|
||||
SuspendThread(*it);
|
||||
} else {
|
||||
// remove thread from thread list if it is dead
|
||||
g_hThreads.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
g_bEmuSuspended = true;
|
||||
}
|
||||
|
||||
void CxbxKrnlResume()
|
||||
{
|
||||
if(!g_bEmuSuspended)
|
||||
return;
|
||||
|
||||
for (auto it = g_hThreads.begin(); it != g_hThreads.end(); ++it)
|
||||
{
|
||||
DWORD dwExitCode;
|
||||
|
||||
if (GetExitCodeThread(*it, &dwExitCode) && dwExitCode == STILL_ACTIVE) {
|
||||
// resume thread if it is active
|
||||
ResumeThread(*it);
|
||||
}
|
||||
else {
|
||||
// remove thread from thread list if it is dead
|
||||
g_hThreads.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
g_bEmuSuspended = false;
|
||||
}
|
||||
|
||||
void CxbxKrnlShutDown(bool is_reboot)
|
||||
{
|
||||
if (!is_reboot) {
|
||||
|
|
|
@ -151,15 +151,6 @@ void CxbxKrnlEmulate(unsigned int system, blocks_reserved_t blocks_reserved);
|
|||
|
||||
#define CxbxrKrnlAbort(fmt, ...) CxbxrKrnlAbortEx(LOG_PREFIX, fmt, ##__VA_ARGS__)
|
||||
|
||||
/*! register a thread handle */
|
||||
void CxbxKrnlRegisterThread(HANDLE hThread);
|
||||
|
||||
/*! suspend emulation */
|
||||
void CxbxKrnlSuspend();
|
||||
|
||||
/*! resume emulation */
|
||||
void CxbxKrnlResume();
|
||||
|
||||
/*! terminate gracefully the emulation */
|
||||
void CxbxKrnlShutDown(bool is_reboot = false);
|
||||
|
||||
|
@ -193,7 +184,7 @@ extern ULONG g_CxbxFatalErrorCode;
|
|||
|
||||
extern size_t g_SystemMaxMemory;
|
||||
|
||||
void InitXboxThread();
|
||||
void InitXboxThread(xbox::PVOID Ethread = xbox::zeroptr);
|
||||
|
||||
/*! thread local storage structure */
|
||||
extern Xbe::TLS *CxbxKrnl_TLS;
|
||||
|
|
|
@ -190,35 +190,39 @@ void EmuKeSetPcr(xbox::KPCR *Pcr)
|
|||
|
||||
void EmuKeFreePcr()
|
||||
{
|
||||
// NOTE: don't call KeGetPcr because that one creates a new pcr for the thread when __readfsdword returns nullptr, which we don't want
|
||||
xbox::PKPCR Pcr = reinterpret_cast<xbox::PKPCR>(__readfsdword(TIB_ArbitraryDataSlot));
|
||||
xbox::PKPCR Pcr = KeGetPcr();
|
||||
|
||||
xbox::PVOID Dummy;
|
||||
xbox::ulong_xt Size;
|
||||
xbox::ntstatus_xt Status;
|
||||
// tls can be nullptr
|
||||
if (Pcr->NtTib.StackBase) {
|
||||
// NOTE: the tls pointer was increased by 12 bytes to enforce the 16 bytes alignment, so adjust it to reach the correct pointer
|
||||
// that was allocated by xbox::NtAllocateVirtualMemory
|
||||
Dummy = static_cast<xbox::PBYTE>(Pcr->NtTib.StackBase) - 12;
|
||||
Size = xbox::zero;
|
||||
Status = xbox::NtFreeVirtualMemory(&Dummy, &Size, XBOX_MEM_RELEASE); // free tls
|
||||
assert(Status == X_STATUS_SUCCESS);
|
||||
}
|
||||
Dummy = Pcr;
|
||||
Size = xbox::zero;
|
||||
Status = xbox::NtFreeVirtualMemory(&Dummy, &Size, XBOX_MEM_RELEASE); // free pcr
|
||||
assert(Status == X_STATUS_SUCCESS);
|
||||
__writefsdword(TIB_ArbitraryDataSlot, NULL);
|
||||
}
|
||||
|
||||
if (Pcr) {
|
||||
// tls can be nullptr
|
||||
xbox::PVOID Dummy;
|
||||
xbox::ulong_xt Size;
|
||||
xbox::ntstatus_xt Status;
|
||||
if (Pcr->NtTib.StackBase) {
|
||||
// NOTE: the tls pointer was increased by 12 bytes to enforce the 16 bytes alignment, so adjust it to reach the correct pointer
|
||||
// that was allocated by xbox::NtAllocateVirtualMemory
|
||||
Dummy = static_cast<xbox::PBYTE>(Pcr->NtTib.StackBase) - 12;
|
||||
Size = xbox::zero;
|
||||
Status = xbox::NtFreeVirtualMemory(&Dummy, &Size, XBOX_MEM_RELEASE); // free tls
|
||||
assert(Status == X_STATUS_SUCCESS);
|
||||
}
|
||||
Dummy = Pcr->Prcb->CurrentThread;
|
||||
Size = xbox::zero;
|
||||
Status = xbox::NtFreeVirtualMemory(&Dummy, &Size, XBOX_MEM_RELEASE); // free ethread
|
||||
assert(Status == X_STATUS_SUCCESS);
|
||||
Dummy = Pcr;
|
||||
Size = xbox::zero;
|
||||
Status = xbox::NtFreeVirtualMemory(&Dummy, &Size, XBOX_MEM_RELEASE); // free pcr
|
||||
assert(Status == X_STATUS_SUCCESS);
|
||||
__writefsdword(TIB_ArbitraryDataSlot, NULL);
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::WARNING, "__readfsdword in EmuKeFreePcr returned nullptr: was this called from a non-xbox thread?");
|
||||
void EmuKeFreeThread()
|
||||
{
|
||||
// This functions is to be used for cxbxr threads that execute xbox code. We can't just call PsTerminateSystemThread because some additional
|
||||
// xbox state is not created for this kind of threads
|
||||
|
||||
xbox::PETHREAD eThread = xbox::PspGetCurrentThread();
|
||||
if (eThread->UniqueThread != NULL) {
|
||||
xbox::NtClose(eThread->UniqueThread);
|
||||
eThread->UniqueThread = NULL;
|
||||
}
|
||||
|
||||
EmuKeFreePcr();
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuFS_RefreshKPCR()
|
||||
|
@ -652,7 +656,7 @@ void EmuInitFS()
|
|||
}
|
||||
|
||||
// generate fs segment selector
|
||||
void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
||||
void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData, xbox::PVOID Ethread)
|
||||
{
|
||||
void *pNewTLS = nullptr;
|
||||
xbox::PVOID base;
|
||||
|
@ -781,14 +785,25 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
|||
|
||||
// Initialize a fake PrcbData.CurrentThread
|
||||
{
|
||||
base = xbox::zeroptr;
|
||||
size = sizeof(xbox::ETHREAD);
|
||||
xbox::NtAllocateVirtualMemory(&base, 0, &size, XBOX_MEM_RESERVE | XBOX_MEM_COMMIT, XBOX_PAGE_READWRITE);
|
||||
xbox::ETHREAD *EThread = (xbox::ETHREAD*)base; // Clear, to prevent side-effects on random contents
|
||||
xbox::RtlZeroMemory(EThread, sizeof(xbox::ETHREAD));
|
||||
xbox::PETHREAD EThread = static_cast<xbox::PETHREAD>(Ethread);
|
||||
if (EThread == xbox::zeroptr) {
|
||||
// If it is nullptr, it means we are creating this thread from cxbxr, otherwise we were created from PsCreateSystemThreadEx
|
||||
xbox::PETHREAD eThread;
|
||||
xbox::ntstatus_xt result = xbox::ObCreateObject(&xbox::PsThreadObjectType, xbox::zeroptr, sizeof(xbox::ETHREAD), reinterpret_cast<PVOID *>(&eThread));
|
||||
if (!X_NT_SUCCESS(result)) {
|
||||
// We can't recover from here, abort execution
|
||||
CxbxrKrnlAbort("ObCreateObject: failed to create new xbox thread!");
|
||||
}
|
||||
std::memset(eThread, 0, sizeof(xbox::ETHREAD));
|
||||
EThread = eThread;
|
||||
result = xbox::ObInsertObject(eThread, xbox::zeroptr, 0, &eThread->UniqueThread);
|
||||
if (!X_NT_SUCCESS(result)) {
|
||||
// We can't recover from here, abort execution
|
||||
CxbxrKrnlAbort("ObInsertObject: failed to create new xbox thread!");
|
||||
}
|
||||
}
|
||||
|
||||
EThread->Tcb.TlsData = pNewTLS;
|
||||
EThread->UniqueThread = GetCurrentThreadId();
|
||||
// Set PrcbData.CurrentThread
|
||||
Prcb->CurrentThread = (xbox::KTHREAD*)EThread;
|
||||
// Initialize the thread header and its wait list
|
||||
|
|
|
@ -33,8 +33,10 @@
|
|||
extern void EmuInitFS();
|
||||
|
||||
// generate fs segment selector
|
||||
extern void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData);
|
||||
extern void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData, xbox::PVOID Ethread);
|
||||
// free resources allocated for the thread
|
||||
void EmuKeFreeThread();
|
||||
// free kpcr allocated for the thread
|
||||
void EmuKeFreePcr();
|
||||
|
||||
typedef struct
|
||||
|
|
Loading…
Reference in New Issue