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.

276 lines
5.9 KiB

  1. #include <ntddk.h>
  2. #include "active.h"
  3. #include "locktest.h"
  4. #if LOCKTEST_ACTIVE
  5. //
  6. // Real implementation if the module is active
  7. //
  8. VOID DeadlockPositiveTest (
  9. PVOID NotUsed
  10. )
  11. {
  12. DbgPrint ("Buggy: not implemented \n");
  13. }
  14. VOID DeadlockNegativeTest (
  15. PVOID NotUsed
  16. )
  17. {
  18. DbgPrint ("Buggy: not implemented \n");
  19. }
  20. /////////////////////////////////////////////////////////////////////
  21. ///////////////////////////////////////////////////////// Stress test
  22. /////////////////////////////////////////////////////////////////////
  23. VOID
  24. StressLockHierarchy (
  25. ULONG NumberOfIterations,
  26. ULONG NumberOfResources,
  27. ULONG Probability,
  28. ULONG Seed,
  29. BOOLEAN InjectDeadlocks
  30. );
  31. NTSYSAPI // ntifs
  32. ULONG // ntifs
  33. NTAPI // ntifs
  34. RtlRandom ( // ntifs
  35. PULONG Seed // ntifs
  36. ); // ntifs
  37. ULONG InjectDeadlocks;
  38. VOID
  39. DeadlockStressTest (
  40. PVOID NotUsed
  41. )
  42. {
  43. StressLockHierarchy (128,
  44. 64,
  45. 20,
  46. 0,
  47. InjectDeadlocks ? TRUE : FALSE);
  48. }
  49. #define LOCK_ACQUIRED 0x0001
  50. #define LOCK_DELETED 0x0002
  51. #define LOCK_RANDOM 0x0004
  52. ULONG Finish;
  53. VOID
  54. StressLockHierarchy (
  55. ULONG NumberOfIterations,
  56. ULONG NumberOfResources,
  57. ULONG Probability,
  58. ULONG Seed,
  59. BOOLEAN InjectDeadlocks
  60. )
  61. {
  62. PFAST_MUTEX * Locks;
  63. PULONG Flags;
  64. ULONG I, J, K, Ri;
  65. BOOLEAN ShouldAcquire;
  66. BOOLEAN ShouldDelete;
  67. Locks = NULL;
  68. Flags = NULL;
  69. Locks = (PFAST_MUTEX *) ExAllocatePool (NonPagedPool, NumberOfResources * sizeof (PFAST_MUTEX));
  70. if (! Locks) {
  71. goto Exit;
  72. }
  73. Flags = (PULONG) ExAllocatePool (NonPagedPool, NumberOfResources * sizeof (ULONG));
  74. if (! Flags) {
  75. goto Exit;
  76. }
  77. RtlZeroMemory (Locks, NumberOfResources * sizeof (PFAST_MUTEX));
  78. RtlZeroMemory (Flags, NumberOfResources * sizeof (ULONG));
  79. for (I = 0; I < NumberOfResources; I += 1) {
  80. Locks[I] = ExAllocatePool (NonPagedPool, sizeof (FAST_MUTEX));
  81. if (! (Locks[I])) {
  82. goto Exit;
  83. }
  84. ExInitializeFastMutex (Locks[I]);
  85. }
  86. DbgPrint ("Starting test iterations ... \n");
  87. KeEnterCriticalRegion ();
  88. for (I = 0; I < NumberOfIterations; I += 1) {
  89. BOOLEAN DeadlockInjected = FALSE;
  90. if (InjectDeadlocks) {
  91. Ri = RtlRandom(&Seed) % NumberOfResources;
  92. if (! (Flags[Ri] & LOCK_DELETED)) {
  93. ExAcquireFastMutexUnsafe (Locks[Ri]);
  94. Flags[Ri] |= LOCK_ACQUIRED;
  95. Flags[Ri] |= LOCK_RANDOM;
  96. DeadlockInjected = TRUE;
  97. }
  98. }
  99. for (J = 0; J < NumberOfResources; J += 1) {
  100. if (Finish) {
  101. return;
  102. }
  103. if ((Flags[J] & LOCK_DELETED)) {
  104. DbgPrint (".");
  105. continue;
  106. }
  107. if ((Flags[J] & LOCK_RANDOM)) {
  108. DbgPrint ("*");
  109. continue;
  110. }
  111. ShouldDelete = ((RtlRandom(&Seed) % 1000) < 10) ? TRUE : FALSE;
  112. if (ShouldDelete) {
  113. DbgPrint ("D");
  114. // mark block in a special way so verifier version of ExFreePool
  115. // will know we are deleting a resource.
  116. *((PULONG)(Locks[J])) = 0xABCDDCBA;
  117. ExFreePool (Locks[J]);
  118. Locks[J] = NULL;
  119. Flags[J] |= LOCK_DELETED;
  120. }
  121. if ((Flags[J] & LOCK_DELETED)) {
  122. continue;
  123. }
  124. ShouldAcquire = ((RtlRandom(&Seed) % 100) < Probability) ? TRUE : FALSE;
  125. if (ShouldAcquire) {
  126. DbgPrint ("A");
  127. ExAcquireFastMutexUnsafe (Locks[J]);
  128. Flags[J] |= LOCK_ACQUIRED;
  129. }
  130. else {
  131. DbgPrint ("-");
  132. }
  133. }
  134. for (J = 0; J < NumberOfResources; J += 1) {
  135. if (Finish) {
  136. return;
  137. }
  138. // K = NumberOfResources - J - 1;
  139. K = J; // release in reverse order
  140. if ((Flags[K] & LOCK_DELETED)) {
  141. continue;
  142. }
  143. if ((Flags[K] & LOCK_RANDOM)) {
  144. continue;
  145. }
  146. if ((Flags[K] & LOCK_ACQUIRED)) {
  147. // DbgPrint ("R");
  148. ExReleaseFastMutexUnsafe (Locks[K]);
  149. Flags[K] &= ~LOCK_ACQUIRED;
  150. }
  151. else {
  152. // DbgPrint ("-");
  153. }
  154. }
  155. if (DeadlockInjected) {
  156. ExReleaseFastMutexUnsafe (Locks[Ri]);
  157. Flags[Ri] &= ~LOCK_ACQUIRED;
  158. Flags[Ri] &= ~LOCK_RANDOM;
  159. }
  160. // if (I && I % 100 == 0) {
  161. DbgPrint ("\n");
  162. // }
  163. }
  164. DbgPrint ("\n");
  165. KeLeaveCriticalRegion ();
  166. Exit:
  167. for (I = 0; I < NumberOfResources; I += 1) {
  168. if (Locks[I]) {
  169. // mark block in a special way so verifier version of ExFreePool
  170. // will know we are deleting a resource.
  171. *((PULONG)(Locks[I])) = 0xABCDDCBA;
  172. ExFreePool (Locks[I]);
  173. }
  174. }
  175. if (Locks) {
  176. ExFreePool (Locks);
  177. }
  178. if (Flags) {
  179. ExFreePool (Flags);
  180. }
  181. }
  182. #else
  183. //
  184. // Dummy implementation if the module is inactive
  185. //
  186. VOID DeadlockPositiveTest (
  187. PVOID NotUsed
  188. )
  189. {
  190. DbgPrint ("Buggy: deadlock module is disabled \n");
  191. }
  192. VOID DeadlockNegativeTest (
  193. PVOID NotUsed
  194. )
  195. {
  196. DbgPrint ("Buggy: deadlock module is disabled \n");
  197. }
  198. VOID DeadlockStressTest (
  199. PVOID NotUsed
  200. )
  201. {
  202. DbgPrint ("Buggy: deadlock module is disabled \n");
  203. }
  204. #endif // #if !NEWSTUFF_ACTIVE