浏览代码

Fixed GC race condition starting an autodelete thread

Brian Fiete 5 年之前
父节点
当前提交
b3354ee635
共有 5 个文件被更改,包括 39 次插入7 次删除
  1. 3 0
      BeefLibs/corlib/src/GC.bf
  2. 2 0
      BeefLibs/corlib/src/Threading/Thread.bf
  3. 25 1
      BeefRT/dbg/gc.cpp
  4. 5 2
      BeefRT/dbg/gc.h
  5. 4 4
      BeefRT/rt/Thread.cpp

+ 3 - 0
BeefLibs/corlib/src/GC.bf

@@ -131,6 +131,8 @@ namespace System
 		public extern static void SetCollectFreeThreshold(int freeBytes); // -1 to disable, 0 to trigger collection after every single free. Defaults to 64MB
 		[CallingConvention(.Cdecl)]
 		public extern static void SetMaxPausePercentage(int maxPausePercentage); // 0 = disabled. Defaults to 20.
+		[CallingConvention(.Cdecl)]
+		extern static void AddPendingThread(void* internalThread);
 #else
 		public static void Collect(bool async = true) {}
 		private static void MarkAllStaticMembers() {}
@@ -141,6 +143,7 @@ namespace System
 		public static void SetAutoCollectPeriod(int periodMS) {}
 		public static void SetCollectFreeThreshold(int freeBytes) {}
 		public static void SetMaxPausePercentage(int maxPausePercentage) {}
+		extern static void AddPendingThread(void* internalThreadInfo) {}
 #endif
 
 		static void MarkDerefedObject(Object* obj)

+ 2 - 0
BeefLibs/corlib/src/Threading/Thread.bf

@@ -41,6 +41,8 @@ namespace System.Threading
 
             static void Thread_SetInternalThread(Object thread, void* internalThread)
             {
+				if (internalThread != null)
+					GC.[Friend]AddPendingThread(internalThread);
                 ((Thread)thread).[Friend]mInternalThread = (int)internalThread;
             }
 

+ 25 - 1
BeefRT/dbg/gc.cpp

@@ -1389,7 +1389,17 @@ bool BFGC::ScanThreads()
 	while (true)
 	{
 		ThreadInfo* thread = NULL;
+		
+		///
+		{
+			AutoCrit autoCrit(mCritSect);
+			for (auto& kv : mPendingThreads)
+			{
+				MarkFromGCThread(kv.mValue->mThread);
+			}
+		}
 
+		///
 		{
 			AutoCrit autoCrit(mCritSect);
 			if (threadIdx >= mThreadList.size())
@@ -1927,7 +1937,7 @@ void BFGC::ThreadStopped(BfDbgInternalThread* thread)
 void BFGC::ThreadStarted()
 {
 	Beefy::AutoCrit autoCrit(mCritSect);
-
+	
 	ThreadInfo* thread = new ThreadInfo();
 	thread->mRunning = true;
 	thread->mThreadHandle = BfpThread_GetCurrent();
@@ -1938,6 +1948,7 @@ void BFGC::ThreadStarted()
 	thread->CalcStackStart();
 
 	mThreadList.Add(thread);
+	mPendingThreads.Remove(thread->mThreadId);
 
 	ThreadInfo::sCurThreadInfo = thread;
 }
@@ -2028,6 +2039,14 @@ void BFGC::RemoveStackMarkableObject(bf::System::Object* obj)
 		threadInfo->mStackMarkableObjects.RemoveAtFast(stackIdx);
 }
 
+void BFGC::AddPendingThread(BfInternalThread* internalThread)
+{
+	if (internalThread->mThread == 0)
+		return;
+	Beefy::AutoCrit autoCrit(mCritSect);
+	mPendingThreads.TryAdd(internalThread->mThreadId, internalThread);
+}
+
 void BFGC::Shutdown()
 {
 	if (mShutdown)
@@ -2710,6 +2729,11 @@ void GC::AddStackMarkableObject(Object* obj)
 	gBFGC.AddStackMarkableObject(obj);
 }
 
+void GC::AddPendingThread(void* internalThreadInfo)
+{
+	gBFGC.AddPendingThread((BfInternalThread*)internalThreadInfo);
+}
+
 void GC::RemoveStackMarkableObject(Object* obj)
 {
 	gBFGC.RemoveStackMarkableObject(obj);

+ 5 - 2
BeefRT/dbg/gc.h

@@ -199,7 +199,7 @@ public:
 		bool WantsSuspend();
 		void CalcStackStart();
 	};
-
+	
 	struct RawLeakInfo
 	{
 		bf::System::DbgRawAllocData* mRawAllocData;
@@ -324,6 +324,7 @@ public:
 	int mCurPendingGCSize;
 	int mMaxPendingGCSize;
 	Beefy::Array<ThreadInfo*> mThreadList;
+	Beefy::Dictionary<BfpThreadId, BfInternalThread*> mPendingThreads;
 	int mCurMutatorMarkCount;
 	int mCurGCMarkCount;
 	int mCurGCObjectQueuedCount;
@@ -390,6 +391,7 @@ public:
 	void StopCollecting();
 	void AddStackMarkableObject(bf::System::Object* obj);
 	void RemoveStackMarkableObject(bf::System::Object* obj);
+	void AddPendingThread(BfInternalThread* internalThread);
 	void Shutdown();	
 	void InitDebugDump();
 	void EndDebugDump();	
@@ -463,6 +465,7 @@ namespace bf
 			BFRT_EXPORT static void StopCollecting();
 			BFRT_EXPORT static void AddStackMarkableObject(Object* obj);
 			BFRT_EXPORT static void RemoveStackMarkableObject(Object* obj);
+			BFRT_EXPORT static void AddPendingThread(void* internalThreadInfo);
 			
 		public:
 			BFRT_EXPORT static void Shutdown();			
@@ -483,7 +486,7 @@ namespace bf
 			BFRT_EXPORT static void SetAutoCollectPeriod(intptr periodMS);
 			BFRT_EXPORT static void SetCollectFreeThreshold(intptr freeBytes);
 			BFRT_EXPORT static void SetMaxPausePercentage(intptr maxPausePercentage);
-			BFRT_EXPORT static void SetMaxRawDeferredObjectFreePercentage(intptr maxPercentage);
+			BFRT_EXPORT static void SetMaxRawDeferredObjectFreePercentage(intptr maxPercentage);			
 		};
 	}
 }

+ 4 - 4
BeefRT/rt/Thread.cpp

@@ -191,10 +191,10 @@ void Thread::StartInternal()
 	BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, 1);
 
 	BfInternalThread* internalThread = SetupInternalThread();
-	SetInternalThread(internalThread);
-			
-	internalThread->mThread = this;	
-	internalThread->mThreadHandle = BfpThread_Create(CStartProc, (void*)this, GetMaxStackSize(), BfpThreadCreateFlag_StackSizeReserve, &internalThread->mThreadId);
+	internalThread->mThread = this;
+	internalThread->mThreadHandle = BfpThread_Create(CStartProc, (void*)this, GetMaxStackSize(), (BfpThreadCreateFlags)(BfpThreadCreateFlag_StackSizeReserve | BfpThreadCreateFlag_Suspended), &internalThread->mThreadId);
+	SetInternalThread(internalThread);				
+	BfpThread_Resume(internalThread->mThreadHandle, NULL);
 }
 
 int Thread::GetThreadId()