blob: ce6c6570ef1b2fc5464acc1a575b55cfd98d8db9 [file] [log] [blame]
/*
* File Name: timer.c
* Purpose: Provides timing routines for the DIS Data Management
* Benchmark application. Preprocessor directives are setup to
* allow either the ANSI/ISO C standard time() routine to be
* used or the BSD Unix gettimeofday() routine to be used. The
* gettimeofday() routine has a fidelity of microseconds while
* the ANSI/ISO time() routine is only seconds. The Data
* Management baseline data sets will generally require a
* better timing resolution than seconds, but nothing exists
* within the ANSI/ISO C standard which provides the required
* fidelity. Because the DIS hardware teams are only required
* to conform to the ANSI/ISO C standard libraries and this
* will cause inaccuracies in the metric statistics, a
* compromise is implemented. If USE_GETTIMEOFDAY is defined
* (not TRUE/FALSE, just defined), the metrics will use the
* Unix standard gettimeofday() promoting the microseconds to
* milliseconds to allow storage in a long integer. If
* USE_GETTIMEOFDAY is not defined, the metrics will use the
* ANSI/ISO C standard time() routine. This will generally
* invalidate the metric statistical values for individual
* commands, but may provide a relatively accurate overall
* time required to complete the data set.
*
* Modifications required to run the program on different
* hardware systems with different system timing routines
* should only need to change this function. As long as the
* getTime() routine returns milliseconds from program start,
* the rest of the baseline source code should function
* correctly.
*
* Revision History:
* Date Name Revision
* ------- --------------- ------------------------------
* 27May99 Matthew Rivas Created
* 04Jun99 Matthew Rivas Added SECONDS_TO_MILLI to ANSI/ISO C standard ver.
*
* Copyright 1999, Atlantic Aerospace Electronics Corp.
*/
#ifdef USE_GETTIMEOFDAY
#include <sys/time.h> /* for timeval definition */
#include <unistd.h> /* for gettimeofday() definition */
#include "errorMessage.h" /* for errorMessage() definition */
#else /* USE_GETTIMEOFDAY undefined */
#include <time.h> /* for time() definition */
#endif /* USE_GETTIMEOFDAY */
#include <assert.h> /* for assert() */
#include "dataManagement.h" /* for primitive type definitions */
#include "metrics.h" /* for Time type definition */
/*
* Static value of program start time
* - value is stored as timeval returned by gettimeofday()
* - timeval struct represents the time in seconds and microseconds since
* Jan 1, 1970.
* - don't use structure because difficulty in working with two longs for
* statistical calcs and milliseconds will suffice for timing fidelity.
*/
#ifdef USE_GETTIMEOFDAY
static struct timeval startTime;
#define MILLION 1000000
#define MILLION_TO_MILLI 1e-3
#define SECONDS_TO_MILLI 1000
#else
static time_t startTime;
#define SECONDS_TO_MILLI 1000
#endif /* USE_GETTIMEOFDAY */
/*
* Name: initTime
* Input: none
* Output: none
* Return: void
* Description: Initialize the static startTime variable which will be used
* by getTime() to return time in milliseconds since program
* start, i.e., when the initTime() routine was called.
* Calls: errorMessage()
* System: gettimeofday(), or
* time()
* Author: M.L.Rivas
*
* Revision History:
*
* Date Name Revision
* ------- --------------- ------------------------------
* 27May99 Matthew Rivas Created
*
* Copyright 1999, Atlantic Aerospace Electronics Corp.
*/
void initTime( void )
{ /* beginning of initTime() */
#ifdef USE_GETTIMEOFDAY
Int error; /* flag for error checking on gettimeofday() */
static Char name[] = "initTime";
#endif /* USE_GETTIMEOFDAY */
#ifdef USE_GETTIMEOFDAY
error = gettimeofday( &startTime, NULL );
if ( error == -1 ) { /* check for error */
errorMessage( "system time failure - can't set start time", REPLACE );
errorMessage( name, PREPEND );
flushErrorMessage();
} /* end of if error == -1 */
/*
* Check that seconds and microseconds from Jan 1, 1970 are positive, and
* that the microseconds value is less than a million, otherwise the
* seconds would have been incremented.
*/
assert( startTime.tv_sec >= 0 && \
startTime.tv_usec >= 0 && \
startTime.tv_usec < MILLION );
#else /* USE_GETTIMEOFDAY undefined */
startTime = time( NULL );
#endif /* USE_GETTIMEOFDAY */
return;
} /* end of initTime() */
/*
* Name: getTime
* Input: none
* Output: milliseconds since program start
* Return: Time
* Description: The routine provides a wrapper for the system timing
* routines and returns the current time in milliseconds from
* the beginning of program execution, i.e., when initTime()
* routine was called. The routine is setup to be compiled
* using the gettimeofday() routine or the ANSI/ISO standard
* time() routine.
* Calls: errorMessage()
* System: gettimeofday(), or
* difftime()
* time()
* Author: M.L.Rivas
*
* Revision History:
*
* Date Name Revision
* ------- --------------- ------------------------------
* 27May99 Matthew Rivas Created
*
* Copyright 1999, Atlantic Aerospace Electronics Corp.
*/
Time getTime( void )
{ /* beginning of getTime() */
Time currentTime; /* current time in milliseconds */
#ifdef USE_GETTIMEOFDAY
Int error; /* flag for checking on gettimeofday() */
struct timeval temp; /* current time returned by gettimeofday() */
static Char name[] = "getTime";
#else /* USE_GETTIMEOFDAY undefined */
time_t temp; /* current time returned by time() */
#endif /* USE_GETTIMEOFDAY */
#ifdef USE_GETTIMEOFDAY
/*
* Check that seconds and microseconds from Jan 1, 1970 are positive, and
* that the microseconds value is less than a million, otherwise the
* seconds would have been incremented.
*/
assert( startTime.tv_sec >= 0 && \
startTime.tv_usec >= 0 && \
startTime.tv_usec < MILLION );
/*
* Get the current time and store in temp. Check for error, an if none,
* calculate difference in milliseconds between current time and startTime.
*/
error = gettimeofday( &temp, NULL );
if ( error == -1 ) { /* check for error */
errorMessage( "system time failure - can't get time", REPLACE );
errorMessage( name, PREPEND );
flushErrorMessage();
currentTime = MINIMUM_VALUE_OF_INT;
} /* end of if error == -1 */
else {
/*
* Check that seconds and microseconds from Jan 1, 1970 are positive,
* and that the microseconds value is less than a million, otherwise
* the seconds would have been incremented.
*/
assert( temp.tv_sec >= 0 && \
temp.tv_usec >= 0 && \
temp.tv_usec < MILLION );
/*
* The current time must be later than the start time for the time
* difference arithmetic to work properly.
*/
assert( temp.tv_sec > startTime.tv_sec || \
( temp.tv_sec == startTime.tv_sec && \
temp.tv_usec >= startTime.tv_usec ) );
/*
* Determine milliseconds conversion of difference between the current
* time, temp, and the start time, startTime. Because 0 <= usec <
* MILLION and it is assumed that the current time is later than the
* start time, only two cases exist for the conversion. The first is
* that the current time microseconds are greater than the start time
* microseconds. For this case, the current time in milliseconds is
* the sum of the seconds difference and the microseconds difference
* with the appropriate conversion factors, i.e., SECONDS_TO_MILLI =
* 1000 and MILLION_TO_MILLI = 1e-3. The second case is that the
* current time microseconds is less than the start time microseconds.
* For this case, the current time in milliseconds is the sum of the
* seconds difference minus one and the microseconds difference plus a
* MILLION with the appropriate conversion factors. Note that the
* minus one to the seconds difference and plus a MILLION to the
* microseconds, is the carry, i.e., a second was taken from the
* seconds place and added to the microseconds place.
*/
if ( temp.tv_usec >= startTime.tv_usec ) {
currentTime = SECONDS_TO_MILLI * ( temp.tv_sec - startTime.tv_sec );
currentTime += MILLION_TO_MILLI * ( temp.tv_usec - startTime.tv_usec );
} /* end of temp.usec >= start.usec */
else {
currentTime = SECONDS_TO_MILLI
* ( temp.tv_sec - startTime.tv_sec - 1 );
currentTime += MILLION_TO_MILLI
* ( temp.tv_usec - startTime.tv_usec + MILLION );
} /* end of temp.usec < start.usec */
/*
* Check for overflow of negative time difference, both of which should
* never happen since the system call should ensure non-negative
* differences and the maximum value for a time difference using
* milliseconds is 49.71 days.
*/
if ( currentTime > MAXIMUM_VALUE_OF_INT ) {
errorMessage( "overflow error calculating current time", REPLACE );
errorMessage( name, PREPEND );
flushErrorMessage();
currentTime = MAXIMUM_VALUE_OF_INT;
} /* end of upper bound check on currentTime */
else if ( currentTime < 0 ) {
errorMessage( "start time appears not to be set", REPLACE );
errorMessage( name, PREPEND );
flushErrorMessage();
currentTime = 0;
} /* end of lower bound check on currentTime */
} /* end of if error != -1 */
#else /* USE_GETTIMEOFDAY undefined */
/*
* Get the current time, determine the difference in seconds since
* the start time, convert seconds to milliseconds, and set current
* time to correct value.
*/
temp = time( NULL );
currentTime = SECONDS_TO_MILLI * (Int)difftime( temp, startTime );
#endif /* USE_GETTIMEOFDAY */
return ( currentTime );
} /* end of getTime() */