windows-nt/Source/XPSP1/NT/com/rpc/perf/context/context.c
2020-09-26 16:20:57 +08:00

510 lines
14 KiB
C

/*++
Copyright (C) Microsoft Corporation, 1994 - 1999
Module Name:
context.c
Abstract:
Performance test comparing different methods of context switching
on NT. The tests process-to-process and thread-to-thread context
switching. This code acts as both a client and a server.
Author:
Mario Goertzel (mariogo) 30-Mar-1994
Revision History:
--*/
#include <rpcperf.h>
static const char *REQUEST_EVENT = "Context Switch Perf Request Event";
static const char *REQUEST_EVENT2 = "Context Switch Perf Request Event #2";
static const char *REPLY_EVENT = "Context Switch Perf Reply Event";
static const char *EVENT_PAIR = "\\RPC Control\\Perf Test: EventPair";
const char *USAGE="-n type -n case\n"
" Types:\n"
" 1: Client and server (thread-to-thread context switches)\n"
" 2: Server side of test (process-to-process)\n"
" 3: Client side of test (process-to-process)\n"
" Cases:\n"
" 1: Use NT eventpairs\n"
" 2: Use NT eventpairs (two step client)\n"
" 3: Use SetEvent/WaitForSingleObject\n"
" 4: Use SetEvent/WaitForSingleObject with timeout\n"
" 5: Use SetEvent/WaitForMultipleObjects\n"
" 6: Use SetEvent/WaitForMultipleObjects with timeout\n"
" 7: Use SignalObjectAndWait on events\n"
" 8: Use SignalObjectAndWait on events w/ timeout\n"
;
//
// The Server function is the server of the test. The client
// maybe in the process, or another process, nobody knows...
//
ULONG Server(ULONG arg)
{
ULONG status;
ULONG i;
switch(Options[1])
{
case 1:
case 2:
{
// NT event pairs
OBJECT_ATTRIBUTES oaEventPair;
ANSI_STRING ansiEventPairName;
UNICODE_STRING unicodeEventPairName;
HANDLE hEventPair;
RtlInitAnsiString(&ansiEventPairName, EVENT_PAIR);
RtlAnsiStringToUnicodeString(&unicodeEventPairName,
&ansiEventPairName,
TRUE);
InitializeObjectAttributes(&oaEventPair,
&unicodeEventPairName,
OBJ_CASE_INSENSITIVE,
0,
0);
status = NtCreateEventPair(&hEventPair,
EVENT_PAIR_ALL_ACCESS,
&oaEventPair);
if (!NT_SUCCESS(status))
{
printf("NtCreateEventPair failed -- %8lX\n", status);
return 1;
}
for(;;)
{
status = NtSetLowWaitHighEventPair(hEventPair);
if (!NT_SUCCESS(status))
{
printf("NtSetLowWaitHighEventPair failed - %08lX\n",
status);
return(1);
}
}
break;
}
case 3:
case 4:
{
// Win32 events (w/ or w/o a timeout)
ULONG timeout = (Options[1] == 3)?INFINITE:2000;
HANDLE hEvent1, hEvent2;
hEvent1 = CreateEvent(0,
FALSE,
FALSE,
REQUEST_EVENT);
hEvent2 = CreateEvent(0,
FALSE,
FALSE,
REPLY_EVENT);
if ( (hEvent1 == 0) || (hEvent2 == 0))
{
printf("CreateEvent failed - %08x\n", GetLastError());
exit(1);
}
for(;;)
{
// Wait for clients request
status = WaitForSingleObject(hEvent1, timeout);
if (status != WAIT_OBJECT_0)
{
printf("Server WaitForSingleObject failed -- %08x\n", GetLastError());
return 1;
}
// Reply
status = SetEvent(hEvent2);
if (status == 0)
{
printf("SetEvent failed - %08x\n", GetLastError());
exit(1);
}
}
CloseHandle(hEvent1);
CloseHandle(hEvent2);
break;
}
case 5:
case 6:
{
// WaitForMultipleObjects/SetEvent w/ and w/o timeouts.
ULONG timeout = (Options[1] == 5)?INFINITE:2000;
ULONG cCount = 2;
HANDLE ahEvents[2];
HANDLE hReplyEvent;
ahEvents[0] = CreateEvent(0,
FALSE,
FALSE,
REQUEST_EVENT);
ahEvents[1] = CreateEvent(0,
FALSE,
FALSE,
REQUEST_EVENT2);
hReplyEvent = CreateEvent(0,
FALSE,
FALSE,
REPLY_EVENT);
if ( (ahEvents[0] == 0) || (ahEvents[1] == 0) || (hReplyEvent == 0))
{
printf("CreateEvent failed - %08x\n", GetLastError());
exit(1);
}
for(;;)
{
// Wait for clients request
status = WaitForMultipleObjects(cCount, ahEvents, FALSE, timeout);
if (status != WAIT_OBJECT_0)
{
printf("Server WaitForMultpleObjects failed -- %08x\n", GetLastError());
return 1;
}
// Reply
status = SetEvent(hReplyEvent);
if (status == 0)
{
printf("SetEvent failed - %08x\n", GetLastError());
exit(1);
}
}
CloseHandle(ahEvents[0]);
CloseHandle(ahEvents[1]);
CloseHandle(hReplyEvent);
break;
}
case 7:
case 8:
{
ULONG timeout = (Options[1] == 7)?INFINITE:2000;
HANDLE hEvent1, hEvent2;
hEvent1 = CreateEvent(0,
FALSE,
FALSE,
REQUEST_EVENT);
hEvent2 = CreateEvent(0,
FALSE,
FALSE,
REPLY_EVENT);
if ( (hEvent1 == 0) || (hEvent2 == 0))
{
printf("CreateEvent failed - %08x\n", GetLastError());
exit(1);
}
status = WaitForSingleObject(hEvent1, INFINITE);
if (status != WAIT_OBJECT_0)
{
printf("Server WaitForSingleObject failed == %08x\n", GetLastError());
}
for(;;)
{
// Wait for clients request
status = SignalObjectAndWait(hEvent2, hEvent1, timeout, FALSE);
if (status != WAIT_OBJECT_0)
{
printf("Server SignalObjectAndWait failed -- %08x\n", GetLastError());
return 1;
}
}
CloseHandle(hEvent1);
CloseHandle(hEvent2);
break;
}
}
return 0;
}
int __cdecl
main(int argc, char **argv)
{
ULONG i;
HANDLE hServer;
ULONG status;
ParseArgv(argc, argv);
if ( (Options[0] < 0)
|| (Options[0] > 3)
|| (Options[1] < 0)
|| (Options[1] > 8) )
{
printf("Usage: %s : %s\n",
argv[0],
USAGE);
return 1;
}
if (Options[0] == 2)
{
// Server only - run server.
return Server(0);
}
if (Options[0] == 1)
{
// Both client and server, start server thread
hServer = CreateThread(0,
0,
(LPTHREAD_START_ROUTINE)Server,
0,
0,
&i);
if (hServer == 0)
{
printf("Create thread failed - %08x\n", GetLastError());
return 1;
}
Sleep(500); // Let the server startup
}
// Run client side
switch(Options[1])
{
case 1:
case 2:
{
// NT event pairs
OBJECT_ATTRIBUTES oaEventPair;
ANSI_STRING ansiEventPairName;
UNICODE_STRING unicodeEventPairName;
HANDLE hEventPair;
char * string =(Options[1]==1)?"eventpair":"eventpair (client set and wait)";
RtlInitAnsiString(&ansiEventPairName, EVENT_PAIR);
RtlAnsiStringToUnicodeString(&unicodeEventPairName,
&ansiEventPairName,
TRUE);
InitializeObjectAttributes(&oaEventPair,
&unicodeEventPairName,
OBJ_CASE_INSENSITIVE,
0,
0);
status = NtOpenEventPair(&hEventPair,
EVENT_PAIR_ALL_ACCESS,
&oaEventPair);
if (!NT_SUCCESS(status))
{
printf("NtOpenEventPair failed -- %8lX\n", status);
return 1;
}
StartTime();
if (Options[1] == 1)
{
for(i = 0; i < Iterations; i++)
{
NtSetHighWaitLowEventPair(hEventPair);
}
}
else
{
for(i = 0; i < Iterations; i++)
{
NtSetHighEventPair(hEventPair);
NtWaitLowEventPair(hEventPair);
}
}
EndTime(string);
break;
}
case 3:
case 4:
case 5:
case 6:
{
// Win32 events (w/ or w/o a timeout, WSO, WMO)
ULONG timeout;
char *string;
HANDLE hEvent1, hEvent2;
if ( (Options[1] == 4) || Options[1] == 6)
timeout = 2000;
else
timeout = INFINITE;
switch(Options[1])
{
case 3:
string = "SetEvent/WaitForSingleObject";
break;
case 4:
string = "SetEvent/WaitForSingleObject with timeout";
break;
case 5:
string = "SetEvent/WaitForMultpleObjects";
break;
case 6:
string = "SetEvent/WaitForMultipleObjects with timeout";
break;
}
hEvent1 = CreateEvent(0,
FALSE,
FALSE,
REQUEST_EVENT);
hEvent2 = CreateEvent(0,
FALSE,
FALSE,
REPLY_EVENT);
if ( (hEvent1 == 0) || (hEvent2 == 0))
{
printf("CreateEvent failed - %08x\n", GetLastError());
return 1;
}
StartTime();
for(i = 0; i < Iterations; i++)
{
status = SetEvent(hEvent1);
if (status == 0)
{
printf("SetEvent failed - %08x\n", GetLastError());
return 1;
}
status = WaitForSingleObject(hEvent2, timeout);
if (status != WAIT_OBJECT_0)
{
printf("WaitForSingleObejct failed -- %08x\n", GetLastError());
return 1;
}
}
EndTime(string);
CloseHandle(hEvent1);
CloseHandle(hEvent2);
break;
}
case 7:
case 8:
{
// Win32 events (w/ or w/o a timeout) and SignalObjectAndWait()
ULONG timeout;
char *string;
HANDLE hEvent1, hEvent2;
if ( (Options[1] == 8) )
timeout = 2000;
else
timeout = INFINITE;
switch(Options[1])
{
case 7:
string = "SignalObjectAndWait";
break;
case 8:
string = "SignalObjectAndWait with timeout";
break;
}
hEvent1 = CreateEvent(0,
FALSE,
FALSE,
REQUEST_EVENT);
hEvent2 = CreateEvent(0,
FALSE,
FALSE,
REPLY_EVENT);
if ( (hEvent1 == 0) || (hEvent2 == 0))
{
printf("CreateEvent failed - %08x\n", GetLastError());
return 1;
}
StartTime();
for(i = 0; i < Iterations; i++)
{
status = SignalObjectAndWait(hEvent1, hEvent2, timeout, FALSE);
if (status != WAIT_OBJECT_0)
{
printf("SignalObjectAndWait failed -- %08x\n", GetLastError());
return 1;
}
}
EndTime(string);
CloseHandle(hEvent1);
CloseHandle(hEvent2);
break;
}
}
// Blow off the server thread.
return 0;
}