Leaked source code of windows server 2003
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.

445 lines
10 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Header Name:
  4. deadlock.h
  5. Abstract:
  6. This module implements a deadlock verification package for
  7. critical section operations. The initial version is based on
  8. the driver verifier deadlock checking package for kernel
  9. synchornization objects.
  10. Author:
  11. Silviu Calinoiu (SilviuC) 6-Feb-2002
  12. Revision History:
  13. --*/
  14. #ifndef _DEADLOCK_H_
  15. #define _DEADLOCK_H_
  16. //
  17. // Deadlock detection package initialization.
  18. //
  19. VOID
  20. AVrfDeadlockDetectionInitialize (
  21. VOID
  22. );
  23. //
  24. // Deadlock verifier main entry points.
  25. //
  26. LOGICAL
  27. AVrfDeadlockResourceInitialize (
  28. PVOID Resource,
  29. PVOID Caller
  30. );
  31. LOGICAL
  32. AVrfDeadlockResourceDelete (
  33. PVOID Resource,
  34. PVOID Caller
  35. );
  36. LOGICAL
  37. AVrfDeadlockResourceAcquire (
  38. PVOID Resource,
  39. PVOID Caller,
  40. LOGICAL TryAcquire
  41. );
  42. LOGICAL
  43. AVrfDeadlockResourceRelease (
  44. PVOID Resource,
  45. PVOID Caller
  46. );
  47. //
  48. // Maximum number of nodes paraticipating in a cycle. We do not
  49. // attempt to find cycles in the graph with more than 32 nodes
  50. // because this would be mind boggling anyway and no human will be
  51. // able to understand it.
  52. //
  53. #define NO_OF_DEADLOCK_PARTICIPANTS 32
  54. //
  55. // AVRF_DEADLOCK_RESOURCE_TYPE
  56. //
  57. typedef enum _AVRF_DEADLOCK_RESOURCE_TYPE {
  58. AVrfpDeadlockTypeUnknown = 0,
  59. AVrfpDeadlockTypeCriticalSection = 1,
  60. AVrfpDeadlockTypeMaximum = 2
  61. } AVRF_DEADLOCK_RESOURCE_TYPE;
  62. //
  63. // AVRF_DEADLOCK_NODE
  64. //
  65. typedef struct _AVRF_DEADLOCK_NODE {
  66. //
  67. // Node representing the acquisition of the previous resource.
  68. //
  69. struct _AVRF_DEADLOCK_NODE * Parent;
  70. //
  71. // Node representing the next resource acquisitions, that are
  72. // done after acquisition of the current resource.
  73. //
  74. struct _LIST_ENTRY ChildrenList;
  75. //
  76. // Field used to chain siblings in the tree. A parent node has the
  77. // ChildrenList field as the head of the children list that is chained
  78. // with the Siblings field.
  79. //
  80. struct _LIST_ENTRY SiblingsList;
  81. union {
  82. //
  83. // List of nodes representing the same resource acquisition
  84. // as the current node but in different contexts (lock combinations).
  85. //
  86. struct _LIST_ENTRY ResourceList;
  87. //
  88. // Used to chain free nodes. This is used only after the node has
  89. // been deleted (resource was freed). Nodes are kept in a cache
  90. // to reduce contention for the kernel pool.
  91. //
  92. struct _LIST_ENTRY FreeListEntry;
  93. };
  94. //
  95. // Back pointer to the descriptor for this resource.
  96. //
  97. struct _AVRF_DEADLOCK_RESOURCE * Root;
  98. //
  99. // When we find a deadlock, we keep this info around in order to
  100. // be able to identify the parties involved who have caused
  101. // the deadlock.
  102. //
  103. struct _AVRF_DEADLOCK_THREAD * ThreadEntry;
  104. //
  105. // Fields used for decision making within the deadlock analysis
  106. // algorithm.
  107. //
  108. // Active: 1 if the node represents a resource currently acquired,
  109. // 0 if resource was acquired in the past.
  110. //
  111. // OnlyTryAcquiredUsed: 1 if resource was always acquired with TryAcquire.
  112. // 0 if at least once normal acquire was used. A node that uses
  113. // only TryAcquire cannot be involved in a deadlock.
  114. //
  115. // ReleasedOutOfOrder: 1 if the resource was at least once released
  116. // out of order. The flag is used while looking for cycles because
  117. // this type of nodes will appear as part of the cycle but there is
  118. // no deadlock.
  119. //
  120. // SequenceNumber: field that gets a unique stamp during each deadlock
  121. // analysis run. It helps figure out if the node was touched
  122. // already in the current graph traversal.
  123. //
  124. struct {
  125. ULONG Active : 1;
  126. ULONG OnlyTryAcquireUsed : 1;
  127. ULONG ReleasedOutOfOrder : 1;
  128. ULONG SequenceNumber : 29;
  129. };
  130. //
  131. // Stack traces for the resource acquisition moment.
  132. // Used when displaying deadlock proofs. On free builds
  133. // anything other than the first entry (return address)
  134. // may be bogus in case stack trace capturing failed.
  135. //
  136. PVOID StackTrace[MAX_TRACE_DEPTH];
  137. PVOID ParentStackTrace[MAX_TRACE_DEPTH];
  138. } AVRF_DEADLOCK_NODE, *PAVRF_DEADLOCK_NODE;
  139. //
  140. // AVRF_DEADLOCK_RESOURCE
  141. //
  142. typedef struct _AVRF_DEADLOCK_RESOURCE {
  143. //
  144. // Resource type (mutex, spinlock, etc.).
  145. //
  146. AVRF_DEADLOCK_RESOURCE_TYPE Type;
  147. //
  148. // Resource flags
  149. //
  150. // NodeCount : number of resource nodes created for this resource.
  151. //
  152. // RecursionCount : number of times this resource has been recursively acquired
  153. // It makes sense to put this counter in the resource because as long as
  154. // resource is acquired only one thread can operate on it.
  155. //
  156. struct {
  157. ULONG NodeCount : 16;
  158. ULONG RecursionCount : 16;
  159. };
  160. //
  161. // The address of the synchronization object used by the kernel.
  162. //
  163. PVOID ResourceAddress;
  164. //
  165. // The thread that currently owns the resource. The field is
  166. // null if nobody owns the resource.
  167. //
  168. struct _AVRF_DEADLOCK_THREAD * ThreadOwner;
  169. //
  170. // List of resource nodes representing acquisitions of this resource.
  171. //
  172. LIST_ENTRY ResourceList;
  173. union {
  174. //
  175. // List used for chaining resources from a hash bucket.
  176. //
  177. LIST_ENTRY HashChainList;
  178. //
  179. // Used to chain free resources. This list is used only after
  180. // the resource has been freed and we put the structure
  181. // into a cache to reduce kernel pool contention.
  182. //
  183. LIST_ENTRY FreeListEntry;
  184. };
  185. //
  186. // Stack trace of the resource creator. On free builds we
  187. // may have here only a return address that is bubbled up
  188. // from verifier thunks.
  189. //
  190. PVOID StackTrace [MAX_TRACE_DEPTH];
  191. //
  192. // Stack trace for last acquire
  193. //
  194. PVOID LastAcquireTrace [MAX_TRACE_DEPTH];
  195. //
  196. // Stack trace for last release
  197. //
  198. PVOID LastReleaseTrace [MAX_TRACE_DEPTH];
  199. } AVRF_DEADLOCK_RESOURCE, * PAVRF_DEADLOCK_RESOURCE;
  200. //
  201. // AVRF_DEADLOCK_THREAD
  202. //
  203. typedef struct _AVRF_DEADLOCK_THREAD {
  204. //
  205. // Kernel thread address
  206. //
  207. PKTHREAD Thread;
  208. //
  209. // The node representing the last resource acquisition made by
  210. // this thread.
  211. //
  212. PAVRF_DEADLOCK_NODE CurrentTopNode;
  213. union {
  214. //
  215. // Thread list. It is used for chaining into a hash bucket.
  216. //
  217. LIST_ENTRY ListEntry;
  218. //
  219. // Used to chain free nodes. The list is used only after we decide
  220. // to delete the thread structure (possibly because it does not
  221. // hold resources anymore). Keeping the structures in a cache
  222. // reduces pool contention.
  223. //
  224. LIST_ENTRY FreeListEntry;
  225. };
  226. //
  227. // Count of resources currently acquired by a thread. When this becomes
  228. // zero the thread will be destroyed. The count goes up during acquire
  229. // and down during release.
  230. //
  231. ULONG NodeCount;
  232. } AVRF_DEADLOCK_THREAD, *PAVRF_DEADLOCK_THREAD;
  233. //
  234. // Deadlock verifier globals
  235. //
  236. typedef struct _AVRF_DEADLOCK_GLOBALS {
  237. //
  238. // Structure counters: [0] - current, [1] - maximum
  239. //
  240. ULONG Nodes[2];
  241. ULONG Resources[2];
  242. ULONG Threads[2];
  243. //
  244. // Total number of kernel pool bytes used by the deadlock verifier
  245. //
  246. SIZE_T BytesAllocated;
  247. //
  248. // Resource and thread collection.
  249. //
  250. PLIST_ENTRY ResourceDatabase;
  251. PLIST_ENTRY ThreadDatabase;
  252. //
  253. // How many times ExAllocatePool failed on us?
  254. // If this is >0 we stop deadlock verification.
  255. //
  256. ULONG AllocationFailures;
  257. //
  258. // How many nodes have been trimmed when we decided to forget
  259. // partially the history of some resources.
  260. //
  261. ULONG NodesTrimmedBasedOnAge;
  262. ULONG NodesTrimmedBasedOnCount;
  263. //
  264. // Deadlock analysis statistics
  265. //
  266. ULONG NodesSearched;
  267. ULONG MaxNodesSearched;
  268. ULONG SequenceNumber;
  269. ULONG RecursionDepthLimit;
  270. ULONG SearchedNodesLimit;
  271. ULONG DepthLimitHits;
  272. ULONG SearchLimitHits;
  273. //
  274. // Number of times we have to exonerate a deadlock because
  275. // it was protected by a common resource (e.g. thread 1 takes ABC,
  276. // thread 2 takes ACB -- this will get flagged initially by our algorithm
  277. // since B&C are taken out of order but is not actually a deadlock.
  278. //
  279. ULONG ABC_ACB_Skipped;
  280. ULONG OutOfOrderReleases;
  281. ULONG NodesReleasedOutOfOrder;
  282. //
  283. // How many locks are held simultaneously while the system is running?
  284. //
  285. ULONG NodeLevelCounter[8];
  286. ULONG GraphNodes[8];
  287. ULONG TotalReleases;
  288. ULONG RootNodesDeleted;
  289. //
  290. // Used to control how often we delete portions of the dependency
  291. // graph.
  292. //
  293. ULONG ForgetHistoryCounter;
  294. //
  295. // How often was a worker items dispatched to trim the
  296. // pool cache.
  297. //
  298. ULONG PoolTrimCounter;
  299. //
  300. // Caches of freed structures (thread, resource, node) used to
  301. // decrease kernel pool contention.
  302. //
  303. LIST_ENTRY FreeResourceList;
  304. LIST_ENTRY FreeThreadList;
  305. LIST_ENTRY FreeNodeList;
  306. ULONG FreeResourceCount;
  307. ULONG FreeThreadCount;
  308. ULONG FreeNodeCount;
  309. //
  310. // Resource address that caused the deadlock
  311. //
  312. PVOID Instigator;
  313. //
  314. // Number of participants in the deadlock
  315. //
  316. ULONG NumberOfParticipants;
  317. //
  318. // List of the nodes that participate in the deadlock
  319. //
  320. PAVRF_DEADLOCK_NODE Participant [NO_OF_DEADLOCK_PARTICIPANTS];
  321. LOGICAL CacheReductionInProgress;
  322. } AVRF_DEADLOCK_GLOBALS, *PAVRF_DEADLOCK_GLOBALS;
  323. #endif // #ifndef _DEADLOCK_H_