/*================================================================\ | | | OS/2 Physical Device Driver Demonstration Code | | for Open Watcom C/C++ | | | | HRTEST.C | | | | This program is an Open Watcom C skeleton for using | | HRTIMER.SYS, the high-resolution timer Physical Device Driver | | (PDD) for OS/2 | | | | Adapted for Open Watcom C/C++ | | Original Author: Rick Fishman | | Code Blazers, Inc. | | 4113 Apricot | | Irvine, CA 92720 | | | | Command Line: hrtest [milliseconds] | | | | milliseconds is the amount of time that this test program | | will sleep for between calls to the timer. A default is | | provided if no parameter is given. | | | | A start timestamp will be retrieved from HRTIMER.SYS. Then | | DosSleep will be issued for the milliseconds specified. Then | | a stop timestamp will be retrieved and an elapsed time | | calculated. The elapsed time should be close to the DosSleep | | interval. Keep in mind that DosSleep has a granularity of 32 | | milliseconds so a discrepency of elapsed time vs | | milliseconds passed to DosSleep is DosSleep's fault, not the | | timer's. | | | | The overhead of a device driver read is also factored in. | | | \================================================================*/ /*********************************************************************/ /*------- Include relevant sections of the OS/2 header files --------*/ /*********************************************************************/ #define INCL_DOSFILEMGR #define INCL_DOSPROCESS /*********************************************************************/ /*------------------- APPLICATION DEFINITIONS -----------------------*/ /*********************************************************************/ #define DEFAULT_TIME_PERIOD 5000 // in Milliseconds /**********************************************************************/ /*----------------------------- INCLUDES -----------------------------*/ /**********************************************************************/ #include #include #include #include "hrtimer.h" /**********************************************************************/ /*---------------------------- STRUCTURES ----------------------------*/ /**********************************************************************/ /**********************************************************************/ /*----------------------- FUNCTION PROTOTYPES ------------------------*/ /**********************************************************************/ BOOL Initialize ( int argc, char *argv[] ); VOID TimeIt ( VOID ); ULONG CalcElapsedTime( PTIMESTAMP ptsStart, PTIMESTAMP ptsStop, ULONG ulOvHdMs, ULONG ulOvHdNs, PULONG pulNs ); VOID Terminate ( VOID ); /**********************************************************************/ /*------------------------ GLOBAL VARIABLES --------------------------*/ /**********************************************************************/ HFILE hfTimer; ULONG ulOverheadMs, ulOverheadNs, ulTimePeriod; /**********************************************************************/ /*------------------------------ MAIN --------------------------------*/ /* */ /* MAIN DRIVER FOR PROGRAM. */ /* */ /* INPUT: nothing */ /* */ /* 1. Initialize program. */ /* 1. Perform timings. */ /* 1. Terminage program. */ /* */ /* OUTPUT: nothing */ /*--------------------------------------------------------------------*/ /**********************************************************************/ int main( int argc, char *argv[] ) { if( Initialize( argc, argv ) ) TimeIt(); Terminate(); return( 0 ); } /**********************************************************************/ /*--------------------------- Initialize -----------------------------*/ /* */ /* INITIALIZE PROGRAM. */ /* */ /* INPUT: command-line argument count, */ /* array of command-line arguments */ /* */ /* 1. Set the time period that we will try to match with the high */ /* resolution timer. */ /* 2. Open the timer device driver. */ /* 3. Read a timestamp from the driver to use as a starting time */ /* used to calculate the overhead of a device-driver read. */ /* 4. Read a timestamp from the driver to use as a stop time for */ /* the overhead calculation. */ /* 5. Calculate the overhead in the read. */ /* */ /* OUTPUT: TRUE or FALSE if successful or not */ /* */ /*--------------------------------------------------------------------*/ /**********************************************************************/ BOOL Initialize( int argc, char *argv[] ) { TIMESTAMP tsStart, tsStop; ULONG ulRC, ulAction, ulBytes; if( argc < 2 ) ulTimePeriod = DEFAULT_TIME_PERIOD; else ulTimePeriod = atoi( argv[ 1 ] ); printf( "\nMeasuring a DosSleep of %u milliseconds\n", ulTimePeriod ); ulRC = DosOpen( "WTIMER$", &hfTimer, &ulAction, 0, FILE_NORMAL, FILE_OPEN, OPEN_SHARE_DENYNONE, NULL ); if( ulRC ) { printf( "\nFailed to open WTIMER$" ); printf( "\nDosOpen got a retcode of %u", ulRC ); return FALSE; } ulRC = DosRead( hfTimer, &tsStart, sizeof( TIMESTAMP ), &ulBytes ); if( ulRC ) { printf( "\nDosRead for start got a retcode of %u", ulRC ); return FALSE; } ulRC = DosRead( hfTimer, &tsStop, sizeof( TIMESTAMP ), &ulBytes ); if( ulRC ) { printf( "\nDosRead for stop got a retcode of %u", ulRC ); return FALSE; } printf( "\nWTIMER$ Version %u.%u\n", tsStop.version, tsStop.revision ); ulOverheadMs = CalcElapsedTime( &tsStart, &tsStop, 0, 0, &ulOverheadNs ); printf( "\nOverhead (ms:ns) = %06u:%06u\n", ulOverheadMs, ulOverheadNs ); return TRUE; } /**********************************************************************/ /*----------------------------- TimeIt -------------------------------*/ /* */ /* DO THE TIMING. */ /* */ /* INPUT: nothing */ /* */ /* 1. Until Ctrl-Break is pressed: */ /* A. Read a starting timestamp from the timer. */ /* B. Sleep for a specified period of time. */ /* C. Read a stop timestamp from the timer. */ /* D. Calculate the elapsed time. */ /* */ /* OUTPUT: nothing */ /* */ /*--------------------------------------------------------------------*/ /**********************************************************************/ VOID TimeIt() { TIMESTAMP tsStart, tsStop; ULONG ulRC, ulMsecs, ulNsecs, ulBytes; printf( "\nHit Ctrl-C to terminate this test program...\n" ); for( ; ; ) { printf( "\nSleeping for %u milliseconds...", ulTimePeriod ); fflush( stdout ); ulRC = DosRead( hfTimer, &tsStart, sizeof( TIMESTAMP ), &ulBytes ); if( ulRC ) { printf( "\nDosRead for start got a retcode of %u", ulRC ); return; } DosSleep( ulTimePeriod ); ulRC = DosRead( hfTimer, &tsStop, sizeof( TIMESTAMP ), &ulBytes ); if( ulRC ) { printf( "\nDosRead for stop got a retcode of %u", ulRC ); return; } ulMsecs = CalcElapsedTime( &tsStart, &tsStop, ulOverheadMs, ulOverheadNs, &ulNsecs ); printf( " elapsed time (ms:ns) = %06u:%06u", ulMsecs, ulNsecs ); } } /**********************************************************************/ /*------------------------- CalcElapsedTime --------------------------*/ /* */ /* CALCULATE ELAPSED TIME GIVEN TWO TIMESTAMPS */ /* */ /* INPUT: pointer to Start timestamp structure, */ /* pointer to Stop timestamp structure, */ /* number of overhead milliseconds, */ /* number of overhead nanoseconds, */ /* address of variable to return remainder nanoseconds */ /* */ /* OUTPUT: Number of elapsed milliseconds */ /* */ /*--------------------------------------------------------------------*/ /**********************************************************************/ ULONG CalcElapsedTime( PTIMESTAMP ptsStart, PTIMESTAMP ptsStop, ULONG ulOverhdMs, ULONG ulOverhdNs, PULONG pulNs ) { ULONG ulMsecs, ulNsecs; TIMESTAMP tsStart, tsStop; // De-reference timestamp structures for speed tsStart = *ptsStart; tsStop = *ptsStop; // Calculate elapsed milliseconds ulMsecs = tsStop.millisecs - tsStart.millisecs; // If nanosecond overflow ... if( tsStart.nanosecs > tsStop.nanosecs ) { // Adjust nanoseconds by adding in 1 millisecond ulNsecs = (1000000 + tsStop.nanosecs) - tsStart.nanosecs; // Adjust milliseconds down by 1 ulMsecs--; } else { // No overflow so calculate elapsed nanoseconds ulNsecs = tsStop.nanosecs - tsStart.nanosecs; } // If caller wants overhead factored in ... if( ulOverhdMs || ulOverhdNs ) { if( ulOverhdNs > ulNsecs ) { ulNsecs = (1000000 + ulNsecs) - ulOverhdNs; ulMsecs--; } else { ulNsecs -= ulOverhdNs; } ulMsecs -= ulOverhdMs; } *pulNs = ulNsecs; return( ulMsecs ); } /**********************************************************************/ /*--------------------------- Terminate ------------------------------*/ /* */ /* TERMINATE PROGRAM */ /* */ /* INPUT: nothing */ /* */ /* 1. Close the device driver. */ /* */ /* OUTPUT: nothing */ /* */ /*--------------------------------------------------------------------*/ /**********************************************************************/ VOID Terminate() { ULONG ulRC; if( hfTimer ) { ulRC = DosClose( hfTimer ); if( ulRC ) { printf( "\nDosClose got a retcode of %u", ulRC ); } } }