internal override void NewThreadNotification(Thread newThread, bool initial) { base.NewThreadNotification(newThread, initial); if (CurrentPhase == StopTheWorldPhase.Synchronizing) { Transitions.MakeGCRequest(newThread.threadIndex); } }
internal static void CoCoLoop() { if (fDebug) { VTable.DebugPrint("coco thread = "); VTable.DebugPrint((ulong)Win32Native.GetCurrentThreadId()); VTable.DebugPrint("\n"); VTable.DebugPrint("CoCo at "); VTable.DebugPrint((ulong)Magic.addressOf(Thread.CurrentThread)); VTable.DebugPrint("\n"); } for (;;) { lock (interlock) { doingCoCo = false; for (;;) { if (die) { return; } else if (didStartTrace) { didStartTrace = false; Monitor.PulseAll(interlock); } else if (didEndTrace) { didEndTrace = false; Monitor.PulseAll(interlock); if (wantCoCo) { break; } } Monitor.Wait(interlock); } wantCoCo = false; } // now further tracing is BLOCKED cyclesStarted++; timingBefore = Environment.TickCount; if (fDebug) { VTable.DebugPrint("+++++ Start Concurrent Copying\n"); } CoCoBarrier.EnablePinning(); doingCoCo = true; ConcurrentMSCollector.stackMarkReferenceVisitor = CoCoMSCollector.nopStackMarker; ConcurrentMSCollector.stackMarkPinnedReferenceVisitor = CoCoMSCollector.pinStackMarker; // Perform a scan of all call stacks, including the call // stack of the CoCo thread. ConcurrentMSCollector.TrivialHandshake = false; ConcurrentMSCollector.IncludeMUWInHandshake = false; ConcurrentMSCollector.CollectorHandshake(cocoThread); // In order to scan the call stack of the current thread, // we need a TransitionRecord for the thread. At this // point we don't have one, so we have to go through // CollectBodyTransition to get one. Transitions.MakeGCRequest(cocoThread.threadIndex); GC.InvokeCollection(cocoThread); ConcurrentMSCollector.TrivialHandshake = true; ConcurrentMSCollector.IncludeMUWInHandshake = true; ConcurrentMSCollector.stackMarkReferenceVisitor = CoCoMSCollector.normalStackMarker; ConcurrentMSCollector.stackMarkPinnedReferenceVisitor = CoCoMSCollector.normalStackMarker; timingAfterPin = Environment.TickCount; if (fDebug) { VTable.DebugPrint("+++++ Copying\n"); } if (CoCoBarrier.instance.NeedsPrepPhase) { CoCoBarrier.ChangePhase(CoCoBarrier.Phase.Prep, false, true); } timingAfterPrep = Environment.TickCount; CoCoBarrier.ChangePhase(CoCoBarrier.Phase.Copy, true, true); numCopied += CoCoBarrier.instance.Copy(); CoCoBarrier.ChangePhase(CoCoBarrier.Phase.Fixup, true, true); AddCollectionRequest(); // wait for a complete collector cycle. This is for fixup. if (fDebug) { VTable.DebugPrint("+++++ Fixup: Waiting to start tracing\n"); } lock (interlock) { while (!didStartTrace && !die) { Monitor.Wait(interlock); } if (die) { return; } didStartTrace = false; inFixUp = true; Monitor.PulseAll(interlock); } if (fDebug) { VTable.DebugPrint("+++++ Fixup: Waiting to end tracing\n"); } lock (interlock) { while (!didEndTrace && !die) { Monitor.Wait(interlock); } if (die) { return; } didEndTrace = false; doingCoCo = false; inFixUp = false; Monitor.PulseAll(interlock); } timingAfter = Environment.TickCount; CoCoBarrier.ChangePhase(CoCoBarrier.Phase.Idle, false, false); if (fDebug) { VTable.DebugPrint("+++++ Finish Concurrent Copying\n"); } pinTime += (timingAfterPin - timingBefore); prepTime += (timingAfterPrep - timingAfterPin); copyTime += (timingAfterCopy - timingAfterPrep); forwardTime += (timingAfter - timingAfterCopy); cycles++; } }