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.

315 lines
8.0 KiB

  1. /*++
  2. Copyright (c) 2001-2001 Microsoft Corporation
  3. Module Name:
  4. ownerref.cxx
  5. Abstract:
  6. This module implements a reference count tracing facility.
  7. Author:
  8. Keith Moore (keithmo) 10-Jun-1998
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. // Globals
  13. LIST_ENTRY g_OwnerRefTraceLogGlobalListHead;
  14. UL_SPIN_LOCK g_OwnerRefTraceLogGlobalSpinLock;
  15. LONG g_OwnerRefTraceLogGlobalCount;
  16. VOID
  17. UlInitializeOwnerRefTraceLog(
  18. VOID)
  19. {
  20. InitializeListHead(&g_OwnerRefTraceLogGlobalListHead);
  21. UlInitializeSpinLock( &g_OwnerRefTraceLogGlobalSpinLock,
  22. "OwnerRefTraceLogGlobal" );
  23. g_OwnerRefTraceLogGlobalCount = 0;
  24. } // UlInitializeOwnerRefTraceLog
  25. VOID
  26. UlTerminateOwnerRefTraceLog(
  27. VOID)
  28. {
  29. ASSERT( IsListEmpty(&g_OwnerRefTraceLogGlobalListHead) );
  30. ASSERT( 0 == g_OwnerRefTraceLogGlobalCount );
  31. } // UlTerminateOwnerRefTraceLog
  32. #if ENABLE_OWNER_REF_TRACE
  33. POWNER_REF_TRACELOG
  34. CreateOwnerRefTraceLog(
  35. IN ULONG LogSize,
  36. IN ULONG ExtraBytesInHeader
  37. )
  38. {
  39. POWNER_REF_TRACELOG pOwnerRefTraceLog = NULL;
  40. PTRACE_LOG pTraceLog
  41. = CreateTraceLog(
  42. OWNER_REF_TRACELOG_SIGNATURE,
  43. LogSize,
  44. sizeof(OWNER_REF_TRACELOG)
  45. - FIELD_OFFSET(OWNER_REF_TRACELOG, OwnerHeader)
  46. + ExtraBytesInHeader,
  47. sizeof(OWNER_REF_TRACE_LOG_ENTRY)
  48. );
  49. if (pTraceLog != NULL)
  50. {
  51. pOwnerRefTraceLog = (POWNER_REF_TRACELOG) pTraceLog;
  52. ASSERT(pOwnerRefTraceLog->TraceLog.TypeSignature
  53. == OWNER_REF_TRACELOG_SIGNATURE);
  54. InitializeListHead(&pOwnerRefTraceLog->OwnerHeader.ListHead);
  55. UlInitializeSpinLock( &pOwnerRefTraceLog->OwnerHeader.SpinLock,
  56. "OwnerRefTraceLog" );
  57. pOwnerRefTraceLog->OwnerHeader.MonotonicId = 0;
  58. pOwnerRefTraceLog->OwnerHeader.OwnersCount = 0;
  59. // insert into global list
  60. ExInterlockedInsertTailList(
  61. &g_OwnerRefTraceLogGlobalListHead,
  62. &pOwnerRefTraceLog->OwnerHeader.GlobalListEntry,
  63. KSPIN_LOCK_FROM_UL_SPIN_LOCK(&g_OwnerRefTraceLogGlobalSpinLock)
  64. );
  65. InterlockedIncrement(&g_OwnerRefTraceLogGlobalCount);
  66. }
  67. return pOwnerRefTraceLog;
  68. } // CreateOwnerRefTraceLog
  69. PREF_OWNER
  70. NewRefOwner(
  71. POWNER_REF_TRACELOG pOwnerRefTraceLog,
  72. PVOID pOwner,
  73. IN PPREF_OWNER ppRefOwner,
  74. IN ULONG OwnerSignature
  75. )
  76. {
  77. PREF_OWNER pRefOwner;
  78. ASSERT( UlDbgSpinLockOwned( &pOwnerRefTraceLog->OwnerHeader.SpinLock ) );
  79. pRefOwner = UL_ALLOCATE_STRUCT(
  80. NonPagedPool,
  81. REF_OWNER,
  82. UL_OWNER_REF_POOL_TAG
  83. );
  84. if (pRefOwner != NULL)
  85. {
  86. int i;
  87. pRefOwner->Signature = OWNER_REF_SIGNATURE;
  88. pRefOwner->OwnerSignature = OwnerSignature;
  89. InsertTailList(
  90. &pOwnerRefTraceLog->OwnerHeader.ListHead,
  91. &pRefOwner->ListEntry
  92. );
  93. ++pOwnerRefTraceLog->OwnerHeader.OwnersCount;
  94. pRefOwner->pOwner = pOwner;
  95. pRefOwner->pOwnerRefTraceLog = pOwnerRefTraceLog;
  96. pRefOwner->RelativeRefCount = 0;
  97. pRefOwner->OwnedNextEntry = -1;
  98. for (i = 0; i < OWNED_REF_NUM_ENTRIES; ++i)
  99. {
  100. pRefOwner->RecentEntries[i].RefIndex = -1;
  101. pRefOwner->RecentEntries[i].MonotonicId = -1;
  102. pRefOwner->RecentEntries[i].Action = -1;
  103. }
  104. *ppRefOwner = pRefOwner;
  105. }
  106. return pRefOwner;
  107. } // NewRefOwner
  108. VOID
  109. InsertRefOwner(
  110. IN POWNER_REF_TRACELOG pOwnerRefTraceLog,
  111. IN PVOID pOwner,
  112. IN PPREF_OWNER ppRefOwner,
  113. IN ULONG OwnerSignature,
  114. IN LONGLONG RefIndex,
  115. IN LONG MonotonicId,
  116. IN LONG IncrementValue,
  117. IN USHORT Action
  118. )
  119. {
  120. PREF_OWNER pRefOwner = NULL;
  121. KIRQL OldIrql;
  122. ASSERT(RefIndex >= 0);
  123. UlAcquireSpinLock(&pOwnerRefTraceLog->OwnerHeader.SpinLock, &OldIrql);
  124. pRefOwner = *ppRefOwner;
  125. if (pRefOwner == NULL)
  126. {
  127. pRefOwner = NewRefOwner(
  128. pOwnerRefTraceLog,
  129. pOwner,
  130. ppRefOwner,
  131. OwnerSignature
  132. );
  133. }
  134. if (pRefOwner != NULL)
  135. {
  136. ULONG Index;
  137. ASSERT(pRefOwner->Signature == OWNER_REF_SIGNATURE);
  138. ASSERT(pRefOwner->pOwner == pOwner);
  139. ASSERT(pRefOwner->OwnerSignature == OwnerSignature);
  140. ASSERT(pRefOwner->pOwnerRefTraceLog == pOwnerRefTraceLog);
  141. Index = ((ULONG) ++pRefOwner->OwnedNextEntry) % OWNED_REF_NUM_ENTRIES;
  142. pRefOwner->RecentEntries[Index].RefIndex = RefIndex;
  143. pRefOwner->RecentEntries[Index].MonotonicId = MonotonicId;
  144. pRefOwner->RecentEntries[Index].Action = Action;
  145. if (IncrementValue > 0)
  146. ++pRefOwner->RelativeRefCount;
  147. else if (IncrementValue < 0)
  148. --pRefOwner->RelativeRefCount;
  149. // else do nothing if IncrementValue == 0.
  150. ASSERT(pRefOwner->RelativeRefCount >= 0);
  151. }
  152. UlReleaseSpinLock(&pOwnerRefTraceLog->OwnerHeader.SpinLock, OldIrql);
  153. } // InsertRefOwner
  154. LONGLONG
  155. WriteOwnerRefTraceLog(
  156. IN POWNER_REF_TRACELOG pOwnerRefTraceLog,
  157. IN PVOID pOwner,
  158. IN PPREF_OWNER ppRefOwner,
  159. IN ULONG OwnerSignature,
  160. IN USHORT Action,
  161. IN LONG NewRefCount,
  162. IN LONG MonotonicId,
  163. IN LONG IncrementValue,
  164. IN PVOID pFileName,
  165. IN USHORT LineNumber
  166. )
  167. {
  168. OWNER_REF_TRACE_LOG_ENTRY entry;
  169. LONGLONG RefIndex;
  170. ASSERT(NULL != ppRefOwner);
  171. ASSERT(Action < (1 << REF_TRACE_ACTION_BITS));
  172. if (NULL == pOwnerRefTraceLog)
  173. return -1;
  174. entry.NewRefCount = NewRefCount;
  175. entry.pOwner = pOwner;
  176. entry.pFileName = pFileName;
  177. entry.LineNumber = LineNumber;
  178. entry.Action = Action;
  179. RefIndex = WriteTraceLog( &pOwnerRefTraceLog->TraceLog, &entry );
  180. InsertRefOwner(
  181. pOwnerRefTraceLog,
  182. pOwner,
  183. ppRefOwner,
  184. OwnerSignature,
  185. RefIndex,
  186. MonotonicId,
  187. IncrementValue,
  188. Action
  189. );
  190. return RefIndex;
  191. } // WriteOwnerRefTraceLog
  192. VOID
  193. DestroyOwnerRefTraceLog(
  194. IN POWNER_REF_TRACELOG pOwnerRefTraceLog
  195. )
  196. {
  197. if (pOwnerRefTraceLog != NULL)
  198. {
  199. KIRQL OldIrql;
  200. PLIST_ENTRY pEntry;
  201. int i = 0;
  202. UlAcquireSpinLock(&pOwnerRefTraceLog->OwnerHeader.SpinLock, &OldIrql);
  203. for (pEntry = pOwnerRefTraceLog->OwnerHeader.ListHead.Flink;
  204. pEntry != &pOwnerRefTraceLog->OwnerHeader.ListHead;
  205. ++i)
  206. {
  207. PREF_OWNER pRefOwner =
  208. CONTAINING_RECORD(pEntry, REF_OWNER, ListEntry);
  209. pEntry = pEntry->Flink; // save before deletion
  210. ASSERT(pRefOwner->Signature == OWNER_REF_SIGNATURE);
  211. ASSERT(pRefOwner->RelativeRefCount == 0);
  212. UL_FREE_POOL_WITH_SIG(pRefOwner, UL_OWNER_REF_POOL_TAG);
  213. }
  214. UlReleaseSpinLock(&pOwnerRefTraceLog->OwnerHeader.SpinLock, OldIrql);
  215. ASSERT(i == pOwnerRefTraceLog->OwnerHeader.OwnersCount);
  216. // Remove log from global list
  217. UlAcquireSpinLock(&g_OwnerRefTraceLogGlobalSpinLock, &OldIrql);
  218. RemoveEntryList(&pOwnerRefTraceLog->OwnerHeader.GlobalListEntry);
  219. UlReleaseSpinLock(&g_OwnerRefTraceLogGlobalSpinLock, OldIrql);
  220. InterlockedDecrement(&g_OwnerRefTraceLogGlobalCount);
  221. DestroyTraceLog( (PTRACE_LOG) pOwnerRefTraceLog );
  222. }
  223. } // DestroyOwnerRefTraceLog
  224. VOID
  225. ResetOwnerRefTraceLog(
  226. IN POWNER_REF_TRACELOG pOwnerRefTraceLog
  227. )
  228. {
  229. // CODEWORK: reset OwnerHeader?
  230. if (pOwnerRefTraceLog != NULL)
  231. {
  232. ResetTraceLog(&pOwnerRefTraceLog->TraceLog);
  233. }
  234. } // ResetOwnerRefTraceLog
  235. #endif // ENABLE_OWNER_REF_TRACE