コード例 #1
0
        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();
            }
        }
コード例 #2
0
        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;
        }
コード例 #3
0
        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;
        }
コード例 #4
0
        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;
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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();
            }
        }
コード例 #7
0
        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;
        }
コード例 #8
0
        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();
            }
        }
コード例 #9
0
        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();
            }
        }