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.

509 lines
14 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1994 - 1999
  3. Module Name:
  4. context.c
  5. Abstract:
  6. Performance test comparing different methods of context switching
  7. on NT. The tests process-to-process and thread-to-thread context
  8. switching. This code acts as both a client and a server.
  9. Author:
  10. Mario Goertzel (mariogo) 30-Mar-1994
  11. Revision History:
  12. --*/
  13. #include <rpcperf.h>
  14. static const char *REQUEST_EVENT = "Context Switch Perf Request Event";
  15. static const char *REQUEST_EVENT2 = "Context Switch Perf Request Event #2";
  16. static const char *REPLY_EVENT = "Context Switch Perf Reply Event";
  17. static const char *EVENT_PAIR = "\\RPC Control\\Perf Test: EventPair";
  18. const char *USAGE="-n type -n case\n"
  19. " Types:\n"
  20. " 1: Client and server (thread-to-thread context switches)\n"
  21. " 2: Server side of test (process-to-process)\n"
  22. " 3: Client side of test (process-to-process)\n"
  23. " Cases:\n"
  24. " 1: Use NT eventpairs\n"
  25. " 2: Use NT eventpairs (two step client)\n"
  26. " 3: Use SetEvent/WaitForSingleObject\n"
  27. " 4: Use SetEvent/WaitForSingleObject with timeout\n"
  28. " 5: Use SetEvent/WaitForMultipleObjects\n"
  29. " 6: Use SetEvent/WaitForMultipleObjects with timeout\n"
  30. " 7: Use SignalObjectAndWait on events\n"
  31. " 8: Use SignalObjectAndWait on events w/ timeout\n"
  32. ;
  33. //
  34. // The Server function is the server of the test. The client
  35. // maybe in the process, or another process, nobody knows...
  36. //
  37. ULONG Server(ULONG arg)
  38. {
  39. ULONG status;
  40. ULONG i;
  41. switch(Options[1])
  42. {
  43. case 1:
  44. case 2:
  45. {
  46. // NT event pairs
  47. OBJECT_ATTRIBUTES oaEventPair;
  48. ANSI_STRING ansiEventPairName;
  49. UNICODE_STRING unicodeEventPairName;
  50. HANDLE hEventPair;
  51. RtlInitAnsiString(&ansiEventPairName, EVENT_PAIR);
  52. RtlAnsiStringToUnicodeString(&unicodeEventPairName,
  53. &ansiEventPairName,
  54. TRUE);
  55. InitializeObjectAttributes(&oaEventPair,
  56. &unicodeEventPairName,
  57. OBJ_CASE_INSENSITIVE,
  58. 0,
  59. 0);
  60. status = NtCreateEventPair(&hEventPair,
  61. EVENT_PAIR_ALL_ACCESS,
  62. &oaEventPair);
  63. if (!NT_SUCCESS(status))
  64. {
  65. printf("NtCreateEventPair failed -- %8lX\n", status);
  66. return 1;
  67. }
  68. for(;;)
  69. {
  70. status = NtSetLowWaitHighEventPair(hEventPair);
  71. if (!NT_SUCCESS(status))
  72. {
  73. printf("NtSetLowWaitHighEventPair failed - %08lX\n",
  74. status);
  75. return(1);
  76. }
  77. }
  78. break;
  79. }
  80. case 3:
  81. case 4:
  82. {
  83. // Win32 events (w/ or w/o a timeout)
  84. ULONG timeout = (Options[1] == 3)?INFINITE:2000;
  85. HANDLE hEvent1, hEvent2;
  86. hEvent1 = CreateEvent(0,
  87. FALSE,
  88. FALSE,
  89. REQUEST_EVENT);
  90. hEvent2 = CreateEvent(0,
  91. FALSE,
  92. FALSE,
  93. REPLY_EVENT);
  94. if ( (hEvent1 == 0) || (hEvent2 == 0))
  95. {
  96. printf("CreateEvent failed - %08x\n", GetLastError());
  97. exit(1);
  98. }
  99. for(;;)
  100. {
  101. // Wait for clients request
  102. status = WaitForSingleObject(hEvent1, timeout);
  103. if (status != WAIT_OBJECT_0)
  104. {
  105. printf("Server WaitForSingleObject failed -- %08x\n", GetLastError());
  106. return 1;
  107. }
  108. // Reply
  109. status = SetEvent(hEvent2);
  110. if (status == 0)
  111. {
  112. printf("SetEvent failed - %08x\n", GetLastError());
  113. exit(1);
  114. }
  115. }
  116. CloseHandle(hEvent1);
  117. CloseHandle(hEvent2);
  118. break;
  119. }
  120. case 5:
  121. case 6:
  122. {
  123. // WaitForMultipleObjects/SetEvent w/ and w/o timeouts.
  124. ULONG timeout = (Options[1] == 5)?INFINITE:2000;
  125. ULONG cCount = 2;
  126. HANDLE ahEvents[2];
  127. HANDLE hReplyEvent;
  128. ahEvents[0] = CreateEvent(0,
  129. FALSE,
  130. FALSE,
  131. REQUEST_EVENT);
  132. ahEvents[1] = CreateEvent(0,
  133. FALSE,
  134. FALSE,
  135. REQUEST_EVENT2);
  136. hReplyEvent = CreateEvent(0,
  137. FALSE,
  138. FALSE,
  139. REPLY_EVENT);
  140. if ( (ahEvents[0] == 0) || (ahEvents[1] == 0) || (hReplyEvent == 0))
  141. {
  142. printf("CreateEvent failed - %08x\n", GetLastError());
  143. exit(1);
  144. }
  145. for(;;)
  146. {
  147. // Wait for clients request
  148. status = WaitForMultipleObjects(cCount, ahEvents, FALSE, timeout);
  149. if (status != WAIT_OBJECT_0)
  150. {
  151. printf("Server WaitForMultpleObjects failed -- %08x\n", GetLastError());
  152. return 1;
  153. }
  154. // Reply
  155. status = SetEvent(hReplyEvent);
  156. if (status == 0)
  157. {
  158. printf("SetEvent failed - %08x\n", GetLastError());
  159. exit(1);
  160. }
  161. }
  162. CloseHandle(ahEvents[0]);
  163. CloseHandle(ahEvents[1]);
  164. CloseHandle(hReplyEvent);
  165. break;
  166. }
  167. case 7:
  168. case 8:
  169. {
  170. ULONG timeout = (Options[1] == 7)?INFINITE:2000;
  171. HANDLE hEvent1, hEvent2;
  172. hEvent1 = CreateEvent(0,
  173. FALSE,
  174. FALSE,
  175. REQUEST_EVENT);
  176. hEvent2 = CreateEvent(0,
  177. FALSE,
  178. FALSE,
  179. REPLY_EVENT);
  180. if ( (hEvent1 == 0) || (hEvent2 == 0))
  181. {
  182. printf("CreateEvent failed - %08x\n", GetLastError());
  183. exit(1);
  184. }
  185. status = WaitForSingleObject(hEvent1, INFINITE);
  186. if (status != WAIT_OBJECT_0)
  187. {
  188. printf("Server WaitForSingleObject failed == %08x\n", GetLastError());
  189. }
  190. for(;;)
  191. {
  192. // Wait for clients request
  193. status = SignalObjectAndWait(hEvent2, hEvent1, timeout, FALSE);
  194. if (status != WAIT_OBJECT_0)
  195. {
  196. printf("Server SignalObjectAndWait failed -- %08x\n", GetLastError());
  197. return 1;
  198. }
  199. }
  200. CloseHandle(hEvent1);
  201. CloseHandle(hEvent2);
  202. break;
  203. }
  204. }
  205. return 0;
  206. }
  207. int __cdecl
  208. main(int argc, char **argv)
  209. {
  210. ULONG i;
  211. HANDLE hServer;
  212. ULONG status;
  213. ParseArgv(argc, argv);
  214. if ( (Options[0] < 0)
  215. || (Options[0] > 3)
  216. || (Options[1] < 0)
  217. || (Options[1] > 8) )
  218. {
  219. printf("Usage: %s : %s\n",
  220. argv[0],
  221. USAGE);
  222. return 1;
  223. }
  224. if (Options[0] == 2)
  225. {
  226. // Server only - run server.
  227. return Server(0);
  228. }
  229. if (Options[0] == 1)
  230. {
  231. // Both client and server, start server thread
  232. hServer = CreateThread(0,
  233. 0,
  234. (LPTHREAD_START_ROUTINE)Server,
  235. 0,
  236. 0,
  237. &i);
  238. if (hServer == 0)
  239. {
  240. printf("Create thread failed - %08x\n", GetLastError());
  241. return 1;
  242. }
  243. Sleep(500); // Let the server startup
  244. }
  245. // Run client side
  246. switch(Options[1])
  247. {
  248. case 1:
  249. case 2:
  250. {
  251. // NT event pairs
  252. OBJECT_ATTRIBUTES oaEventPair;
  253. ANSI_STRING ansiEventPairName;
  254. UNICODE_STRING unicodeEventPairName;
  255. HANDLE hEventPair;
  256. char * string =(Options[1]==1)?"eventpair":"eventpair (client set and wait)";
  257. RtlInitAnsiString(&ansiEventPairName, EVENT_PAIR);
  258. RtlAnsiStringToUnicodeString(&unicodeEventPairName,
  259. &ansiEventPairName,
  260. TRUE);
  261. InitializeObjectAttributes(&oaEventPair,
  262. &unicodeEventPairName,
  263. OBJ_CASE_INSENSITIVE,
  264. 0,
  265. 0);
  266. status = NtOpenEventPair(&hEventPair,
  267. EVENT_PAIR_ALL_ACCESS,
  268. &oaEventPair);
  269. if (!NT_SUCCESS(status))
  270. {
  271. printf("NtOpenEventPair failed -- %8lX\n", status);
  272. return 1;
  273. }
  274. StartTime();
  275. if (Options[1] == 1)
  276. {
  277. for(i = 0; i < Iterations; i++)
  278. {
  279. NtSetHighWaitLowEventPair(hEventPair);
  280. }
  281. }
  282. else
  283. {
  284. for(i = 0; i < Iterations; i++)
  285. {
  286. NtSetHighEventPair(hEventPair);
  287. NtWaitLowEventPair(hEventPair);
  288. }
  289. }
  290. EndTime(string);
  291. break;
  292. }
  293. case 3:
  294. case 4:
  295. case 5:
  296. case 6:
  297. {
  298. // Win32 events (w/ or w/o a timeout, WSO, WMO)
  299. ULONG timeout;
  300. char *string;
  301. HANDLE hEvent1, hEvent2;
  302. if ( (Options[1] == 4) || Options[1] == 6)
  303. timeout = 2000;
  304. else
  305. timeout = INFINITE;
  306. switch(Options[1])
  307. {
  308. case 3:
  309. string = "SetEvent/WaitForSingleObject";
  310. break;
  311. case 4:
  312. string = "SetEvent/WaitForSingleObject with timeout";
  313. break;
  314. case 5:
  315. string = "SetEvent/WaitForMultpleObjects";
  316. break;
  317. case 6:
  318. string = "SetEvent/WaitForMultipleObjects with timeout";
  319. break;
  320. }
  321. hEvent1 = CreateEvent(0,
  322. FALSE,
  323. FALSE,
  324. REQUEST_EVENT);
  325. hEvent2 = CreateEvent(0,
  326. FALSE,
  327. FALSE,
  328. REPLY_EVENT);
  329. if ( (hEvent1 == 0) || (hEvent2 == 0))
  330. {
  331. printf("CreateEvent failed - %08x\n", GetLastError());
  332. return 1;
  333. }
  334. StartTime();
  335. for(i = 0; i < Iterations; i++)
  336. {
  337. status = SetEvent(hEvent1);
  338. if (status == 0)
  339. {
  340. printf("SetEvent failed - %08x\n", GetLastError());
  341. return 1;
  342. }
  343. status = WaitForSingleObject(hEvent2, timeout);
  344. if (status != WAIT_OBJECT_0)
  345. {
  346. printf("WaitForSingleObejct failed -- %08x\n", GetLastError());
  347. return 1;
  348. }
  349. }
  350. EndTime(string);
  351. CloseHandle(hEvent1);
  352. CloseHandle(hEvent2);
  353. break;
  354. }
  355. case 7:
  356. case 8:
  357. {
  358. // Win32 events (w/ or w/o a timeout) and SignalObjectAndWait()
  359. ULONG timeout;
  360. char *string;
  361. HANDLE hEvent1, hEvent2;
  362. if ( (Options[1] == 8) )
  363. timeout = 2000;
  364. else
  365. timeout = INFINITE;
  366. switch(Options[1])
  367. {
  368. case 7:
  369. string = "SignalObjectAndWait";
  370. break;
  371. case 8:
  372. string = "SignalObjectAndWait with timeout";
  373. break;
  374. }
  375. hEvent1 = CreateEvent(0,
  376. FALSE,
  377. FALSE,
  378. REQUEST_EVENT);
  379. hEvent2 = CreateEvent(0,
  380. FALSE,
  381. FALSE,
  382. REPLY_EVENT);
  383. if ( (hEvent1 == 0) || (hEvent2 == 0))
  384. {
  385. printf("CreateEvent failed - %08x\n", GetLastError());
  386. return 1;
  387. }
  388. StartTime();
  389. for(i = 0; i < Iterations; i++)
  390. {
  391. status = SignalObjectAndWait(hEvent1, hEvent2, timeout, FALSE);
  392. if (status != WAIT_OBJECT_0)
  393. {
  394. printf("SignalObjectAndWait failed -- %08x\n", GetLastError());
  395. return 1;
  396. }
  397. }
  398. EndTime(string);
  399. CloseHandle(hEvent1);
  400. CloseHandle(hEvent2);
  401. break;
  402. }
  403. }
  404. // Blow off the server thread.
  405. return 0;
  406. }