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.

447 lines
9.1 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 progress limit report value.
  24. //
  25. #define PROGRESS_LIMIT 1000000
  26. ULONG Iteration = 0;
  27. LONG Progress = 0;
  28. //
  29. // Define processor yield for hyperthreaded systems.
  30. //
  31. #if defined(_X86_)
  32. #define YieldProcessor() __asm {rep nop}
  33. #else
  34. #define YieldProcessor()
  35. #endif
  36. //
  37. // Define locals constants.
  38. //
  39. #define TABLE_SIZE 2
  40. #define THREAD_NUMBER 2
  41. //
  42. // Define external prototypes.
  43. //
  44. typedef struct _NBQUEUE_BLOCK {
  45. ULONG64 Next;
  46. ULONG64 Data;
  47. } NBQUEUE_BLOCK, *PNBQUEUE_BLOCK;
  48. PVOID
  49. ExInitializeNBQueueHead (
  50. IN PSLIST_HEADER SlistHead
  51. );
  52. BOOLEAN
  53. ExInsertTailNBQueue (
  54. IN PVOID Header,
  55. IN ULONG64 Value
  56. );
  57. BOOLEAN
  58. ExRemoveHeadNBQueue (
  59. IN PVOID Header,
  60. OUT PULONG64 Value
  61. );
  62. //
  63. // Define local routine prototypes.
  64. //
  65. NTSTATUS
  66. MyCreateThread (
  67. OUT PHANDLE Handle,
  68. IN PUSER_THREAD_START_ROUTINE StartRoutine,
  69. PVOID Context
  70. );
  71. VOID
  72. StressNBQueueEven (
  73. VOID
  74. );
  75. VOID
  76. StressNBQueueOdd (
  77. VOID
  78. );
  79. NTSTATUS
  80. ThreadMain (
  81. IN PVOID Context
  82. );
  83. //
  84. // Define static storage.
  85. //
  86. HANDLE Thread1Handle;
  87. HANDLE Thread2Handle;
  88. //
  89. // Define nonblocking queues
  90. //
  91. PVOID ClrQueue;
  92. PVOID SetQueue;
  93. SLIST_HEADER SListHead;
  94. LONG Table[TABLE_SIZE];
  95. volatile ULONG StartSignal = 0;
  96. ULONG StopSignal = 0;
  97. //
  98. // Begin test code.
  99. //
  100. int
  101. __cdecl
  102. main(
  103. int argc,
  104. char *argv[]
  105. )
  106. {
  107. ULONG Index;
  108. PSLIST_ENTRY Entry;
  109. NTSTATUS Status;
  110. //
  111. // Initialize the SLIST headers and insert TABLE_SIZE + 2 entries.
  112. //
  113. RtlInitializeSListHead(&SListHead);
  114. for (Index = 0; Index < (TABLE_SIZE + 2); Index += 1) {
  115. Entry = (PSLIST_ENTRY)malloc(sizeof(NBQUEUE_BLOCK));
  116. if (Entry == NULL) {
  117. printf("unable to allocate SLIST entry\n");
  118. return 0;
  119. }
  120. InterlockedPushEntrySList(&SListHead, Entry);
  121. }
  122. //
  123. // Initialize the clear entry nonblocking queue elements.
  124. //
  125. ClrQueue = ExInitializeNBQueueHead(&SListHead);
  126. if (ClrQueue == NULL) {
  127. printf("unable to initialize clr nonblock queue\n");
  128. return 0;
  129. }
  130. for (Index = 0; Index < (TABLE_SIZE / 2); Index += 1) {
  131. if (ExInsertTailNBQueue(ClrQueue, Index) == FALSE) {
  132. printf("unable to insert in clear nonblocking queue\n");
  133. return 0;
  134. }
  135. Table[Index] = 0;
  136. }
  137. //
  138. // Initialize the set entry nonblocking queue elements.
  139. //
  140. SetQueue = ExInitializeNBQueueHead(&SListHead);
  141. if (SetQueue == NULL) {
  142. printf("unable to initialize set nonblock queue\n");
  143. return 0;
  144. }
  145. for (Index = (TABLE_SIZE / 2); Index < TABLE_SIZE; Index += 1) {
  146. if (ExInsertTailNBQueue(SetQueue, Index) == FALSE) {
  147. printf("unable to insert in set nonblocking queue\n");
  148. return 0;
  149. }
  150. Table[Index] = 1;
  151. }
  152. //
  153. // Create and start second thread.
  154. //
  155. Status = MyCreateThread(&Thread1Handle,
  156. ThreadMain,
  157. (PVOID)1);
  158. if (!NT_SUCCESS(Status)) {
  159. printf("Failed to create thread during initialization\n");
  160. return 0;
  161. } else {
  162. StartSignal = 1;
  163. StressNBQueueEven();
  164. }
  165. return 0;
  166. }
  167. VOID
  168. StressNBQueueEven (
  169. VOID
  170. )
  171. {
  172. ULONG64 Value;
  173. do {
  174. do {
  175. //
  176. // Attempt to remove an entry from the clear queue.
  177. //
  178. // Entries in this list should be clear in the table array.
  179. //
  180. if (ExRemoveHeadNBQueue(ClrQueue, &Value) != FALSE) {
  181. if ((ULONG)Value > 63) {
  182. StopSignal = 1;
  183. DbgBreakPoint();
  184. }
  185. if (InterlockedExchange(&Table[(ULONG)Value], 1) != 0) {
  186. StopSignal = 1;
  187. DbgBreakPoint();
  188. }
  189. if (ExInsertTailNBQueue(SetQueue, (ULONG)Value) == FALSE) {
  190. StopSignal = 1;
  191. DbgBreakPoint();
  192. }
  193. } else {
  194. break;
  195. }
  196. if (InterlockedIncrement(&Progress) > PROGRESS_LIMIT) {
  197. InterlockedExchange(&Progress, 0);
  198. Iteration += 1;
  199. printf("progress report iteration %d\n", Iteration);
  200. }
  201. YieldProcessor();
  202. } while (TRUE);
  203. do {
  204. //
  205. // Attempt to remove an entry from the set queue.
  206. //
  207. // Entries in this list should be set in the table array.
  208. //
  209. if (ExRemoveHeadNBQueue(SetQueue, &Value) != FALSE) {
  210. if ((ULONG)Value > 63) {
  211. StopSignal = 1;
  212. DbgBreakPoint();
  213. }
  214. if (InterlockedExchange(&Table[(ULONG)Value], 0) != 1) {
  215. StopSignal = 1;
  216. DbgBreakPoint();
  217. }
  218. if (ExInsertTailNBQueue(ClrQueue, (ULONG)Value) == FALSE) {
  219. StopSignal = 1;
  220. DbgBreakPoint();
  221. }
  222. } else {
  223. break;
  224. }
  225. if (InterlockedIncrement(&Progress) > PROGRESS_LIMIT) {
  226. InterlockedExchange(&Progress, 0);
  227. Iteration += 1;
  228. printf("progress report iteration %d\n", Iteration);
  229. }
  230. YieldProcessor();
  231. } while (TRUE);
  232. } while (TRUE);
  233. return;
  234. }
  235. VOID
  236. StressNBQueueOdd (
  237. VOID
  238. )
  239. {
  240. ULONG64 Value;
  241. do {
  242. do {
  243. //
  244. // Attempt to remove an entry from the set queue.
  245. //
  246. // Entries in this list should be set in the table array.
  247. //
  248. if (ExRemoveHeadNBQueue(SetQueue, &Value) != FALSE) {
  249. if ((ULONG)Value > 63) {
  250. StopSignal = 1;
  251. DbgBreakPoint();
  252. }
  253. if (InterlockedExchange(&Table[(ULONG)Value], 0) != 1) {
  254. StopSignal = 1;
  255. DbgBreakPoint();
  256. }
  257. if (ExInsertTailNBQueue(ClrQueue, (ULONG)Value) == FALSE) {
  258. StopSignal = 1;
  259. DbgBreakPoint();
  260. }
  261. } else {
  262. break;
  263. }
  264. InterlockedIncrement(&Progress);
  265. YieldProcessor();
  266. } while (TRUE);
  267. do {
  268. //
  269. // Attempt to remove an entry from the clear queue.
  270. //
  271. // Entries in this list should be clear in the table array.
  272. //
  273. if (ExRemoveHeadNBQueue(ClrQueue, &Value) != FALSE) {
  274. if ((ULONG)Value > 63) {
  275. StopSignal = 1;
  276. DbgBreakPoint();
  277. }
  278. if (InterlockedExchange(&Table[(ULONG)Value], 1) != 0) {
  279. StopSignal = 1;
  280. DbgBreakPoint();
  281. }
  282. if (ExInsertTailNBQueue(SetQueue, (ULONG)Value) == FALSE) {
  283. StopSignal = 1;
  284. DbgBreakPoint();
  285. }
  286. } else {
  287. break;
  288. }
  289. InterlockedIncrement(&Progress);
  290. YieldProcessor();
  291. } while (TRUE);
  292. } while (TRUE);
  293. return;
  294. }
  295. NTSTATUS
  296. ThreadMain (
  297. IN PVOID Context
  298. )
  299. {
  300. //
  301. // Wait until start signal is given.
  302. //
  303. do {
  304. } while (StartSignal == 0);
  305. StressNBQueueOdd();
  306. return STATUS_SUCCESS;
  307. }
  308. NTSTATUS
  309. MyCreateThread (
  310. OUT PHANDLE Handle,
  311. IN PUSER_THREAD_START_ROUTINE StartRoutine,
  312. PVOID Context
  313. )
  314. {
  315. NTSTATUS Status;
  316. //
  317. // Create a thread and start its execution.
  318. //
  319. Status = RtlCreateUserThread(NtCurrentProcess(),
  320. NULL,
  321. FALSE,
  322. 0,
  323. 0,
  324. 0,
  325. StartRoutine,
  326. Context,
  327. Handle,
  328. NULL);
  329. if (!NT_SUCCESS(Status)) {
  330. return Status;
  331. }
  332. return Status;
  333. }