Пример #1
0
 private static string KindString(this BlockingReason kind)
 {
     switch (kind)
     {
         case BlockingReason.None:
             return "None";
         case BlockingReason.Unknown:
             return "Unknown";
         case BlockingReason.Monitor:
             return "Monitor";
         case BlockingReason.MonitorWait:
             return "MonitorWait";
         case BlockingReason.WaitOne:
             return "WaitOne";
         case BlockingReason.WaitAll:
             return "WaitAll";
         case BlockingReason.WaitAny:
             return "WaitAny";
         case BlockingReason.ThreadJoin:
             return "ThreadJoin";
         case BlockingReason.ReaderAcquired:
             return "ReaderAcquired";
         case BlockingReason.WriterAcquired:
             return "WriterAcquired";
         default:
             return "Unknown";
     }
 }
Пример #2
0
 public DesktopBlockingObject(ulong obj, bool locked, int recursion, BlockingReason reason)
 {
     Object         = obj;
     _locked        = locked;
     RecursionCount = recursion;
     _reason        = reason;
 }
Пример #3
0
 public DesktopBlockingObject(ulong obj, bool locked, int recursion, BlockingReason reason, ClrThread[] owners)
 {
     Object         = obj;
     _locked        = locked;
     RecursionCount = recursion;
     _reason        = reason;
     _owners        = owners;
 }
Пример #4
0
 public DesktopBlockingObject(ulong obj, bool locked, int recursion, ClrThread owner, BlockingReason reason)
 {
     Object         = obj;
     _locked        = locked;
     RecursionCount = recursion;
     _reason        = reason;
     _owners        = new ClrThread[1];
     _owners[0]     = owner;
 }
Пример #5
0
 private ClrtBlkObject(ulong address, bool taken, BlockingReason blkReason, int recursionCnt, int typeId, int blockInfoNdx)
 {
     _address      = address;
     _recursionCnt = recursionCnt;
     _blkReason    = blkReason;
     _taken        = taken;
     _index        = blockInfoNdx;
     _typeId       = typeId;
 }
Пример #6
0
 /// <summary>
 /// Create instance of our version BlockingObject.
 /// </summary>
 /// <param name="bo">Instance of BlockingObject from ClrHeap.</param>
 /// <param name="blockInfoNdx">Index of the owners,waiters information.</param>
 /// <param name="typeId">Type of this object.</param>
 public ClrtBlkObject(BlockingObject bo, int blockInfoNdx, int typeId)
 {
     _address      = bo.Object;
     _recursionCnt = bo.RecursionCount;
     _blkReason    = bo.Reason;
     _taken        = bo.Taken;
     _index        = blockInfoNdx;
     _typeId       = typeId;
 }
Пример #7
0
        public static ClrtBlkObject Load(BinaryReader bw)
        {
            ulong          addr         = bw.ReadUInt64();
            int            recursionCnt = bw.ReadInt32();
            BlockingReason blkReason    = (BlockingReason)bw.ReadInt32();
            int            blockInfoNdx = bw.ReadInt32();
            int            typeId       = bw.ReadInt32();
            bool           taken        = bw.ReadBoolean();

            return(new ClrtBlkObject(addr, taken, blkReason, recursionCnt, typeId, blockInfoNdx));
        }
