Merge pull request #2171 from ergo720/free_thread_resources
Free thread resources upon termination
This commit is contained in:
commit
187f4a8162
|
@ -264,6 +264,10 @@ 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)));
|
||||
if (handle == NULL) {
|
||||
delete iPCSTProxyParam;
|
||||
RETURN(xbox::status_insufficient_resources);
|
||||
}
|
||||
*ThreadHandle = handle;
|
||||
if (ThreadId != NULL)
|
||||
*ThreadId = dwThreadId;
|
||||
|
@ -378,6 +382,7 @@ XBSYSAPI EXPORTNUM(258) xbox::void_xt NTAPI xbox::PsTerminateSystemThread
|
|||
}
|
||||
}*/
|
||||
|
||||
EmuKeFreePcr();
|
||||
_endthreadex(ExitStatus);
|
||||
// ExitThread(ExitStatus);
|
||||
// CxbxKrnlTerminateThread();
|
||||
|
|
|
@ -188,6 +188,39 @@ void EmuKeSetPcr(xbox::KPCR *Pcr)
|
|||
__writefsdword(TIB_ArbitraryDataSlot, (DWORD)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));
|
||||
|
||||
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 == xbox::status_success);
|
||||
}
|
||||
Dummy = Pcr->Prcb->CurrentThread;
|
||||
Size = xbox::zero;
|
||||
Status = xbox::NtFreeVirtualMemory(&Dummy, &Size, XBOX_MEM_RELEASE); // free ethread
|
||||
assert(Status == xbox::status_success);
|
||||
Dummy = Pcr;
|
||||
Size = xbox::zero;
|
||||
Status = xbox::NtFreeVirtualMemory(&Dummy, &Size, XBOX_MEM_RELEASE); // free pcr
|
||||
assert(Status == xbox::status_success);
|
||||
__writefsdword(TIB_ArbitraryDataSlot, NULL);
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::WARNING, "__readfsdword in EmuKeFreePcr returned nullptr: was this called from a non-xbox thread?");
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void EmuFS_RefreshKPCR()
|
||||
{
|
||||
// Backup all registers, call KeGetPcr and then restore all registers
|
||||
|
@ -517,6 +550,8 @@ void EmuInitFS()
|
|||
void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
||||
{
|
||||
void *pNewTLS = nullptr;
|
||||
xbox::PVOID base;
|
||||
xbox::ulong_xt size;
|
||||
|
||||
// Be aware that TLS might be absent (for example in homebrew "Wolf3d-xbox")
|
||||
if (pTLS != nullptr) {
|
||||
|
@ -536,9 +571,12 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
|||
}
|
||||
|
||||
/* + HACK: extra safety padding 0x100 */
|
||||
pNewTLS = (void*)xbox::ExAllocatePool(dwCopySize + dwZeroSize + 0x100 + 0xC);
|
||||
base = xbox::zeroptr;
|
||||
size = dwCopySize + dwZeroSize + 0x100 + 0xC;
|
||||
xbox::NtAllocateVirtualMemory(&base, 0, &size, XBOX_MEM_RESERVE | XBOX_MEM_COMMIT, XBOX_PAGE_READWRITE);
|
||||
pNewTLS = (void*)base;
|
||||
xbox::RtlZeroMemory(pNewTLS, dwCopySize + dwZeroSize + 0x100 + 0xC);
|
||||
/* Skip the first 12 bytes so that TLSData will be 16 byte aligned (addr returned by AllocateZeroed is 4K aligned) */
|
||||
/* Skip the first 12 bytes so that TLSData will be 16 byte aligned (addr returned by NtAllocateVirtualMemory is 4K aligned) */
|
||||
pNewTLS = (uint8_t*)pNewTLS + 12;
|
||||
|
||||
if (dwCopySize > 0) {
|
||||
|
@ -583,7 +621,10 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
|||
}
|
||||
|
||||
// Allocate the xbox KPCR structure
|
||||
xbox::KPCR *NewPcr = (xbox::KPCR*)xbox::ExAllocatePool(sizeof(xbox::KPCR));
|
||||
base = xbox::zeroptr;
|
||||
size = sizeof(xbox::KPCR);
|
||||
xbox::NtAllocateVirtualMemory(&base, 0, &size, XBOX_MEM_RESERVE | XBOX_MEM_COMMIT, XBOX_PAGE_READWRITE);
|
||||
xbox::KPCR *NewPcr = (xbox::KPCR*)base;
|
||||
xbox::RtlZeroMemory(NewPcr, sizeof(xbox::KPCR));
|
||||
xbox::NT_TIB *XbTib = &(NewPcr->NtTib);
|
||||
xbox::PKPRCB Prcb = &(NewPcr->PrcbData);
|
||||
|
@ -630,7 +671,10 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
|||
|
||||
// Initialize a fake PrcbData.CurrentThread
|
||||
{
|
||||
xbox::ETHREAD *EThread = (xbox::ETHREAD*)xbox::ExAllocatePool(sizeof(xbox::ETHREAD)); // Clear, to prevent side-effects on random contents
|
||||
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));
|
||||
|
||||
EThread->Tcb.TlsData = pNewTLS;
|
||||
|
|
|
@ -34,6 +34,8 @@ extern void EmuInitFS();
|
|||
|
||||
// generate fs segment selector
|
||||
extern void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData);
|
||||
// free resources allocated for the thread
|
||||
void EmuKeFreePcr();
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue