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

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
timt.c
Abstract:
This module contains native NT performance tests for the system
calls and context switching.
Author:
David N. Cutler (davec) 23-Nov-1991
Environment:
Kernel mode only.
Revision History:
--*/
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "nt.h"
#include "ntrtl.h"
#include "nturtl.h"
#include "windef.h"
#include "winbase.h"
//
// Define locals constants.
//
#define CHECKSUM_BUFFER_SIZE (1 << 16)
#define CHECKSUM_ITERATIONS 4000
#define CHECKSUM_IP_ITERATIONS 40000000
#define EVENT_CLEAR_ITERATIONS 3000000
#define EVENT_CREATION_ITERATIONS 400000
#define EVENT_OPEN_ITERATIONS 200000
#define EVENT_QUERY_ITERATIONS 2000000
#define EVENT_RESET_ITERATIONS 2000000
#define EVENT1_SWITCHES 300000
#define EVENT2_SWITCHES 200000
#define EVENT3_SWITCHES 400000
#define IO_ITERATIONS 350000
#define MUTANT_SWITCHES 200000
#define SLIST_ITERATIONS 20000000
#define SEMAPHORE1_SWITCHES 300000
#define SEMAPHORE2_SWITCHES 600000
#define SYSCALL_ITERATIONS 6000000
#define TIMER_OPERATION_ITERATIONS 500000
#define UNALIGNED_ITERATIONS 400000000
#define WAIT_SINGLE_ITERATIONS 2000000
#define WAIT_MULTIPLE_ITERATIONS 2000000
//
// Define event desired access.
//
#define DESIRED_EVENT_ACCESS (EVENT_QUERY_STATE | EVENT_MODIFY_STATE | SYNCHRONIZE)
//
// Define local types.
//
typedef struct _PERFINFO {
LARGE_INTEGER StartTime;
LARGE_INTEGER StopTime;
LARGE_INTEGER StartCycles;
LARGE_INTEGER StopCycles;
ULONG ContextSwitches;
ULONG SystemCalls;
PCHAR Title;
ULONG Iterations;
} PERFINFO, *PPERFINFO;
//
// Define test prototypes.
//
VOID
ChecksumTest (
VOID
);
VOID
EventClearTest (
VOID
);
VOID
EventCreationTest (
VOID
);
VOID
EventOpenTest (
VOID
);
VOID
EventQueryTest (
VOID
);
VOID
EventResetTest (
VOID
);
VOID
Event1SwitchTest (
VOID
);
VOID
Event2SwitchTest (
VOID
);
VOID
Event3SwitchTest (
VOID
);
VOID
Io1Test (
VOID
);
VOID
MutantSwitchTest (
VOID
);
VOID
Semaphore1SwitchTest (
VOID
);
VOID
Semaphore2SwitchTest (
VOID
);
LONG
SetProcessPrivilege (
TCHAR *PrivilegeName
);
VOID
SlistTest (
VOID
);
VOID
SystemCallTest (
VOID
);
VOID
TimerOperationTest (
VOID
);
VOID
UnalignedTest1 (
VOID
);
VOID
UnalignedTest2 (
VOID
);
VOID
WaitSingleTest (
VOID
);
VOID
WaitMultipleTest (
VOID
);
//
// Define thread routine prototypes.
//
NTSTATUS
Event1Thread1 (
IN PVOID Context
);
NTSTATUS
Event1Thread2 (
IN PVOID Context
);
NTSTATUS
Event2Thread1 (
IN PVOID Context
);
NTSTATUS
Event2Thread2 (
IN PVOID Context
);
NTSTATUS
Event3Thread1 (
IN PVOID Context
);
NTSTATUS
Event3Thread2 (
IN PVOID Context
);
NTSTATUS
MutantThread1 (
IN PVOID Context
);
NTSTATUS
MutantThread2 (
IN PVOID Context
);
NTSTATUS
Semaphore1Thread1 (
IN PVOID Context
);
NTSTATUS
Semaphore1Thread2 (
IN PVOID Context
);
NTSTATUS
Semaphore2Thread1 (
IN PVOID Context
);
NTSTATUS
Semaphore2Thread2 (
IN PVOID Context
);
NTSTATUS
TimerThread (
IN PVOID Context
);
//
// Define utility routine prototypes.
//
NTSTATUS
xCreateThread (
OUT PHANDLE Handle,
IN PUSER_THREAD_START_ROUTINE StartRoutine,
IN KPRIORITY Priority
);
VOID
FinishBenchMark (
IN PPERFINFO PerfInfo
);
VOID
StartBenchMark (
IN PCHAR Title,
IN ULONG Iterations,
IN PPERFINFO PerfInfo
);
//
// Define external routine prototypes.
//
ULONG
ComputeTimerTableIndex32 (
IN LARGE_INTEGER Interval,
IN LARGE_INTEGER CurrentTime,
IN PULONGLONG DueTime
);
ULONG
ComputeTimerTableIndex64 (
IN LARGE_INTEGER Interval,
IN LARGE_INTEGER CurrentTime,
IN PULONGLONG DueTime
);
ULONG
ChkSum (
IN ULONG Sum,
IN PUSHORT Buffer,
IN ULONG Length
);
ULONG
tcpxsum (
IN ULONG Sum,
IN PVOID Buffer,
IN ULONG Length
);
//
// Define static storage.
//
HANDLE EventHandle1;
HANDLE EventHandle2;
HANDLE EventPairHandle;
HANDLE MutantHandle;
HANDLE SemaphoreHandle1;
HANDLE SemaphoreHandle2;
HANDLE Thread1Handle;
HANDLE Thread2Handle;
HANDLE TimerEventHandle;
HANDLE TimerTimerHandle;
HANDLE TimerThreadHandle;
USHORT ChecksumBuffer[CHECKSUM_BUFFER_SIZE / sizeof(USHORT)];
VOID
__cdecl
main(
int argc,
char *argv[]
)
{
KPRIORITY Priority = LOW_REALTIME_PRIORITY + 8;
NTSTATUS Status;
//
// Set process privilege to increase priority.
//
if (SetProcessPrivilege(SE_INC_BASE_PRIORITY_NAME) != 0) {
printf("Failed to set process privilege to increase priority\n");
goto EndOfTest;
}
//
// set priority of current thread.
//
Status = NtSetInformationThread(NtCurrentThread(),
ThreadPriority,
&Priority,
sizeof(KPRIORITY));
if (!NT_SUCCESS(Status)) {
printf("Failed to set thread priority during initialization\n");
goto EndOfTest;
}
//
// Create an event object to signal the timer thread at the end of the
// test.
//
Status = NtCreateEvent(&TimerEventHandle,
DESIRED_EVENT_ACCESS,
NULL,
NotificationEvent,
FALSE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event during initialization\n");
goto EndOfTest;
}
//
// Create a timer object for use by the timer thread.
//
Status = NtCreateTimer(&TimerTimerHandle,
TIMER_ALL_ACCESS,
NULL,
NotificationTimer);
if (!NT_SUCCESS(Status)) {
printf("Failed to create timer during initialization\n");
goto EndOfTest;
}
//
// Create and start the background timer thread.
//
Status = xCreateThread(&TimerThreadHandle,
TimerThread,
LOW_REALTIME_PRIORITY + 12);
if (!NT_SUCCESS(Status)) {
printf("Failed to create timer thread during initialization\n");
goto EndOfTest;
}
//
// Execute performance tests.
//
// ChecksumTest();
// EventClearTest();
// EventCreationTest();
// EventOpenTest();
// EventQueryTest();
// EventResetTest();
// Event1SwitchTest();
// Event2SwitchTest();
// Event3SwitchTest();
// Io1Test();
// MutantSwitchTest();
// Semaphore1SwitchTest();
// Semaphore2SwitchTest();
// SlistTest();
// SystemCallTest();
// TimerOperationTest();
// WaitSingleTest();
// WaitMultipleTest();
UnalignedTest1();
UnalignedTest2();
//
// Set timer event and wait for timer thread to terminate.
//
Status = NtSetEvent(TimerEventHandle, NULL);
if (!NT_SUCCESS(Status)) {
printf("Failed to set event in main loop\n");
goto EndOfTest;
}
Status = NtWaitForSingleObject(TimerThreadHandle,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("Failed to wait for timer thread at end of test\n");
}
//
// Close event, timer, and timer thread handles.
//
EndOfTest:
NtClose(TimerEventHandle);
NtClose(TimerTimerHandle);
NtClose(TimerThreadHandle);
return;
}
VOID
ChecksumTest (
VOID
)
{
LONG Count;
LONG Index;
PERFINFO PerfInfo;
ULONG Sum1;
ULONG Sum2 = 0;
PUCHAR Source;
//
// Initialize the checksum buffer.
//
for (Index = 0; Index < (CHECKSUM_BUFFER_SIZE / sizeof(USHORT)); Index += 1) {
ChecksumBuffer[Index] = (USHORT)rand();
}
Source = (PUCHAR)&ChecksumBuffer[0];
Source += 1;
//
// Announce start of benchmark and capture performance parameters.
//
StartBenchMark("Checksum (aligned) Benchmark",
CHECKSUM_ITERATIONS,
&PerfInfo);
//
// Repeatedly checksum buffers of varying sizes.
//
for (Count = 0; Count < CHECKSUM_ITERATIONS; Count += 1) {
for (Index = 1024; Index >= 2 ; Index -= 1) {
Sum2 = tcpxsum(Sum2, &ChecksumBuffer[0], Index);
}
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// Announce start of benchmark and capture performance parameters.
//
StartBenchMark("Checksum (unaligned) Benchmark",
CHECKSUM_ITERATIONS,
&PerfInfo);
//
// Repeatedly checksum buffers of varying sizes.
//
for (Count = 0; Count < CHECKSUM_ITERATIONS; Count += 1) {
for (Index = 1024; Index >= 2 ; Index -= 1) {
Sum2 = tcpxsum(Sum2, Source, Index);
}
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// Announce start of benchmark and capture performance parameters.
//
StartBenchMark("Ip Header Checksum (aligned) Benchmark",
CHECKSUM_IP_ITERATIONS,
&PerfInfo);
//
// Repeatedly checksum buffers of varying sizes.
//
for (Count = 0; Count < CHECKSUM_IP_ITERATIONS; Count += 1) {
Sum1 = tcpxsum(0, &ChecksumBuffer[0], 20);
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// Announce start of benchmark and capture performance parameters.
//
StartBenchMark("Ip Header Checksum (unaligned) Benchmark",
CHECKSUM_IP_ITERATIONS,
&PerfInfo);
//
// Repeatedly checksum buffers of varying sizes.
//
for (Count = 0; Count < CHECKSUM_IP_ITERATIONS; Count += 1) {
Sum2 = tcpxsum(0, Source, 20);
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
return;
}
VOID
EventClearTest (
VOID
)
{
HANDLE EventHandle;
LONG Index;
PERFINFO PerfInfo;
NTSTATUS Status;
//
// Create an event for clear operations.
//
Status = NtCreateEvent(&EventHandle,
DESIRED_EVENT_ACCESS,
NULL,
NotificationEvent,
TRUE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event object for clear test\n");
goto EndOfTest;
}
//
// Announce start of benchmark and capture performance parameters.
//
StartBenchMark("Clear Event Benchmark",
EVENT_CLEAR_ITERATIONS,
&PerfInfo);
//
// Repeatedly clear an event.
//
for (Index = 0; Index < EVENT_RESET_ITERATIONS; Index += 1) {
Status = NtClearEvent(EventHandle);
if (!NT_SUCCESS(Status)) {
printf(" Clear event bad status, %x\n", Status);
goto EndOfTest;
}
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of clear event test.
//
EndOfTest:
NtClose(EventHandle);
return;
}
VOID
EventCreationTest (
VOID
)
{
ULONG Index;
PERFINFO PerfInfo;
NTSTATUS Status;
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("Event Creation Benchmark",
EVENT_CREATION_ITERATIONS,
&PerfInfo);
//
// Create an event and then close it.
//
for (Index = 0; Index < EVENT_CREATION_ITERATIONS; Index += 1) {
Status = NtCreateEvent(&EventHandle1,
DESIRED_EVENT_ACCESS,
NULL,
SynchronizationEvent,
FALSE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event object for event creation test.\n");
goto EndOfTest;
}
NtClose(EventHandle1);
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of event creation test.
//
EndOfTest:
return;
}
VOID
EventOpenTest (
VOID
)
{
ANSI_STRING EventName;
ULONG Index;
OBJECT_ATTRIBUTES ObjectAttributes;
PERFINFO PerfInfo;
NTSTATUS Status;
UNICODE_STRING UnicodeEventName;
//
// Create a named event for event open test.
//
RtlInitAnsiString(&EventName, "\\BaseNamedObjects\\EventOpenName");
Status = RtlAnsiStringToUnicodeString(&UnicodeEventName,
&EventName,
TRUE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create UNICODE string for event open test\n");
goto EndOfTest;
}
InitializeObjectAttributes(&ObjectAttributes,
&UnicodeEventName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtCreateEvent(&EventHandle1,
DESIRED_EVENT_ACCESS,
&ObjectAttributes,
SynchronizationEvent,
FALSE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event object for event open test.\n");
goto EndOfTest;
}
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("Event Open Benchmark",
EVENT_OPEN_ITERATIONS,
&PerfInfo);
//
// Open a named event and then close it.
//
for (Index = 0; Index < EVENT_OPEN_ITERATIONS; Index += 1) {
Status = NtOpenEvent(&EventHandle2,
EVENT_QUERY_STATE | EVENT_MODIFY_STATE | SYNCHRONIZE,
&ObjectAttributes);
if (!NT_SUCCESS(Status)) {
printf("Failed to open event for open event test\n");
goto EndOfTest;
}
NtClose(EventHandle2);
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of event open test.
//
EndOfTest:
NtClose(EventHandle1);
return;
}
VOID
EventQueryTest (
VOID
)
{
HANDLE EventHandle;
EVENT_BASIC_INFORMATION EventInformation;
LONG Index;
PERFINFO PerfInfo;
NTSTATUS Status;
//
// Create an event for query operations.
//
Status = NtCreateEvent(&EventHandle,
DESIRED_EVENT_ACCESS,
NULL,
NotificationEvent,
TRUE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event object for query test\n");
goto EndOfTest;
}
//
// Announce start of benchmark and capture performance parameters.
//
StartBenchMark("Query Event Benchmark",
EVENT_QUERY_ITERATIONS,
&PerfInfo);
//
// Repeatedly query an event.
//
for (Index = 0; Index < EVENT_QUERY_ITERATIONS; Index += 1) {
Status = NtQueryEvent(EventHandle,
EventBasicInformation,
&EventInformation,
sizeof(EVENT_BASIC_INFORMATION),
NULL);
if (!NT_SUCCESS(Status)) {
printf(" Query event bad status, %x\n", Status);
goto EndOfTest;
}
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of query event test.
//
EndOfTest:
NtClose(EventHandle);
return;
}
VOID
EventResetTest (
VOID
)
{
HANDLE EventHandle;
LONG Index;
PERFINFO PerfInfo;
NTSTATUS Status;
//
// Create an event for reset operations.
//
Status = NtCreateEvent(&EventHandle,
DESIRED_EVENT_ACCESS,
NULL,
NotificationEvent,
TRUE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event object for reset test\n");
goto EndOfTest;
}
//
// Announce start of benchmark and capture performance parameters.
//
StartBenchMark("Reset Event Benchmark",
EVENT_RESET_ITERATIONS,
&PerfInfo);
//
// Repeatedly reset an event.
//
for (Index = 0; Index < EVENT_RESET_ITERATIONS; Index += 1) {
Status = NtResetEvent(EventHandle,
NULL);
if (!NT_SUCCESS(Status)) {
printf(" Reset event bad status, %x\n", Status);
goto EndOfTest;
}
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of reset event test.
//
EndOfTest:
NtClose(EventHandle);
return;
}
VOID
Event1SwitchTest (
VOID
)
{
PERFINFO PerfInfo;
NTSTATUS Status;
HANDLE WaitObjects[2];
//
// Create two event objects for the event1 context switch test.
//
Status = NtCreateEvent(&EventHandle1,
DESIRED_EVENT_ACCESS,
NULL,
SynchronizationEvent,
FALSE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event1 object for context switch test.\n");
goto EndOfTest;
}
Status = NtCreateEvent(&EventHandle2,
DESIRED_EVENT_ACCESS,
NULL,
SynchronizationEvent,
FALSE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event1 object for context switch test.\n");
goto EndOfTest;
}
//
// Create the thread objects to execute the test.
//
Status = xCreateThread(&Thread1Handle,
Event1Thread1,
LOW_REALTIME_PRIORITY - 2);
if (!NT_SUCCESS(Status)) {
printf("Failed to create first thread event1 context switch test\n");
goto EndOfTest;
}
Status = xCreateThread(&Thread2Handle,
Event1Thread2,
LOW_REALTIME_PRIORITY - 2);
if (!NT_SUCCESS(Status)) {
printf("Failed to create second thread event1 context switch test\n");
goto EndOfTest;
}
//
// Initialize the wait objects array.
//
WaitObjects[0] = Thread1Handle;
WaitObjects[1] = Thread2Handle;
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("Event (synchronization) Context Switch Benchmark (Round Trips)",
EVENT1_SWITCHES,
&PerfInfo);
//
// Set event and wait for threads to terminate.
//
Status = NtSetEvent(EventHandle1, NULL);
if (!NT_SUCCESS(Status)) {
printf("Failed to set event event1 context switch test.\n");
goto EndOfTest;
}
Status = NtWaitForMultipleObjects(2,
WaitObjects,
WaitAll,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("Failed to wait event1 context switch test.\n");
goto EndOfTest;
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of event1 context switch test.
//
EndOfTest:
NtClose(EventHandle1);
NtClose(EventHandle2);
NtClose(Thread1Handle);
NtClose(Thread2Handle);
return;
}
NTSTATUS
Event1Thread1 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for event 1 and then set event 2.
//
for (Index = 0; Index < EVENT1_SWITCHES; Index += 1) {
Status = NtWaitForSingleObject(EventHandle1,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread1 event1 test bad wait status, %x\n", Status);
break;
}
Status = NtSetEvent(EventHandle2, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread1 event1 test bad set status, %x\n", Status);
break;
}
}
NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
NTSTATUS
Event1Thread2 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for event 2 and then set event 1.
//
for (Index = 0; Index < EVENT1_SWITCHES; Index += 1) {
Status = NtWaitForSingleObject(EventHandle2,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread2 event1 test bad wait status, %x\n", Status);
break;
}
Status = NtSetEvent(EventHandle1, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread2 event1 test bad set status, %x\n", Status);
break;
}
}
NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
VOID
Event2SwitchTest (
VOID
)
{
PERFINFO PerfInfo;
NTSTATUS Status;
PVOID WaitObjects[2];
//
// Create two event objects for the event2 context switch test.
//
Status = NtCreateEvent(&EventHandle1,
DESIRED_EVENT_ACCESS,
NULL,
NotificationEvent,
FALSE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event2 object for context switch test.\n");
goto EndOfTest;
}
Status = NtCreateEvent(&EventHandle2,
DESIRED_EVENT_ACCESS,
NULL,
NotificationEvent,
FALSE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event2 object for context switch test.\n");
goto EndOfTest;
}
//
// Create the thread objects to execute the test.
//
Status = xCreateThread(&Thread1Handle,
Event2Thread1,
LOW_REALTIME_PRIORITY - 2);
if (!NT_SUCCESS(Status)) {
printf("Failed to create first thread event2 context switch test\n");
goto EndOfTest;
}
Status = xCreateThread(&Thread2Handle,
Event2Thread2,
LOW_REALTIME_PRIORITY - 2);
if (!NT_SUCCESS(Status)) {
printf("Failed to create second thread event2 context switch test\n");
goto EndOfTest;
}
//
// Initialize the wait objects array.
//
WaitObjects[0] = Thread1Handle;
WaitObjects[1] = Thread2Handle;
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("Event (notification) Context Switch Benchmark (Round Trips)",
EVENT2_SWITCHES,
&PerfInfo);
//
// Set event and wait for threads to terminate.
//
Status = NtSetEvent(EventHandle1, NULL);
if (!NT_SUCCESS(Status)) {
printf("Failed to set event2 object for context switch test.\n");
goto EndOfTest;
}
Status = NtWaitForMultipleObjects(2,
WaitObjects,
WaitAll,
FALSE,
NULL);
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of event2 context switch test.
//
EndOfTest:
NtClose(EventHandle1);
NtClose(EventHandle2);
NtClose(Thread1Handle);
NtClose(Thread2Handle);
return;
}
NTSTATUS
Event2Thread1 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for event 1, reset event 1, and then set event 2.
//
for (Index = 0; Index < EVENT2_SWITCHES; Index += 1) {
Status = NtWaitForSingleObject(EventHandle1, FALSE, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread1 event2 test bad wait status, %x\n", Status);
break;
}
Status = NtResetEvent(EventHandle1, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread1 event2 test bad reset status, %x\n", Status);
break;
}
Status = NtSetEvent(EventHandle2, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread1 event2 test bad set status, %x\n", Status);
break;
}
}
NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
NTSTATUS
Event2Thread2 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for event 2, reset event 2, and then set event 1.
//
for (Index = 0; Index < EVENT2_SWITCHES; Index += 1) {
Status = NtWaitForSingleObject(EventHandle2, FALSE, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread2 event2 test bad wait status, %x\n", Status);
break;
}
Status = NtResetEvent(EventHandle2, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread1 event2 test bad reset status, %x\n", Status);
break;
}
Status = NtSetEvent(EventHandle1, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread2 event2 test bad set status, %x\n", Status);
break;
}
}
NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
VOID
Event3SwitchTest (
VOID
)
{
PERFINFO PerfInfo;
NTSTATUS Status;
PVOID WaitObjects[2];
//
// Create two event objects for the event1 context switch test.
//
Status = NtCreateEvent(&EventHandle1,
DESIRED_EVENT_ACCESS,
NULL,
SynchronizationEvent,
FALSE);
if (!NT_SUCCESS(Status)) {
printf("EVENT3: Failed to create event1 object for context switch test.\n");
goto EndOfTest;
}
Status = NtCreateEvent(&EventHandle2,
DESIRED_EVENT_ACCESS,
NULL,
SynchronizationEvent,
FALSE);
if (!NT_SUCCESS(Status)) {
printf("EVENT3: Failed to create event2 object for context switch test.\n");
goto EndOfTest;
}
//
// Create the thread objects to execute the test.
//
Status = xCreateThread(&Thread1Handle,
Event3Thread1,
LOW_REALTIME_PRIORITY - 2);
if (!NT_SUCCESS(Status)) {
printf("EVENT3: Failed to create first thread event3 context switch test\n");
goto EndOfTest;
}
Status = xCreateThread(&Thread2Handle,
Event3Thread2,
LOW_REALTIME_PRIORITY - 2);
if (!NT_SUCCESS(Status)) {
printf("EVENT3: Failed to create second thread event3 context switch test\n");
goto EndOfTest;
}
//
// Initialize the wait objects array.
//
WaitObjects[0] = Thread1Handle;
WaitObjects[1] = Thread2Handle;
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("Event (signal/wait) Context Switch Benchmark (Round Trips)",
EVENT3_SWITCHES,
&PerfInfo);
//
// Set event and wait for threads to terminate.
//
Status = NtSetEvent(EventHandle1, NULL);
if (!NT_SUCCESS(Status)) {
printf("EVENT3: Failed to set event event1 context switch test.\n");
goto EndOfTest;
}
Status = NtWaitForMultipleObjects(2,
WaitObjects,
WaitAll,
FALSE,
NULL);
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of event3 context switch test.
//
EndOfTest:
NtClose(EventHandle1);
NtClose(EventHandle2);
NtClose(Thread1Handle);
NtClose(Thread2Handle);
return;
}
NTSTATUS
Event3Thread1 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for event 1 and then enter signal/wait loop.
//
Status = NtWaitForSingleObject(EventHandle1,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("EVENT3: Thread1 initial wait failed, %x\n", Status);
} else {
for (Index = 0; Index < EVENT3_SWITCHES; Index += 1) {
Status = NtSignalAndWaitForSingleObject(EventHandle2,
EventHandle1,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("EVENT3: Thread1 signal/wait failed, %x\n", Status);
break;
}
}
}
Status = NtSetEvent(EventHandle2, NULL);
NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
NTSTATUS
Event3Thread2 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for event 1 and then enter signal/wait loop.
//
Status = NtWaitForSingleObject(EventHandle2,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("EVENT3: Thread2 initial wait failed, %x\n", Status);
} else {
for (Index = 0; Index < EVENT3_SWITCHES; Index += 1) {
Status = NtSignalAndWaitForSingleObject(EventHandle1,
EventHandle2,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("EVENT3: Thread2 signal/wait failed, %x\n", Status);
break;
}
}
}
NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
VOID
Io1Test (
VOID
)
{
ULONG Buffer[128];
HANDLE DeviceHandle;
ANSI_STRING AnsiName;
HANDLE EventHandle;
LARGE_INTEGER FileAddress;
LONG Index;
IO_STATUS_BLOCK IoStatus;
OBJECT_ATTRIBUTES ObjectAttributes;
PERFINFO PerfInfo;
NTSTATUS Status;
LARGE_INTEGER SystemTime;
UNICODE_STRING UnicodeName;
//
// Create an event for synchronization of I/O operations.
//
Status = NtCreateEvent(&EventHandle,
DESIRED_EVENT_ACCESS,
NULL,
NotificationEvent,
FALSE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event object for I/O test 1\n");
goto EndOfTest;
}
//
// Open device object for I/O operations.
//
RtlInitString(&AnsiName, "\\Device\\Null");
Status = RtlAnsiStringToUnicodeString(&UnicodeName,
&AnsiName,
TRUE);
if (!NT_SUCCESS(Status)) {
printf("Failed to convert device name to unicode for I/O test 1\n");
goto EndOfTest;
}
InitializeObjectAttributes(&ObjectAttributes,
&UnicodeName,
0,
(HANDLE)0,
NULL);
Status = NtOpenFile(&DeviceHandle,
FILE_READ_DATA | FILE_WRITE_DATA,
&ObjectAttributes,
&IoStatus,
0,
0);
RtlFreeUnicodeString(&UnicodeName);
if (!NT_SUCCESS(Status)) {
printf("Failed to open device I/O test 1, status = %lx\n", Status);
goto EndOfTest;
}
//
// Initialize file address parameter.
//
FileAddress.LowPart = 0;
FileAddress.HighPart = 0;
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("I/O Benchmark for Synchronous Null Device",
IO_ITERATIONS,
&PerfInfo);
//
// Repeatedly write data to null device.
//
for (Index = 0; Index < IO_ITERATIONS; Index += 1) {
Status = NtWriteFile(DeviceHandle,
EventHandle,
NULL,
NULL,
&IoStatus,
Buffer,
512,
&FileAddress,
NULL);
if (!NT_SUCCESS(Status)) {
printf(" Failed to write device I/O test 1, status = %lx\n",
Status);
goto EndOfTest;
}
Status = NtWaitForSingleObject(EventHandle, FALSE, NULL);
if (!NT_SUCCESS(Status)) {
printf(" I/O test 1 bad wait status, %x\n", Status);
goto EndOfTest;
}
if (NT_SUCCESS(IoStatus.Status) == FALSE) {
printf(" I/O test 1 bad I/O status, %x\n", Status);
goto EndOfTest;
}
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of I/O test 1.
//
EndOfTest:
NtClose(DeviceHandle);
NtClose(EventHandle);
return;
}
VOID
MutantSwitchTest (
VOID
)
{
PERFINFO PerfInfo;
NTSTATUS Status;
HANDLE WaitObjects[2];
//
// Create a mutant object for the mutant context switch test.
//
Status = NtCreateMutant(&MutantHandle, MUTANT_ALL_ACCESS, NULL, TRUE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create mutant object for context switch test.\n");
goto EndOfTest;
}
//
// Create the thread objects to execute the test.
//
Status = xCreateThread(&Thread1Handle,
MutantThread1,
LOW_REALTIME_PRIORITY + 11);
if (!NT_SUCCESS(Status)) {
printf("Failed to create first thread mutant context switch test\n");
goto EndOfTest;
}
Status = xCreateThread(&Thread2Handle,
MutantThread2,
LOW_REALTIME_PRIORITY + 11);
if (!NT_SUCCESS(Status)) {
printf("Failed to create second thread mutant context switch test\n");
goto EndOfTest;
}
//
// Initialize the wait objects array.
//
WaitObjects[0] = Thread1Handle;
WaitObjects[1] = Thread2Handle;
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("Mutant Context Switch Benchmark (Round Trips)",
MUTANT_SWITCHES,
&PerfInfo);
//
// Release mutant and wait for threads to terminate.
//
Status = NtReleaseMutant(MutantHandle, NULL);
if (!NT_SUCCESS(Status)) {
printf("Failed to release mutant object for context switch test.\n");
goto EndOfTest;
}
Status = NtWaitForMultipleObjects(2,
WaitObjects,
WaitAll,
FALSE,
NULL);
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of mutant context switch test.
//
EndOfTest:
NtClose(MutantHandle);
NtClose(Thread1Handle);
NtClose(Thread2Handle);
return;
}
NTSTATUS
MutantThread1 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for mutant and then release mutant.
//
for (Index = 0; Index < MUTANT_SWITCHES; Index += 1) {
Status = NtWaitForSingleObject(MutantHandle, FALSE, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread1 mutant test bad wait status, %x\n", Status);
break;
}
Status = NtReleaseMutant(MutantHandle, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread1 mutant test bad release status, %x\n", Status);
break;
}
}
NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
NTSTATUS
MutantThread2 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for mutant and then release mutant.
//
for (Index = 0; Index < MUTANT_SWITCHES; Index += 1) {
Status = NtWaitForSingleObject(MutantHandle, FALSE, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread2 mutant test bad wait status, %x\n", Status);
break;
}
Status = NtReleaseMutant(MutantHandle, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Thread2 mutant test bad release status, %x\n", Status);
break;
}
}
NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
VOID
Semaphore1SwitchTest (
VOID
)
{
PERFINFO PerfInfo;
NTSTATUS Status;
HANDLE WaitObjects[2];
//
// Create two semaphore objects for the semaphore1 context switch test.
//
Status = NtCreateSemaphore(&SemaphoreHandle1,
DESIRED_EVENT_ACCESS,
NULL,
0,
1);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE1: Failed to create semaphore1 object.\n");
goto EndOfTest;
}
Status = NtCreateSemaphore(&SemaphoreHandle2,
DESIRED_EVENT_ACCESS,
NULL,
0,
1);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE1: Failed to create semaphore2 object.\n");
goto EndOfTest;
}
//
// Create the thread objects to execute the test.
//
Status = xCreateThread(&Thread1Handle,
Semaphore1Thread1,
LOW_REALTIME_PRIORITY - 2);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE1: Failed to create thread1 object.\n");
goto EndOfTest;
}
Status = xCreateThread(&Thread2Handle,
Semaphore1Thread2,
LOW_REALTIME_PRIORITY - 2);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE1: Failed to create thread2 object.\n");
goto EndOfTest;
}
//
// Initialize the wait objects array.
//
WaitObjects[0] = Thread1Handle;
WaitObjects[1] = Thread2Handle;
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("Semaphore (release/wait) Context Switch Benchmark (Round Trips)",
SEMAPHORE1_SWITCHES,
&PerfInfo);
//
// Release semaphore and wait for threads to terminate.
//
Status = NtReleaseSemaphore(SemaphoreHandle1, 1, NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE1: Failed to release semaphore1 at start of test.\n");
goto EndOfTest;
}
Status = NtWaitForMultipleObjects(2,
WaitObjects,
WaitAll,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE1: Failed to wait for threads.\n");
goto EndOfTest;
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of semaphore1 context switch test.
//
EndOfTest:
NtClose(SemaphoreHandle1);
NtClose(SemaphoreHandle2);
NtClose(Thread1Handle);
NtClose(Thread2Handle);
return;
}
NTSTATUS
Semaphore1Thread1 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for semaphore 1 and then release semaphore 2.
//
for (Index = 0; Index < SEMAPHORE1_SWITCHES; Index += 1) {
Status = NtWaitForSingleObject(SemaphoreHandle1,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE1: Thread1 bad wait status, %x\n", Status);
break;
}
Status = NtReleaseSemaphore(SemaphoreHandle2, 1, NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE1: Thread1 bad release status, %x\n", Status);
break;
}
}
NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
NTSTATUS
Semaphore1Thread2 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for semaphore 2 and then release semaphore 1.
//
for (Index = 0; Index < SEMAPHORE1_SWITCHES; Index += 1) {
Status = NtWaitForSingleObject(SemaphoreHandle2,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE1: Thread2 bad wait status, %x\n", Status);
break;
}
Status = NtReleaseSemaphore(SemaphoreHandle1, 1, NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE1: Thread2 bad release status, %x\n", Status);
break;
}
}
NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
VOID
Semaphore2SwitchTest (
VOID
)
{
PERFINFO PerfInfo;
NTSTATUS Status;
HANDLE WaitObjects[2];
//
// Create two semaphore objects for the semaphore1 context switch test.
//
Status = NtCreateSemaphore(&SemaphoreHandle1,
DESIRED_EVENT_ACCESS,
NULL,
0,
1);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE2: Failed to create semaphore1 object.\n");
goto EndOfTest;
}
Status = NtCreateSemaphore(&SemaphoreHandle2,
DESIRED_EVENT_ACCESS,
NULL,
0,
1);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE2: Failed to create semaphore2 object.\n");
goto EndOfTest;
}
//
// Create the thread objects to execute the test.
//
Status = xCreateThread(&Thread1Handle,
Semaphore2Thread1,
LOW_REALTIME_PRIORITY - 2);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE2: Failed to create thread1 object.\n");
goto EndOfTest;
}
Status = xCreateThread(&Thread2Handle,
Semaphore2Thread2,
LOW_REALTIME_PRIORITY - 2);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE2: Failed to create thread2 object.\n");
goto EndOfTest;
}
//
// Initialize the wait objects array.
//
WaitObjects[0] = Thread1Handle;
WaitObjects[1] = Thread2Handle;
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("Semaphore (signal/wait) Context Switch Benchmark (Round Trips)",
SEMAPHORE2_SWITCHES,
&PerfInfo);
//
// Release semaphore and wait for threads to terminate.
//
Status = NtReleaseSemaphore(SemaphoreHandle1, 1, NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE2: Failed to release semaphore1 at start of test.\n");
goto EndOfTest;
}
Status = NtWaitForMultipleObjects(2,
WaitObjects,
WaitAll,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE2: Failed to wait for threads.\n");
goto EndOfTest;
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of semaphore 2 context switch test.
//
EndOfTest:
NtClose(SemaphoreHandle1);
NtClose(SemaphoreHandle2);
NtClose(Thread1Handle);
NtClose(Thread2Handle);
return;
}
NTSTATUS
Semaphore2Thread1 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for semaphore 1 and then enter signal/wait loop.
//
Status = NtWaitForSingleObject(SemaphoreHandle1,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE2: Thread1 initial wait failed, %x\n", Status);
} else {
for (Index = 0; Index < SEMAPHORE2_SWITCHES; Index += 1) {
Status = NtSignalAndWaitForSingleObject(SemaphoreHandle2,
SemaphoreHandle1,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE2: Thread1 signal/wait failed, %x\n", Status);
break;
}
}
}
Status = NtReleaseSemaphore(SemaphoreHandle2, 1, NULL);
NtTerminateThread(Thread1Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
NTSTATUS
Semaphore2Thread2 (
IN PVOID Context
)
{
ULONG Index;
NTSTATUS Status;
//
// Wait for semaphore 2 and then enter signal/wait loop.
//
Status = NtWaitForSingleObject(SemaphoreHandle2,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE2: Thread2 initial wait failed, %x\n", Status);
} else {
for (Index = 0; Index < SEMAPHORE2_SWITCHES; Index += 1) {
Status = NtSignalAndWaitForSingleObject(SemaphoreHandle1,
SemaphoreHandle2,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf("SEMAPHORE2: Thread2 signal/wait failed, %x\n", Status);
break;
}
}
}
NtTerminateThread(Thread2Handle, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
VOID
SlistTest (
VOID
)
{
SLIST_ENTRY Entry;
SLIST_HEADER SListHead;
ULONG Index;
PERFINFO PerfInfo;
LARGE_INTEGER SystemTime;
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("S-List Benchmark",
SLIST_ITERATIONS,
&PerfInfo);
//
// Repeatedly call a short system service.
//
InitializeSListHead(&SListHead);
for (Index = 0; Index < SLIST_ITERATIONS; Index += 1) {
InterlockedPushEntrySList(&SListHead, &Entry);
if (InterlockedPopEntrySList(&SListHead) != (PVOID)&Entry) {
printf("SLIST: Entry does match %lx\n", Entry);
}
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
return;
}
VOID
SystemCallTest (
VOID
)
{
ULONG Index;
PERFINFO PerfInfo;
LARGE_INTEGER SystemTime;
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("System Call Benchmark (NtQuerySystemTime)",
SYSCALL_ITERATIONS,
&PerfInfo);
//
// Repeatedly call a short system service.
//
for (Index = 0; Index < SYSCALL_ITERATIONS; Index += 1) {
NtQuerySystemTime(&SystemTime);
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
return;
}
VOID
TimerOperationTest (
VOID
)
{
LARGE_INTEGER DueTime;
HANDLE Handle;
ULONG Index;
PERFINFO PerfInfo;
LARGE_INTEGER SystemTime;
NTSTATUS Status;
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("Timer Operation Benchmark (NtSet/CancelTimer)",
TIMER_OPERATION_ITERATIONS,
&PerfInfo);
//
// Create a timer object for use in the test.
//
Status = NtCreateTimer(&Handle,
TIMER_ALL_ACCESS,
NULL,
NotificationTimer);
if (!NT_SUCCESS(Status)) {
printf("Failed to create timer during initialization\n");
goto EndOfTest;
}
//
// Repeatedly set and cancel a timer.
//
DueTime = RtlConvertLongToLargeInteger(- 100 * 1000 * 10);
for (Index = 0; Index < TIMER_OPERATION_ITERATIONS; Index += 1) {
NtSetTimer(Handle, &DueTime, NULL, NULL, FALSE, 0, NULL);
NtCancelTimer(Handle, NULL);
}
//
// Print out performance statistics.
//
EndOfTest:
FinishBenchMark(&PerfInfo);
return;
}
VOID
UnalignedTest1 (
VOID
)
{
PULONG Address;
UCHAR Array[128];
ULONG Count;
ULONG Index;
PERFINFO PerfInfo;
ULONG Sum = 0;
//
// Announce start of benchmark and capture performance parmeters.
//
for (Index = 1; Index < 65; Index += 1) {
Array[Index] = (UCHAR)Index;
}
StartBenchMark("Unaligned DWORD Access Test - Hardware",
UNALIGNED_ITERATIONS,
&PerfInfo);
//
// Repeatedly sum array;
//
for (Count = 0; Count < UNALIGNED_ITERATIONS; Count += 1) {
Address = (PULONG)&Array[1];
for (Index = 1; Index < 65; Index += 4) {
Sum += *Address;
Address += 1;
}
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
printf("final sum %d\n", Sum);
return;
}
VOID
UnalignedTest2 (
VOID
)
{
PULONG Address;
UCHAR Array[128];
ULONG Count;
ULONG Index;
PERFINFO PerfInfo;
ULONG Sum = 0;
ULONG Value;
//
// Announce start of benchmark and capture performance parmeters.
//
for (Index = 1; Index < 65; Index += 1) {
Array[Index] = (UCHAR)Index;
}
StartBenchMark("Unaligned DWORD Access Test - Software",
UNALIGNED_ITERATIONS,
&PerfInfo);
//
// Repeatedly sum array;
//
for (Count = 0; Count < UNALIGNED_ITERATIONS; Count += 1) {
Address = (PULONG)&Array[1];
for (Index = 1; Index < 65; Index += 4) {
Value = *((PUCHAR)Address + 3);
Value = (Value << 8) + *((PUCHAR)Address + 2);
Value = (Value << 8) + *((PUCHAR)Address + 1);
Value = (Value << 8) + *((PUCHAR)Address + 0);
Address += 1;
Sum += Value;
}
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
printf("final sum %d\n", Sum);
return;
}
VOID
WaitSingleTest (
VOID
)
{
HANDLE EventHandle;
LONG Index;
PERFINFO PerfInfo;
NTSTATUS Status;
//
// Create an event for synchronization of wait single operations.
//
Status = NtCreateEvent(&EventHandle,
DESIRED_EVENT_ACCESS,
NULL,
NotificationEvent,
TRUE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event object for wait single test\n");
goto EndOfTest;
}
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("Wait Single Benchmark",
WAIT_SINGLE_ITERATIONS,
&PerfInfo);
//
// Repeatedly wait for a single event.
//
for (Index = 0; Index < WAIT_SINGLE_ITERATIONS; Index += 1) {
Status = NtWaitForSingleObject(EventHandle, FALSE, NULL);
if (!NT_SUCCESS(Status)) {
printf(" Wait single bad wait status, %x\n", Status);
goto EndOfTest;
}
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of Wait Single Test.
//
EndOfTest:
NtClose(EventHandle);
return;
}
VOID
WaitMultipleTest (
VOID
)
{
HANDLE Event1Handle;
HANDLE Event2Handle;
HANDLE WaitObjects[2];
LONG Index;
PERFINFO PerfInfo;
NTSTATUS Status;
//
// Create two events for synchronization of wait multiple operations.
//
Status = NtCreateEvent(&Event1Handle,
DESIRED_EVENT_ACCESS,
NULL,
NotificationEvent,
TRUE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event object 1 for wait multiple test\n");
goto EndOfTest;
}
Status = NtCreateEvent(&Event2Handle,
DESIRED_EVENT_ACCESS,
NULL,
NotificationEvent,
TRUE);
if (!NT_SUCCESS(Status)) {
printf("Failed to create event object 2 for wait multiple test\n");
goto EndOfTest;
}
//
// Announce start of benchmark and capture performance parmeters.
//
StartBenchMark("Wait Multiple Benchmark",
WAIT_MULTIPLE_ITERATIONS,
&PerfInfo);
//
// Repeatedly wait for a multiple events.
//
WaitObjects[0] = Event1Handle;
WaitObjects[1] = Event2Handle;
for (Index = 0; Index < WAIT_SINGLE_ITERATIONS; Index += 1) {
Status = NtWaitForMultipleObjects(2,
WaitObjects,
WaitAny,
FALSE,
NULL);
if (!NT_SUCCESS(Status)) {
printf(" Wait multiple bad wait status, %x\n", Status);
goto EndOfTest;
}
}
//
// Print out performance statistics.
//
FinishBenchMark(&PerfInfo);
//
// End of Wait Multiple Test.
//
EndOfTest:
NtClose(Event1Handle);
NtClose(Event2Handle);
return;
}
NTSTATUS
TimerThread (
IN PVOID Context
)
{
LARGE_INTEGER DueTime;
NTSTATUS Status;
HANDLE WaitObjects[2];
//
// Initialize variables and loop until the timer event is set.
//
DueTime.LowPart = -(5 * 1000 * 1000);
DueTime.HighPart = -1;
WaitObjects[0] = TimerEventHandle;
WaitObjects[1] = TimerTimerHandle;
do {
Status = NtSetTimer(TimerTimerHandle,
&DueTime,
NULL,
NULL,
FALSE,
0,
NULL);
if (!NT_SUCCESS(Status)) {
break;
}
Status = NtWaitForMultipleObjects(2,
WaitObjects,
WaitAny,
FALSE,
NULL);
} while (Status != STATUS_SUCCESS);
NtTerminateThread(TimerThreadHandle, Status);
return STATUS_SUCCESS;
}
NTSTATUS
xCreateThread (
OUT PHANDLE Handle,
IN PUSER_THREAD_START_ROUTINE StartRoutine,
IN KPRIORITY Priority
)
{
NTSTATUS Status;
//
// Create a thread in the suspended state, sets its priority, and then
// resume the thread.
//
Status = RtlCreateUserThread(NtCurrentProcess(),
NULL,
TRUE,
0,
0,
0,
StartRoutine,
NULL,
Handle,
NULL);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = NtSetInformationThread(*Handle,
ThreadPriority,
&Priority,
sizeof(KPRIORITY));
if (!NT_SUCCESS(Status)) {
NtClose(*Handle);
return Status;
}
Status = NtResumeThread(*Handle,
NULL);
if (!NT_SUCCESS(Status)) {
NtClose(*Handle);
}
return Status;
}
VOID
FinishBenchMark (
IN PPERFINFO PerfInfo
)
{
ULONG ContextSwitches;
LARGE_INTEGER Duration;
ULONG FirstLevelFills;
ULONG InterruptCount;
ULONG Length;
ULONG Performance;
ULONG Remainder;
ULONG SecondLevelFills;
NTSTATUS Status;
ULONG SystemCalls;
SYSTEM_PERFORMANCE_INFORMATION SystemInfo;
LARGE_INTEGER TotalCycles;
//
// Print results and announce end of test.
//
NtQuerySystemTime((PLARGE_INTEGER)&PerfInfo->StopTime);
Status = NtQueryInformationThread(NtCurrentThread(),
ThreadPerformanceCount,
&PerfInfo->StopCycles,
sizeof(LARGE_INTEGER),
NULL);
if (!NT_SUCCESS(Status)) {
printf("Failed to query performance count, status = %lx\n", Status);
return;
}
Status = NtQuerySystemInformation(SystemPerformanceInformation,
(PVOID)&SystemInfo,
sizeof(SYSTEM_PERFORMANCE_INFORMATION),
NULL);
if (!NT_SUCCESS(Status)) {
printf("Failed to query performance information, status = %lx\n", Status);
return;
}
Duration.QuadPart = PerfInfo->StopTime.QuadPart - PerfInfo->StartTime.QuadPart;
Length = Duration.LowPart / 10000;
TotalCycles.QuadPart = PerfInfo->StopCycles.QuadPart - PerfInfo->StartCycles.QuadPart;
TotalCycles = RtlExtendedLargeIntegerDivide(TotalCycles,
PerfInfo->Iterations,
&Remainder);
printf(" Test time in milliseconds %d\n", Length);
printf(" Number of iterations %d\n", PerfInfo->Iterations);
// printf(" Cycles per iteration %d\n", TotalCycles.LowPart);
Performance = PerfInfo->Iterations * 1000 / Length;
printf(" Iterations per second %d\n", Performance);
ContextSwitches = SystemInfo.ContextSwitches - PerfInfo->ContextSwitches;
SystemCalls = SystemInfo.SystemCalls - PerfInfo->SystemCalls;
printf(" Total Context Switches %d\n", ContextSwitches);
printf(" Number of System Calls %d\n", SystemCalls);
printf("*** End of Test ***\n\n");
return;
}
VOID
StartBenchMark (
IN PCHAR Title,
IN ULONG Iterations,
IN PPERFINFO PerfInfo
)
{
NTSTATUS Status;
SYSTEM_PERFORMANCE_INFORMATION SystemInfo;
//
// Announce start of test and the number of iterations.
//
printf("*** Start of test ***\n %s\n", Title);
PerfInfo->Title = Title;
PerfInfo->Iterations = Iterations;
NtQuerySystemTime((PLARGE_INTEGER)&PerfInfo->StartTime);
Status = NtQueryInformationThread(NtCurrentThread(),
ThreadPerformanceCount,
&PerfInfo->StartCycles,
sizeof(LARGE_INTEGER),
NULL);
if (!NT_SUCCESS(Status)) {
printf("Failed to query performance count, status = %lx\n", Status);
return;
}
Status = NtQuerySystemInformation(SystemPerformanceInformation,
(PVOID)&SystemInfo,
sizeof(SYSTEM_PERFORMANCE_INFORMATION),
NULL);
if (!NT_SUCCESS(Status)) {
printf("Failed to query performance information, status = %lx\n", Status);
return;
}
PerfInfo->ContextSwitches = SystemInfo.ContextSwitches;
PerfInfo->SystemCalls = SystemInfo.SystemCalls;
return;
}
LONG
SetProcessPrivilege (
TCHAR *PrivilegeName
)
{
TOKEN_PRIVILEGES NewPrivileges;
BOOL Status;
HANDLE Token = NULL;
LONG Value = - 1;
//
// Open process token.
//
Status = OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES,
&Token);
if (Status == FALSE) {
goto Done;
}
//
// Look up privilege value.
//
Status = LookupPrivilegeValue(NULL,
PrivilegeName,
&NewPrivileges.Privileges[0].Luid);
if (Status == FALSE) {
goto Done;
}
//
// Adjust token privileges.
//
NewPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
NewPrivileges.PrivilegeCount = 1;
Status = AdjustTokenPrivileges(Token,
FALSE,
&NewPrivileges,
0,
NULL,
NULL);
if (Status != FALSE) {
Value = 0;
}
//
// Close handle and return status.
//
Done:
if (Token != NULL) {
CloseHandle(Token);
}
return Value;
}