This repository has been archived on 2024-12-16. You can view files and clone it, but cannot push or open issues or pull requests.
CodeBlocksPortable/WATCOM/samples/os2/pdd/hrtest.c

298 lines
13 KiB
C

/*================================================================\
| |
| 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 <os2.h>
#include <stdio.h>
#include <stdlib.h>
#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 );
}
}
}