|
|
/*++
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; }
|