internal override void CollectStoppable(int currentThreadIndex, int generation) { int foundIndex = Interlocked.CompareExchange(ref StopTheWorldGCData.collectorThreadIndex, currentThreadIndex, -1); if (foundIndex < 0) { // We are the designated collector thread PerformCollection(currentThreadIndex, generation); } else { Transitions.TakeDormantControlNoGC(currentThreadIndex); if (Transitions.TakeGCControl(currentThreadIndex)) { // The 'foundIndex' thread may have completed its // collection and another thread may have started // another collection after we read // 'collectorThreadIndex'. The collector thread may // have decided to wait for us before we entered // DormantState, so we have to read // 'collectorThreadIndex' again. foundIndex = collectorThreadIndex; if (foundIndex >= 0) { Thread.SignalGCEvent(foundIndex); } } Transitions.TakeMutatorControlNoGC(currentThreadIndex); } }
internal static void AllThreadRendezvous(int currentThreadIndex) { Transitions.MakeGCRequests(currentThreadIndex); for (int i = 0; i < Thread.threadTable.Length; i++) { if (Thread.threadTable[i] == null || i == currentThreadIndex) { continue; } CollectorStatistics.Event(GCEvent.StopThread, i); while (!Transitions.TakeGCControl(i) && !Transitions.UnderGCControl(i) && Transitions.HasGCRequest(i) && Thread.threadTable[i] != null) { // NOTE: there is no code in this loop that could // cause a signal on an event to be consumed. Thread.WaitForGCEvent(currentThreadIndex); } } }