//++ // //Copyright (c) Microsoft Corporation // //Abstract: // //User Mode Client Test program for the LPC subcomponent of the NTOS project // //-- // // Read the processor's time stamp counter register // #include "ulpc.h" _inline _declspec( naked ) UINT64 RDTSC() { __asm { rdtsc; ret; } } #define GetCycleCount() RDTSC() #define BENCH_ITERATIONS 10000 #define MAX_CLIENT_PROCESSES 9 #define MAX_CLIENT_THREADS 9 CHAR ProcessName[ 32 ]; HANDLE PortHandle = NULL; HANDLE ClientThreadHandles[ MAX_CLIENT_THREADS ] = {NULL}; DWORD ClientThreadClientIds[ MAX_CLIENT_THREADS ]; DWORD ClientThread( LPVOID Context ) { CHAR ThreadName[ 64 ]; NTSTATUS Status = STATUS_SUCCESS; ULONG MsgLength; PTEB Teb = NtCurrentTeb(); ULONG64 startCount, endCount; INT i; Teb->ActiveRpcHandle = NULL; strcpy( ThreadName, "Client Thread Id: " ); RtlIntegerToChar( (ULONG)Teb->ClientId.UniqueProcess, 16, 9, ThreadName + strlen( ThreadName ) ); strcat( ThreadName, "." ); RtlIntegerToChar( (ULONG)Teb->ClientId.UniqueThread, 16, 9, ThreadName + strlen( ThreadName ) ); EnterThread( ThreadName, (ULONG)Context ); MsgLength = 0; while (NT_SUCCESS( Status )) { startCount = GetCycleCount(); for (i = 0; i < BENCH_ITERATIONS; i++) { Status = SendRequest( 1, ThreadName, PortHandle, Context, MsgLength, NULL, FALSE ); if (!NT_SUCCESS( Status )) { fprintf(stderr, "FAILED %d\n", i); break; } } endCount = GetCycleCount(); fprintf(stdout, "Message Bytes %d Iterations %d Cycles %I64d Cycles/Iteration %I64d\n", MsgLength, BENCH_ITERATIONS, (endCount - startCount), (endCount - startCount) / BENCH_ITERATIONS); MsgLength += sizeof( ULONG ); if (MsgLength >= (TLPC_MAX_MSG_DATA_LENGTH * sizeof( ULONG ))) { break; } } if (PortHandle != NULL) { if (!CloseHandle( PortHandle )) { fprintf( stderr, "CloseHandle( 0x%lx ) failed - %u\n", PortHandle, GetLastError() ); } else { PortHandle = NULL; } } fprintf( stderr, "%s %s\n", NT_SUCCESS( Status ) ? "Exiting" : "ABORTING", ThreadName ); return RtlNtStatusToDosError( Status ); } VOID Usage( VOID ) { fprintf( stderr, "usage: UCLIENT ClientNumber [#threads]\n" ); ExitProcess( 1 ); } int _cdecl main( int argc, char *argv[] ) { NTSTATUS Status; DWORD rc; PORT_VIEW ClientView; REMOTE_PORT_VIEW ServerView; ULONG ClientNumber; ULONG NumberOfThreads; ULONG MaxMessageLength; ULONG ConnectionInformationLength; UCHAR ConnectionInformation[ 64 ]; ULONG i; PULONG p; PTEB Teb = NtCurrentTeb(); LARGE_INTEGER MaximumSize; Status = STATUS_SUCCESS; fprintf( stderr, "Entering UCLIENT User Mode LPC Test Program\n" ); if (argc < 2) { Usage(); } ClientNumber = xatoi( argv[ 1 ] ); if (argc < 3) { NumberOfThreads = 1; } else { NumberOfThreads = xatoi( argv[ 2 ] ); } if (ClientNumber > MAX_CLIENT_PROCESSES || NumberOfThreads > MAX_CLIENT_THREADS ) { Usage(); } sprintf( ProcessName, "Client Process %08x", Teb->ClientId.UniqueProcess ); strcpy( ConnectionInformation, ProcessName ); ConnectionInformationLength = strlen( ProcessName ) + 1; RtlInitUnicodeString( &PortName, PORT_NAME ); fprintf( stderr, "Creating Port Memory Section" ); MaximumSize.QuadPart = 0x4000 * NumberOfThreads; Status = NtCreateSection( &ClientView.SectionHandle, SECTION_MAP_READ | SECTION_MAP_WRITE, NULL, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, NULL ); if (ShowHandleOrStatus( Status, ClientView.SectionHandle )) { ClientView.Length = sizeof( ClientView ); ClientView.SectionOffset = 0; ClientView.ViewSize = 0x2000; ClientView.ViewBase = 0; ClientView.ViewRemoteBase = 0; ServerView.Length = sizeof( ServerView ); ServerView.ViewSize = 0; ServerView.ViewBase = 0; fprintf( stderr, "%s calling NtConnectPort( %wZ )\n", ProcessName, &PortName ); Status = NtConnectPort( &PortHandle, &PortName, &DynamicQos, &ClientView, &ServerView, (PULONG)&MaxMessageLength, (PVOID)ConnectionInformation, (PULONG)&ConnectionInformationLength ); if (ShowHandleOrStatus( Status, PortHandle )) { fprintf( stderr, " MaxMessageLength: %ld\n", MaxMessageLength ); fprintf( stderr, " ConnectionInfo: (%ld) '%.*s'\n", ConnectionInformationLength, ConnectionInformationLength, (PSZ)&ConnectionInformation[0] ); fprintf( stderr, " ClientView: Base=%lx, Size=%lx, RemoteBase: %lx\n", ClientView.ViewBase, ClientView.ViewSize, ClientView.ViewRemoteBase ); fprintf( stderr, " ServerView: Base=%lx, Size=%lx\n", ServerView.ViewBase, ServerView.ViewSize ); ClientMemoryBase = ClientView.ViewBase; ClientMemorySize = ClientView.ViewSize; ServerMemoryBase = ClientView.ViewRemoteBase; ServerMemoryDelta = (ULONG)ServerMemoryBase - (ULONG)ClientMemoryBase; p = (PULONG)ClientMemoryBase; i = ClientMemorySize; while (i) { fprintf( stderr, "ClientView[%lx] == %lx (%lx)\n", p, *p, *p - ServerMemoryDelta ); p += (0x1000/sizeof( ULONG )); i -= 0x1000; } p = (PULONG)ServerView.ViewBase; i = ServerView.ViewSize; while (i) { fprintf( stderr, "ServerView[%lx] == %lx\n", p, *p ); p += (0x1000/sizeof( ULONG )); i -= 0x1000; } } } rc = RtlNtStatusToDosError( Status ); if (rc == NO_ERROR) { ClientThreadHandles[ 0 ] = GetCurrentThread(); ClientThreadClientIds[ 0 ] = GetCurrentThreadId(); for (i=1; i< NumberOfThreads; i++) { fprintf( stderr, "Creating %s, Thread %ld\n", ProcessName, i+1 ); rc = NO_ERROR; ClientThreadHandles[ i ] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ClientThread, (LPVOID)((ClientNumber << 4) | (i+1)), CREATE_SUSPENDED, &ClientThreadClientIds[ i ] ); if (ClientThreadHandles[ i ] == NULL) { rc = GetLastError(); break; } } if (rc == NO_ERROR) { for (i=1; i