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.

510 lines
11 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1994 - 1999
  3. Module Name:
  4. Server.c
  5. Abstract:
  6. Server side of RPC runtime performance test.
  7. Author:
  8. Mario Goertzel (mariogo) 31-Mar-1994
  9. Revision History:
  10. --*/
  11. #include <rpcperf.h>
  12. #include <rpcrt.h>
  13. // Usage
  14. const char *USAGE =
  15. "[-i iterations] [-l logfile] [-n clients] [-n minthreads] [-n case]*\n"
  16. " Client - default 1\n"
  17. " MinThreads - default 3\n"
  18. " Cases, you may specify up to five, default is all:\n"
  19. " 0: Null Call\n"
  20. " 1: Null Call (Non-Idem)\n"
  21. " 2: 1K IN\n"
  22. " 3: 1K OUT\n"
  23. " 4: 4K IN\n"
  24. " 5: 4K OUT\n"
  25. " 6: 32K IN\n"
  26. " 7: 32K OUT\n"
  27. " 8: Null Call (Non-Idem) w/ Context handle\n"
  28. " 9: Bind (fixed endpoint)\n"
  29. " 10: Re-Bind\n"
  30. " 11: Bind (dynamic endpoint)\n"
  31. " 12: Async Null Call\n"
  32. #ifdef WIN98
  33. " 13: Async STA Null Call\n"
  34. #endif
  35. "\n"
  36. " Note: Results are milliseconds/call/client\n"
  37. ;
  38. //
  39. // Globals making it easier.
  40. //
  41. int CurrentCase;
  42. char TestCases[TEST_MAX];
  43. long CurrentIter;
  44. unsigned long *Results;
  45. long Clients, ActiveClients, ClientsLeft;
  46. CRITICAL_SECTION CritSec;
  47. HANDLE GoEvent = 0;
  48. HANDLE DoneEvent = 0;
  49. char *TestNames[TEST_MAX] =
  50. {
  51. "Void Call",
  52. "Void Call (non-idem)",
  53. "1Kb Write (in)",
  54. "1Kb Read (out)",
  55. "4Kb Write (in)",
  56. "4Kb Read (out)",
  57. "32Kb Write (in)",
  58. "32Kb Read (out)",
  59. "Context Handle",
  60. "Bind (fixed ep)",
  61. "Re-bind",
  62. "Bind (dynamic ep)",
  63. "Async Void Call"
  64. #ifdef WIN98
  65. , "Async STA Void Call"
  66. #endif
  67. };
  68. long TestIterFactors[TEST_MAX] =
  69. {
  70. 1,1,
  71. 1,1,
  72. 4,4,
  73. 16,16,
  74. 1,
  75. 8,
  76. 2,
  77. 16,
  78. 1
  79. #ifdef WIN98
  80. ,1
  81. #endif
  82. };
  83. //
  84. // Figure out what we're testing and start listening.
  85. //
  86. int __cdecl
  87. main (int argc, char **argv)
  88. {
  89. unsigned int MinThreads;
  90. unsigned long i, status;
  91. RPC_BINDING_VECTOR *pBindingVector;
  92. #ifdef WIN98
  93. BOOL fIsPortseqWmsg;
  94. HWND hWnd;
  95. #endif
  96. ParseArgv(argc, argv);
  97. InitAllocator();
  98. #ifdef WIN98
  99. if (strcmp(Protseq, "mswmsg") == 0)
  100. fIsPortseqWmsg = TRUE;
  101. else
  102. fIsPortseqWmsg = FALSE;
  103. #endif
  104. MinThreads = 3;
  105. ClientsLeft = Clients = 1;
  106. ActiveClients = 0;
  107. if (Options[0] > 0)
  108. ClientsLeft = Clients = Options[0];
  109. Results = MIDL_user_allocate(4 * Clients);
  110. if (Options[1] > 0)
  111. MinThreads = Options[1];
  112. if (Options[2] < 0)
  113. {
  114. memset(TestCases, 1, TEST_MAX);
  115. }
  116. else
  117. {
  118. memset(TestCases, 0, TEST_MAX);
  119. for(i = 2; i < 7; i++)
  120. {
  121. if ( Options[i] < 0)
  122. break;
  123. if ( Options[i] >= TEST_MAX)
  124. break;
  125. TestCases[Options[i]] = 1;
  126. }
  127. }
  128. CurrentCase = 0;
  129. for(i = 0; i < TEST_MAX; i++)
  130. {
  131. if (TestCases[i])
  132. {
  133. CurrentCase = i;
  134. break;
  135. }
  136. }
  137. if (i == TEST_MAX)
  138. {
  139. printf("No test cases selected!\n");
  140. return 1;
  141. }
  142. CurrentIter = Iterations / TestIterFactors[CurrentCase];
  143. if (CurrentIter == 0) CurrentIter = 1;
  144. InitializeCriticalSection(&CritSec);
  145. GoEvent = CreateEvent(0,
  146. TRUE,
  147. FALSE,
  148. 0);
  149. DoneEvent = CreateEvent(0,
  150. TRUE,
  151. FALSE,
  152. 0);
  153. //
  154. // Actually start the server
  155. //
  156. if (Endpoint)
  157. {
  158. status = RpcServerUseProtseqEp(Protseq, 100, Endpoint, 0);
  159. CHECK_STATUS(status, "RpcServerUseProtseqEp");
  160. }
  161. else
  162. {
  163. char *string_binding;
  164. status = RpcServerUseProtseq(Protseq, 100, 0);
  165. CHECK_STATUS(status, "RpcServerUseProtseqEp");
  166. status = RpcServerInqBindings(&pBindingVector);
  167. CHECK_STATUS(status, "RpcServerInqBindings");
  168. status = RpcEpRegister(RpcRuntimePerf_v2_0_s_ifspec,
  169. pBindingVector,
  170. 0,
  171. 0);
  172. CHECK_STATUS(status, "RpcEpRegister");
  173. status = RpcBindingToStringBinding(pBindingVector->BindingH[0],
  174. &string_binding);
  175. CHECK_STATUS(status, "RpcBindingToStringBinding");
  176. status = RpcStringBindingParse(string_binding,
  177. 0, 0, 0, &Endpoint, 0);
  178. CHECK_STATUS(status, "RpcStringBindingParse");
  179. printf("Listening to %s:[%s]\n\n", Protseq, Endpoint);
  180. }
  181. #ifdef WIN98
  182. if (fIsPortseqWmsg)
  183. {
  184. hWnd = CreateSTAWindow("Perf Server");
  185. if (hWnd == NULL)
  186. {
  187. printf("Creation of an STA window failed: %ld\n", GetLastError());
  188. return 2;
  189. }
  190. I_RpcServerStartListening(hWnd);
  191. }
  192. #endif
  193. status =
  194. RpcServerRegisterIf(RpcRuntimePerf_v2_0_s_ifspec,0,0);
  195. CHECK_STATUS(status, "RpcServerRegisterIf");
  196. status = RpcServerRegisterAuthInfo(NULL,
  197. RPC_C_AUTHN_WINNT,
  198. NULL,
  199. NULL);
  200. CHECK_STATUS(status, "RpcServerRegisterAuthInfo");
  201. printf("Base Iterations: %d, Clients %d, MinThreads %d\n",
  202. Iterations,
  203. Clients,
  204. MinThreads);
  205. printf("Server listening\n");
  206. #ifndef WIN98
  207. status = RpcServerListen(MinThreads, 100, 0);
  208. CHECK_STATUS(status, "RpcServerListen");
  209. #else
  210. if (fIsPortseqWmsg)
  211. {
  212. status = RpcServerListen(MinThreads, 100, TRUE);
  213. CHECK_STATUS(status, "RpcServerListen");
  214. RunMessageLoop(hWnd);
  215. }
  216. else
  217. {
  218. status = RpcServerListen(MinThreads, 100, 0);
  219. CHECK_STATUS(status, "RpcServerListen");
  220. }
  221. #endif
  222. printf("This doesn't stop listening..hmm\n");
  223. return 0;
  224. }
  225. //
  226. // Control APIs that the client(s) call to sync on test cases, iterations
  227. // and to report results.
  228. //
  229. error_status_t
  230. BeginTest(handle_t b,
  231. long *ClientId)
  232. {
  233. long status = 0;
  234. EnterCriticalSection(&CritSec);
  235. if (ActiveClients < Clients)
  236. {
  237. ActiveClients++;
  238. *ClientId = ActiveClients;
  239. }
  240. else
  241. {
  242. status = PERF_TOO_MANY_CLIENTS;
  243. }
  244. LeaveCriticalSection(&CritSec);
  245. return status;
  246. }
  247. error_status_t
  248. NextTest(handle_t b,
  249. TEST_TYPE *Test,
  250. long *Iters)
  251. {
  252. long wait = 1;
  253. long done = 0;
  254. int i;
  255. EnterCriticalSection(&CritSec);
  256. *Test = CurrentCase;
  257. *Iters = CurrentIter;
  258. ClientsLeft--;
  259. if (CurrentCase == TEST_MAX)
  260. {
  261. done = 1;
  262. }
  263. if (ClientsLeft == 0)
  264. {
  265. //
  266. // Let all the waiting clients go
  267. //
  268. wait = 0;
  269. ResetEvent(DoneEvent);
  270. SetEvent(GoEvent);
  271. }
  272. LeaveCriticalSection(&CritSec);
  273. if (wait)
  274. {
  275. WaitForSingleObject(GoEvent, INFINITE);
  276. }
  277. if (done)
  278. {
  279. if (ClientsLeft == 0)
  280. {
  281. // I'm the last client, sleep and then reset for
  282. // a new set of clients. Sleep avoids a race (usually).
  283. Sleep(1000);
  284. for(i = 0; i < TEST_MAX; i++)
  285. {
  286. if (TestCases[i])
  287. {
  288. CurrentCase = i;
  289. break;
  290. }
  291. }
  292. CurrentIter = Iterations / TestIterFactors[CurrentCase];
  293. if (CurrentIter == 0) CurrentIter = 1;
  294. ActiveClients = 0;
  295. ClientsLeft = Clients;
  296. ResetEvent(GoEvent);
  297. ResetEvent(DoneEvent);
  298. }
  299. return PERF_TESTS_DONE;
  300. }
  301. return 0;
  302. }
  303. error_status_t
  304. EndTest(handle_t b,
  305. unsigned long mseconds)
  306. {
  307. long status, i;
  308. long wait = 1;
  309. EnterCriticalSection(&CritSec);
  310. Results[ClientsLeft] = mseconds;
  311. ClientsLeft++;
  312. if (ClientsLeft == Clients)
  313. {
  314. // All clients have finished
  315. // Report results
  316. printf("| % 3d | %-20s | % 6d |",
  317. CurrentCase,
  318. TestNames[CurrentCase],
  319. CurrentIter
  320. );
  321. for(i = 0; i < Clients; i++)
  322. printf(" % 3d.%03d |",
  323. Results[i] / CurrentIter,
  324. Results[i] % CurrentIter * 1000 / CurrentIter
  325. );
  326. printf("\n");
  327. // Setup next case
  328. for(i = CurrentCase + 1; i < TEST_MAX; i++)
  329. {
  330. #ifdef PROTOCOL_TRIM
  331. if (i == 11)
  332. continue;
  333. #endif
  334. #ifndef WIN98
  335. // NT does not test Async STA calls.
  336. if (i == 13)
  337. continue;
  338. #else
  339. // Win9x also doesn't want to test Async STA calls unless the protseq is
  340. if ((i == 13) && (strcmp(Protseq, "mswmsg") != 0))
  341. continue;
  342. #endif
  343. if (TestCases[i])
  344. {
  345. CurrentCase = i;
  346. break;
  347. }
  348. }
  349. if (i == TEST_MAX)
  350. {
  351. CurrentCase = TEST_MAX;
  352. printf("TEST DONE\n");
  353. }
  354. else
  355. {
  356. CurrentIter = Iterations / TestIterFactors[CurrentCase];
  357. if (CurrentIter == 0) CurrentIter = 1;
  358. }
  359. //
  360. // We're setup for the next test (or to finish) let the clients go.
  361. //
  362. wait = 0;
  363. ResetEvent(GoEvent);
  364. SetEvent(DoneEvent);
  365. }
  366. LeaveCriticalSection(&CritSec);
  367. if (wait)
  368. WaitForSingleObject(DoneEvent, INFINITE);
  369. return 0;
  370. }
  371. //
  372. // For fixed endpoint and re-bind test case
  373. //
  374. unsigned char *GetFixedEp(handle_t h)
  375. {
  376. char *r;
  377. r = malloc(strlen(Endpoint) + 1);
  378. strcpy(r, Endpoint);
  379. return (unsigned char *)r;
  380. }
  381. //
  382. // For context handle tests
  383. //
  384. PERF_CONTEXT OpenContext (handle_t b) { return (PERF_CONTEXT)1; }
  385. void CloseContext(PERF_CONTEXT *pp) { *pp = 0; }
  386. void PERF_CONTEXT_rundown(PERF_CONTEXT pp)
  387. {
  388. printf("Failure - a context randown\n");
  389. }
  390. //
  391. // Regular test calls do nothing...
  392. //
  393. void NullCall(handle_t h) { return; }
  394. void NICall (handle_t h) { return; }
  395. void ContextNullCall (PERF_CONTEXT h) { return; }
  396. void Write1K (handle_t h, unsigned char *p) { return; }
  397. void Read1K (handle_t h, unsigned char *p) { return; }
  398. void Write4K (handle_t h, unsigned char *p) { return; }
  399. void Read4K (handle_t h, unsigned char *p) { return; }
  400. void Write32K(handle_t h, unsigned char *p) { return; }
  401. void Read32K (handle_t h, unsigned char *p) { return; }
  402. void AsyncNullCall(RPC_ASYNC_STATE *AsyncHandle, handle_t h)
  403. {
  404. RpcAsyncCompleteCall(AsyncHandle, NULL);
  405. }
  406. void AsyncSTANullCall(RPC_ASYNC_STATE *AsyncHandle, handle_t h)
  407. {
  408. RpcAsyncCompleteCall(AsyncHandle, NULL);
  409. }