Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
7.8 KiB

  1. //+-----------------------------------------------------------------------------
  2. //
  3. // File: lockperf.hxx
  4. //
  5. // Contents: class for lock monitoring for locks used by ole32.dll
  6. //
  7. // Classes: CLockPerfTracker
  8. //
  9. // History: 20-Dec-98 mprabhu Created
  10. //
  11. //------------------------------------------------------------------------------
  12. #ifndef _LOCKPERF_HXX_
  13. #define _LOCKPERF_HXX_
  14. #if LOCK_PERF==1
  15. // Max entries in the file-line table
  16. #define MAX_LOCKPERF_FILEENTRY 512
  17. // Max # of (different) locks tracked
  18. #define MAX_LOCKS 64
  19. //+-----------------------------------------------------------------------------
  20. //
  21. // Structure: CTlsLockPerf
  22. //
  23. // Synopsis: TlsEntry used when a lock is requested/held
  24. //
  25. //------------------------------------------------------------------------------
  26. struct CTlsLockPerf {
  27. void *_lpLockPtr;
  28. DWORD _dwFlags;
  29. ULONG _loc;
  30. ULONG _idx;
  31. DWORD _dwRecursion;
  32. LARGE_INTEGER _liRequest;
  33. LARGE_INTEGER _liEntered;
  34. };
  35. // Flags for TLS entries used when a lock is requested/held by a thread
  36. #define TLS_LOCKPERF_INUSE 0x00000001
  37. #define TLS_LOCKPERF_WAITING 0x00000010
  38. #define TLS_LOCKPERF_ENTERED 0x00000020
  39. // Max # of Tls Entries (== max # different locks a thread can hold at a time)
  40. #define TLS_LOCKPERF_MAX 8
  41. // LockPerf does not use OleTls, it allocates its own data during
  42. // Thread_Attach and frees it during Thread_Detach.
  43. // These two functions are used for the purpose.
  44. HRESULT AllocLockPerfPvtTlsData();
  45. void FreeLockPerfPvtTlsData();
  46. // TlsIndex allocated during Process_Attach (DllMain)
  47. extern DWORD gTlsLockPerfIndex;
  48. //+-----------------------------------------------------------------------------
  49. //
  50. // Structure: CTlsLockPerf
  51. //
  52. // Synopsis: Represents a critical section guarded by a lock at a {file, line}
  53. // in the code.
  54. //
  55. //------------------------------------------------------------------------------
  56. class CFileLineEntry {
  57. public:
  58. DWORD dwNext; // wsed to chain data by LockName (i.e. by lpLockPtr).
  59. BOOL bWriteCritSec; // are we writing to shared data at this location?
  60. ULONG ulLockTableIdx; // index in the lock table for lpLockPtr
  61. DWORD dwLine; // Line number, eg. 2345
  62. const char *pszFile; // File name, eg. d:\nt\private\ole32\com\dcomrem\marshal.cxx
  63. const char *pszLockName; // Name of the lock, eg. gComLock
  64. void *lpLockPtr; // Critical section used by the lock.
  65. DWORD dwNumEntrys; // Count of visits to this {file,line} by all threads.
  66. DWORD dwWaitTime; // cumulative waiting time at this {file,line} entry point
  67. DWORD dwLockedTime; // cumulative locked time.
  68. DWORD dwContentionCount; // obtained from the lock.
  69. DWORD dwAvgTime; // average time spent in this critical section.
  70. };
  71. //+-----------------------------------------------------------------------------
  72. //
  73. // Structure: CLockEntry
  74. //
  75. // Synopsis: Stores data for each individual lock object
  76. //
  77. //------------------------------------------------------------------------------
  78. // This is used for cumulative data and for reader-writer locks when different
  79. // reader threads could be at different locations in the code at a time.
  80. // We keep track of the time when the first thread entered and the time the last
  81. // thread left (possibly at different code locations) so as to calculate
  82. // a shared lock time.
  83. class CLockEntry {
  84. public:
  85. void *lpLockPtr; // the lock this entry represents
  86. const char *pszLockName; // name of the lock
  87. DWORD dwHead; // these two are used to chain the data by
  88. DWORD dwTail; // LockName in the _LockPerfData array.
  89. DWORD dwTotalWriteWaitTime; // total write wait time.
  90. DWORD dwTotalWriteLockTime; // overall time spent holding this lock for Writes.
  91. DWORD dwTotalWriteEntrys; // total write entry count for this lock.
  92. DWORD dwTotalReadWaitTime; // total read wait time.
  93. DWORD dwTotalReadLockTime; // overall time spent holding this lock for Reads.
  94. DWORD dwTotalReadEntrys; // total read entry count for this lock.
  95. DWORD dwWriterContentionCount; // overall write contention for this lock.
  96. DWORD dwReaderContentionCount; // overall read contention for this lock.
  97. DWORD dwSharedTime; // cumulative shared time
  98. DWORD dwNumReaders; // count of simultaneous readers in the lock
  99. LARGE_INTEGER liEntered; // time when the first reader entered this lock.
  100. };
  101. //+-----------------------------------------------------------------------------
  102. //
  103. // Class: CLockPerfTracker
  104. //
  105. // Synopsis: Exposes lock monitoring functionality.
  106. //
  107. //------------------------------------------------------------------------------
  108. //
  109. // This is the main lock tracking class. We just have one object called gLockTracker
  110. // of this class. All locks interested in timing data must Register themselves before
  111. // use and call appropriate methods eg. gLockTrack.ReaderWaiting ... etc.
  112. // A lock is responsible for maintaining Contention counts (and optionally entry counts).
  113. // These must be reported before the lock is destroyed.
  114. //
  115. class CLockPerfTracker {
  116. public:
  117. // called by the lock instance creation function.
  118. void RegisterLock(void *lpLockPtr, BOOL bReadWrite);
  119. // called by the lock code as its state changes depending upon the request
  120. // bWriter argument of WriterWaiting and WriterEntered is only used internally.
  121. void ReaderWaiting(const char*pszFile, DWORD dwLine, const char* pszLockName, void *lpLockPtr);
  122. void WriterWaiting(const char*pszFile, DWORD dwLine, const char* pszLockName, void *lpLockPtr, BOOL bWriter=TRUE);
  123. void ReaderEntered(const char*pszFile, DWORD dwLine, const char* pszLockName, void *lpLockPtr);
  124. void WriterEntered(const char*pszFile, DWORD dwLine, const char* pszLockName, void *lpLockPtr, BOOL bWriter=TRUE);
  125. void ReaderLeaving(void *lpLockPtr);
  126. void WriterLeaving(void *lpLockPtr);
  127. // called by the lock instance prior to destruction/cleanup
  128. void ReportContention(void *lpLockPtr, DWORD dwWriteEntrys, DWORD dwWriteContention, DWORD dwReadEntrys, DWORD dwReadContention);
  129. // called during Process_Attach to initialize statics
  130. HRESULT Init();
  131. // called during Process_Detach to report the timing information
  132. void OutputPerfData();
  133. private:
  134. // internal functions used by the tracker
  135. ULONG FindOrCreateFileTableEntry(const char*pszFile, DWORD dwLine, const char* pszLockName, void *lpLockPtr, BOOL bWriter, ULONG *lpIdx);
  136. ULONG FindLockTableEntry(void *lpLockPtr);
  137. void ProcessPerfData();
  138. void UpdateFileTableEntry(CTlsLockPerf *pTlsEntry, LARGE_INTEGER *pLiUnlock);
  139. void OutputFileTableEntry(ULONG index, ULONG bByName, ULONG percent);
  140. void UpdateHoggers(ULONG* hogList, ULONG index, ULONG listType);
  141. void OutputHoggers(ULONG *list);
  142. // These are the tables that lock data is collected in.
  143. // Each entry in _FileLineData corresponds to a code critical section.
  144. // ({File, line} where the lock is entered).
  145. static CFileLineEntry _FileLineData[MAX_LOCKPERF_FILEENTRY];
  146. // Each entry in _LockData corresponds to a lock eg. gIPIDLock
  147. static CLockEntry _LockData[MAX_LOCKS];
  148. static LARGE_INTEGER _liFreq; // Performance Frequency on the system
  149. static ULONG _numCritSecs; // count of {file,line} critical sections monitored
  150. static ULONG _numLocks; // count of distinct locks being monitored
  151. };
  152. // single global object
  153. extern CLockPerfTracker gLockTracker;
  154. #endif //LOCK_PERF==1
  155. #endif //_LOCKPERF_HXX_