286 lines
8.5 KiB
C
286 lines
8.5 KiB
C
|
//++
|
||
|
//
|
||
|
//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<NumberOfThreads; i++) {
|
||
|
ResumeThread( ClientThreadHandles[ i ] );
|
||
|
}
|
||
|
|
||
|
ClientThread( (LPVOID)((ClientNumber << 4) | 1) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (rc == NO_ERROR) {
|
||
|
}
|
||
|
else {
|
||
|
fprintf( stderr, "UCLIENT: Initialization Failed - %u\n", rc );
|
||
|
ExitProcess( rc );
|
||
|
}
|
||
|
|
||
|
return( rc );
|
||
|
}
|