1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

Allows for stack base to change

This commit is contained in:
Brian Fiete 2020-05-16 10:07:17 -07:00
parent 2510c16389
commit 4472449cc4
6 changed files with 135 additions and 66 deletions

View file

@ -214,6 +214,8 @@ BFGC::ThreadInfo::~ThreadInfo()
{ {
if (mThreadHandle != NULL) if (mThreadHandle != NULL)
BfpThread_Release(mThreadHandle); BfpThread_Release(mThreadHandle);
if (mThreadInfo != NULL)
BfpThreadInfo_Release(mThreadInfo);
} }
bool BFGC::ThreadInfo::WantsSuspend() bool BFGC::ThreadInfo::WantsSuspend()
@ -226,6 +228,14 @@ bool BFGC::ThreadInfo::WantsSuspend()
#endif #endif
} }
void BFGC::ThreadInfo::CalcStackStart()
{
intptr stackBase;
int stackLimit;
BfpThreadInfo_GetStackInfo(mThreadInfo, &stackBase, &stackLimit, BfpThreadInfoFlags_NoCache, NULL);
mStackStart = stackBase;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#ifdef BF_GC_LOG_ENABLED #ifdef BF_GC_LOG_ENABLED
@ -1447,6 +1457,7 @@ bool BFGC::ScanThreads()
mQueueMarkObjects = true; mQueueMarkObjects = true;
ConservativeScan(regVals, regValCount * sizeof(intptr)); ConservativeScan(regVals, regValCount * sizeof(intptr));
thread->CalcStackStart();
int length = thread->mStackStart - stackPtr; int length = thread->mStackStart - stackPtr;
AdjustStackPtr(stackPtr, length); AdjustStackPtr(stackPtr, length);
@ -1895,11 +1906,9 @@ void BFGC::ThreadStarted()
thread->mThreadHandle = BfpThread_GetCurrent(); thread->mThreadHandle = BfpThread_GetCurrent();
thread->mThreadId = BfpThread_GetCurrentId(); thread->mThreadId = BfpThread_GetCurrentId();
thread->mTEB = GetTEB((HANDLE)thread->mThreadHandle); thread->mTEB = GetTEB((HANDLE)thread->mThreadHandle);
thread->mThreadInfo = BfpThreadInfo_Create();
intptr stackBase; thread->CalcStackStart();
int stackLimit;
BfpThread_GetStackInfo(thread->mThreadHandle, &stackBase, &stackLimit, NULL);
thread->mStackStart = stackBase;
mThreadList.Add(thread); mThreadList.Add(thread);

View file

@ -170,6 +170,7 @@ public:
Beefy::CritSect mCritSect; Beefy::CritSect mCritSect;
BfpThread* mThreadHandle; BfpThread* mThreadHandle;
BfpThreadInfo* mThreadInfo;
BfpThreadId mThreadId; BfpThreadId mThreadId;
void* mTEB; void* mTEB;
intptr mStackStart; intptr mStackStart;
@ -180,6 +181,7 @@ public:
{ {
mThreadId = 0; mThreadId = 0;
mThreadHandle = NULL; mThreadHandle = NULL;
mThreadInfo = NULL;
mTEB = NULL; mTEB = NULL;
mStackStart = NULL; mStackStart = NULL;
mRunning = true; mRunning = true;
@ -188,6 +190,7 @@ public:
~ThreadInfo(); ~ThreadInfo();
bool WantsSuspend(); bool WantsSuspend();
void CalcStackStart();
}; };
struct RawLeakInfo struct RawLeakInfo

View file

@ -24,6 +24,7 @@ typedef uint64 BfpTimeStamp;
typedef intptr BfpThreadId; typedef intptr BfpThreadId;
struct BfpThread; struct BfpThread;
struct BfpThreadInfo;
struct BfpFile; struct BfpFile;
struct BfpSpawn; struct BfpSpawn;
struct BfpFileWatcher; struct BfpFileWatcher;
@ -231,6 +232,12 @@ enum BfpThreadPriority
BfpThreadPriority_VeryHigh =2 BfpThreadPriority_VeryHigh =2
}; };
enum BfpThreadInfoFlags
{
BfpThreadInfoFlags_None = 0,
BfpThreadInfoFlags_NoCache = 1
};
enum BfpThreadResult enum BfpThreadResult
{ {
BfpThreadResult_Ok = BfpResult_Ok, BfpThreadResult_Ok = BfpResult_Ok,
@ -251,10 +258,13 @@ BFP_EXPORT void BFP_CALLTYPE BfpThread_SetPriority(BfpThread* thread, BfpThreadP
BFP_EXPORT void BFP_CALLTYPE BfpThread_Suspend(BfpThread* thread, BfpThreadResult* outResult); BFP_EXPORT void BFP_CALLTYPE BfpThread_Suspend(BfpThread* thread, BfpThreadResult* outResult);
BFP_EXPORT void BFP_CALLTYPE BfpThread_Resume(BfpThread* thread, BfpThreadResult* outResult); BFP_EXPORT void BFP_CALLTYPE BfpThread_Resume(BfpThread* thread, BfpThreadResult* outResult);
BFP_EXPORT void BFP_CALLTYPE BfpThread_GetIntRegisters(BfpThread* thread, intptr* outStackPtr, intptr* outIntRegs, int* inOutIntRegCount, BfpThreadResult* outResult); BFP_EXPORT void BFP_CALLTYPE BfpThread_GetIntRegisters(BfpThread* thread, intptr* outStackPtr, intptr* outIntRegs, int* inOutIntRegCount, BfpThreadResult* outResult);
BFP_EXPORT void BFP_CALLTYPE BfpThread_GetStackInfo(BfpThread* thread, intptr* outStackBase, int* outStackLimit, BfpThreadResult* outResult);
BFP_EXPORT void BFP_CALLTYPE BfpThread_Sleep(int sleepMS); BFP_EXPORT void BFP_CALLTYPE BfpThread_Sleep(int sleepMS);
BFP_EXPORT bool BFP_CALLTYPE BfpThread_Yield(); BFP_EXPORT bool BFP_CALLTYPE BfpThread_Yield();
BFP_EXPORT BfpThreadInfo* BFP_CALLTYPE BfpThreadInfo_Create();
BFP_EXPORT void BFP_CALLTYPE BfpThreadInfo_Release(BfpThreadInfo* threadInfo);
BFP_EXPORT void BFP_CALLTYPE BfpThreadInfo_GetStackInfo(BfpThreadInfo* thread, intptr* outStackBase, int* outStackLimit, BfpThreadInfoFlags flags, BfpThreadResult* outResult);
struct BfpCritSect; struct BfpCritSect;
BFP_EXPORT BfpCritSect* BFP_CALLTYPE BfpCritSect_Create(); BFP_EXPORT BfpCritSect* BFP_CALLTYPE BfpCritSect_Create();
BFP_EXPORT void BFP_CALLTYPE BfpCritSect_Release(BfpCritSect* critSect); BFP_EXPORT void BFP_CALLTYPE BfpCritSect_Release(BfpCritSect* critSect);

View file

@ -1166,6 +1166,7 @@ struct BfpThreadInfo
{ {
intptr mStackBase; intptr mStackBase;
int mStackLimit; int mStackLimit;
pthread_t mPThread;
}; };
static __thread BfpThread* gCurrentThread; static __thread BfpThread* gCurrentThread;
@ -1338,32 +1339,6 @@ BFP_EXPORT void BFP_CALLTYPE BfpThread_GetIntRegisters(BfpThread* thread, intptr
NOT_IMPL; NOT_IMPL;
} }
BFP_EXPORT void BFP_CALLTYPE BfpThread_GetStackInfo(BfpThread* thread, intptr* outStackBase, int* outStackLimit, BfpThreadResult* outResult)
{
#ifdef BFP_HAS_PTHREAD_GETATTR_NP
if (gCurrentThreadInfo.mStackBase == 0)
{
void* stackBase = 0;
size_t stackLimit = 0;
pthread_attr_t attr;
pthread_getattr_np(pthread_self(), &attr);
pthread_attr_getstack(&attr, &stackBase, &stackLimit);
gCurrentThreadInfo.mStackBase = (intptr)stackBase + stackLimit;
gCurrentThreadInfo.mStackLimit = (int)stackLimit;
pthread_attr_destroy(&attr);
}
*outStackBase = gCurrentThreadInfo.mStackBase;
*outStackLimit = gCurrentThreadInfo.mStackLimit;
OUTRESULT(BfpThreadResult_Ok);
#else
OUTRESULT(BfpThreadResult_UnknownError);
#endif
}
BFP_EXPORT void BFP_CALLTYPE BfpThread_Sleep(int sleepMS) BFP_EXPORT void BFP_CALLTYPE BfpThread_Sleep(int sleepMS)
{ {
usleep(sleepMS * 1000); usleep(sleepMS * 1000);
@ -1374,6 +1349,55 @@ BFP_EXPORT bool BFP_CALLTYPE BfpThread_Yield()
return sched_yield() == 0; return sched_yield() == 0;
} }
///
BFP_EXPORT BfpThreadInfo* BFP_CALLTYPE BfpThreadInfo_Create()
{
BfpThreadInfo* threadInfo = new BfpThreadInfo();
threadInfo->mStackBase = 0;
threadInfo->mStackLimit = 0;
threadInfo->mPThread = pthread_self();
}
BFP_EXPORT void BFP_CALLTYPE BfpThreadInfo_Release(BfpThreadInfo* threadInfo)
{
delete threadInfo;
}
BFP_EXPORT void BFP_CALLTYPE BfpThreadInfo_GetStackInfo(BfpThreadInfo* threadInfo, intptr* outStackBase, int* outStackLimit, BfpThreadResult* outResult)
{
#ifdef BFP_HAS_PTHREAD_GETATTR_NP
if (threadInfo == NULL)
{
threadInfo = &gCurrentThreadInfo;
threadInfo->mPThread = pthread_self();
}
if (threadInfo->mStackBase == 0)
{
void* stackBase = 0;
size_t stackLimit = 0;
pthread_attr_t attr;
pthread_getattr_np(threadInfo->mPThread, &attr);
pthread_attr_getstack(&attr, &stackBase, &stackLimit);
threadInfo->mStackBase = (intptr)stackBase + stackLimit;
threadInfo->mStackLimit = (int)stackLimit;
pthread_attr_destroy(&attr);
}
*outStackBase = threadInfo->mStackBase;
*outStackLimit = threadInfo->mStackLimit;
OUTRESULT(BfpThreadResult_Ok);
#else
OUTRESULT(BfpThreadResult_UnknownError);
#endif
}
///
struct BfpCritSect struct BfpCritSect
{ {
pthread_mutex_t mPMutex; pthread_mutex_t mPMutex;

View file

@ -2253,39 +2253,6 @@ BFP_EXPORT void BFP_CALLTYPE BfpThread_GetIntRegisters(BfpThread* thread, intptr
*inOutIntRegCount = (int)(curPtr - outIntRegs); *inOutIntRegCount = (int)(curPtr - outIntRegs);
} }
struct BfpThreadStackInfo
{
intptr mStackBase;
intptr mStackLimit;
};
static __declspec(thread) BfpThreadStackInfo gThreadStackInfo;
BFP_EXPORT void BFP_CALLTYPE BfpThread_GetStackInfo(BfpThread* thread, intptr* outStackBase, int* outStackLimit, BfpThreadResult* outResult)
{
if (gThreadStackInfo.mStackBase == 0)
{
auto teb = (NT_TIB*)NtCurrentTeb();
MEMORY_BASIC_INFORMATION stackInfo = { 0 };
// We subtract one page for our request. VirtualQuery rounds UP to the next page.
// Unfortunately, the stack grows down. If we're on the first page (last page in the
// VirtualAlloc), we'll be moved to the next page, which is off the stack! Note this
// doesn't work right for IA64 due to bigger pages.
void* currentAddr = (void*)((intptr_t)&stackInfo - 4096);
// Query for the current stack allocation information.
VirtualQuery(currentAddr, &stackInfo, sizeof(MEMORY_BASIC_INFORMATION));
gThreadStackInfo.mStackBase = (uintptr_t)teb->StackBase;
gThreadStackInfo.mStackLimit = (uintptr_t)stackInfo.AllocationBase;
}
*outStackBase = (intptr)gThreadStackInfo.mStackBase;
*outStackLimit = (int)(gThreadStackInfo.mStackBase - gThreadStackInfo.mStackLimit);
OUTRESULT(BfpThreadResult_Ok);
return;
}
struct BfpCritSect struct BfpCritSect
{ {
CRITICAL_SECTION mCritSect; CRITICAL_SECTION mCritSect;
@ -2303,6 +2270,62 @@ BFP_EXPORT bool BFP_CALLTYPE BfpThread_Yield()
/// ///
struct BfpThreadInfo
{
intptr mStackBase;
intptr mStackLimit;
NT_TIB* mTeb;
};
BFP_EXPORT BfpThreadInfo* BFP_CALLTYPE BfpThreadInfo_Create()
{
BfpThreadInfo* threadInfo = new BfpThreadInfo();
threadInfo->mStackBase = 0;
threadInfo->mStackLimit = 0;
threadInfo->mTeb = (NT_TIB*)NtCurrentTeb();
return threadInfo;
}
BFP_EXPORT void BFP_CALLTYPE BfpThreadInfo_Release(BfpThreadInfo* threadInfo)
{
delete threadInfo;
}
static __declspec(thread) BfpThreadInfo gThreadStackInfo;
BFP_EXPORT void BFP_CALLTYPE BfpThreadInfo_GetStackInfo(BfpThreadInfo* threadInfo, intptr* outStackBase, int* outStackLimit, BfpThreadInfoFlags flags, BfpThreadResult* outResult)
{
if (threadInfo == NULL)
{
threadInfo = &gThreadStackInfo;
if (threadInfo->mTeb == NULL)
threadInfo->mTeb = (NT_TIB*)NtCurrentTeb();
}
if ((threadInfo->mStackBase == 0) || ((flags & BfpThreadInfoFlags_NoCache) != 0))
{
MEMORY_BASIC_INFORMATION stackInfo = { 0 };
// We subtract one page for our request. VirtualQuery rounds UP to the next page.
// Unfortunately, the stack grows down. If we're on the first page (last page in the
// VirtualAlloc), we'll be moved to the next page, which is off the stack! Note this
// doesn't work right for IA64 due to bigger pages.
void* currentAddr = (void*)((intptr_t)&stackInfo - 4096);
// Query for the current stack allocation information.
VirtualQuery(currentAddr, &stackInfo, sizeof(MEMORY_BASIC_INFORMATION));
threadInfo->mStackBase = (uintptr_t)threadInfo->mTeb->StackBase;
threadInfo->mStackLimit = (uintptr_t)stackInfo.AllocationBase;
}
*outStackBase = (intptr)threadInfo->mStackBase;
*outStackLimit = (int)(threadInfo->mStackBase - threadInfo->mStackLimit);
OUTRESULT(BfpThreadResult_Ok);
return;
}
///
BFP_EXPORT BfpCritSect* BFP_CALLTYPE BfpCritSect_Create() BFP_EXPORT BfpCritSect* BFP_CALLTYPE BfpCritSect_Create()
{ {
BfpCritSect* critSect = new BfpCritSect(); BfpCritSect* critSect = new BfpCritSect();

View file

@ -25,7 +25,7 @@ bool StackHelper::CanStackExpand(int wantBytes)
intptr stackBase = 0; intptr stackBase = 0;
int stackLimit = 0; int stackLimit = 0;
BfpThreadResult threadResult; BfpThreadResult threadResult;
BfpThread_GetStackInfo(NULL, &stackBase, &stackLimit, &threadResult); BfpThreadInfo_GetStackInfo(NULL, &stackBase, &stackLimit, BfpThreadInfoFlags_None, &threadResult);
if (threadResult != BfpThreadResult_Ok) if (threadResult != BfpThreadResult_Ok)
return true; return true;