static internal unsafe void ThawAllProcessors() { // This method is only called on MP systems when the // number of running processors is greater than 1. freezeLock.Acquire(); try { if (FreezeRequested == false) { return; } freezeCount--; if (freezeCount != 0) { return; } FreezeRequested = false; ProcessorContext *context = activeCpuContext; do { context->ipiFreeze = TargetThaw; context = context->nextProcessorContext; } while (context != activeCpuContext); } finally { freezeLock.Release(); } }
static internal unsafe void GCSynchronizationInterrupt() { // - member barriers and other issues with spinwaiting on a variable bool en = Processor.DisableInterrupts(); //DebugStub.WriteLine("Processor {0} received GCSynchronizationInterrupt!\n", //__arglist(Processor.GetCurrentProcessorId())); ProcessorContext *current = Processor.GetCurrentProcessorContext(); // Write value for this processor stating we ackknowledge the interrupt current->gcIpiGate = 1; // Question: Are we at a GC safe point? For all GC's? // // Spinwait until the GC processor indicates its done by clearing // this flag. // while (current->gcIpiGate != 0) { // } Processor.RestoreInterrupts(en); //DebugStub.WriteLine("Processor {0} done with GCSynchronizationInterrupt!\n", //__arglist(Processor.GetCurrentProcessorId())); return; }
static internal unsafe void StopProcessorsForGC() { ProcessorContext *current = Processor.GetCurrentProcessorContext(); // Set gcIpiGate to 0 for all processors ProcessorContext *context = current; do { context->gcIpiGate = 0; context = context->nextProcessorContext; } while (context != current); // // We don't want to send a broadcast to all but self on a single // processor system since the call will fail with no receivers. // // Note we may have other processors that have not been enabled // by the OS and are sitting in SIPI, and won't answer the IPI. // if (Processor.GetRunningProcessorCount() > 1) { Platform.BroadcastFixedIPI((byte)Isal.IX.EVectors.GCSynchronization, false); } // Wait for ackknowledgement from all CPU's but self context = current->nextProcessorContext; //DebugStub.WriteLine("StopProcessorsForGC: GC CPU (sender) is {0}\n", //__arglist(current->cpuId)); while (context != current) { //DebugStub.WriteLine("StopProcessorsForGC: Waiting for CPU {0}\n", //__arglist(context->cpuId)); while (context->gcIpiGate == 0) { ; } //DebugStub.WriteLine("StopProcessorsForGC: CPU {0} Acknowledged\n", //__arglist(context->cpuId)); context = context->nextProcessorContext; } return; }
static internal unsafe void ResumeProcessorsAfterGC() { // clear the GC wait flag for each CPU ProcessorContext *current = Processor.GetCurrentProcessorContext(); ProcessorContext *context = current; do { context->gcIpiGate = 0; context = context->nextProcessorContext; } while (context != current); //DebugStub.WriteLine("ResumeProcessorsAfterGC: All processors resumed\n"); return; }
static internal unsafe bool SwitchFrozenProcessor(int cpuId) { ProcessorContext *currentContext = Processor.GetCurrentProcessorContext(); if (currentContext->cpuRecord.id == cpuId) { // No processor to switch to. return(false); } ProcessorContext *context = currentContext->nextProcessorContext; do { if (context->cpuRecord.id == cpuId) { currentContext->ipiFreeze &= ~FreezeActive; context->ipiFreeze |= FreezeActive; goto WaitForWakeupOrReselection; } context = context->nextProcessorContext; } while (context != activeCpuContext); // cpuId not found so no processor to switch to. return(false); WaitForWakeupOrReselection: // If this processor is in the frozen state already, return // (it'll fall back into FreezeProcessor() loop). NB Initiating // processor can never be in this state. if (currentContext->ipiFreeze == TargetFrozen) { return(true); } // This processor is the freeze owner, wait to be // reselected as the active processor. while ((currentContext->ipiFreeze & FreezeActive) != FreezeActive) { ; } return(false); }
static internal unsafe void FreezeAllProcessors() { // This method is only called on MP systems when the // number of running processors is greater than 1. freezeLock.Acquire(); try { freezeCount++; if (FreezeRequested == true) { // Processors are already frozen return; } ownerCpuContext = Processor.GetCurrentProcessorContext(); activeCpuContext = ownerCpuContext; if (activeCpuContext->nextProcessorContext == activeCpuContext) { return; } FreezeRequested = true; activeCpuContext->ipiFreeze = FreezeActive | FreezeOwner; // Generate an NMI on all processors (except this one) Platform.ThePlatform.FreezeAllCpus(); // Wait until all running processors have gone into freeze ProcessorContext *context = activeCpuContext->nextProcessorContext; do { if ((context->ipiFreeze & (TargetFrozen | FreezeActive)) != 0) { context = context->nextProcessorContext; } } while (context != activeCpuContext); } finally { freezeLock.Release(); } }
FreezeProcessor(ref SpillContext threadContext) { ProcessorContext *context = Processor.GetCurrentProcessorContext(); if (context->ipiFreeze == Uninitialized) { // Processor was still being initialized when IPI issued while (FreezeRequested == true) { ; // just spin until thaw occurs } return; } context->ipiFreeze = TargetFrozen; while (context->ipiFreeze != TargetThaw && FreezeRequested) { if ((context->ipiFreeze & FreezeActive) == FreezeActive) { // // This processor has been made the active processor // activeCpuContext = context; // Pass state over to debugger stub if (DebugStub.TrapForProcessorSwitch(ref threadContext)) { // We're returning to Freeze owner, make it active context->ipiFreeze &= ~FreezeActive; ownerCpuContext->ipiFreeze |= FreezeActive; } } } context->ipiFreeze = Running; }
static internal unsafe void FreezeAllProcessors() { freezeLock.Acquire(); try { freezeCount++; if (FreezeRequested == true) { // Processors are already frozen return; } ownerCpuContext = Processor.GetCurrentProcessorContext(); activeCpuContext = ownerCpuContext; if (activeCpuContext->displacedProcessorContext->nextProcessorContext == activeCpuContext) { return; } FreezeRequested = true; activeCpuContext->displacedProcessorContext->ipiFreeze = FreezeActive | FreezeOwner; //TODOMP Platform.FreezeProcessors(); // Wait until all running processors have gone into freeze ProcessorContext *context = activeCpuContext->displacedProcessorContext->nextProcessorContext; do { if ((context->displacedProcessorContext->ipiFreeze & (TargetFrozen | FreezeActive)) != 0) { context = context->displacedProcessorContext->nextProcessorContext; } } while (context->displacedProcessorContext->nextProcessorContext != activeCpuContext); } finally { freezeLock.Release(); } }
static internal unsafe void AddProcessorContext(ProcessorContext *context) { // Add processor to list of processors in MP system. Careful // to avoid adding processor mid-freeze or without lock. start: freezeLock.Acquire(); try { if (FreezeRequested) { goto start; } ProcessorContext *head = Processor.processorTable[0].context; context->nextProcessorContext = head->nextProcessorContext; head->nextProcessorContext = context; context->ipiFreeze = Running; // From this point on the processor is visible // in the debugger DebugStub.AddProcessor(context->cpuRecord.id); } finally { freezeLock.Release(); } }