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.

418 lines
7.9 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. nbtest.c
  5. Abstract:
  6. This module contains code to stress test the nonblocking queue functions.
  7. Author:
  8. David N. Cutler (davec) 19-May-2001
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "stdlib.h"
  14. #include "stdio.h"
  15. #include "string.h"
  16. #include "nt.h"
  17. #include "ntrtl.h"
  18. #include "nturtl.h"
  19. #include "zwapi.h"
  20. #include "windef.h"
  21. #include "winbase.h"
  22. //
  23. // Define locals constants.
  24. //
  25. #define TABLE_SIZE 2
  26. #define THREAD_NUMBER 2
  27. //
  28. // Define external prototypes.
  29. //
  30. typedef struct _NBQUEUE_BLOCK {
  31. ULONG64 Next;
  32. ULONG64 Data;
  33. } NBQUEUE_BLOCK, *PNBQUEUE_BLOCK;
  34. PVOID
  35. ExInitializeNBQueueHead (
  36. IN PSLIST_HEADER SlistHead
  37. );
  38. BOOLEAN
  39. ExInsertTailNBQueue (
  40. IN PVOID Header,
  41. IN ULONG64 Value
  42. );
  43. BOOLEAN
  44. ExRemoveHeadNBQueue (
  45. IN PVOID Header,
  46. OUT PULONG64 Value
  47. );
  48. //
  49. // Define local routine prototypes.
  50. //
  51. NTSTATUS
  52. MyCreateThread (
  53. OUT PHANDLE Handle,
  54. IN PUSER_THREAD_START_ROUTINE StartRoutine,
  55. PVOID Context
  56. );
  57. VOID
  58. StressNBQueueEven (
  59. VOID
  60. );
  61. VOID
  62. StressNBQueueOdd (
  63. VOID
  64. );
  65. NTSTATUS
  66. ThreadMain (
  67. IN PVOID Context
  68. );
  69. //
  70. // Define static storage.
  71. //
  72. HANDLE Thread1Handle;
  73. HANDLE Thread2Handle;
  74. HANDLE Thread3Handle;
  75. HANDLE Thread4Handle;
  76. HANDLE Thread5Handle;
  77. HANDLE Thread6Handle;
  78. HANDLE Thread7Handle;
  79. HANDLE Thread8Handle;
  80. //
  81. // Define nonblocking queues
  82. //
  83. PVOID ClrQueue;
  84. PVOID SetQueue;
  85. SLIST_HEADER SListHead;
  86. LONG Table[TABLE_SIZE];
  87. volatile ULONG StartSignal = 0;
  88. ULONG StopSignal = 0;
  89. //
  90. // Begin test code.
  91. //
  92. int
  93. __cdecl
  94. main(
  95. int argc,
  96. char *argv[]
  97. )
  98. {
  99. ULONG Index;
  100. PSINGLE_LIST_ENTRY Entry;
  101. NTSTATUS Status;
  102. //
  103. // Initialize the SLIST headers and insert TABLE_SIZE + 2 entries.
  104. //
  105. RtlInitializeSListHead(&SListHead);
  106. for (Index = 0; Index < (TABLE_SIZE + 2); Index += 1) {
  107. Entry = (PSINGLE_LIST_ENTRY)malloc(sizeof(NBQUEUE_BLOCK));
  108. if (Entry == NULL) {
  109. printf("unable to allocate SLIST entry\n");
  110. return 0;
  111. }
  112. InterlockedPushEntrySList(&SListHead, Entry);
  113. }
  114. //
  115. // Initialize the clear entry nonblocking queue elements.
  116. //
  117. ClrQueue = ExInitializeNBQueueHead(&SListHead);
  118. if (ClrQueue == NULL) {
  119. printf("unable to initialize clr nonblock queue\n");
  120. return 0;
  121. }
  122. for (Index = 0; Index < (TABLE_SIZE / 2); Index += 1) {
  123. if (ExInsertTailNBQueue(ClrQueue, Index) == FALSE) {
  124. printf("unable to insert in clear nonblocking queue\n");
  125. return 0;
  126. }
  127. Table[Index] = 0;
  128. }
  129. //
  130. // Initialize the set entry nonblocking queue elements.
  131. //
  132. SetQueue = ExInitializeNBQueueHead(&SListHead);
  133. if (SetQueue == NULL) {
  134. printf("unable to initialize set nonblock queue\n");
  135. return 0;
  136. }
  137. for (Index = (TABLE_SIZE / 2); Index < TABLE_SIZE; Index += 1) {
  138. if (ExInsertTailNBQueue(SetQueue, Index) == FALSE) {
  139. printf("unable to insert in set nonblocking queue\n");
  140. return 0;
  141. }
  142. Table[Index] = 1;
  143. }
  144. //
  145. // Create and start the background timer thread.
  146. //
  147. Status = MyCreateThread(&Thread1Handle,
  148. ThreadMain,
  149. (PVOID)1);
  150. if (!NT_SUCCESS(Status)) {
  151. printf("Failed to create thread during initialization\n");
  152. return 0;
  153. } else {
  154. StartSignal = 1;
  155. StressNBQueueEven();
  156. }
  157. return 0;
  158. }
  159. VOID
  160. StressNBQueueEven (
  161. VOID
  162. )
  163. {
  164. ULONG64 Value;
  165. do {
  166. do {
  167. //
  168. // Attempt to remove an entry from the clear queue.
  169. //
  170. // Entries in this list should be clear in the table array.
  171. //
  172. if (ExRemoveHeadNBQueue(ClrQueue, &Value) != FALSE) {
  173. if ((ULONG)Value > 63) {
  174. StopSignal = 1;
  175. DbgBreakPoint();
  176. }
  177. if (InterlockedExchange(&Table[(ULONG)Value], 1) != 0) {
  178. StopSignal = 1;
  179. DbgBreakPoint();
  180. }
  181. if (ExInsertTailNBQueue(SetQueue, (ULONG)Value) == FALSE) {
  182. StopSignal = 1;
  183. DbgBreakPoint();
  184. }
  185. } else {
  186. break;
  187. }
  188. } while (TRUE);
  189. do {
  190. //
  191. // Attempt to remove an entry from the set queue.
  192. //
  193. // Entries in this list should be set in the table array.
  194. //
  195. if (ExRemoveHeadNBQueue(SetQueue, &Value) != FALSE) {
  196. if ((ULONG)Value > 63) {
  197. StopSignal = 1;
  198. DbgBreakPoint();
  199. }
  200. if (InterlockedExchange(&Table[(ULONG)Value], 0) != 1) {
  201. StopSignal = 1;
  202. DbgBreakPoint();
  203. }
  204. if (ExInsertTailNBQueue(ClrQueue, (ULONG)Value) == FALSE) {
  205. StopSignal = 1;
  206. DbgBreakPoint();
  207. }
  208. } else {
  209. break;
  210. }
  211. } while (TRUE);
  212. } while (TRUE);
  213. return;
  214. }
  215. VOID
  216. StressNBQueueOdd (
  217. VOID
  218. )
  219. {
  220. ULONG64 Value;
  221. do {
  222. do {
  223. //
  224. // Attempt to remove an entry from the set queue.
  225. //
  226. // Entries in this list should be set in the table array.
  227. //
  228. if (ExRemoveHeadNBQueue(SetQueue, &Value) != FALSE) {
  229. if ((ULONG)Value > 63) {
  230. StopSignal = 1;
  231. DbgBreakPoint();
  232. }
  233. if (InterlockedExchange(&Table[(ULONG)Value], 0) != 1) {
  234. StopSignal = 1;
  235. DbgBreakPoint();
  236. }
  237. if (ExInsertTailNBQueue(ClrQueue, (ULONG)Value) == FALSE) {
  238. StopSignal = 1;
  239. DbgBreakPoint();
  240. }
  241. } else {
  242. break;
  243. }
  244. } while (TRUE);
  245. do {
  246. //
  247. // Attempt to remove an entry from the clear queue.
  248. //
  249. // Entries in this list should be clear in the table array.
  250. //
  251. if (ExRemoveHeadNBQueue(ClrQueue, &Value) != FALSE) {
  252. if ((ULONG)Value > 63) {
  253. StopSignal = 1;
  254. DbgBreakPoint();
  255. }
  256. if (InterlockedExchange(&Table[(ULONG)Value], 1) != 0) {
  257. StopSignal = 1;
  258. DbgBreakPoint();
  259. }
  260. if (ExInsertTailNBQueue(SetQueue, (ULONG)Value) == FALSE) {
  261. StopSignal = 1;
  262. DbgBreakPoint();
  263. }
  264. } else {
  265. break;
  266. }
  267. } while (TRUE);
  268. } while (TRUE);
  269. return;
  270. }
  271. NTSTATUS
  272. ThreadMain (
  273. IN PVOID Context
  274. )
  275. {
  276. //
  277. // Wait until start signal is given.
  278. //
  279. do {
  280. } while (StartSignal == 0);
  281. if (((ULONG_PTR)Context & 1) == 0) {
  282. StressNBQueueEven();
  283. } else {
  284. StressNBQueueOdd();
  285. }
  286. return STATUS_SUCCESS;
  287. }
  288. NTSTATUS
  289. MyCreateThread (
  290. OUT PHANDLE Handle,
  291. IN PUSER_THREAD_START_ROUTINE StartRoutine,
  292. PVOID Context
  293. )
  294. {
  295. NTSTATUS Status;
  296. //
  297. // Create a thread and start its execution.
  298. //
  299. Status = RtlCreateUserThread(NtCurrentProcess(),
  300. NULL,
  301. FALSE,
  302. 0,
  303. 0,
  304. 0,
  305. StartRoutine,
  306. Context,
  307. Handle,
  308. NULL);
  309. if (!NT_SUCCESS(Status)) {
  310. return Status;
  311. }
  312. return Status;
  313. }