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.

2783 lines
63 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. timt.c
  5. Abstract:
  6. This module contains native NT performance tests for the system
  7. calls and context switching.
  8. Author:
  9. David N. Cutler (davec) 23-Nov-1991
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "stdlib.h"
  15. #include "stdio.h"
  16. #include "string.h"
  17. #include "nt.h"
  18. #include "ntrtl.h"
  19. #include "nturtl.h"
  20. #include "windef.h"
  21. #include "winbase.h"
  22. //
  23. // Define locals constants.
  24. //
  25. #define CHECKSUM_BUFFER_SIZE (1 << 16)
  26. #define CHECKSUM_ITERATIONS 4000
  27. #define CHECKSUM_IP_ITERATIONS 40000000
  28. #define EVENT_CLEAR_ITERATIONS 3000000
  29. #define EVENT_CREATION_ITERATIONS 400000
  30. #define EVENT_OPEN_ITERATIONS 200000
  31. #define EVENT_QUERY_ITERATIONS 2000000
  32. #define EVENT_RESET_ITERATIONS 2000000
  33. #define EVENT1_SWITCHES 300000
  34. #define EVENT2_SWITCHES 200000
  35. #define EVENT3_SWITCHES 400000
  36. #define IO_ITERATIONS 350000
  37. #define MUTANT_SWITCHES 200000
  38. #define SLIST_ITERATIONS 20000000
  39. #define SEMAPHORE1_SWITCHES 300000
  40. #define SEMAPHORE2_SWITCHES 600000
  41. #define SYSCALL_ITERATIONS 6000000
  42. #define TIMER_OPERATION_ITERATIONS 500000
  43. #define UNALIGNED_ITERATIONS 400000000
  44. #define WAIT_SINGLE_ITERATIONS 2000000
  45. #define WAIT_MULTIPLE_ITERATIONS 2000000
  46. //
  47. // Define event desired access.
  48. //
  49. #define DESIRED_EVENT_ACCESS (EVENT_QUERY_STATE | EVENT_MODIFY_STATE | SYNCHRONIZE)
  50. //
  51. // Define local types.
  52. //
  53. typedef struct _PERFINFO {
  54. LARGE_INTEGER StartTime;
  55. LARGE_INTEGER StopTime;
  56. LARGE_INTEGER StartCycles;
  57. LARGE_INTEGER StopCycles;
  58. ULONG ContextSwitches;
  59. ULONG SystemCalls;
  60. PCHAR Title;
  61. ULONG Iterations;
  62. } PERFINFO, *PPERFINFO;
  63. //
  64. // Define test prototypes.
  65. //
  66. VOID
  67. ChecksumTest (
  68. VOID
  69. );
  70. VOID
  71. EventClearTest (
  72. VOID
  73. );
  74. VOID
  75. EventCreationTest (
  76. VOID
  77. );
  78. VOID
  79. EventOpenTest (
  80. VOID
  81. );
  82. VOID
  83. EventQueryTest (
  84. VOID
  85. );
  86. VOID
  87. EventResetTest (
  88. VOID
  89. );
  90. VOID
  91. Event1SwitchTest (
  92. VOID
  93. );
  94. VOID
  95. Event2SwitchTest (
  96. VOID
  97. );
  98. VOID
  99. Event3SwitchTest (
  100. VOID
  101. );
  102. VOID
  103. Io1Test (
  104. VOID
  105. );
  106. VOID
  107. MutantSwitchTest (
  108. VOID
  109. );
  110. VOID
  111. Semaphore1SwitchTest (
  112. VOID
  113. );
  114. VOID
  115. Semaphore2SwitchTest (
  116. VOID
  117. );
  118. LONG
  119. SetProcessPrivilege (
  120. TCHAR *PrivilegeName
  121. );
  122. VOID
  123. SlistTest (
  124. VOID
  125. );
  126. VOID
  127. SystemCallTest (
  128. VOID
  129. );
  130. VOID
  131. TimerOperationTest (
  132. VOID
  133. );
  134. VOID
  135. UnalignedTest1 (
  136. VOID
  137. );
  138. VOID
  139. UnalignedTest2 (
  140. VOID
  141. );
  142. VOID
  143. WaitSingleTest (
  144. VOID
  145. );
  146. VOID
  147. WaitMultipleTest (
  148. VOID
  149. );
  150. //
  151. // Define thread routine prototypes.
  152. //
  153. NTSTATUS
  154. Event1Thread1 (
  155. IN PVOID Context
  156. );
  157. NTSTATUS
  158. Event1Thread2 (
  159. IN PVOID Context
  160. );
  161. NTSTATUS
  162. Event2Thread1 (
  163. IN PVOID Context
  164. );
  165. NTSTATUS
  166. Event2Thread2 (
  167. IN PVOID Context
  168. );
  169. NTSTATUS
  170. Event3Thread1 (
  171. IN PVOID Context
  172. );
  173. NTSTATUS
  174. Event3Thread2 (
  175. IN PVOID Context
  176. );
  177. NTSTATUS
  178. MutantThread1 (
  179. IN PVOID Context
  180. );
  181. NTSTATUS
  182. MutantThread2 (
  183. IN PVOID Context
  184. );
  185. NTSTATUS
  186. Semaphore1Thread1 (
  187. IN PVOID Context
  188. );
  189. NTSTATUS
  190. Semaphore1Thread2 (
  191. IN PVOID Context
  192. );
  193. NTSTATUS
  194. Semaphore2Thread1 (
  195. IN PVOID Context
  196. );
  197. NTSTATUS
  198. Semaphore2Thread2 (
  199. IN PVOID Context
  200. );
  201. NTSTATUS
  202. TimerThread (
  203. IN PVOID Context
  204. );
  205. //
  206. // Define utility routine prototypes.
  207. //
  208. NTSTATUS
  209. xCreateThread (
  210. OUT PHANDLE Handle,
  211. IN PUSER_THREAD_START_ROUTINE StartRoutine,
  212. IN KPRIORITY Priority
  213. );
  214. VOID
  215. FinishBenchMark (
  216. IN PPERFINFO PerfInfo
  217. );
  218. VOID
  219. StartBenchMark (
  220. IN PCHAR Title,
  221. IN ULONG Iterations,
  222. IN PPERFINFO PerfInfo
  223. );
  224. //
  225. // Define external routine prototypes.
  226. //
  227. ULONG
  228. ComputeTimerTableIndex32 (
  229. IN LARGE_INTEGER Interval,
  230. IN LARGE_INTEGER CurrentTime,
  231. IN PULONGLONG DueTime
  232. );
  233. ULONG
  234. ComputeTimerTableIndex64 (
  235. IN LARGE_INTEGER Interval,
  236. IN LARGE_INTEGER CurrentTime,
  237. IN PULONGLONG DueTime
  238. );
  239. ULONG
  240. ChkSum (
  241. IN ULONG Sum,
  242. IN PUSHORT Buffer,
  243. IN ULONG Length
  244. );
  245. ULONG
  246. tcpxsum (
  247. IN ULONG Sum,
  248. IN PVOID Buffer,
  249. IN ULONG Length
  250. );
  251. //
  252. // Define static storage.
  253. //
  254. HANDLE EventHandle1;
  255. HANDLE EventHandle2;
  256. HANDLE EventPairHandle;
  257. HANDLE MutantHandle;
  258. HANDLE SemaphoreHandle1;
  259. HANDLE SemaphoreHandle2;
  260. HANDLE Thread1Handle;
  261. HANDLE Thread2Handle;
  262. HANDLE TimerEventHandle;
  263. HANDLE TimerTimerHandle;
  264. HANDLE TimerThreadHandle;
  265. USHORT ChecksumBuffer[CHECKSUM_BUFFER_SIZE / sizeof(USHORT)];
  266. VOID
  267. __cdecl
  268. main(
  269. int argc,
  270. char *argv[]
  271. )
  272. {
  273. KPRIORITY Priority = LOW_REALTIME_PRIORITY + 8;
  274. NTSTATUS Status;
  275. //
  276. // Set process privilege to increase priority.
  277. //
  278. if (SetProcessPrivilege(SE_INC_BASE_PRIORITY_NAME) != 0) {
  279. printf("Failed to set process privilege to increase priority\n");
  280. goto EndOfTest;
  281. }
  282. //
  283. // set priority of current thread.
  284. //
  285. Status = NtSetInformationThread(NtCurrentThread(),
  286. ThreadPriority,
  287. &Priority,
  288. sizeof(KPRIORITY));
  289. if (!NT_SUCCESS(Status)) {
  290. printf("Failed to set thread priority during initialization\n");
  291. goto EndOfTest;
  292. }
  293. //
  294. // Create an event object to signal the timer thread at the end of the
  295. // test.
  296. //
  297. Status = NtCreateEvent(&TimerEventHandle,
  298. DESIRED_EVENT_ACCESS,
  299. NULL,
  300. NotificationEvent,
  301. FALSE);
  302. if (!NT_SUCCESS(Status)) {
  303. printf("Failed to create event during initialization\n");
  304. goto EndOfTest;
  305. }
  306. //
  307. // Create a timer object for use by the timer thread.
  308. //
  309. Status = NtCreateTimer(&TimerTimerHandle,
  310. TIMER_ALL_ACCESS,
  311. NULL,
  312. NotificationTimer);
  313. if (!NT_SUCCESS(Status)) {
  314. printf("Failed to create timer during initialization\n");
  315. goto EndOfTest;
  316. }
  317. //
  318. // Create and start the background timer thread.
  319. //
  320. Status = xCreateThread(&TimerThreadHandle,
  321. TimerThread,
  322. LOW_REALTIME_PRIORITY + 12);
  323. if (!NT_SUCCESS(Status)) {
  324. printf("Failed to create timer thread during initialization\n");
  325. goto EndOfTest;
  326. }
  327. //
  328. // Execute performance tests.
  329. //
  330. // ChecksumTest();
  331. // EventClearTest();
  332. // EventCreationTest();
  333. // EventOpenTest();
  334. // EventQueryTest();
  335. // EventResetTest();
  336. // Event1SwitchTest();
  337. // Event2SwitchTest();
  338. // Event3SwitchTest();
  339. // Io1Test();
  340. // MutantSwitchTest();
  341. // Semaphore1SwitchTest();
  342. // Semaphore2SwitchTest();
  343. // SlistTest();
  344. // SystemCallTest();
  345. // TimerOperationTest();
  346. // WaitSingleTest();
  347. // WaitMultipleTest();
  348. UnalignedTest1();
  349. UnalignedTest2();
  350. //
  351. // Set timer event and wait for timer thread to terminate.
  352. //
  353. Status = NtSetEvent(TimerEventHandle, NULL);
  354. if (!NT_SUCCESS(Status)) {
  355. printf("Failed to set event in main loop\n");
  356. goto EndOfTest;
  357. }
  358. Status = NtWaitForSingleObject(TimerThreadHandle,
  359. FALSE,
  360. NULL);
  361. if (!NT_SUCCESS(Status)) {
  362. printf("Failed to wait for timer thread at end of test\n");
  363. }
  364. //
  365. // Close event, timer, and timer thread handles.
  366. //
  367. EndOfTest:
  368. NtClose(TimerEventHandle);
  369. NtClose(TimerTimerHandle);
  370. NtClose(TimerThreadHandle);
  371. return;
  372. }
  373. VOID
  374. ChecksumTest (
  375. VOID
  376. )
  377. {
  378. LONG Count;
  379. LONG Index;
  380. PERFINFO PerfInfo;
  381. ULONG Sum1;
  382. ULONG Sum2 = 0;
  383. PUCHAR Source;
  384. //
  385. // Initialize the checksum buffer.
  386. //
  387. for (Index = 0; Index < (CHECKSUM_BUFFER_SIZE / sizeof(USHORT)); Index += 1) {
  388. ChecksumBuffer[Index] = (USHORT)rand();
  389. }
  390. Source = (PUCHAR)&ChecksumBuffer[0];
  391. Source += 1;
  392. //
  393. // Announce start of benchmark and capture performance parameters.
  394. //
  395. StartBenchMark("Checksum (aligned) Benchmark",
  396. CHECKSUM_ITERATIONS,
  397. &PerfInfo);
  398. //
  399. // Repeatedly checksum buffers of varying sizes.
  400. //
  401. for (Count = 0; Count < CHECKSUM_ITERATIONS; Count += 1) {
  402. for (Index = 1024; Index >= 2 ; Index -= 1) {
  403. Sum2 = tcpxsum(Sum2, &ChecksumBuffer[0], Index);
  404. }
  405. }
  406. //
  407. // Print out performance statistics.
  408. //
  409. FinishBenchMark(&PerfInfo);
  410. //
  411. // Announce start of benchmark and capture performance parameters.
  412. //
  413. StartBenchMark("Checksum (unaligned) Benchmark",
  414. CHECKSUM_ITERATIONS,
  415. &PerfInfo);
  416. //
  417. // Repeatedly checksum buffers of varying sizes.
  418. //
  419. for (Count = 0; Count < CHECKSUM_ITERATIONS; Count += 1) {
  420. for (Index = 1024; Index >= 2 ; Index -= 1) {
  421. Sum2 = tcpxsum(Sum2, Source, Index);
  422. }
  423. }
  424. //
  425. // Print out performance statistics.
  426. //
  427. FinishBenchMark(&PerfInfo);
  428. //
  429. // Announce start of benchmark and capture performance parameters.
  430. //
  431. StartBenchMark("Ip Header Checksum (aligned) Benchmark",
  432. CHECKSUM_IP_ITERATIONS,
  433. &PerfInfo);
  434. //
  435. // Repeatedly checksum buffers of varying sizes.
  436. //
  437. for (Count = 0; Count < CHECKSUM_IP_ITERATIONS; Count += 1) {
  438. Sum1 = tcpxsum(0, &ChecksumBuffer[0], 20);
  439. }
  440. //
  441. // Print out performance statistics.
  442. //
  443. FinishBenchMark(&PerfInfo);
  444. //
  445. // Announce start of benchmark and capture performance parameters.
  446. //
  447. StartBenchMark("Ip Header Checksum (unaligned) Benchmark",
  448. CHECKSUM_IP_ITERATIONS,
  449. &PerfInfo);
  450. //
  451. // Repeatedly checksum buffers of varying sizes.
  452. //
  453. for (Count = 0; Count < CHECKSUM_IP_ITERATIONS; Count += 1) {
  454. Sum2 = tcpxsum(0, Source, 20);
  455. }
  456. //
  457. // Print out performance statistics.
  458. //
  459. FinishBenchMark(&PerfInfo);
  460. return;
  461. }
  462. VOID
  463. EventClearTest (
  464. VOID
  465. )
  466. {
  467. HANDLE EventHandle;
  468. LONG Index;
  469. PERFINFO PerfInfo;
  470. NTSTATUS Status;
  471. //
  472. // Create an event for clear operations.
  473. //
  474. Status = NtCreateEvent(&EventHandle,
  475. DESIRED_EVENT_ACCESS,
  476. NULL,
  477. NotificationEvent,
  478. TRUE);
  479. if (!NT_SUCCESS(Status)) {
  480. printf("Failed to create event object for clear test\n");
  481. goto EndOfTest;
  482. }
  483. //
  484. // Announce start of benchmark and capture performance parameters.
  485. //
  486. StartBenchMark("Clear Event Benchmark",
  487. EVENT_CLEAR_ITERATIONS,
  488. &PerfInfo);
  489. //
  490. // Repeatedly clear an event.
  491. //
  492. for (Index = 0; Index < EVENT_RESET_ITERATIONS; Index += 1) {
  493. Status = NtClearEvent(EventHandle);
  494. if (!NT_SUCCESS(Status)) {
  495. printf(" Clear event bad status, %x\n", Status);
  496. goto EndOfTest;
  497. }
  498. }
  499. //
  500. // Print out performance statistics.
  501. //
  502. FinishBenchMark(&PerfInfo);
  503. //
  504. // End of clear event test.
  505. //
  506. EndOfTest:
  507. NtClose(EventHandle);
  508. return;
  509. }
  510. VOID
  511. EventCreationTest (
  512. VOID
  513. )
  514. {
  515. ULONG Index;
  516. PERFINFO PerfInfo;
  517. NTSTATUS Status;
  518. //
  519. // Announce start of benchmark and capture performance parmeters.
  520. //
  521. StartBenchMark("Event Creation Benchmark",
  522. EVENT_CREATION_ITERATIONS,
  523. &PerfInfo);
  524. //
  525. // Create an event and then close it.
  526. //
  527. for (Index = 0; Index < EVENT_CREATION_ITERATIONS; Index += 1) {
  528. Status = NtCreateEvent(&EventHandle1,
  529. DESIRED_EVENT_ACCESS,
  530. NULL,
  531. SynchronizationEvent,
  532. FALSE);
  533. if (!NT_SUCCESS(Status)) {
  534. printf("Failed to create event object for event creation test.\n");
  535. goto EndOfTest;
  536. }
  537. NtClose(EventHandle1);
  538. }
  539. //
  540. // Print out performance statistics.
  541. //
  542. FinishBenchMark(&PerfInfo);
  543. //
  544. // End of event creation test.
  545. //
  546. EndOfTest:
  547. return;
  548. }
  549. VOID
  550. EventOpenTest (
  551. VOID
  552. )
  553. {
  554. ANSI_STRING EventName;
  555. ULONG Index;
  556. OBJECT_ATTRIBUTES ObjectAttributes;
  557. PERFINFO PerfInfo;
  558. NTSTATUS Status;
  559. UNICODE_STRING UnicodeEventName;
  560. //
  561. // Create a named event for event open test.
  562. //
  563. RtlInitAnsiString(&EventName, "\\BaseNamedObjects\\EventOpenName");
  564. Status = RtlAnsiStringToUnicodeString(&UnicodeEventName,
  565. &EventName,
  566. TRUE);
  567. if (!NT_SUCCESS(Status)) {
  568. printf("Failed to create UNICODE string for event open test\n");
  569. goto EndOfTest;
  570. }
  571. InitializeObjectAttributes(&ObjectAttributes,
  572. &UnicodeEventName,
  573. OBJ_CASE_INSENSITIVE,
  574. NULL,
  575. NULL);
  576. Status = NtCreateEvent(&EventHandle1,
  577. DESIRED_EVENT_ACCESS,
  578. &ObjectAttributes,
  579. SynchronizationEvent,
  580. FALSE);
  581. if (!NT_SUCCESS(Status)) {
  582. printf("Failed to create event object for event open test.\n");
  583. goto EndOfTest;
  584. }
  585. //
  586. // Announce start of benchmark and capture performance parmeters.
  587. //
  588. StartBenchMark("Event Open Benchmark",
  589. EVENT_OPEN_ITERATIONS,
  590. &PerfInfo);
  591. //
  592. // Open a named event and then close it.
  593. //
  594. for (Index = 0; Index < EVENT_OPEN_ITERATIONS; Index += 1) {
  595. Status = NtOpenEvent(&EventHandle2,
  596. EVENT_QUERY_STATE | EVENT_MODIFY_STATE | SYNCHRONIZE,
  597. &ObjectAttributes);
  598. if (!NT_SUCCESS(Status)) {
  599. printf("Failed to open event for open event test\n");
  600. goto EndOfTest;
  601. }
  602. NtClose(EventHandle2);
  603. }
  604. //
  605. // Print out performance statistics.
  606. //
  607. FinishBenchMark(&PerfInfo);
  608. //
  609. // End of event open test.
  610. //
  611. EndOfTest:
  612. NtClose(EventHandle1);
  613. return;
  614. }
  615. VOID
  616. EventQueryTest (
  617. VOID
  618. )
  619. {
  620. HANDLE EventHandle;
  621. EVENT_BASIC_INFORMATION EventInformation;
  622. LONG Index;
  623. PERFINFO PerfInfo;
  624. NTSTATUS Status;
  625. //
  626. // Create an event for query operations.
  627. //
  628. Status = NtCreateEvent(&EventHandle,
  629. DESIRED_EVENT_ACCESS,
  630. NULL,
  631. NotificationEvent,
  632. TRUE);
  633. if (!NT_SUCCESS(Status)) {
  634. printf("Failed to create event object for query test\n");
  635. goto EndOfTest;
  636. }
  637. //
  638. // Announce start of benchmark and capture performance parameters.
  639. //
  640. StartBenchMark("Query Event Benchmark",
  641. EVENT_QUERY_ITERATIONS,
  642. &PerfInfo);
  643. //
  644. // Repeatedly query an event.
  645. //
  646. for (Index = 0; Index < EVENT_QUERY_ITERATIONS; Index += 1) {
  647. Status = NtQueryEvent(EventHandle,
  648. EventBasicInformation,
  649. &EventInformation,
  650. sizeof(EVENT_BASIC_INFORMATION),
  651. NULL);
  652. if (!NT_SUCCESS(Status)) {
  653. printf(" Query event bad status, %x\n", Status);
  654. goto EndOfTest;
  655. }
  656. }
  657. //
  658. // Print out performance statistics.
  659. //
  660. FinishBenchMark(&PerfInfo);
  661. //
  662. // End of query event test.
  663. //
  664. EndOfTest:
  665. NtClose(EventHandle);
  666. return;
  667. }
  668. VOID
  669. EventResetTest (
  670. VOID
  671. )
  672. {
  673. HANDLE EventHandle;
  674. LONG Index;
  675. PERFINFO PerfInfo;
  676. NTSTATUS Status;
  677. //
  678. // Create an event for reset operations.
  679. //
  680. Status = NtCreateEvent(&EventHandle,
  681. DESIRED_EVENT_ACCESS,
  682. NULL,
  683. NotificationEvent,
  684. TRUE);
  685. if (!NT_SUCCESS(Status)) {
  686. printf("Failed to create event object for reset test\n");
  687. goto EndOfTest;
  688. }
  689. //
  690. // Announce start of benchmark and capture performance parameters.
  691. //
  692. StartBenchMark("Reset Event Benchmark",
  693. EVENT_RESET_ITERATIONS,
  694. &PerfInfo);
  695. //
  696. // Repeatedly reset an event.
  697. //
  698. for (Index = 0; Index < EVENT_RESET_ITERATIONS; Index += 1) {
  699. Status = NtResetEvent(EventHandle,
  700. NULL);
  701. if (!NT_SUCCESS(Status)) {
  702. printf(" Reset event bad status, %x\n", Status);
  703. goto EndOfTest;
  704. }
  705. }
  706. //
  707. // Print out performance statistics.
  708. //
  709. FinishBenchMark(&PerfInfo);
  710. //
  711. // End of reset event test.
  712. //
  713. EndOfTest:
  714. NtClose(EventHandle);
  715. return;
  716. }
  717. VOID
  718. Event1SwitchTest (
  719. VOID
  720. )
  721. {
  722. PERFINFO PerfInfo;
  723. NTSTATUS Status;
  724. HANDLE WaitObjects[2];
  725. //
  726. // Create two event objects for the event1 context switch test.
  727. //
  728. Status = NtCreateEvent(&EventHandle1,
  729. DESIRED_EVENT_ACCESS,
  730. NULL,
  731. SynchronizationEvent,
  732. FALSE);
  733. if (!NT_SUCCESS(Status)) {
  734. printf("Failed to create event1 object for context switch test.\n");
  735. goto EndOfTest;
  736. }
  737. Status = NtCreateEvent(&EventHandle2,
  738. DESIRED_EVENT_ACCESS,
  739. NULL,
  740. SynchronizationEvent,
  741. FALSE);
  742. if (!NT_SUCCESS(Status)) {
  743. printf("Failed to create event1 object for context switch test.\n");
  744. goto EndOfTest;
  745. }
  746. //
  747. // Create the thread objects to execute the test.
  748. //
  749. Status = xCreateThread(&Thread1Handle,
  750. Event1Thread1,
  751. LOW_REALTIME_PRIORITY - 2);
  752. if (!NT_SUCCESS(Status)) {
  753. printf("Failed to create first thread event1 context switch test\n");
  754. goto EndOfTest;
  755. }
  756. Status = xCreateThread(&Thread2Handle,
  757. Event1Thread2,
  758. LOW_REALTIME_PRIORITY - 2);
  759. if (!NT_SUCCESS(Status)) {
  760. printf("Failed to create second thread event1 context switch test\n");
  761. goto EndOfTest;
  762. }
  763. //
  764. // Initialize the wait objects array.
  765. //
  766. WaitObjects[0] = Thread1Handle;
  767. WaitObjects[1] = Thread2Handle;
  768. //
  769. // Announce start of benchmark and capture performance parmeters.
  770. //
  771. StartBenchMark("Event (synchronization) Context Switch Benchmark (Round Trips)",
  772. EVENT1_SWITCHES,
  773. &PerfInfo);
  774. //
  775. // Set event and wait for threads to terminate.
  776. //
  777. Status = NtSetEvent(EventHandle1, NULL);
  778. if (!NT_SUCCESS(Status)) {
  779. printf("Failed to set event event1 context switch test.\n");
  780. goto EndOfTest;
  781. }
  782. Status = NtWaitForMultipleObjects(2,
  783. WaitObjects,
  784. WaitAll,
  785. FALSE,
  786. NULL);
  787. if (!NT_SUCCESS(Status)) {
  788. printf("Failed to wait event1 context switch test.\n");
  789. goto EndOfTest;
  790. }
  791. //
  792. // Print out performance statistics.
  793. //
  794. FinishBenchMark(&PerfInfo);
  795. //
  796. // End of event1 context switch test.
  797. //
  798. EndOfTest:
  799. NtClose(EventHandle1);
  800. NtClose(EventHandle2);
  801. NtClose(Thread1Handle);
  802. NtClose(Thread2Handle);
  803. return;
  804. }
  805. NTSTATUS
  806. Event1Thread1 (
  807. IN PVOID Context
  808. )
  809. {
  810. ULONG Index;
  811. NTSTATUS Status;
  812. //
  813. // Wait for event 1 and then set event 2.
  814. //
  815. for (Index = 0; Index < EVENT1_SWITCHES; Index += 1) {
  816. Status = NtWaitForSingleObject(EventHandle1,
  817. FALSE,
  818. NULL);
  819. if (!NT_SUCCESS(Status)) {
  820. printf(" Thread1 event1 test bad wait status, %x\n", Status);
  821. break;
  822. }
  823. Status = NtSetEvent(EventHandle2, NULL);
  824. if (!NT_SUCCESS(Status)) {
  825. printf(" Thread1 event1 test bad set status, %x\n", Status);
  826. break;
  827. }
  828. }
  829. NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
  830. return STATUS_SUCCESS;
  831. }
  832. NTSTATUS
  833. Event1Thread2 (
  834. IN PVOID Context
  835. )
  836. {
  837. ULONG Index;
  838. NTSTATUS Status;
  839. //
  840. // Wait for event 2 and then set event 1.
  841. //
  842. for (Index = 0; Index < EVENT1_SWITCHES; Index += 1) {
  843. Status = NtWaitForSingleObject(EventHandle2,
  844. FALSE,
  845. NULL);
  846. if (!NT_SUCCESS(Status)) {
  847. printf(" Thread2 event1 test bad wait status, %x\n", Status);
  848. break;
  849. }
  850. Status = NtSetEvent(EventHandle1, NULL);
  851. if (!NT_SUCCESS(Status)) {
  852. printf(" Thread2 event1 test bad set status, %x\n", Status);
  853. break;
  854. }
  855. }
  856. NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
  857. return STATUS_SUCCESS;
  858. }
  859. VOID
  860. Event2SwitchTest (
  861. VOID
  862. )
  863. {
  864. PERFINFO PerfInfo;
  865. NTSTATUS Status;
  866. PVOID WaitObjects[2];
  867. //
  868. // Create two event objects for the event2 context switch test.
  869. //
  870. Status = NtCreateEvent(&EventHandle1,
  871. DESIRED_EVENT_ACCESS,
  872. NULL,
  873. NotificationEvent,
  874. FALSE);
  875. if (!NT_SUCCESS(Status)) {
  876. printf("Failed to create event2 object for context switch test.\n");
  877. goto EndOfTest;
  878. }
  879. Status = NtCreateEvent(&EventHandle2,
  880. DESIRED_EVENT_ACCESS,
  881. NULL,
  882. NotificationEvent,
  883. FALSE);
  884. if (!NT_SUCCESS(Status)) {
  885. printf("Failed to create event2 object for context switch test.\n");
  886. goto EndOfTest;
  887. }
  888. //
  889. // Create the thread objects to execute the test.
  890. //
  891. Status = xCreateThread(&Thread1Handle,
  892. Event2Thread1,
  893. LOW_REALTIME_PRIORITY - 2);
  894. if (!NT_SUCCESS(Status)) {
  895. printf("Failed to create first thread event2 context switch test\n");
  896. goto EndOfTest;
  897. }
  898. Status = xCreateThread(&Thread2Handle,
  899. Event2Thread2,
  900. LOW_REALTIME_PRIORITY - 2);
  901. if (!NT_SUCCESS(Status)) {
  902. printf("Failed to create second thread event2 context switch test\n");
  903. goto EndOfTest;
  904. }
  905. //
  906. // Initialize the wait objects array.
  907. //
  908. WaitObjects[0] = Thread1Handle;
  909. WaitObjects[1] = Thread2Handle;
  910. //
  911. // Announce start of benchmark and capture performance parmeters.
  912. //
  913. StartBenchMark("Event (notification) Context Switch Benchmark (Round Trips)",
  914. EVENT2_SWITCHES,
  915. &PerfInfo);
  916. //
  917. // Set event and wait for threads to terminate.
  918. //
  919. Status = NtSetEvent(EventHandle1, NULL);
  920. if (!NT_SUCCESS(Status)) {
  921. printf("Failed to set event2 object for context switch test.\n");
  922. goto EndOfTest;
  923. }
  924. Status = NtWaitForMultipleObjects(2,
  925. WaitObjects,
  926. WaitAll,
  927. FALSE,
  928. NULL);
  929. //
  930. // Print out performance statistics.
  931. //
  932. FinishBenchMark(&PerfInfo);
  933. //
  934. // End of event2 context switch test.
  935. //
  936. EndOfTest:
  937. NtClose(EventHandle1);
  938. NtClose(EventHandle2);
  939. NtClose(Thread1Handle);
  940. NtClose(Thread2Handle);
  941. return;
  942. }
  943. NTSTATUS
  944. Event2Thread1 (
  945. IN PVOID Context
  946. )
  947. {
  948. ULONG Index;
  949. NTSTATUS Status;
  950. //
  951. // Wait for event 1, reset event 1, and then set event 2.
  952. //
  953. for (Index = 0; Index < EVENT2_SWITCHES; Index += 1) {
  954. Status = NtWaitForSingleObject(EventHandle1, FALSE, NULL);
  955. if (!NT_SUCCESS(Status)) {
  956. printf(" Thread1 event2 test bad wait status, %x\n", Status);
  957. break;
  958. }
  959. Status = NtResetEvent(EventHandle1, NULL);
  960. if (!NT_SUCCESS(Status)) {
  961. printf(" Thread1 event2 test bad reset status, %x\n", Status);
  962. break;
  963. }
  964. Status = NtSetEvent(EventHandle2, NULL);
  965. if (!NT_SUCCESS(Status)) {
  966. printf(" Thread1 event2 test bad set status, %x\n", Status);
  967. break;
  968. }
  969. }
  970. NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
  971. return STATUS_SUCCESS;
  972. }
  973. NTSTATUS
  974. Event2Thread2 (
  975. IN PVOID Context
  976. )
  977. {
  978. ULONG Index;
  979. NTSTATUS Status;
  980. //
  981. // Wait for event 2, reset event 2, and then set event 1.
  982. //
  983. for (Index = 0; Index < EVENT2_SWITCHES; Index += 1) {
  984. Status = NtWaitForSingleObject(EventHandle2, FALSE, NULL);
  985. if (!NT_SUCCESS(Status)) {
  986. printf(" Thread2 event2 test bad wait status, %x\n", Status);
  987. break;
  988. }
  989. Status = NtResetEvent(EventHandle2, NULL);
  990. if (!NT_SUCCESS(Status)) {
  991. printf(" Thread1 event2 test bad reset status, %x\n", Status);
  992. break;
  993. }
  994. Status = NtSetEvent(EventHandle1, NULL);
  995. if (!NT_SUCCESS(Status)) {
  996. printf(" Thread2 event2 test bad set status, %x\n", Status);
  997. break;
  998. }
  999. }
  1000. NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
  1001. return STATUS_SUCCESS;
  1002. }
  1003. VOID
  1004. Event3SwitchTest (
  1005. VOID
  1006. )
  1007. {
  1008. PERFINFO PerfInfo;
  1009. NTSTATUS Status;
  1010. PVOID WaitObjects[2];
  1011. //
  1012. // Create two event objects for the event1 context switch test.
  1013. //
  1014. Status = NtCreateEvent(&EventHandle1,
  1015. DESIRED_EVENT_ACCESS,
  1016. NULL,
  1017. SynchronizationEvent,
  1018. FALSE);
  1019. if (!NT_SUCCESS(Status)) {
  1020. printf("EVENT3: Failed to create event1 object for context switch test.\n");
  1021. goto EndOfTest;
  1022. }
  1023. Status = NtCreateEvent(&EventHandle2,
  1024. DESIRED_EVENT_ACCESS,
  1025. NULL,
  1026. SynchronizationEvent,
  1027. FALSE);
  1028. if (!NT_SUCCESS(Status)) {
  1029. printf("EVENT3: Failed to create event2 object for context switch test.\n");
  1030. goto EndOfTest;
  1031. }
  1032. //
  1033. // Create the thread objects to execute the test.
  1034. //
  1035. Status = xCreateThread(&Thread1Handle,
  1036. Event3Thread1,
  1037. LOW_REALTIME_PRIORITY - 2);
  1038. if (!NT_SUCCESS(Status)) {
  1039. printf("EVENT3: Failed to create first thread event3 context switch test\n");
  1040. goto EndOfTest;
  1041. }
  1042. Status = xCreateThread(&Thread2Handle,
  1043. Event3Thread2,
  1044. LOW_REALTIME_PRIORITY - 2);
  1045. if (!NT_SUCCESS(Status)) {
  1046. printf("EVENT3: Failed to create second thread event3 context switch test\n");
  1047. goto EndOfTest;
  1048. }
  1049. //
  1050. // Initialize the wait objects array.
  1051. //
  1052. WaitObjects[0] = Thread1Handle;
  1053. WaitObjects[1] = Thread2Handle;
  1054. //
  1055. // Announce start of benchmark and capture performance parmeters.
  1056. //
  1057. StartBenchMark("Event (signal/wait) Context Switch Benchmark (Round Trips)",
  1058. EVENT3_SWITCHES,
  1059. &PerfInfo);
  1060. //
  1061. // Set event and wait for threads to terminate.
  1062. //
  1063. Status = NtSetEvent(EventHandle1, NULL);
  1064. if (!NT_SUCCESS(Status)) {
  1065. printf("EVENT3: Failed to set event event1 context switch test.\n");
  1066. goto EndOfTest;
  1067. }
  1068. Status = NtWaitForMultipleObjects(2,
  1069. WaitObjects,
  1070. WaitAll,
  1071. FALSE,
  1072. NULL);
  1073. //
  1074. // Print out performance statistics.
  1075. //
  1076. FinishBenchMark(&PerfInfo);
  1077. //
  1078. // End of event3 context switch test.
  1079. //
  1080. EndOfTest:
  1081. NtClose(EventHandle1);
  1082. NtClose(EventHandle2);
  1083. NtClose(Thread1Handle);
  1084. NtClose(Thread2Handle);
  1085. return;
  1086. }
  1087. NTSTATUS
  1088. Event3Thread1 (
  1089. IN PVOID Context
  1090. )
  1091. {
  1092. ULONG Index;
  1093. NTSTATUS Status;
  1094. //
  1095. // Wait for event 1 and then enter signal/wait loop.
  1096. //
  1097. Status = NtWaitForSingleObject(EventHandle1,
  1098. FALSE,
  1099. NULL);
  1100. if (!NT_SUCCESS(Status)) {
  1101. printf("EVENT3: Thread1 initial wait failed, %x\n", Status);
  1102. } else {
  1103. for (Index = 0; Index < EVENT3_SWITCHES; Index += 1) {
  1104. Status = NtSignalAndWaitForSingleObject(EventHandle2,
  1105. EventHandle1,
  1106. FALSE,
  1107. NULL);
  1108. if (!NT_SUCCESS(Status)) {
  1109. printf("EVENT3: Thread1 signal/wait failed, %x\n", Status);
  1110. break;
  1111. }
  1112. }
  1113. }
  1114. Status = NtSetEvent(EventHandle2, NULL);
  1115. NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
  1116. return STATUS_SUCCESS;
  1117. }
  1118. NTSTATUS
  1119. Event3Thread2 (
  1120. IN PVOID Context
  1121. )
  1122. {
  1123. ULONG Index;
  1124. NTSTATUS Status;
  1125. //
  1126. // Wait for event 1 and then enter signal/wait loop.
  1127. //
  1128. Status = NtWaitForSingleObject(EventHandle2,
  1129. FALSE,
  1130. NULL);
  1131. if (!NT_SUCCESS(Status)) {
  1132. printf("EVENT3: Thread2 initial wait failed, %x\n", Status);
  1133. } else {
  1134. for (Index = 0; Index < EVENT3_SWITCHES; Index += 1) {
  1135. Status = NtSignalAndWaitForSingleObject(EventHandle1,
  1136. EventHandle2,
  1137. FALSE,
  1138. NULL);
  1139. if (!NT_SUCCESS(Status)) {
  1140. printf("EVENT3: Thread2 signal/wait failed, %x\n", Status);
  1141. break;
  1142. }
  1143. }
  1144. }
  1145. NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
  1146. return STATUS_SUCCESS;
  1147. }
  1148. VOID
  1149. Io1Test (
  1150. VOID
  1151. )
  1152. {
  1153. ULONG Buffer[128];
  1154. HANDLE DeviceHandle;
  1155. ANSI_STRING AnsiName;
  1156. HANDLE EventHandle;
  1157. LARGE_INTEGER FileAddress;
  1158. LONG Index;
  1159. IO_STATUS_BLOCK IoStatus;
  1160. OBJECT_ATTRIBUTES ObjectAttributes;
  1161. PERFINFO PerfInfo;
  1162. NTSTATUS Status;
  1163. LARGE_INTEGER SystemTime;
  1164. UNICODE_STRING UnicodeName;
  1165. //
  1166. // Create an event for synchronization of I/O operations.
  1167. //
  1168. Status = NtCreateEvent(&EventHandle,
  1169. DESIRED_EVENT_ACCESS,
  1170. NULL,
  1171. NotificationEvent,
  1172. FALSE);
  1173. if (!NT_SUCCESS(Status)) {
  1174. printf("Failed to create event object for I/O test 1\n");
  1175. goto EndOfTest;
  1176. }
  1177. //
  1178. // Open device object for I/O operations.
  1179. //
  1180. RtlInitString(&AnsiName, "\\Device\\Null");
  1181. Status = RtlAnsiStringToUnicodeString(&UnicodeName,
  1182. &AnsiName,
  1183. TRUE);
  1184. if (!NT_SUCCESS(Status)) {
  1185. printf("Failed to convert device name to unicode for I/O test 1\n");
  1186. goto EndOfTest;
  1187. }
  1188. InitializeObjectAttributes(&ObjectAttributes,
  1189. &UnicodeName,
  1190. 0,
  1191. (HANDLE)0,
  1192. NULL);
  1193. Status = NtOpenFile(&DeviceHandle,
  1194. FILE_READ_DATA | FILE_WRITE_DATA,
  1195. &ObjectAttributes,
  1196. &IoStatus,
  1197. 0,
  1198. 0);
  1199. RtlFreeUnicodeString(&UnicodeName);
  1200. if (!NT_SUCCESS(Status)) {
  1201. printf("Failed to open device I/O test 1, status = %lx\n", Status);
  1202. goto EndOfTest;
  1203. }
  1204. //
  1205. // Initialize file address parameter.
  1206. //
  1207. FileAddress.LowPart = 0;
  1208. FileAddress.HighPart = 0;
  1209. //
  1210. // Announce start of benchmark and capture performance parmeters.
  1211. //
  1212. StartBenchMark("I/O Benchmark for Synchronous Null Device",
  1213. IO_ITERATIONS,
  1214. &PerfInfo);
  1215. //
  1216. // Repeatedly write data to null device.
  1217. //
  1218. for (Index = 0; Index < IO_ITERATIONS; Index += 1) {
  1219. Status = NtWriteFile(DeviceHandle,
  1220. EventHandle,
  1221. NULL,
  1222. NULL,
  1223. &IoStatus,
  1224. Buffer,
  1225. 512,
  1226. &FileAddress,
  1227. NULL);
  1228. if (!NT_SUCCESS(Status)) {
  1229. printf(" Failed to write device I/O test 1, status = %lx\n",
  1230. Status);
  1231. goto EndOfTest;
  1232. }
  1233. Status = NtWaitForSingleObject(EventHandle, FALSE, NULL);
  1234. if (!NT_SUCCESS(Status)) {
  1235. printf(" I/O test 1 bad wait status, %x\n", Status);
  1236. goto EndOfTest;
  1237. }
  1238. if (NT_SUCCESS(IoStatus.Status) == FALSE) {
  1239. printf(" I/O test 1 bad I/O status, %x\n", Status);
  1240. goto EndOfTest;
  1241. }
  1242. }
  1243. //
  1244. // Print out performance statistics.
  1245. //
  1246. FinishBenchMark(&PerfInfo);
  1247. //
  1248. // End of I/O test 1.
  1249. //
  1250. EndOfTest:
  1251. NtClose(DeviceHandle);
  1252. NtClose(EventHandle);
  1253. return;
  1254. }
  1255. VOID
  1256. MutantSwitchTest (
  1257. VOID
  1258. )
  1259. {
  1260. PERFINFO PerfInfo;
  1261. NTSTATUS Status;
  1262. HANDLE WaitObjects[2];
  1263. //
  1264. // Create a mutant object for the mutant context switch test.
  1265. //
  1266. Status = NtCreateMutant(&MutantHandle, MUTANT_ALL_ACCESS, NULL, TRUE);
  1267. if (!NT_SUCCESS(Status)) {
  1268. printf("Failed to create mutant object for context switch test.\n");
  1269. goto EndOfTest;
  1270. }
  1271. //
  1272. // Create the thread objects to execute the test.
  1273. //
  1274. Status = xCreateThread(&Thread1Handle,
  1275. MutantThread1,
  1276. LOW_REALTIME_PRIORITY + 11);
  1277. if (!NT_SUCCESS(Status)) {
  1278. printf("Failed to create first thread mutant context switch test\n");
  1279. goto EndOfTest;
  1280. }
  1281. Status = xCreateThread(&Thread2Handle,
  1282. MutantThread2,
  1283. LOW_REALTIME_PRIORITY + 11);
  1284. if (!NT_SUCCESS(Status)) {
  1285. printf("Failed to create second thread mutant context switch test\n");
  1286. goto EndOfTest;
  1287. }
  1288. //
  1289. // Initialize the wait objects array.
  1290. //
  1291. WaitObjects[0] = Thread1Handle;
  1292. WaitObjects[1] = Thread2Handle;
  1293. //
  1294. // Announce start of benchmark and capture performance parmeters.
  1295. //
  1296. StartBenchMark("Mutant Context Switch Benchmark (Round Trips)",
  1297. MUTANT_SWITCHES,
  1298. &PerfInfo);
  1299. //
  1300. // Release mutant and wait for threads to terminate.
  1301. //
  1302. Status = NtReleaseMutant(MutantHandle, NULL);
  1303. if (!NT_SUCCESS(Status)) {
  1304. printf("Failed to release mutant object for context switch test.\n");
  1305. goto EndOfTest;
  1306. }
  1307. Status = NtWaitForMultipleObjects(2,
  1308. WaitObjects,
  1309. WaitAll,
  1310. FALSE,
  1311. NULL);
  1312. //
  1313. // Print out performance statistics.
  1314. //
  1315. FinishBenchMark(&PerfInfo);
  1316. //
  1317. // End of mutant context switch test.
  1318. //
  1319. EndOfTest:
  1320. NtClose(MutantHandle);
  1321. NtClose(Thread1Handle);
  1322. NtClose(Thread2Handle);
  1323. return;
  1324. }
  1325. NTSTATUS
  1326. MutantThread1 (
  1327. IN PVOID Context
  1328. )
  1329. {
  1330. ULONG Index;
  1331. NTSTATUS Status;
  1332. //
  1333. // Wait for mutant and then release mutant.
  1334. //
  1335. for (Index = 0; Index < MUTANT_SWITCHES; Index += 1) {
  1336. Status = NtWaitForSingleObject(MutantHandle, FALSE, NULL);
  1337. if (!NT_SUCCESS(Status)) {
  1338. printf(" Thread1 mutant test bad wait status, %x\n", Status);
  1339. break;
  1340. }
  1341. Status = NtReleaseMutant(MutantHandle, NULL);
  1342. if (!NT_SUCCESS(Status)) {
  1343. printf(" Thread1 mutant test bad release status, %x\n", Status);
  1344. break;
  1345. }
  1346. }
  1347. NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
  1348. return STATUS_SUCCESS;
  1349. }
  1350. NTSTATUS
  1351. MutantThread2 (
  1352. IN PVOID Context
  1353. )
  1354. {
  1355. ULONG Index;
  1356. NTSTATUS Status;
  1357. //
  1358. // Wait for mutant and then release mutant.
  1359. //
  1360. for (Index = 0; Index < MUTANT_SWITCHES; Index += 1) {
  1361. Status = NtWaitForSingleObject(MutantHandle, FALSE, NULL);
  1362. if (!NT_SUCCESS(Status)) {
  1363. printf(" Thread2 mutant test bad wait status, %x\n", Status);
  1364. break;
  1365. }
  1366. Status = NtReleaseMutant(MutantHandle, NULL);
  1367. if (!NT_SUCCESS(Status)) {
  1368. printf(" Thread2 mutant test bad release status, %x\n", Status);
  1369. break;
  1370. }
  1371. }
  1372. NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
  1373. return STATUS_SUCCESS;
  1374. }
  1375. VOID
  1376. Semaphore1SwitchTest (
  1377. VOID
  1378. )
  1379. {
  1380. PERFINFO PerfInfo;
  1381. NTSTATUS Status;
  1382. HANDLE WaitObjects[2];
  1383. //
  1384. // Create two semaphore objects for the semaphore1 context switch test.
  1385. //
  1386. Status = NtCreateSemaphore(&SemaphoreHandle1,
  1387. DESIRED_EVENT_ACCESS,
  1388. NULL,
  1389. 0,
  1390. 1);
  1391. if (!NT_SUCCESS(Status)) {
  1392. printf("SEMAPHORE1: Failed to create semaphore1 object.\n");
  1393. goto EndOfTest;
  1394. }
  1395. Status = NtCreateSemaphore(&SemaphoreHandle2,
  1396. DESIRED_EVENT_ACCESS,
  1397. NULL,
  1398. 0,
  1399. 1);
  1400. if (!NT_SUCCESS(Status)) {
  1401. printf("SEMAPHORE1: Failed to create semaphore2 object.\n");
  1402. goto EndOfTest;
  1403. }
  1404. //
  1405. // Create the thread objects to execute the test.
  1406. //
  1407. Status = xCreateThread(&Thread1Handle,
  1408. Semaphore1Thread1,
  1409. LOW_REALTIME_PRIORITY - 2);
  1410. if (!NT_SUCCESS(Status)) {
  1411. printf("SEMAPHORE1: Failed to create thread1 object.\n");
  1412. goto EndOfTest;
  1413. }
  1414. Status = xCreateThread(&Thread2Handle,
  1415. Semaphore1Thread2,
  1416. LOW_REALTIME_PRIORITY - 2);
  1417. if (!NT_SUCCESS(Status)) {
  1418. printf("SEMAPHORE1: Failed to create thread2 object.\n");
  1419. goto EndOfTest;
  1420. }
  1421. //
  1422. // Initialize the wait objects array.
  1423. //
  1424. WaitObjects[0] = Thread1Handle;
  1425. WaitObjects[1] = Thread2Handle;
  1426. //
  1427. // Announce start of benchmark and capture performance parmeters.
  1428. //
  1429. StartBenchMark("Semaphore (release/wait) Context Switch Benchmark (Round Trips)",
  1430. SEMAPHORE1_SWITCHES,
  1431. &PerfInfo);
  1432. //
  1433. // Release semaphore and wait for threads to terminate.
  1434. //
  1435. Status = NtReleaseSemaphore(SemaphoreHandle1, 1, NULL);
  1436. if (!NT_SUCCESS(Status)) {
  1437. printf("SEMAPHORE1: Failed to release semaphore1 at start of test.\n");
  1438. goto EndOfTest;
  1439. }
  1440. Status = NtWaitForMultipleObjects(2,
  1441. WaitObjects,
  1442. WaitAll,
  1443. FALSE,
  1444. NULL);
  1445. if (!NT_SUCCESS(Status)) {
  1446. printf("SEMAPHORE1: Failed to wait for threads.\n");
  1447. goto EndOfTest;
  1448. }
  1449. //
  1450. // Print out performance statistics.
  1451. //
  1452. FinishBenchMark(&PerfInfo);
  1453. //
  1454. // End of semaphore1 context switch test.
  1455. //
  1456. EndOfTest:
  1457. NtClose(SemaphoreHandle1);
  1458. NtClose(SemaphoreHandle2);
  1459. NtClose(Thread1Handle);
  1460. NtClose(Thread2Handle);
  1461. return;
  1462. }
  1463. NTSTATUS
  1464. Semaphore1Thread1 (
  1465. IN PVOID Context
  1466. )
  1467. {
  1468. ULONG Index;
  1469. NTSTATUS Status;
  1470. //
  1471. // Wait for semaphore 1 and then release semaphore 2.
  1472. //
  1473. for (Index = 0; Index < SEMAPHORE1_SWITCHES; Index += 1) {
  1474. Status = NtWaitForSingleObject(SemaphoreHandle1,
  1475. FALSE,
  1476. NULL);
  1477. if (!NT_SUCCESS(Status)) {
  1478. printf("SEMAPHORE1: Thread1 bad wait status, %x\n", Status);
  1479. break;
  1480. }
  1481. Status = NtReleaseSemaphore(SemaphoreHandle2, 1, NULL);
  1482. if (!NT_SUCCESS(Status)) {
  1483. printf("SEMAPHORE1: Thread1 bad release status, %x\n", Status);
  1484. break;
  1485. }
  1486. }
  1487. NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
  1488. return STATUS_SUCCESS;
  1489. }
  1490. NTSTATUS
  1491. Semaphore1Thread2 (
  1492. IN PVOID Context
  1493. )
  1494. {
  1495. ULONG Index;
  1496. NTSTATUS Status;
  1497. //
  1498. // Wait for semaphore 2 and then release semaphore 1.
  1499. //
  1500. for (Index = 0; Index < SEMAPHORE1_SWITCHES; Index += 1) {
  1501. Status = NtWaitForSingleObject(SemaphoreHandle2,
  1502. FALSE,
  1503. NULL);
  1504. if (!NT_SUCCESS(Status)) {
  1505. printf("SEMAPHORE1: Thread2 bad wait status, %x\n", Status);
  1506. break;
  1507. }
  1508. Status = NtReleaseSemaphore(SemaphoreHandle1, 1, NULL);
  1509. if (!NT_SUCCESS(Status)) {
  1510. printf("SEMAPHORE1: Thread2 bad release status, %x\n", Status);
  1511. break;
  1512. }
  1513. }
  1514. NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
  1515. return STATUS_SUCCESS;
  1516. }
  1517. VOID
  1518. Semaphore2SwitchTest (
  1519. VOID
  1520. )
  1521. {
  1522. PERFINFO PerfInfo;
  1523. NTSTATUS Status;
  1524. HANDLE WaitObjects[2];
  1525. //
  1526. // Create two semaphore objects for the semaphore1 context switch test.
  1527. //
  1528. Status = NtCreateSemaphore(&SemaphoreHandle1,
  1529. DESIRED_EVENT_ACCESS,
  1530. NULL,
  1531. 0,
  1532. 1);
  1533. if (!NT_SUCCESS(Status)) {
  1534. printf("SEMAPHORE2: Failed to create semaphore1 object.\n");
  1535. goto EndOfTest;
  1536. }
  1537. Status = NtCreateSemaphore(&SemaphoreHandle2,
  1538. DESIRED_EVENT_ACCESS,
  1539. NULL,
  1540. 0,
  1541. 1);
  1542. if (!NT_SUCCESS(Status)) {
  1543. printf("SEMAPHORE2: Failed to create semaphore2 object.\n");
  1544. goto EndOfTest;
  1545. }
  1546. //
  1547. // Create the thread objects to execute the test.
  1548. //
  1549. Status = xCreateThread(&Thread1Handle,
  1550. Semaphore2Thread1,
  1551. LOW_REALTIME_PRIORITY - 2);
  1552. if (!NT_SUCCESS(Status)) {
  1553. printf("SEMAPHORE2: Failed to create thread1 object.\n");
  1554. goto EndOfTest;
  1555. }
  1556. Status = xCreateThread(&Thread2Handle,
  1557. Semaphore2Thread2,
  1558. LOW_REALTIME_PRIORITY - 2);
  1559. if (!NT_SUCCESS(Status)) {
  1560. printf("SEMAPHORE2: Failed to create thread2 object.\n");
  1561. goto EndOfTest;
  1562. }
  1563. //
  1564. // Initialize the wait objects array.
  1565. //
  1566. WaitObjects[0] = Thread1Handle;
  1567. WaitObjects[1] = Thread2Handle;
  1568. //
  1569. // Announce start of benchmark and capture performance parmeters.
  1570. //
  1571. StartBenchMark("Semaphore (signal/wait) Context Switch Benchmark (Round Trips)",
  1572. SEMAPHORE2_SWITCHES,
  1573. &PerfInfo);
  1574. //
  1575. // Release semaphore and wait for threads to terminate.
  1576. //
  1577. Status = NtReleaseSemaphore(SemaphoreHandle1, 1, NULL);
  1578. if (!NT_SUCCESS(Status)) {
  1579. printf("SEMAPHORE2: Failed to release semaphore1 at start of test.\n");
  1580. goto EndOfTest;
  1581. }
  1582. Status = NtWaitForMultipleObjects(2,
  1583. WaitObjects,
  1584. WaitAll,
  1585. FALSE,
  1586. NULL);
  1587. if (!NT_SUCCESS(Status)) {
  1588. printf("SEMAPHORE2: Failed to wait for threads.\n");
  1589. goto EndOfTest;
  1590. }
  1591. //
  1592. // Print out performance statistics.
  1593. //
  1594. FinishBenchMark(&PerfInfo);
  1595. //
  1596. // End of semaphore 2 context switch test.
  1597. //
  1598. EndOfTest:
  1599. NtClose(SemaphoreHandle1);
  1600. NtClose(SemaphoreHandle2);
  1601. NtClose(Thread1Handle);
  1602. NtClose(Thread2Handle);
  1603. return;
  1604. }
  1605. NTSTATUS
  1606. Semaphore2Thread1 (
  1607. IN PVOID Context
  1608. )
  1609. {
  1610. ULONG Index;
  1611. NTSTATUS Status;
  1612. //
  1613. // Wait for semaphore 1 and then enter signal/wait loop.
  1614. //
  1615. Status = NtWaitForSingleObject(SemaphoreHandle1,
  1616. FALSE,
  1617. NULL);
  1618. if (!NT_SUCCESS(Status)) {
  1619. printf("SEMAPHORE2: Thread1 initial wait failed, %x\n", Status);
  1620. } else {
  1621. for (Index = 0; Index < SEMAPHORE2_SWITCHES; Index += 1) {
  1622. Status = NtSignalAndWaitForSingleObject(SemaphoreHandle2,
  1623. SemaphoreHandle1,
  1624. FALSE,
  1625. NULL);
  1626. if (!NT_SUCCESS(Status)) {
  1627. printf("SEMAPHORE2: Thread1 signal/wait failed, %x\n", Status);
  1628. break;
  1629. }
  1630. }
  1631. }
  1632. Status = NtReleaseSemaphore(SemaphoreHandle2, 1, NULL);
  1633. NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
  1634. return STATUS_SUCCESS;
  1635. }
  1636. NTSTATUS
  1637. Semaphore2Thread2 (
  1638. IN PVOID Context
  1639. )
  1640. {
  1641. ULONG Index;
  1642. NTSTATUS Status;
  1643. //
  1644. // Wait for semaphore 2 and then enter signal/wait loop.
  1645. //
  1646. Status = NtWaitForSingleObject(SemaphoreHandle2,
  1647. FALSE,
  1648. NULL);
  1649. if (!NT_SUCCESS(Status)) {
  1650. printf("SEMAPHORE2: Thread2 initial wait failed, %x\n", Status);
  1651. } else {
  1652. for (Index = 0; Index < SEMAPHORE2_SWITCHES; Index += 1) {
  1653. Status = NtSignalAndWaitForSingleObject(SemaphoreHandle1,
  1654. SemaphoreHandle2,
  1655. FALSE,
  1656. NULL);
  1657. if (!NT_SUCCESS(Status)) {
  1658. printf("SEMAPHORE2: Thread2 signal/wait failed, %x\n", Status);
  1659. break;
  1660. }
  1661. }
  1662. }
  1663. NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
  1664. return STATUS_SUCCESS;
  1665. }
  1666. VOID
  1667. SlistTest (
  1668. VOID
  1669. )
  1670. {
  1671. SLIST_ENTRY Entry;
  1672. SLIST_HEADER SListHead;
  1673. ULONG Index;
  1674. PERFINFO PerfInfo;
  1675. LARGE_INTEGER SystemTime;
  1676. //
  1677. // Announce start of benchmark and capture performance parmeters.
  1678. //
  1679. StartBenchMark("S-List Benchmark",
  1680. SLIST_ITERATIONS,
  1681. &PerfInfo);
  1682. //
  1683. // Repeatedly call a short system service.
  1684. //
  1685. InitializeSListHead(&SListHead);
  1686. for (Index = 0; Index < SLIST_ITERATIONS; Index += 1) {
  1687. InterlockedPushEntrySList(&SListHead, &Entry);
  1688. if (InterlockedPopEntrySList(&SListHead) != (PVOID)&Entry) {
  1689. printf("SLIST: Entry does match %lx\n", Entry);
  1690. }
  1691. }
  1692. //
  1693. // Print out performance statistics.
  1694. //
  1695. FinishBenchMark(&PerfInfo);
  1696. return;
  1697. }
  1698. VOID
  1699. SystemCallTest (
  1700. VOID
  1701. )
  1702. {
  1703. ULONG Index;
  1704. PERFINFO PerfInfo;
  1705. LARGE_INTEGER SystemTime;
  1706. //
  1707. // Announce start of benchmark and capture performance parmeters.
  1708. //
  1709. StartBenchMark("System Call Benchmark (NtQuerySystemTime)",
  1710. SYSCALL_ITERATIONS,
  1711. &PerfInfo);
  1712. //
  1713. // Repeatedly call a short system service.
  1714. //
  1715. for (Index = 0; Index < SYSCALL_ITERATIONS; Index += 1) {
  1716. NtQuerySystemTime(&SystemTime);
  1717. }
  1718. //
  1719. // Print out performance statistics.
  1720. //
  1721. FinishBenchMark(&PerfInfo);
  1722. return;
  1723. }
  1724. VOID
  1725. TimerOperationTest (
  1726. VOID
  1727. )
  1728. {
  1729. LARGE_INTEGER DueTime;
  1730. HANDLE Handle;
  1731. ULONG Index;
  1732. PERFINFO PerfInfo;
  1733. LARGE_INTEGER SystemTime;
  1734. NTSTATUS Status;
  1735. //
  1736. // Announce start of benchmark and capture performance parmeters.
  1737. //
  1738. StartBenchMark("Timer Operation Benchmark (NtSet/CancelTimer)",
  1739. TIMER_OPERATION_ITERATIONS,
  1740. &PerfInfo);
  1741. //
  1742. // Create a timer object for use in the test.
  1743. //
  1744. Status = NtCreateTimer(&Handle,
  1745. TIMER_ALL_ACCESS,
  1746. NULL,
  1747. NotificationTimer);
  1748. if (!NT_SUCCESS(Status)) {
  1749. printf("Failed to create timer during initialization\n");
  1750. goto EndOfTest;
  1751. }
  1752. //
  1753. // Repeatedly set and cancel a timer.
  1754. //
  1755. DueTime = RtlConvertLongToLargeInteger(- 100 * 1000 * 10);
  1756. for (Index = 0; Index < TIMER_OPERATION_ITERATIONS; Index += 1) {
  1757. NtSetTimer(Handle, &DueTime, NULL, NULL, FALSE, 0, NULL);
  1758. NtCancelTimer(Handle, NULL);
  1759. }
  1760. //
  1761. // Print out performance statistics.
  1762. //
  1763. EndOfTest:
  1764. FinishBenchMark(&PerfInfo);
  1765. return;
  1766. }
  1767. VOID
  1768. UnalignedTest1 (
  1769. VOID
  1770. )
  1771. {
  1772. PULONG Address;
  1773. UCHAR Array[128];
  1774. ULONG Count;
  1775. ULONG Index;
  1776. PERFINFO PerfInfo;
  1777. ULONG Sum = 0;
  1778. //
  1779. // Announce start of benchmark and capture performance parmeters.
  1780. //
  1781. for (Index = 1; Index < 65; Index += 1) {
  1782. Array[Index] = (UCHAR)Index;
  1783. }
  1784. StartBenchMark("Unaligned DWORD Access Test - Hardware",
  1785. UNALIGNED_ITERATIONS,
  1786. &PerfInfo);
  1787. //
  1788. // Repeatedly sum array;
  1789. //
  1790. for (Count = 0; Count < UNALIGNED_ITERATIONS; Count += 1) {
  1791. Address = (PULONG)&Array[1];
  1792. for (Index = 1; Index < 65; Index += 4) {
  1793. Sum += *Address;
  1794. Address += 1;
  1795. }
  1796. }
  1797. //
  1798. // Print out performance statistics.
  1799. //
  1800. FinishBenchMark(&PerfInfo);
  1801. printf("final sum %d\n", Sum);
  1802. return;
  1803. }
  1804. VOID
  1805. UnalignedTest2 (
  1806. VOID
  1807. )
  1808. {
  1809. PULONG Address;
  1810. UCHAR Array[128];
  1811. ULONG Count;
  1812. ULONG Index;
  1813. PERFINFO PerfInfo;
  1814. ULONG Sum = 0;
  1815. ULONG Value;
  1816. //
  1817. // Announce start of benchmark and capture performance parmeters.
  1818. //
  1819. for (Index = 1; Index < 65; Index += 1) {
  1820. Array[Index] = (UCHAR)Index;
  1821. }
  1822. StartBenchMark("Unaligned DWORD Access Test - Software",
  1823. UNALIGNED_ITERATIONS,
  1824. &PerfInfo);
  1825. //
  1826. // Repeatedly sum array;
  1827. //
  1828. for (Count = 0; Count < UNALIGNED_ITERATIONS; Count += 1) {
  1829. Address = (PULONG)&Array[1];
  1830. for (Index = 1; Index < 65; Index += 4) {
  1831. Value = *((PUCHAR)Address + 3);
  1832. Value = (Value << 8) + *((PUCHAR)Address + 2);
  1833. Value = (Value << 8) + *((PUCHAR)Address + 1);
  1834. Value = (Value << 8) + *((PUCHAR)Address + 0);
  1835. Address += 1;
  1836. Sum += Value;
  1837. }
  1838. }
  1839. //
  1840. // Print out performance statistics.
  1841. //
  1842. FinishBenchMark(&PerfInfo);
  1843. printf("final sum %d\n", Sum);
  1844. return;
  1845. }
  1846. VOID
  1847. WaitSingleTest (
  1848. VOID
  1849. )
  1850. {
  1851. HANDLE EventHandle;
  1852. LONG Index;
  1853. PERFINFO PerfInfo;
  1854. NTSTATUS Status;
  1855. //
  1856. // Create an event for synchronization of wait single operations.
  1857. //
  1858. Status = NtCreateEvent(&EventHandle,
  1859. DESIRED_EVENT_ACCESS,
  1860. NULL,
  1861. NotificationEvent,
  1862. TRUE);
  1863. if (!NT_SUCCESS(Status)) {
  1864. printf("Failed to create event object for wait single test\n");
  1865. goto EndOfTest;
  1866. }
  1867. //
  1868. // Announce start of benchmark and capture performance parmeters.
  1869. //
  1870. StartBenchMark("Wait Single Benchmark",
  1871. WAIT_SINGLE_ITERATIONS,
  1872. &PerfInfo);
  1873. //
  1874. // Repeatedly wait for a single event.
  1875. //
  1876. for (Index = 0; Index < WAIT_SINGLE_ITERATIONS; Index += 1) {
  1877. Status = NtWaitForSingleObject(EventHandle, FALSE, NULL);
  1878. if (!NT_SUCCESS(Status)) {
  1879. printf(" Wait single bad wait status, %x\n", Status);
  1880. goto EndOfTest;
  1881. }
  1882. }
  1883. //
  1884. // Print out performance statistics.
  1885. //
  1886. FinishBenchMark(&PerfInfo);
  1887. //
  1888. // End of Wait Single Test.
  1889. //
  1890. EndOfTest:
  1891. NtClose(EventHandle);
  1892. return;
  1893. }
  1894. VOID
  1895. WaitMultipleTest (
  1896. VOID
  1897. )
  1898. {
  1899. HANDLE Event1Handle;
  1900. HANDLE Event2Handle;
  1901. HANDLE WaitObjects[2];
  1902. LONG Index;
  1903. PERFINFO PerfInfo;
  1904. NTSTATUS Status;
  1905. //
  1906. // Create two events for synchronization of wait multiple operations.
  1907. //
  1908. Status = NtCreateEvent(&Event1Handle,
  1909. DESIRED_EVENT_ACCESS,
  1910. NULL,
  1911. NotificationEvent,
  1912. TRUE);
  1913. if (!NT_SUCCESS(Status)) {
  1914. printf("Failed to create event object 1 for wait multiple test\n");
  1915. goto EndOfTest;
  1916. }
  1917. Status = NtCreateEvent(&Event2Handle,
  1918. DESIRED_EVENT_ACCESS,
  1919. NULL,
  1920. NotificationEvent,
  1921. TRUE);
  1922. if (!NT_SUCCESS(Status)) {
  1923. printf("Failed to create event object 2 for wait multiple test\n");
  1924. goto EndOfTest;
  1925. }
  1926. //
  1927. // Announce start of benchmark and capture performance parmeters.
  1928. //
  1929. StartBenchMark("Wait Multiple Benchmark",
  1930. WAIT_MULTIPLE_ITERATIONS,
  1931. &PerfInfo);
  1932. //
  1933. // Repeatedly wait for a multiple events.
  1934. //
  1935. WaitObjects[0] = Event1Handle;
  1936. WaitObjects[1] = Event2Handle;
  1937. for (Index = 0; Index < WAIT_SINGLE_ITERATIONS; Index += 1) {
  1938. Status = NtWaitForMultipleObjects(2,
  1939. WaitObjects,
  1940. WaitAny,
  1941. FALSE,
  1942. NULL);
  1943. if (!NT_SUCCESS(Status)) {
  1944. printf(" Wait multiple bad wait status, %x\n", Status);
  1945. goto EndOfTest;
  1946. }
  1947. }
  1948. //
  1949. // Print out performance statistics.
  1950. //
  1951. FinishBenchMark(&PerfInfo);
  1952. //
  1953. // End of Wait Multiple Test.
  1954. //
  1955. EndOfTest:
  1956. NtClose(Event1Handle);
  1957. NtClose(Event2Handle);
  1958. return;
  1959. }
  1960. NTSTATUS
  1961. TimerThread (
  1962. IN PVOID Context
  1963. )
  1964. {
  1965. LARGE_INTEGER DueTime;
  1966. NTSTATUS Status;
  1967. HANDLE WaitObjects[2];
  1968. //
  1969. // Initialize variables and loop until the timer event is set.
  1970. //
  1971. DueTime.LowPart = -(5 * 1000 * 1000);
  1972. DueTime.HighPart = -1;
  1973. WaitObjects[0] = TimerEventHandle;
  1974. WaitObjects[1] = TimerTimerHandle;
  1975. do {
  1976. Status = NtSetTimer(TimerTimerHandle,
  1977. &DueTime,
  1978. NULL,
  1979. NULL,
  1980. FALSE,
  1981. 0,
  1982. NULL);
  1983. if (!NT_SUCCESS(Status)) {
  1984. break;
  1985. }
  1986. Status = NtWaitForMultipleObjects(2,
  1987. WaitObjects,
  1988. WaitAny,
  1989. FALSE,
  1990. NULL);
  1991. } while (Status != STATUS_SUCCESS);
  1992. NtTerminateThread(TimerThreadHandle, Status);
  1993. return STATUS_SUCCESS;
  1994. }
  1995. NTSTATUS
  1996. xCreateThread (
  1997. OUT PHANDLE Handle,
  1998. IN PUSER_THREAD_START_ROUTINE StartRoutine,
  1999. IN KPRIORITY Priority
  2000. )
  2001. {
  2002. NTSTATUS Status;
  2003. //
  2004. // Create a thread in the suspended state, sets its priority, and then
  2005. // resume the thread.
  2006. //
  2007. Status = RtlCreateUserThread(NtCurrentProcess(),
  2008. NULL,
  2009. TRUE,
  2010. 0,
  2011. 0,
  2012. 0,
  2013. StartRoutine,
  2014. NULL,
  2015. Handle,
  2016. NULL);
  2017. if (!NT_SUCCESS(Status)) {
  2018. return Status;
  2019. }
  2020. Status = NtSetInformationThread(*Handle,
  2021. ThreadPriority,
  2022. &Priority,
  2023. sizeof(KPRIORITY));
  2024. if (!NT_SUCCESS(Status)) {
  2025. NtClose(*Handle);
  2026. return Status;
  2027. }
  2028. Status = NtResumeThread(*Handle,
  2029. NULL);
  2030. if (!NT_SUCCESS(Status)) {
  2031. NtClose(*Handle);
  2032. }
  2033. return Status;
  2034. }
  2035. VOID
  2036. FinishBenchMark (
  2037. IN PPERFINFO PerfInfo
  2038. )
  2039. {
  2040. ULONG ContextSwitches;
  2041. LARGE_INTEGER Duration;
  2042. ULONG FirstLevelFills;
  2043. ULONG InterruptCount;
  2044. ULONG Length;
  2045. ULONG Performance;
  2046. ULONG Remainder;
  2047. ULONG SecondLevelFills;
  2048. NTSTATUS Status;
  2049. ULONG SystemCalls;
  2050. SYSTEM_PERFORMANCE_INFORMATION SystemInfo;
  2051. LARGE_INTEGER TotalCycles;
  2052. //
  2053. // Print results and announce end of test.
  2054. //
  2055. NtQuerySystemTime((PLARGE_INTEGER)&PerfInfo->StopTime);
  2056. Status = NtQueryInformationThread(NtCurrentThread(),
  2057. ThreadPerformanceCount,
  2058. &PerfInfo->StopCycles,
  2059. sizeof(LARGE_INTEGER),
  2060. NULL);
  2061. if (!NT_SUCCESS(Status)) {
  2062. printf("Failed to query performance count, status = %lx\n", Status);
  2063. return;
  2064. }
  2065. Status = NtQuerySystemInformation(SystemPerformanceInformation,
  2066. (PVOID)&SystemInfo,
  2067. sizeof(SYSTEM_PERFORMANCE_INFORMATION),
  2068. NULL);
  2069. if (!NT_SUCCESS(Status)) {
  2070. printf("Failed to query performance information, status = %lx\n", Status);
  2071. return;
  2072. }
  2073. Duration.QuadPart = PerfInfo->StopTime.QuadPart - PerfInfo->StartTime.QuadPart;
  2074. Length = Duration.LowPart / 10000;
  2075. TotalCycles.QuadPart = PerfInfo->StopCycles.QuadPart - PerfInfo->StartCycles.QuadPart;
  2076. TotalCycles = RtlExtendedLargeIntegerDivide(TotalCycles,
  2077. PerfInfo->Iterations,
  2078. &Remainder);
  2079. printf(" Test time in milliseconds %d\n", Length);
  2080. printf(" Number of iterations %d\n", PerfInfo->Iterations);
  2081. // printf(" Cycles per iteration %d\n", TotalCycles.LowPart);
  2082. Performance = PerfInfo->Iterations * 1000 / Length;
  2083. printf(" Iterations per second %d\n", Performance);
  2084. ContextSwitches = SystemInfo.ContextSwitches - PerfInfo->ContextSwitches;
  2085. SystemCalls = SystemInfo.SystemCalls - PerfInfo->SystemCalls;
  2086. printf(" Total Context Switches %d\n", ContextSwitches);
  2087. printf(" Number of System Calls %d\n", SystemCalls);
  2088. printf("*** End of Test ***\n\n");
  2089. return;
  2090. }
  2091. VOID
  2092. StartBenchMark (
  2093. IN PCHAR Title,
  2094. IN ULONG Iterations,
  2095. IN PPERFINFO PerfInfo
  2096. )
  2097. {
  2098. NTSTATUS Status;
  2099. SYSTEM_PERFORMANCE_INFORMATION SystemInfo;
  2100. //
  2101. // Announce start of test and the number of iterations.
  2102. //
  2103. printf("*** Start of test ***\n %s\n", Title);
  2104. PerfInfo->Title = Title;
  2105. PerfInfo->Iterations = Iterations;
  2106. NtQuerySystemTime((PLARGE_INTEGER)&PerfInfo->StartTime);
  2107. Status = NtQueryInformationThread(NtCurrentThread(),
  2108. ThreadPerformanceCount,
  2109. &PerfInfo->StartCycles,
  2110. sizeof(LARGE_INTEGER),
  2111. NULL);
  2112. if (!NT_SUCCESS(Status)) {
  2113. printf("Failed to query performance count, status = %lx\n", Status);
  2114. return;
  2115. }
  2116. Status = NtQuerySystemInformation(SystemPerformanceInformation,
  2117. (PVOID)&SystemInfo,
  2118. sizeof(SYSTEM_PERFORMANCE_INFORMATION),
  2119. NULL);
  2120. if (!NT_SUCCESS(Status)) {
  2121. printf("Failed to query performance information, status = %lx\n", Status);
  2122. return;
  2123. }
  2124. PerfInfo->ContextSwitches = SystemInfo.ContextSwitches;
  2125. PerfInfo->SystemCalls = SystemInfo.SystemCalls;
  2126. return;
  2127. }
  2128. LONG
  2129. SetProcessPrivilege (
  2130. TCHAR *PrivilegeName
  2131. )
  2132. {
  2133. TOKEN_PRIVILEGES NewPrivileges;
  2134. BOOL Status;
  2135. HANDLE Token = NULL;
  2136. LONG Value = - 1;
  2137. //
  2138. // Open process token.
  2139. //
  2140. Status = OpenProcessToken(GetCurrentProcess(),
  2141. TOKEN_ADJUST_PRIVILEGES,
  2142. &Token);
  2143. if (Status == FALSE) {
  2144. goto Done;
  2145. }
  2146. //
  2147. // Look up privilege value.
  2148. //
  2149. Status = LookupPrivilegeValue(NULL,
  2150. PrivilegeName,
  2151. &NewPrivileges.Privileges[0].Luid);
  2152. if (Status == FALSE) {
  2153. goto Done;
  2154. }
  2155. //
  2156. // Adjust token privileges.
  2157. //
  2158. NewPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  2159. NewPrivileges.PrivilegeCount = 1;
  2160. Status = AdjustTokenPrivileges(Token,
  2161. FALSE,
  2162. &NewPrivileges,
  2163. 0,
  2164. NULL,
  2165. NULL);
  2166. if (Status != FALSE) {
  2167. Value = 0;
  2168. }
  2169. //
  2170. // Close handle and return status.
  2171. //
  2172. Done:
  2173. if (Token != NULL) {
  2174. CloseHandle(Token);
  2175. }
  2176. return Value;
  2177. }