コード例 #1
0
ファイル: Finalizer.cs プロジェクト: Paul1nh0/Singularity
        void VisitBootstrapData(DirectReferenceVisitor visitor)
        {
#if !(REFERENCE_COUNTING_GC || DEFERRED_REFERENCE_COUNTING_GC)
            VisitAllRunFinalizer(visitor, true, false);

            // Trace other GC data. Being careful to NOT trace the Shadow
            visitor.VisitReferenceFields(CandidateTable);
            visitor.VisitReferenceFields(RunFinalizerTable);
            visitor.VisitReferenceFields(RunFinalizerTable[0]);
#endif // REFERENCE_COUNTING_GC
        }
コード例 #2
0
ファイル: Finalizer.cs プロジェクト: Paul1nh0/Singularity
        void ResurrectCandidates(DirectReferenceVisitor forwardVisitor,
                                 DirectReferenceVisitor resurrectVisitor,
                                 bool copyFirst)
        {
#if !(REFERENCE_COUNTING_GC || DEFERRED_REFERENCE_COUNTING_GC)
            UIntPtr[] runTable      = null;
            int       runTableIndex = 0;
            int       runIndex      = 0;

            // For the concurrent collector, ResurrectCandidates could happen
            // while the application threads are calling SuppressFinalize and
            // ReRegisterForFinalize.  So we need to use the spinLock to prevent
            // races.  But we do not want to hold the spinLock while allocating
            // (i.e. when we grow the RunFinalizerTable[Shadow]) because our
            // spinLock is a leaf lock.  We don't want to worry about deadlocks
            // involving the spinLock and any locking that occurs as part of a
            // GC provoked by an allocation attempt.
#if SINGULARITY
            bool disabled = Processor.DisableLocalPreemption();
#endif
            spinLock.Acquire();
            bool lockHeld = true;
            try {
                int logicalIndex = 0;
                for (int i = 0; i < CandidateTableShadow.Length; i++)
                {
                    UIntPtr[] table = copyFirst
                      ? CandidateTable[i]
                      : CandidateTableShadow[i];

                    if (table == null)
                    {
                        VTable.Assert(logicalIndex == lastCandidateIndex);
                        break;
                    }
                    for (int j = 0; j < table.Length; j++, logicalIndex++)
                    {
                        if (table[j] == UIntPtr.Zero)
                        {
                            VTable.Assert(logicalIndex == lastCandidateIndex);
                            break;
                        }
                        fixed(UIntPtr *loc = &table[j])
                        {
                            if (!IsLink((int)*loc))
                            {
                                UIntPtr oldVal = *loc;
                                forwardVisitor.Visit(loc);
                                if (*loc == UIntPtr.Zero)
                                {
                                    // Put this slot onto the CandidateTable's free list
                                    *loc = (UIntPtr)freeCandidateLink;
                                    freeCandidateLink = IndexToLink(logicalIndex);

                                    // marching forward through the RunFinalizer[Shadow] table, find an
                                    // empty slot to install this object.  Maintain the cursor across
                                    // objects, so we can efficiently transfer an entire batch.

                                    for (; runTableIndex < RunFinalizerTableShadow.Length; runTableIndex++)
                                    {
                                        runTable = copyFirst
                                          ? RunFinalizerTable[runTableIndex]
                                          : RunFinalizerTableShadow[runTableIndex];

                                        if (runTable == null)
                                        {
                                            // Create a new table
                                            int length = RunFinalizerTableShadow[runTableIndex - 1].Length * 2;

                                            lockHeld = false;
                                            spinLock.Release();
#if SINGULARITY
                                            Processor.RestoreLocalPreemption(disabled);
#endif
                                            UIntPtr[] newTable = new UIntPtr[length];
#if SINGULARITY
                                            disabled = Processor.DisableLocalPreemption();
#endif
                                            spinLock.Acquire();
                                            lockHeld = true;

                                            // There is no race with the RunFinalizerTable[Shadow].
                                            // The spinLock serializes access to the CandidateTable[Shadow].
                                            runTable = newTable;
                                            RunFinalizerTable[runTableIndex]       = newTable;
                                            RunFinalizerTableShadow[runTableIndex] = newTable;
                                            UIntPtr tableAddr = Magic.addressOf(newTable);
                                            resurrectVisitor.Visit(&tableAddr);
                                            resurrectVisitor.VisitReferenceFields(RunFinalizerTable[runTableIndex]);
                                            resurrectVisitor.VisitReferenceFields(RunFinalizerTableShadow[runTableIndex]);
                                        }

                                        for (; runIndex < runTable.Length; runIndex++)
                                        {
                                            if (runTable[runIndex] == UIntPtr.Zero)
                                            {
                                                goto outer;
                                            }
                                        }
                                        runIndex -= runTable.Length;
                                        VTable.Assert(runIndex == 0);   // ready for next sub-table
                                    }
outer:
                                    // We found an empty slot in the RunFinalizerTable[Shadow],
                                    // where we can put our ready Candidate.  It's also possible
                                    // to reach this label by falling through after exhausting the
                                    // entire table.  This will result in an exception when we
                                    // attempt to over-index the array.  It's not clear what more
                                    // protections are required... the process has exceeded an
                                    // unlikely and hard-wired capacity limit.
                                    Interlocked.Increment(ref WaitingToRun);
                                    madeRunnable = true;

                                    if (copyFirst)
                                    {
                                        RunFinalizerTable[runTableIndex][runIndex]
                                            = oldVal | new UIntPtr(1);
                                    }
                                    else
                                    {
                                        RunFinalizerTableShadow[runTableIndex][runIndex]
                                            = oldVal | new UIntPtr(1);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            finally {
                if (lockHeld)
                {
                    spinLock.Release();
#if SINGULARITY
                    Processor.RestoreLocalPreemption(disabled);
#endif
                }
            }

            if (madeRunnable)
            {
                // Resurrect objects!
                VisitAllRunFinalizer(resurrectVisitor, copyFirst, true);
            }
#endif // REFERENCE_COUNTING_GC
        }