use high precision timers

This commit is contained in:
Jeff Hill
1998-07-07 22:43:26 +00:00
parent a8dfe7b4f4
commit 17d233c2d7
3 changed files with 205 additions and 142 deletions

View File

@@ -1,24 +1,13 @@
#include <math.h>
#include <time.h>
#include <winsock2.h>
#include <mmsystem.h>
#define epicsExportSharedSymbols
#include <osiTime.h>
/*
* This code is mainly adapted form Chris Timossi's windows_depen.c
*
* 8-2-96 -kuk-
*/
/* offset from timeGetTime() to 1970 */
static unsigned long offset_secs;
static DWORD prev_time = 0;
static UINT res;
static char init = 0;
static long offset_time_s = 0; /* time diff (sec) from 1990 when EPICS started */
static LARGE_INTEGER time_prev, time_freq;
/*
* init_osi_time has to be called before using the timer,
@@ -26,40 +15,29 @@ static char init = 0;
*/
int init_osi_time ()
{
TIMECAPS tc;
if (init) {
return 1;
if (offset_time_s == 0) {
/*
* initialize elapsed time counters
*
* All CPUs running win32 currently have HR
* counters (Intel and Mips processors do)
*/
if (QueryPerformanceCounter (&time_prev)==0) {
return 1;
}
if (QueryPerformanceFrequency (&time_freq)==0) {
return 1;
}
offset_time_s = (long)time(NULL) -
(long)(time_prev.QuadPart/time_freq.QuadPart);
}
if (timeGetDevCaps (&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR)
{
fprintf (stderr, "init_osi_time: cannot get timer info\n");
return 1;
}
/* set for 1 ms resoulution */
res = min(max(tc.wPeriodMin, 1), tc.wPeriodMax);
if (timeBeginPeriod (res) != TIMERR_NOERROR)
{
fprintf(stderr,"timer setup failed\n");
return 2;
}
prev_time = timeGetTime();
offset_secs = (long)time(NULL) - (long)prev_time/1000;
init = 1;
return 0;
}
int exit_osi_time ()
{
if (!init) {
return 0;
}
timeEndPeriod (res);
init = 0;
offset_time_s = 0;
return 0;
}
@@ -70,31 +48,61 @@ int exit_osi_time ()
//
osiTime osiTime::getCurrent ()
{
unsigned long now;
LARGE_INTEGER time_cur, time_sec, time_remainder;
unsigned long sec, nsec;
/*
* this allows the code to work when it is in an object
* library (in addition to inside a dll)
*/
if (!init) {
if (offset_time_s==0) {
init_osi_time();
init = 1;
}
/* MS Online help:
* Note that the value returned by the timeGetTime function is
* a DWORD value. The return value wraps around to
* 0 every 2^32 milliseconds, which is about 49.71 days.
/*
* dont need to check status since it was checked once
* during initialization to see if the CPU has HR
* counters (Intel and Mips processors do)
*/
QueryPerformanceCounter (&time_cur);
if (time_prev.QuadPart > time_cur.QuadPart) { /* must have been a timer roll-over */
double offset;
/*
* must have been a timer roll-over
* It takes 9.223372036855e+18/time_freq sec
* to roll over this counter (time_freq is 1193182
* sec on my system). This is currently about 245118 years.
*
* attempt to add number of seconds in a 64 bit integer
* in case the timer resolution improves
*/
offset = pow(2.0, 63.0)-1.0/time_freq.QuadPart;
if (offset<=LONG_MAX-offset_time_s) {
offset_time_s += (long) offset;
}
else {
/*
* this problem cant be fixed, but hopefully will never occurr
*/
fprintf (stderr, "%s.%d Timer overflowed\n", __FILE__, __LINE__);
return osiTime (0, 0);
}
}
time_sec.QuadPart = time_cur.QuadPart / time_freq.QuadPart;
time_remainder.QuadPart = time_cur.QuadPart % time_freq.QuadPart;
if (time_sec.QuadPart > LONG_MAX-offset_time_s) {
/*
* this problem cant be fixed, but hopefully will never occurr
*/
fprintf (stderr, "%s.%d Timer value larger than storage\n", __FILE__, __LINE__);
return osiTime (0, 0);
}
// get millisecs, timeGetTime gives DWORD
now = timeGetTime ();
if (prev_time > now) /* looks like a DWORD overflow */
offset_secs += 4294967ul; /* 0x100000000 / 1000 */
prev_time = now;
/* add time (sec) since 1970 */
sec = offset_time_s + (long)time_sec.QuadPart;
nsec = (long)((time_remainder.QuadPart*1000000000)/time_freq.QuadPart);
// compute secs and nanosecs from millisecs:
return osiTime (now / 1000ul + offset_secs, (now % 1000ul) * 1000000ul);
time_prev = time_cur;
return osiTime (sec, nsec);
}

View File

@@ -1,24 +1,13 @@
#include <math.h>
#include <time.h>
#include <winsock2.h>
#include <mmsystem.h>
#define epicsExportSharedSymbols
#include <osiTime.h>
/*
* This code is mainly adapted form Chris Timossi's windows_depen.c
*
* 8-2-96 -kuk-
*/
/* offset from timeGetTime() to 1970 */
static unsigned long offset_secs;
static DWORD prev_time = 0;
static UINT res;
static char init = 0;
static long offset_time_s = 0; /* time diff (sec) from 1990 when EPICS started */
static LARGE_INTEGER time_prev, time_freq;
/*
* init_osi_time has to be called before using the timer,
@@ -26,40 +15,29 @@ static char init = 0;
*/
int init_osi_time ()
{
TIMECAPS tc;
if (init) {
return 1;
if (offset_time_s == 0) {
/*
* initialize elapsed time counters
*
* All CPUs running win32 currently have HR
* counters (Intel and Mips processors do)
*/
if (QueryPerformanceCounter (&time_prev)==0) {
return 1;
}
if (QueryPerformanceFrequency (&time_freq)==0) {
return 1;
}
offset_time_s = (long)time(NULL) -
(long)(time_prev.QuadPart/time_freq.QuadPart);
}
if (timeGetDevCaps (&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR)
{
fprintf (stderr, "init_osi_time: cannot get timer info\n");
return 1;
}
/* set for 1 ms resoulution */
res = min(max(tc.wPeriodMin, 1), tc.wPeriodMax);
if (timeBeginPeriod (res) != TIMERR_NOERROR)
{
fprintf(stderr,"timer setup failed\n");
return 2;
}
prev_time = timeGetTime();
offset_secs = (long)time(NULL) - (long)prev_time/1000;
init = 1;
return 0;
}
int exit_osi_time ()
{
if (!init) {
return 0;
}
timeEndPeriod (res);
init = 0;
offset_time_s = 0;
return 0;
}
@@ -70,31 +48,61 @@ int exit_osi_time ()
//
osiTime osiTime::getCurrent ()
{
unsigned long now;
LARGE_INTEGER time_cur, time_sec, time_remainder;
unsigned long sec, nsec;
/*
* this allows the code to work when it is in an object
* library (in addition to inside a dll)
*/
if (!init) {
if (offset_time_s==0) {
init_osi_time();
init = 1;
}
/* MS Online help:
* Note that the value returned by the timeGetTime function is
* a DWORD value. The return value wraps around to
* 0 every 2^32 milliseconds, which is about 49.71 days.
/*
* dont need to check status since it was checked once
* during initialization to see if the CPU has HR
* counters (Intel and Mips processors do)
*/
QueryPerformanceCounter (&time_cur);
if (time_prev.QuadPart > time_cur.QuadPart) { /* must have been a timer roll-over */
double offset;
/*
* must have been a timer roll-over
* It takes 9.223372036855e+18/time_freq sec
* to roll over this counter (time_freq is 1193182
* sec on my system). This is currently about 245118 years.
*
* attempt to add number of seconds in a 64 bit integer
* in case the timer resolution improves
*/
offset = pow(2.0, 63.0)-1.0/time_freq.QuadPart;
if (offset<=LONG_MAX-offset_time_s) {
offset_time_s += (long) offset;
}
else {
/*
* this problem cant be fixed, but hopefully will never occurr
*/
fprintf (stderr, "%s.%d Timer overflowed\n", __FILE__, __LINE__);
return osiTime (0, 0);
}
}
time_sec.QuadPart = time_cur.QuadPart / time_freq.QuadPart;
time_remainder.QuadPart = time_cur.QuadPart % time_freq.QuadPart;
if (time_sec.QuadPart > LONG_MAX-offset_time_s) {
/*
* this problem cant be fixed, but hopefully will never occurr
*/
fprintf (stderr, "%s.%d Timer value larger than storage\n", __FILE__, __LINE__);
return osiTime (0, 0);
}
// get millisecs, timeGetTime gives DWORD
now = timeGetTime ();
if (prev_time > now) /* looks like a DWORD overflow */
offset_secs += 4294967ul; /* 0x100000000 / 1000 */
prev_time = now;
/* add time (sec) since 1970 */
sec = offset_time_s + (long)time_sec.QuadPart;
nsec = (long)((time_remainder.QuadPart*1000000000)/time_freq.QuadPart);
// compute secs and nanosecs from millisecs:
return osiTime (now / 1000ul + offset_secs, (now % 1000ul) * 1000000ul);
time_prev = time_cur;
return osiTime (sec, nsec);
}

View File

@@ -118,6 +118,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#define INC_tsDefs_h
#if defined(vxWorks)
@@ -130,7 +131,6 @@
#elif defined(_WIN32)
# include <winsock2.h>
# include <time.h>
# include <mmsystem.h>
#else
# include <sys/time.h>
#endif
@@ -670,41 +670,88 @@ long epicsShareAPI tsLocalTime(TS_STAMP *pStamp)
# if defined(vxWorks)
retStat = TScurrentTimeStamp((struct timespec*)pStamp);
if (retStat == 0) {
return S_ts_OK;
return S_ts_OK;
}
else {
return S_ts_sysTimeError;
return S_ts_sysTimeError;
}
# elif defined(_WIN32)
DWORD win_sys_time_ms; /* time (ms) since windows started */
static DWORD prev_time_ms; /* time (ms) of previous call */
static long start_time_s=0; /* time (sec) from 1990 when windows started */
static long offset_time_s = 0; /* time diff (sec) from 1990 when EPICS started */
static LARGE_INTEGER time_prev, time_freq;
LARGE_INTEGER time_cur, time_sec, time_remainder;
if (start_time_s == 0) {
prev_time_ms = timeGetTime();
start_time_s = time(NULL)
- TS_EPOCH_SEC_PAST_1970 - (long)prev_time_ms/1000;
}
win_sys_time_ms = timeGetTime();
if (prev_time_ms > win_sys_time_ms) {
/* must have been a timer roll-over */
if (offset_time_s == 0) {
/*
* initialize elapsed time counters
*
* All CPUs running win32 currently have HR
* counters (Intel and Mips processors do)
*/
if (QueryPerformanceCounter (&time_prev)==0) {
return S_ts_sysTimeError;
}
if (QueryPerformanceFrequency (&time_freq)==0) {
return S_ts_sysTimeError;
}
offset_time_s = (long)time(NULL) - TS_EPOCH_SEC_PAST_1970
- (long)(time_prev.QuadPart/time_freq.QuadPart);
}
/*
* dont need to check status since it was checked once
* during initialization to see if the CPU has HR
* counters (Intel and Mips processors do)
*/
QueryPerformanceCounter (&time_cur);
if (time_prev.QuadPart > time_cur.QuadPart) { /* must have been a timer roll-over */
double offset;
/*
* must have been a timer roll-over
* It takes 9.223372036855e+18/time_freq sec
* to roll over this counter (time_freq is 1193182
* sec on my system). This is currently about 245118 years.
*
* attempt to add number of seconds in a 64 bit integer
* in case the timer resolution improves
*/
offset = pow(2.0, 63.0)-1.0/time_freq.QuadPart;
if (offset<=LONG_MAX-offset_time_s) {
offset_time_s += (long) offset;
}
else {
/*
* this problem cant be fixed, but hopefully will never occurr
*/
fprintf (stderr, "%s.%d Timer overflowed\n", __FILE__, __LINE__);
return S_ts_sysTimeError;
}
}
time_sec.QuadPart = time_cur.QuadPart / time_freq.QuadPart;
time_remainder.QuadPart = time_cur.QuadPart % time_freq.QuadPart;
if (time_sec.QuadPart > LONG_MAX-offset_time_s) {
/*
* this problem cant be fixed, but hopefully will never occurr
*/
fprintf (stderr, "%s.%d Timer value larger than storage\n", __FILE__, __LINE__);
return S_ts_sysTimeError;
}
/* add time (sec) since 1990 */
pStamp->secPastEpoch = offset_time_s + (long)time_sec.QuadPart;
pStamp->nsec = (long)((time_remainder.QuadPart*1000000000)/time_freq.QuadPart);
time_prev = time_cur;
start_time_s += 4294967; /* add number of seconds in 49.7 days */
}
/* time (sec) since 1990 */
pStamp->secPastEpoch = (long)win_sys_time_ms/1000 + start_time_s;
pStamp->nsec = (long)((win_sys_time_ms % 1000) * 1000000);
prev_time_ms = win_sys_time_ms;
# else
struct timeval curtime;
struct timeval curtime;
assert(pStamp != NULL);
if (gettimeofday(&curtime, (struct timezone *)NULL) == -1)
retStat = S_ts_sysTimeError;
else {
pStamp->nsec = ( curtime.tv_usec/1000 ) * 1000000;
pStamp->secPastEpoch = curtime.tv_sec - TS_EPOCH_SEC_PAST_1970;
}
assert(pStamp != NULL);
if (gettimeofday(&curtime, (struct timezone *)NULL) == -1)
retStat = S_ts_sysTimeError;
else {
pStamp->nsec = curtime.tv_usec * 1000;
pStamp->secPastEpoch = curtime.tv_sec - TS_EPOCH_SEC_PAST_1970;
}
# endif
}