Beispiel #1
0
        internal DesktopBlockingObject[] InitLockInspection()
        {
            if (_result != null)
            {
                return(_result);
            }

            // First, enumerate all thinlocks on the heap.
            foreach (var seg in _heap.Segments)
            {
                for (ulong obj = seg.FirstObject; obj != 0; obj = seg.NextObject(obj))
                {
                    ClrType type = _heap.GetObjectType(obj);
                    if (IsReaderWriterLock(obj, type))
                    {
                        _locks[obj] = CreateRWLObject(obj, type);
                    }
                    else if (IsReaderWriterSlim(obj, type))
                    {
                        _locks[obj] = CreateRWSObject(obj, type);
                    }

                    // Does this object have a syncblk with monitor associated with it?
                    if (!_heap.GetObjectHeader(obj, out uint header))
                    {
                        continue;
                    }

                    if ((header & (BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX | BIT_SBLK_SPIN_LOCK)) != 0)
                    {
                        continue;
                    }

                    uint threadId = header & SBLK_MASK_LOCK_THREADID;
                    if (threadId == 0)
                    {
                        continue;
                    }

                    ClrThread thread = _runtime.GetThreadFromThinlockID(threadId);
                    if (thread != null)
                    {
                        int recursion = ((int)header & SBLK_MASK_LOCK_RECLEVEL) >> SBLK_RECLEVEL_SHIFT;
                        _monitors[obj] = new DesktopBlockingObject(obj, true, recursion + 1, thread, BlockingReason.Monitor);
                    }
                }
            }

            // Enumerate syncblocks to find locks
            int syncblkCnt = _runtime.GetSyncblkCount();

            for (int i = 0; i < syncblkCnt; ++i)
            {
                ISyncBlkData data = _runtime.GetSyncblkData(i);
                if (data == null || data.Free)
                {
                    continue;
                }

                _syncblks[data.Address] = data.Object;
                _syncblks[data.Object]  = data.Object;
                ClrThread thread = null;
                if (data.MonitorHeld)
                {
                    ulong threadAddr = data.OwningThread;
                    foreach (var clrThread in _runtime.Threads)
                    {
                        if (clrThread.Address == threadAddr)
                        {
                            thread = clrThread;
                            break;
                        }
                    }
                }

                _monitors[data.Object] = new DesktopBlockingObject(data.Object, data.MonitorHeld, (int)data.Recursion, thread, BlockingReason.Monitor);
            }

            SetThreadWaiters();

            int total = _monitors.Count + _locks.Count + _joinLocks.Count + _waitLocks.Count;

            _result = new DesktopBlockingObject[total];

            int j = 0;

            foreach (DesktopBlockingObject blocker in _monitors.Values)
            {
                _result[j++] = blocker;
            }

            foreach (DesktopBlockingObject blocker in _locks.Values)
            {
                _result[j++] = blocker;
            }

            foreach (DesktopBlockingObject blocker in _joinLocks.Values)
            {
                _result[j++] = blocker;
            }

            foreach (DesktopBlockingObject blocker in _waitLocks.Values)
            {
                _result[j++] = blocker;
            }

            Debug.Assert(j == _result.Length);

            // Free up some memory.
            _monitors  = null;
            _locks     = null;
            _joinLocks = null;
            _waitLocks = null;
            _syncblks  = null;

            return(_result);
        }