#ifdef WIN32 #include #define delay(a) Sleep((a)) #else #define INCL_BASE #define INCL_DOSSEMAPHORES #include #define delay(a) DosSleep((a)) #endif #include #include #include #define MAX_THREADS 32 #ifdef WIN32 // // - hStartOfRace is a manual reset event that is signalled when // all of the threads are supposed to cut loose and begin working // // - hEndOfRace is a manual reset event that is signalled once the end time // has been retrieved and it is ok for the threads to exit // HANDLE hStartOfRace; HANDLE hEndOfRace; // // - ThreadReadyDoneEvents are an array of autoclearing events. The threads // initially signal these events once they have reached their start routines // and are ready to being processing. Once they are done processing, they // signal thier event to indicate that they are done processing. // // - ThreadHandles are an array of thread handles to the worker threads. The // main thread waits on these to know when all of the threads have exited. // HANDLE ThreadReadyDoneEvents[MAX_THREADS]; HANDLE ThreadHandles[MAX_THREADS]; DWORD WorkerThread(PVOID ThreadIndex); DWORD ThreadId; DWORD StartTicks, EndTicks; HANDLE IoHandle; #else /* // - hStartOfRace is a manual reset event that is signalled when // all of the threads are supposed to cut loose and begin working // // - hEndOfRace is a manual reset event that is signalled once the end time // has been retrieved and it is ok for the threads to exit */ HEV hStartOfRace; HEV hEndOfRace; /* // - ThreadReadyDoneEvents are an array of autoclearing events. The threads // initially signal these events once they have reached their start routines // and are ready to being processing. Once they are done processing, they // signal thier event to indicate that they are done processing. // // - ThreadHandles are an array of thread handles to the worker threads. The // main thread waits on these to know when all of the threads have exited. */ SEMRECORD ThreadReadyDoneEvents1[MAX_THREADS]; SEMRECORD ThreadReadyDoneEvents2[MAX_THREADS]; TID ThreadHandles[MAX_THREADS]; HMUX MuxWait1; HMUX MuxWait2; VOID WorkerThread(PVOID ThreadIndex); #pragma linkage(WorkerThread,system) #define _CRTAPI1 APIRET rv1, rv2; clock_t StartTicks, EndTicks; #define ExitProcess(a) DosExit(EXIT_PROCESS,(a)) #define GetTickCount clock HFILE IoHandle; HMTX MutexHandle; #endif #define SIXTY_FOUR_K (64*1024) #define SIXTEEN_K (16*1024) unsigned int InitialBuffer[SIXTY_FOUR_K/sizeof(unsigned int)]; #define NUMBER_OF_WRITES ((1024*1024*4)/SIXTY_FOUR_K) #define BUFFER_MAX (64*1024) #define FILE_SIZE ((1024*1024*4)-BUFFER_MAX) /* // Each thread has a THREAD_WORK structure. This contains the address // of the cells that this thread is responsible for, and the number of // cells it is supposed to process. */ typedef struct _THREAD_WORK { char ReadBuffer[BUFFER_MAX]; char SortedBuffer[BUFFER_MAX]; int KbytesTransfered; #ifdef WIN32 HANDLE SourceHandle; HANDLE DestinationHandle; #else HFILE SourceHandle; HFILE DestinationHandle; #endif } THREAD_WORK, *PTHREAD_WORK; THREAD_WORK ThreadWork[MAX_THREADS]; #define ONE_MB (1024*1024) unsigned long Mb = 4; int NumberOfThreads = 1; unsigned long ExpectedRecalcValue; unsigned long ActualRecalcValue; unsigned long ContentionValue; int fIoMode; int BufferSize; void SortTheBuffer( unsigned int *Destination, unsigned int *Source, int DwordCount ); unsigned int Random ( unsigned int nMaxValue ) { return(((2 * rand() * nMaxValue + RAND_MAX) / RAND_MAX - 1) / 2); } int _CRTAPI1 main( int argc, char *argv[], char *envp[] ) { int i; int fShowUsage; char c, *p, *whocares; unsigned long x; char fname[256]; ULONG ulAction; int iKb; double fDiff, fSec, fKb; fShowUsage = 0; BufferSize = 32 * 1024; if (argc <= 1) { goto showUsage; } while (--argc) { p = *++argv; if (*p == '/' || *p == '-') { while (c = *++p) switch (toupper( c )) { case '?': fShowUsage = 1; goto showUsage; break; case 'T': if (!argc--) { fShowUsage = 1; goto showUsage; } argv++; NumberOfThreads = strtoul(*argv,&whocares,10); if ( NumberOfThreads > MAX_THREADS ) { fShowUsage = 1; goto showUsage; } break; case 'B': if (!argc--) { fShowUsage = 1; goto showUsage; } argv++; BufferSize = strtoul(*argv,&whocares,10) * 1024; if ( BufferSize > BUFFER_MAX ) { BufferSize = BUFFER_MAX; } break; default: fprintf( stderr, "IOBNCH: Invalid switch - /%c\n", c ); goto showUsage; break; } } } showUsage: if ( fShowUsage ) { fprintf(stderr,"usage: IOBNCH\n" ); fprintf(stderr," [-?] display this message\n" ); fprintf(stderr," [-t n] use n threads for benchmark (less than 32)\n" ); fprintf(stderr," [-b n] use an n Kb buffer size (default 32kb\n" ); ExitProcess(1); } /* // Prepare the race events. These are manual reset events. */ #ifdef WIN32 hStartOfRace = CreateEvent(NULL,TRUE,FALSE,NULL); hEndOfRace = CreateEvent(NULL,TRUE,FALSE,NULL); if ( !hStartOfRace || !hEndOfRace ) { #else rv1 = DosCreateEventSem(NULL,&hStartOfRace,0,FALSE); rv2 = DosCreateEventSem(NULL,&hEndOfRace,0,FALSE); if ( rv1 || rv2 ) { #endif fprintf(stderr,"IOBNCH: Race Event Creation Failed\n"); ExitProcess(1); } /* // In I/O mode, we create a large file and fill it with random // values */ srand(1); #ifdef WIN32 DeleteFile("mtbnch.dat"); IoHandle = CreateFile( "mtbnch.dat", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if ( IoHandle == INVALID_HANDLE_VALUE ) { fprintf(stderr, "IOBNCH: Error opening file %d\n",GetLastError()); exit(1); } // // Initialize the file with random data // { DWORD lc; INT i; BOOL b; int WriteCount; for (WriteCount = 0; WriteCount < NUMBER_OF_WRITES; WriteCount++){ for(lc=0;lc