Пример #8
0
        private void SetThreadWaiters()
        {
            HashSet <string>      eventTypes = null;
            List <BlockingObject> blobjs     = new List <BlockingObject>();

            foreach (DesktopThread thread in _runtime.Threads)
            {
                int max = thread.StackTrace.Count;
                if (max > 10)
                {
                    max = 10;
                }

                blobjs.Clear();
                for (int i = 0; i < max; ++i)
                {
                    DesktopBlockingObject blockingObj = null;
                    ClrMethod             method      = thread.StackTrace[i].Method;
                    if (method == null)
                    {
                        continue;
                    }

                    ClrType type = method.Type;
                    if (type == null)
                    {
                        continue;
                    }

                    switch (method.Name)
                    {
                    case "AcquireWriterLockInternal":
                    case "FCallUpgradeToWriterLock":
                    case "UpgradeToWriterLock":
                    case "AcquireReaderLockInternal":
                    case "AcquireReaderLock":
                        if (type.Name == "System.Threading.ReaderWriterLock")
                        {
                            blockingObj = FindLocks(thread.StackLimit, thread.StackTrace[i].StackPointer, IsReaderWriterLock);
                            if (blockingObj == null)
                            {
                                blockingObj = FindLocks(thread.StackTrace[i].StackPointer, thread.StackBase, IsReaderWriterLock);
                            }

                            if (blockingObj != null && (blockingObj.Reason == BlockingReason.Unknown || blockingObj.Reason == BlockingReason.None))
                            {
                                // This should have already been set correctly when the BlockingObject was created.  This is just a best-guess.
                                if (method.Name == "AcquireReaderLockInternal" || method.Name == "AcquireReaderLock")
                                {
                                    blockingObj.Reason = BlockingReason.WriterAcquired;
                                }
                                else
                                {
                                    blockingObj.Reason = BlockingReason.ReaderAcquired;
                                }
                            }
                        }
                        break;

                    case "TryEnterReadLockCore":
                    case "TryEnterReadLock":
                    case "TryEnterUpgradeableReadLock":
                    case "TryEnterUpgradeableReadLockCore":
                    case "TryEnterWriteLock":
                    case "TryEnterWriteLockCore":
                        if (type.Name == "System.Threading.ReaderWriterLockSlim")
                        {
                            blockingObj = FindLocks(thread.StackLimit, thread.StackTrace[i].StackPointer, IsReaderWriterSlim);
                            if (blockingObj == null)
                            {
                                blockingObj = FindLocks(thread.StackTrace[i].StackPointer, thread.StackBase, IsReaderWriterSlim);
                            }


                            if (blockingObj != null && (blockingObj.Reason == BlockingReason.Unknown || blockingObj.Reason == BlockingReason.None))
                            {
                                // This should have already been set correctly when the BlockingObject was created.  This is just a best-guess.
                                if (method.Name == "TryEnterWriteLock" || method.Name == "TryEnterWriteLockCore")
                                {
                                    blockingObj.Reason = BlockingReason.ReaderAcquired;
                                }
                                else
                                {
                                    blockingObj.Reason = BlockingReason.WriterAcquired;
                                }
                            }
                        }

                        break;

                    case "JoinInternal":
                    case "Join":
                        if (type.Name == "System.Threading.Thread")
                        {
                            if (FindThread(thread.StackLimit, thread.StackTrace[i].StackPointer, out ulong threadAddr, out ClrThread target) ||
                                FindThread(thread.StackTrace[i].StackPointer, thread.StackBase, out threadAddr, out target))
                            {
                                if (!_joinLocks.TryGetValue(target, out blockingObj))
                                {
                                    _joinLocks[target] = blockingObj = new DesktopBlockingObject(threadAddr, true, 0, target, BlockingReason.ThreadJoin);
                                }
                            }
                        }
                        break;

                    case "Wait":
                    case "ObjWait":
                        if (type.Name == "System.Threading.Monitor")
                        {
                            blockingObj = FindMonitor(thread.StackLimit, thread.StackTrace[i].StackPointer);
                            if (blockingObj == null)
                            {
                                blockingObj = FindMonitor(thread.StackTrace[i].StackPointer, thread.StackBase);
                            }

                            blockingObj.Reason = BlockingReason.MonitorWait;
                        }
                        break;

                    case "WaitAny":
                    case "WaitAll":
                        if (type.Name == "System.Threading.WaitHandle")
                        {
                            ulong obj = FindWaitObjects(thread.StackLimit, thread.StackTrace[i].StackPointer, "System.Threading.WaitHandle[]");
                            if (obj == 0)
                            {
                                obj = FindWaitObjects(thread.StackTrace[i].StackPointer, thread.StackBase, "System.Threading.WaitHandle[]");
                            }

                            if (obj != 0)
                            {
                                BlockingReason reason = method.Name == "WaitAny" ? BlockingReason.WaitAny : BlockingReason.WaitAll;
                                if (!_waitLocks.TryGetValue(obj, out blockingObj))
                                {
                                    _waitLocks[obj] = blockingObj = new DesktopBlockingObject(obj, true, 0, null, reason);
                                }
                            }
                        }
                        break;

                    case "WaitOne":
                    case "InternalWaitOne":
                    case "WaitOneNative":
                        if (type.Name == "System.Threading.WaitHandle")
                        {
                            if (eventTypes == null)
                            {
                                eventTypes = new HashSet <string>
                                {
                                    "System.Threading.Mutex",
                                    "System.Threading.Semaphore",
                                    "System.Threading.ManualResetEvent",
                                    "System.Threading.AutoResetEvent",
                                    "System.Threading.WaitHandle",
                                    "Microsoft.Win32.SafeHandles.SafeWaitHandle"
                                };
                            }

                            ulong obj = FindWaitHandle(thread.StackLimit, thread.StackTrace[i].StackPointer, eventTypes);
                            if (obj == 0)
                            {
                                obj = FindWaitHandle(thread.StackTrace[i].StackPointer, thread.StackBase, eventTypes);
                            }

                            if (obj != 0)
                            {
                                if (_waitLocks == null)
                                {
                                    _waitLocks = new Dictionary <ulong, DesktopBlockingObject>();
                                }

                                if (!_waitLocks.TryGetValue(obj, out blockingObj))
                                {
                                    _waitLocks[obj] = blockingObj = new DesktopBlockingObject(obj, true, 0, null, BlockingReason.WaitOne);
                                }
                            }
                        }
                        break;


                    case "TryEnter":
                    case "ReliableEnterTimeout":
                    case "TryEnterTimeout":
                    case "ReliableEnter":
                    case "Enter":
                        if (type.Name == "System.Threading.Monitor")
                        {
                            blockingObj = FindMonitor(thread.StackLimit, thread.StackTrace[i].StackPointer);
                            if (blockingObj != null)
                            {
                                blockingObj.Reason = BlockingReason.Monitor;
                            }
                        }
                        break;
                    }


                    if (blockingObj != null)
                    {
                        bool alreadyEncountered = false;
                        foreach (var blobj in blobjs)
                        {
                            if (blobj.Object == blockingObj.Object)
                            {
                                alreadyEncountered = true;
                                break;
                            }
                        }

                        if (!alreadyEncountered)
                        {
                            blobjs.Add(blockingObj);
                        }
                    }
                }

                foreach (DesktopBlockingObject blobj in blobjs)
                {
                    blobj.AddWaiter(thread);
                }
                thread.SetBlockingObjects(blobjs.ToArray());
            }
        }