many improvements to osiTime

This commit is contained in:
Jeff Hill
1999-05-07 19:12:40 +00:00
parent ce42f0c56a
commit a51ea84a3a
10 changed files with 969 additions and 445 deletions
-6
View File
@@ -46,9 +46,6 @@
#error This source is specific to WIN32
#endif
extern int init_osi_time ();
extern int exit_osi_time ();
#if !defined(EPICS_DLL_NO)
BOOL WINAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
@@ -57,8 +54,6 @@ BOOL WINAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
case DLL_PROCESS_ATTACH:
if (!bsdSockAttach())
return FALSE;
if (init_osi_time ())
return FALSE;
# ifdef _DEBUG
fprintf(stderr, "Process attached to Com.dll version %s\n", EPICS_VERSION_STRING);
# endif
@@ -66,7 +61,6 @@ BOOL WINAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
case DLL_PROCESS_DETACH:
bsdSockRelease();
exit_osi_time ();
# ifdef _DEBUG
fprintf(stderr, "Process detached from Com.dll version %s\n", EPICS_VERSION_STRING);
# endif
+198 -64
View File
@@ -1,62 +1,199 @@
//
// osiTime.cc
//
// Author: Jeff Hill
//
//
#include <math.h>
#include <time.h>
#include <winsock2.h>
/*
* for _ftime()
*/
#include <sys/types.h>
#include <sys/timeb.h>
#define epicsExportSharedSymbols
#include <osiTime.h>
static long offset_time_s = 0; /* time diff (sec) from 1990 when EPICS started */
static LARGE_INTEGER time_prev, time_freq;
//
// performance counter last value, ticks per sec,
// and its offset from the EPICS epoch.
//
static LONGLONG perf_last, perf_freq, perf_offset;
//
// divide the offset into seconds and
// fractions of a second so that overflow is less
// likely (we dont know the magnitude of perf_freq
// until run time)
//
static LONGLONG perf_sec_offset=-1, perf_frac_offset;
static const SYSTEMTIME epicsEpochST = {
1990, // year
1, // month
1, // day of the week (Monday)
1, // day of the month
0, // hour
0, // min
0, // sec
0 // milli sec
};
static LONGLONG epicsEpoch;
#define FILE_TIME_TICKS_PER_SEC 10000000L
/*
* init_osi_time has to be called before using the timer,
* exit_osi_time has to be called in balance.
* synchronize()
*/
int init_osi_time ()
void osiTime::synchronize()
{
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);
static int init = 0;
LONGLONG new_sec_offset, new_frac_offset;
LARGE_INTEGER parm;
LONGLONG secondsSinceBoot;
FILETIME currentTimeFT;
LONGLONG currentTime;
BOOL win32Stat;
//
// one time initialization of constants
//
if (!init) {
FILETIME epicsEpochFT;
//
// initialize elapsed time counters
//
// All CPUs running win32 currently have HR
// counters (Intel and Mips processors do)
//
assert (QueryPerformanceFrequency (&parm)!=0);
perf_freq = parm.QuadPart;
//
// convert the EPICS epoch to file time
//
win32Stat = SystemTimeToFileTime (&epicsEpochST, &epicsEpochFT);
assert (win32Stat!=0);
parm.LowPart = epicsEpochFT.dwLowDateTime;
parm.HighPart = epicsEpochFT.dwHighDateTime;
epicsEpoch = parm.QuadPart;
init = 1;
}
return 0;
//
// its important that the following two time queries
// are close together (immediately adjacent to each
// other) in the code
//
GetSystemTimeAsFileTime (&currentTimeFT);
// this one is second because QueryPerformanceFrequency()
// has forced its code to load
assert (QueryPerformanceCounter (&parm)!=0);
perf_last = parm.QuadPart;
parm.LowPart = currentTimeFT.dwLowDateTime;
parm.HighPart = currentTimeFT.dwHighDateTime;
currentTime = parm.QuadPart;
//
// check for strange date, and clamp to the
// epics epoch if so
//
if (currentTime>epicsEpoch) {
//
// compute the offset from the EPICS epoch
//
LONGLONG diff = currentTime - epicsEpoch;
//
// compute the seconds offset and the
// fractional offset part in the FILETIME timebase
//
new_sec_offset = diff / FILE_TIME_TICKS_PER_SEC;
new_frac_offset = diff % FILE_TIME_TICKS_PER_SEC;
//
// compute the fractional second offset in the performance
// counter time base
//
new_frac_offset = (new_frac_offset*perf_freq) / FILE_TIME_TICKS_PER_SEC;
}
else {
new_sec_offset = 0;
new_frac_offset = 0;
}
//
// subtract out the perormance counter ticks since the
// begining of windows
//
secondsSinceBoot = perf_last / perf_freq;
if (new_sec_offset>=secondsSinceBoot) {
new_sec_offset -= secondsSinceBoot;
LONGLONG fracSinceBoot = perf_last % perf_freq;
if (new_frac_offset>=fracSinceBoot) {
new_frac_offset -= fracSinceBoot;
}
else if (new_sec_offset>0) {
//
// borrow
//
new_sec_offset--;
new_frac_offset += perf_freq - fracSinceBoot;
}
else {
new_frac_offset = 0;
}
}
else {
new_sec_offset = 0;
new_frac_offset = 0;
}
#if 0
//
// calculate the change
//
{
double change;
change = (double) (perf_sec_offset-new_sec_offset)*perf_freq +
(perf_frac_offset-new_frac_offset);
change /= perf_freq;
printf ("The performance counter drifted by %f sec\n", change);
}
#endif
//
// update the current value
//
perf_sec_offset = new_sec_offset;
perf_frac_offset = new_frac_offset;
}
int exit_osi_time ()
{
offset_time_s = 0;
return 0;
}
//
// osiTime::getCurrent ()
// osiTime::osdGetCurrent ()
//
osiTime osiTime::getCurrent ()
osiTime osiTime::osdGetCurrent ()
{
LARGE_INTEGER time_cur, time_sec, time_remainder;
LONGLONG time_cur, time_sec, time_remainder;
LARGE_INTEGER parm;
unsigned long sec, nsec;
/*
* this allows the code to work when it is in an object
* library (in addition to inside a dll)
* lazy init
*/
if (offset_time_s==0) {
init_osi_time();
if (perf_sec_offset<0) {
osiTime::synchronize();
}
/*
@@ -64,45 +201,42 @@ osiTime osiTime::getCurrent ()
* 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;
QueryPerformanceCounter (&parm);
time_cur = parm.QuadPart;
if (perf_last > time_cur) { /* must have been a timer roll-over */
/*
* must have been a timer roll-over
* It takes 9.223372036855e+18/time_freq sec
* to roll over this counter (time_freq is 1193182
* It takes 9.223372036855e+18/perf_freq sec
* to roll over this counter (perf_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);
perf_sec_offset += MAXLONGLONG / perf_freq;
perf_frac_offset += MAXLONGLONG % perf_freq;
if (perf_frac_offset>=perf_freq) {
perf_sec_offset++;
perf_frac_offset -= perf_freq;
}
}
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);
time_sec = time_cur / perf_freq;
time_remainder = time_cur % perf_freq;
/*
* add time (sec) since the EPICS epoch
*/
time_sec += perf_sec_offset;
time_remainder += perf_frac_offset;
if (time_remainder>=perf_freq) {
time_sec += 1;
time_remainder -= perf_freq;
}
/* add time (sec) since 1970 */
sec = offset_time_s + (long)time_sec.QuadPart;
nsec = (long)((time_remainder.QuadPart*1000000000)/time_freq.QuadPart);
time_prev = time_cur;
perf_last = time_cur;
sec = (unsigned long) (time_sec%ULONG_MAX);
nsec = (unsigned long) ((time_remainder*nSecPerSec)/perf_freq);
return osiTime (sec, nsec);
}
+10 -1
View File
@@ -7,6 +7,12 @@
#define epicsExportSharedSymbols
#include "osiTime.h"
//
// osiTime::synchronize()
//
void osiTime::synchronize()
{
}
//
// osiTime::getCurrent ()
@@ -19,6 +25,9 @@ osiTime osiTime::getCurrent ()
status = gettimeofday (&tv, NULL);
assert (status==0);
return osiTime(tv.tv_sec, tv.tv_usec * nSecPerUSec);
if (tv.tv_sec<osiTime::epicsEpochSecPast1970) {
return osiTime();
}
return osiTime (tv.tv_sec-osiTime::epicsEpochSecPast1970, tv.tv_usec * nSecPerUSec);
}
+11
View File
@@ -7,6 +7,13 @@
#include <tickLib.h>
#include <sysLib.h>
//
// osiTime::synchronize()
//
void osiTime::synchronize()
{
}
//
// osiTime::getCurrent ()
//
@@ -17,6 +24,10 @@ osiTime osiTime::getCurrent ()
ULONG nsec;
ULONG rate = sysClkRateGet();
//
// currently assuming that this has been already adjusted
// for the EPICS epoch
//
ticks = tickGet();
sec = ticks/rate;
nsec = (ticks%rate)*(nSecPerSec/rate);
-6
View File
@@ -46,9 +46,6 @@
#error This source is specific to WIN32
#endif
extern int init_osi_time ();
extern int exit_osi_time ();
#if !defined(EPICS_DLL_NO)
BOOL WINAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
@@ -57,8 +54,6 @@ BOOL WINAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
case DLL_PROCESS_ATTACH:
if (!bsdSockAttach())
return FALSE;
if (init_osi_time ())
return FALSE;
# ifdef _DEBUG
fprintf(stderr, "Process attached to Com.dll version %s\n", EPICS_VERSION_STRING);
# endif
@@ -66,7 +61,6 @@ BOOL WINAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
case DLL_PROCESS_DETACH:
bsdSockRelease();
exit_osi_time ();
# ifdef _DEBUG
fprintf(stderr, "Process detached from Com.dll version %s\n", EPICS_VERSION_STRING);
# endif
+198 -64
View File
@@ -1,62 +1,199 @@
//
// osiTime.cc
//
// Author: Jeff Hill
//
//
#include <math.h>
#include <time.h>
#include <winsock2.h>
/*
* for _ftime()
*/
#include <sys/types.h>
#include <sys/timeb.h>
#define epicsExportSharedSymbols
#include <osiTime.h>
static long offset_time_s = 0; /* time diff (sec) from 1990 when EPICS started */
static LARGE_INTEGER time_prev, time_freq;
//
// performance counter last value, ticks per sec,
// and its offset from the EPICS epoch.
//
static LONGLONG perf_last, perf_freq, perf_offset;
//
// divide the offset into seconds and
// fractions of a second so that overflow is less
// likely (we dont know the magnitude of perf_freq
// until run time)
//
static LONGLONG perf_sec_offset=-1, perf_frac_offset;
static const SYSTEMTIME epicsEpochST = {
1990, // year
1, // month
1, // day of the week (Monday)
1, // day of the month
0, // hour
0, // min
0, // sec
0 // milli sec
};
static LONGLONG epicsEpoch;
#define FILE_TIME_TICKS_PER_SEC 10000000L
/*
* init_osi_time has to be called before using the timer,
* exit_osi_time has to be called in balance.
* synchronize()
*/
int init_osi_time ()
void osiTime::synchronize()
{
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);
static int init = 0;
LONGLONG new_sec_offset, new_frac_offset;
LARGE_INTEGER parm;
LONGLONG secondsSinceBoot;
FILETIME currentTimeFT;
LONGLONG currentTime;
BOOL win32Stat;
//
// one time initialization of constants
//
if (!init) {
FILETIME epicsEpochFT;
//
// initialize elapsed time counters
//
// All CPUs running win32 currently have HR
// counters (Intel and Mips processors do)
//
assert (QueryPerformanceFrequency (&parm)!=0);
perf_freq = parm.QuadPart;
//
// convert the EPICS epoch to file time
//
win32Stat = SystemTimeToFileTime (&epicsEpochST, &epicsEpochFT);
assert (win32Stat!=0);
parm.LowPart = epicsEpochFT.dwLowDateTime;
parm.HighPart = epicsEpochFT.dwHighDateTime;
epicsEpoch = parm.QuadPart;
init = 1;
}
return 0;
//
// its important that the following two time queries
// are close together (immediately adjacent to each
// other) in the code
//
GetSystemTimeAsFileTime (&currentTimeFT);
// this one is second because QueryPerformanceFrequency()
// has forced its code to load
assert (QueryPerformanceCounter (&parm)!=0);
perf_last = parm.QuadPart;
parm.LowPart = currentTimeFT.dwLowDateTime;
parm.HighPart = currentTimeFT.dwHighDateTime;
currentTime = parm.QuadPart;
//
// check for strange date, and clamp to the
// epics epoch if so
//
if (currentTime>epicsEpoch) {
//
// compute the offset from the EPICS epoch
//
LONGLONG diff = currentTime - epicsEpoch;
//
// compute the seconds offset and the
// fractional offset part in the FILETIME timebase
//
new_sec_offset = diff / FILE_TIME_TICKS_PER_SEC;
new_frac_offset = diff % FILE_TIME_TICKS_PER_SEC;
//
// compute the fractional second offset in the performance
// counter time base
//
new_frac_offset = (new_frac_offset*perf_freq) / FILE_TIME_TICKS_PER_SEC;
}
else {
new_sec_offset = 0;
new_frac_offset = 0;
}
//
// subtract out the perormance counter ticks since the
// begining of windows
//
secondsSinceBoot = perf_last / perf_freq;
if (new_sec_offset>=secondsSinceBoot) {
new_sec_offset -= secondsSinceBoot;
LONGLONG fracSinceBoot = perf_last % perf_freq;
if (new_frac_offset>=fracSinceBoot) {
new_frac_offset -= fracSinceBoot;
}
else if (new_sec_offset>0) {
//
// borrow
//
new_sec_offset--;
new_frac_offset += perf_freq - fracSinceBoot;
}
else {
new_frac_offset = 0;
}
}
else {
new_sec_offset = 0;
new_frac_offset = 0;
}
#if 0
//
// calculate the change
//
{
double change;
change = (double) (perf_sec_offset-new_sec_offset)*perf_freq +
(perf_frac_offset-new_frac_offset);
change /= perf_freq;
printf ("The performance counter drifted by %f sec\n", change);
}
#endif
//
// update the current value
//
perf_sec_offset = new_sec_offset;
perf_frac_offset = new_frac_offset;
}
int exit_osi_time ()
{
offset_time_s = 0;
return 0;
}
//
// osiTime::getCurrent ()
// osiTime::osdGetCurrent ()
//
osiTime osiTime::getCurrent ()
osiTime osiTime::osdGetCurrent ()
{
LARGE_INTEGER time_cur, time_sec, time_remainder;
LONGLONG time_cur, time_sec, time_remainder;
LARGE_INTEGER parm;
unsigned long sec, nsec;
/*
* this allows the code to work when it is in an object
* library (in addition to inside a dll)
* lazy init
*/
if (offset_time_s==0) {
init_osi_time();
if (perf_sec_offset<0) {
osiTime::synchronize();
}
/*
@@ -64,45 +201,42 @@ osiTime osiTime::getCurrent ()
* 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;
QueryPerformanceCounter (&parm);
time_cur = parm.QuadPart;
if (perf_last > time_cur) { /* must have been a timer roll-over */
/*
* must have been a timer roll-over
* It takes 9.223372036855e+18/time_freq sec
* to roll over this counter (time_freq is 1193182
* It takes 9.223372036855e+18/perf_freq sec
* to roll over this counter (perf_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);
perf_sec_offset += MAXLONGLONG / perf_freq;
perf_frac_offset += MAXLONGLONG % perf_freq;
if (perf_frac_offset>=perf_freq) {
perf_sec_offset++;
perf_frac_offset -= perf_freq;
}
}
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);
time_sec = time_cur / perf_freq;
time_remainder = time_cur % perf_freq;
/*
* add time (sec) since the EPICS epoch
*/
time_sec += perf_sec_offset;
time_remainder += perf_frac_offset;
if (time_remainder>=perf_freq) {
time_sec += 1;
time_remainder -= perf_freq;
}
/* add time (sec) since 1970 */
sec = offset_time_s + (long)time_sec.QuadPart;
nsec = (long)((time_remainder.QuadPart*1000000000)/time_freq.QuadPart);
time_prev = time_cur;
perf_last = time_cur;
sec = (unsigned long) (time_sec%ULONG_MAX);
nsec = (unsigned long) ((time_remainder*nSecPerSec)/perf_freq);
return osiTime (sec, nsec);
}
+360 -25
View File
@@ -4,34 +4,12 @@
// Author: Jeff Hill
//
#include <stdio.h>
#include <limits.h>
#include <time.h>
#define epicsExportSharedSymbols
//
// force this module to include code to convert to TS_STAMP
//
#include <tsDefs.h>
//
// force this module to include code that can convert
// to GDD's aitTimeStamp, but dont force it
// to link with gdd
//
#define aitHelpersInclude
class aitTimeStamp {
public:
aitTimeStamp (const unsigned long tv_secIn, const unsigned long tv_nsecIn) :
tv_sec(tv_secIn), tv_nsec(tv_nsecIn) {}
void get(unsigned long &tv_secOut, unsigned long &tv_nsecOut) const
{
tv_secOut = this->tv_sec;
tv_nsecOut = this->tv_nsec;
}
private:
unsigned long tv_sec;
unsigned long tv_nsec;
};
#include <osiTime.h>
//
@@ -39,3 +17,360 @@ private:
//
const unsigned osiTime::epicsEpochSecPast1970 = 7305 * 86400;
const unsigned osiTime::mSecPerSec = 1000u;
const unsigned osiTime::nSecPerSec = 1000000000u;
const unsigned osiTime::nSecPerUSec = 1000u;
const unsigned osiTime::secPerMin = 60u;
//
// osiTime (const unsigned long secIn, const unsigned long nSecIn)
//
osiTime::osiTime (const unsigned long secIn, const unsigned long nSecIn)
{
if (nSecIn<nSecPerSec) {
this->sec = secIn;
this->nSec = nSecIn;
}
else if (nSecIn<(nSecPerSec*2)){
this->sec = secIn + 1u;
this->nSec = nSecIn-nSecPerSec;
}
else {
this->sec = nSecIn/nSecPerSec + secIn;
this->nSec = nSecIn%nSecPerSec;
}
}
//
// getCurrent ()
//
// force a logical progression of time
//
// (this does not appear to add any significant
// overhead when the code is optimized)
//
osiTime osiTime::getCurrent ()
{
static osiTime last;
osiTime ts = osiTime::osdGetCurrent();
if (last<ts) {
last = ts;
return ts;
}
else {
return last;
}
}
//
// this is part of the POSIX RT standard but some OS
// still do not define this so this code intentionally
// does not include header files that do define this
//
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
//
// operator struct timespec ()
//
osiTime::operator struct timespec () const
{
struct timespec ts;
assert (this->sec<=LONG_MAX-osiTime::epicsEpochSecPast1970);
ts.tv_sec = this->sec + osiTime::epicsEpochSecPast1970;
ts.tv_nsec = this->nSec;
return ts;
}
//
// osiTime (const struct timespec &ts)
//
osiTime::osiTime (const struct timespec &ts)
{
assert (ts.tv_sec >= osiTime::epicsEpochSecPast1970);
this->sec = ((unsigned long)ts.tv_sec) - osiTime::epicsEpochSecPast1970;
assert (ts.tv_nsec>=0 && ts.tv_nsec<osiTime::nSecPerSec);
this->nSec = (unsigned long) ts.tv_nsec;
}
//
// operator = (const struct timespec &rhs)
//
osiTime::operator = (const struct timespec &rhs)
{
assert (rhs.tv_sec >= osiTime::epicsEpochSecPast1970);
this->sec = ((unsigned long)rhs.tv_sec) - osiTime::epicsEpochSecPast1970;
assert (rhs.tv_nsec>=0 && rhs.tv_nsec<osiTime::nSecPerSec);
this->nSec = (unsigned long) rhs.tv_nsec;
}
//
// force this module to include code that can convert
// to GDD's aitTimeStamp, but dont require that it must
// link with gdd. Therefore, gdd.h is not included here.
//
class aitTimeStamp {
public:
unsigned long tv_sec;
unsigned long tv_nsec;
};
//
// operator aitTimeStamp ()
//
osiTime::operator aitTimeStamp () const
{
aitTimeStamp ts;
assert (this->sec<=ULONG_MAX-osiTime::epicsEpochSecPast1970);
ts.tv_sec = this->sec + osiTime::epicsEpochSecPast1970;
ts.tv_nsec = this->nSec;
return ts;
}
//
// osiTime (const aitTimeStamp &ts)
//
osiTime::osiTime (const aitTimeStamp &ts)
{
assert (ts.tv_sec >= osiTime::epicsEpochSecPast1970);
this->sec = ts.tv_sec - osiTime::epicsEpochSecPast1970;
assert (ts.tv_nsec<osiTime::nSecPerSec);
this->nSec = ts.tv_nsec;
}
//
// operator = (const aitTimeStamp &rhs)
//
osiTime::operator = (const aitTimeStamp &rhs)
{
assert (rhs.tv_sec >= osiTime::epicsEpochSecPast1970);
this->sec = rhs.tv_sec - osiTime::epicsEpochSecPast1970;
assert (rhs.tv_nsec<osiTime::nSecPerSec);
this->nSec = rhs.tv_nsec;
}
//
// operator TS_STAMP ()
//
osiTime::operator struct TS_STAMP () const
{
struct TS_STAMP ts;
ts.secPastEpoch = this->sec;
ts.nsec = this->nSec;
return ts;
}
//
// osiTime (const TS_STAMP &ts)
//
osiTime::osiTime (const struct TS_STAMP &ts)
{
this->sec = ts.secPastEpoch;
this->nSec = ts.nsec;
}
//
// operator = (const TS_STAMP &rhs)
//
osiTime::operator = (const struct TS_STAMP &rhs)
{
this->sec = rhs.secPastEpoch;
this->nSec = rhs.nsec;
}
//
// osiTime::show (unsigned)
//
void osiTime::show (unsigned) const
{
//
// lame way to print the time ...
//
printf ("osiTime: sec=%lu nSec=%lu\n",
this->sec, this->nSec);
}
//
// operator -
//
// Since negative discontinuities in time are of particular
// concern, the "A-B" operator has special code executed
// as follows:
//
// when B is greater than A:
// B-A > one half full scale => assume time stamp wrap around
// B-A <= one half full scale => return a difference of zero
//
// when A is greater than or equal to B
// A-B > one half full scale => return a difference of zero
// A-B <= one half full scale => return A-B
//
osiTime osiTime::operator - (const osiTime &rhs) const
{
unsigned long nSec, sec;
if (this->sec<rhs.sec) {
if (rhs.sec-this->sec < ULONG_MAX/2) {
//
// In this situation where the difference is less than
// 69 years assume that someone adjusted the time
// backwards slightly. This would happen if a high
// resolution counter drift was realigned to some master
// time source
//
return osiTime ();
}
else {
//
// In this situation where the difference is more than
// 69 years assume that the seconds counter has rolled
// over and compute the "wrap around" difference
//
sec = 1 + this->sec + (ULONG_MAX - rhs.sec);
}
}
else {
sec = this->sec - rhs.sec;
if (sec > ULONG_MAX/2) {
//
// assume that someone adjusted the time
// backwards slightly. This would happen if a high
// resolution counter drift was realigned to some master
// time source
//
return osiTime ();
}
}
if (this->nSec>=rhs.nSec) {
nSec = this->nSec - rhs.nSec;
}
else {
if (sec>0) {
//
// Borrow
//
nSec = this->nSec + (osiTime::nSecPerSec - rhs.nSec);
sec--;
}
else {
//
// In this situation where the difference is less than
// 69 years assume that someone adjusted the time
// backwards slightly. This would happen if the high
// resolution counter drift was realigned to some master
// time source
//
return osiTime ();
}
}
return osiTime (sec, nSec);
}
//
// operator <=
//
int osiTime::operator <= (const osiTime &rhs) const
{
int rc;
if (this->sec<rhs.sec) {
if (rhs.sec-this->sec < ULONG_MAX/2) {
//
// In this situation where the difference is less than
// 69 years compute the expected result
//
rc = 1;
}
else {
//
// In this situation where the difference is more than
// 69 years assume that the seconds counter has rolled
// over and compute the "wrap around" result
//
rc = 0;
}
}
else if (this->sec>rhs.sec) {
if (this->sec-rhs.sec < ULONG_MAX/2) {
//
// In this situation where the difference is less than
// 69 years compute the expected result
//
rc = 0;
}
else {
//
// In this situation where the difference is more than
// 69 years assume that the seconds counter has rolled
// over and compute the "wrap around" result
//
rc = 1;
}
}
else {
if (this->nSec<=rhs.nSec) {
rc = 1;
}
else {
rc = 0;
}
}
return rc;
}
//
// operator <
//
int osiTime::operator < (const osiTime &rhs) const
{
int rc;
if (this->sec<rhs.sec) {
if (rhs.sec-this->sec < ULONG_MAX/2) {
//
// In this situation where the difference is less than
// 69 years compute the expected result
//
rc = 1;
}
else {
//
// In this situation where the difference is more than
// 69 years assume that the seconds counter has rolled
// over and compute the "wrap around" result
//
rc = 0;
}
}
else if (this->sec>rhs.sec) {
if (this->sec-rhs.sec < ULONG_MAX/2) {
//
// In this situation where the difference is less than
// 69 years compute the expected result
//
rc = 0;
}
else {
//
// In this situation where the difference is more than
// 69 years assume that the seconds counter has rolled
// over and compute the "wrap around" result
//
rc = 1;
}
}
else {
if (this->nSec<rhs.nSec) {
rc = 1;
}
else {
rc = 0;
}
}
return rc;
}
+184 -277
View File
@@ -29,6 +29,9 @@
*
* History
* $Log$
* Revision 1.8 1999/05/03 16:22:29 jhill
* allow osiTime to convert toaitTimeStamp without binding to gdd
*
* Revision 1.7 1999/04/30 00:02:02 jhill
* added getCurrentEPICS()
*
@@ -70,328 +73,190 @@
#include <assert.h>
#endif
#define nSecPerSec 1000000000u
#define nSecPerUSec 1000u
#define secPerMin 60u
#include "shareLib.h"
struct timespec;
struct TS_STAMP;
class aitTimeStamp;
//
// class osiTime
//
// NOTE: this is an unsigned data type. It is not possible
// to store a negative time value using this class.
//
class epicsShareClass osiTime {
friend osiTime operator+
(const osiTime &lhs, const osiTime &rhs);
friend osiTime operator-
(const osiTime &lhs, const osiTime &rhs);
friend int operator>=
(const osiTime &lhs, const osiTime &rhs);
friend int operator>
(const osiTime &lhs, const osiTime &rhs);
friend int operator<=
(const osiTime &lhs, const osiTime &rhs);
friend int operator<
(const osiTime &lhs, const osiTime &rhs);
friend int operator==
(const osiTime &lhs, const osiTime &rhs);
public:
osiTime () : sec(0u), nSec(0u) {}
osiTime (const osiTime &t) : sec(t.sec), nSec(t.nSec) {}
osiTime (const unsigned long secIn, const unsigned long nSecIn)
{
if (nSecIn<nSecPerSec) {
this->sec = secIn;
this->nSec = nSecIn;
}
else if (nSecIn<(nSecPerSec<<1u)){
this->sec = secIn + 1u;
this->nSec = nSecIn-nSecPerSec;
}
else {
this->sec = nSecIn/nSecPerSec + secIn;
this->nSec = nSecIn%nSecPerSec;
}
}
osiTime (double t)
{
double intPart;
if (t<0.0l) {
t = 0.0l;
}
this->sec = (unsigned long) t;
intPart = (double) this->sec;
this->nSec = (unsigned long) ((t-intPart)*nSecPerSec);
}
//
// fetch value as an integer
// fetch the current time
//
unsigned long getSec() const
{
return this->sec;
}
unsigned long getUSec() const
{
return (this->nSec/nSecPerUSec);
}
unsigned long getNSec() const
{
return this->nSec;
}
// (always returns a time value that is greater than or equal
// to all previous time values returned)
//
// non standard calls for the many strange
// time formats that still exist
//
long getSecTruncToLong() const
{
assert (this->sec<=LONG_MAX);
return (long) this->sec;
}
long getUSecTruncToLong() const
{
return (long) (this->nSec/nSecPerUSec);
}
long getNSecTruncToLong() const
{
assert (this->nSec<=LONG_MAX);
return (long) this->nSec;
}
operator double() const
{
return ((double)this->nSec)/nSecPerSec+this->sec;
}
operator float() const
{
return ((float)this->nSec)/nSecPerSec+this->sec;
}
static osiTime getCurrent();
//
// some systems have a high resolution time source which
// gradually drifts away from the master time base. Calling
// this routine will cause osiTime to realign the high
// resolution result from getCurrent() with some master
// time base.
//
// if this routine has not been called at least once so far
// by the current process then it is called the first time
// that getCurrent() is called
//
static void synchronize();
//
// create an osiTime for the EPICS epoch
//
osiTime () : sec(0u), nSec(0u) {}
//
// create an osiTime from another osiTime
//
osiTime (const osiTime &t) : sec(t.sec), nSec(t.nSec) {}
//
// create an osiTime from sec and fractional nano-seconds
//
osiTime (const unsigned long secIn, const unsigned long nSecIn);
//
// convert to and from floating point
//
osiTime (double t);
operator double() const;
operator float() const;
//
// convert to and from EPICS TS_STAMP format
//
// include tsDefs.h prior to including osiTime.h
// if you need these capabilities
//
#ifdef INC_tsDefs_h
operator TS_STAMP () const
{
TS_STAMP ts;
assert (this->sec>=osiTime::epicsEpochSecPast1970);
ts.secPastEpoch = this->sec - osiTime::epicsEpochSecPast1970;
ts.nsec = this->nSec;
return ts;
}
osiTime (const TS_STAMP &ts)
{
this->sec = ts.secPastEpoch + osiTime::epicsEpochSecPast1970;
this->nSec = ts.nsec;
}
operator = (const TS_STAMP &rhs)
{
this->sec = rhs.secPastEpoch + osiTime::epicsEpochSecPast1970;
this->nSec = rhs.nsec;
}
#endif
operator struct TS_STAMP () const;
osiTime (const struct TS_STAMP &ts);
operator = (const struct TS_STAMP &rhs);
//
// convert to and from GDD's aitTimeStamp format
//
// include aitHelpers.h prior to including osiTime.h
// if you need these capabilities
operator aitTimeStamp () const;
osiTime (const aitTimeStamp &ts);
operator = (const aitTimeStamp &rhs);
//
#ifdef aitHelpersInclude
operator aitTimeStamp () const
{
return aitTimeStamp (this->sec, this->nSec);
}
// convert to and from POSIX RT's "struct timespec"
//
operator struct timespec () const;
osiTime (const struct timespec &ts);
operator = (const struct timespec &rhs);
osiTime (const aitTimeStamp &ts)
{
ts.get (this->sec, this->nSec);
}
//
// arithmetic operators
//
osiTime operator- (const osiTime &rhs) const;
osiTime operator+ (const osiTime &rhs) const;
osiTime operator+= (const osiTime &rhs);
osiTime operator-= (const osiTime &rhs);
operator = (const aitTimeStamp &rhs)
{
rhs.get (this->sec, this->nSec);
}
#endif
//
// comparison operators
//
int operator == (const osiTime &rhs) const;
int operator != (const osiTime &rhs) const;
int operator <= (const osiTime &rhs) const;
int operator < (const osiTime &rhs) const;
int operator >= (const osiTime &rhs) const;
int operator > (const osiTime &rhs) const;
osiTime operator+= (const osiTime &rhs)
{
*this = *this + rhs;
return *this;
}
//
// dump current state to standard out
//
void show (unsigned interestLevel) const;
osiTime operator-= (const osiTime &rhs)
{
*this = *this - rhs;
return *this;
}
//
// useful public constants
//
static const unsigned nSecPerSec;
static const unsigned mSecPerSec;
static const unsigned nSecPerUSec;
static const unsigned secPerMin;
//
// fetch value as an unsigned integer
//
unsigned long getSec() const;
unsigned long getUSec() const;
unsigned long getNSec() const;
//
// non standard calls for the many different
// time formats that exist
//
long getSecTruncToLong() const;
long getUSecTruncToLong() const;
long getNSecTruncToLong() const;
void show(unsigned)
{
printf("osiTime: sec=%lu nSec=%lu\n",
this->sec, this->nSec);
}
private:
unsigned long sec;
unsigned long nSec;
static const unsigned epicsEpochSecPast1970;
static const unsigned epicsEpochSecPast1970;
static osiTime osdGetCurrent();
};
inline osiTime operator+ (const osiTime &lhs, const osiTime &rhs)
inline unsigned long osiTime::getSec() const
{
return osiTime(lhs.sec + rhs.sec, lhs.nSec + rhs.nSec);
return this->sec;
}
//
// like data type unsigned this assumes that the lhs > rhs
// (otherwise we assume sec wrap around)
//
inline osiTime operator- (const osiTime &lhs, const osiTime &rhs)
{
unsigned long nSec, sec;
if (lhs.sec<rhs.sec) {
//
// wrap around
//
sec = 1 + lhs.sec + (ULONG_MAX - rhs.sec);
}
else {
sec = lhs.sec - rhs.sec;
}
if (lhs.nSec<rhs.nSec) {
//
// Borrow
//
nSec = 1 + lhs.nSec + (nSecPerSec - rhs.nSec);
sec--;
}
else {
nSec = lhs.nSec - rhs.nSec;
}
return osiTime(sec, nSec);
inline unsigned long osiTime::getUSec() const
{
return (this->nSec/nSecPerUSec);
}
inline int operator <= (const osiTime &lhs, const osiTime &rhs)
{
int rc;
//
// Sun's CC -O generates bad code when this was rearranged
//
if (lhs.sec<rhs.sec) {
rc = 1;
}
else if (lhs.sec>rhs.sec) {
rc = 0;
}
else {
if (lhs.nSec<=rhs.nSec) {
rc = 1;
}
else {
rc = 0;
}
}
return rc;
inline unsigned long osiTime::getNSec() const
{
return this->nSec;
}
inline int operator < (const osiTime &lhs, const osiTime &rhs)
inline osiTime::osiTime (double t)
{
int rc;
//
// Sun's CC -O generates bad code when this was rearranged
//
if (lhs.sec<rhs.sec) {
rc = 1;
}
else if (lhs.sec>rhs.sec) {
rc = 0;
}
else {
if (lhs.nSec<rhs.nSec) {
rc = 1;
}
else {
rc = 0;
}
}
return rc;
assert (t>0.0);
this->sec = (unsigned long) t;
this->nSec = (unsigned long) ((t-this->sec)*nSecPerSec);
}
inline int operator >= (const osiTime &lhs, const osiTime &rhs)
inline osiTime::operator double() const
{
int rc;
//
// Sun's CC -O generates bad code here
//
//
//
#if 0
if (lhs.sec>rhs.sec) {
return 1;
}
else if (lhs.sec==rhs.sec) {
if (lhs.nSec>=rhs.nSec) {
return 1;
}
}
assert(lhs.sec<=rhs.sec);
return 0;
#endif
if (lhs.sec>rhs.sec) {
rc = 1;
}
else if (lhs.sec<rhs.sec) {
rc = 0;
}
else {
if (lhs.nSec>=rhs.nSec) {
rc = 1;
}
else {
rc = 0;
}
}
return rc;
return ((double)this->nSec)/nSecPerSec+this->sec;
}
inline int operator > (const osiTime &lhs, const osiTime &rhs)
inline osiTime::operator float() const
{
int rc;
//
// Sun's CC -O generates bad code when this was rearranged
//
if (lhs.sec>rhs.sec) {
rc = 1;
}
else if (lhs.sec<rhs.sec) {
rc = 0;
}
else {
if (lhs.nSec>rhs.nSec) {
rc = 1;
}
else {
rc = 0;
}
}
return rc;
return ((float)this->nSec)/nSecPerSec+this->sec;
}
inline int operator==
(const osiTime &lhs, const osiTime &rhs)
inline osiTime osiTime::operator + (const osiTime &rhs) const
{
if (lhs.sec == rhs.sec && lhs.nSec == rhs.nSec) {
return osiTime(this->sec + rhs.sec, this->nSec + rhs.nSec);
}
inline osiTime osiTime::operator += (const osiTime &rhs)
{
*this = *this + rhs;
return *this;
}
inline osiTime osiTime::operator -= (const osiTime &rhs)
{
*this = *this - rhs;
return *this;
}
inline int osiTime::operator == (const osiTime &rhs) const
{
if (this->sec == rhs.sec && this->nSec == rhs.nSec) {
return 1;
}
else {
@@ -399,5 +264,47 @@ inline int operator==
}
}
inline int osiTime::operator != (const osiTime &rhs) const
{
if (this->sec != rhs.sec || this->nSec != rhs.nSec) {
return 1;
}
else {
return 0;
}
}
//
// operator >= (const osiTime &lhs, const osiTime &rhs)
//
inline int osiTime::operator >= (const osiTime &rhs) const
{
return !(*this < rhs);
}
//
// operator > (const osiTime &lhs, const osiTime &rhs)
//
inline int osiTime::operator > (const osiTime &rhs) const
{
return !(*this <= rhs);
}
inline long osiTime::getSecTruncToLong() const
{
assert (this->sec<=LONG_MAX);
return (long) this->sec;
}
inline long osiTime::getUSecTruncToLong() const
{
return (long) (this->nSec/nSecPerUSec);
}
inline long osiTime::getNSecTruncToLong() const
{
return (long) this->nSec;
}
#endif // osiTimehInclude
+4 -1
View File
@@ -29,6 +29,9 @@
*
* History
* $Log$
* Revision 1.9 1997/08/05 00:37:06 jhill
* removed warnings
*
* Revision 1.8 1997/06/25 05:45:54 jhill
* cleaned up pc port
*
@@ -247,7 +250,7 @@ osiTime osiTimerQueue::delayToFirstExpire() const
//
// no timer in the queue - return a long delay - 30 min
//
delay = osiTime(30u * secPerMin, 0u);
delay = osiTime (30u * osiTime::secPerMin, 0u);
}
#ifdef DEBUG
printf("delay to first item on the queue %f\n", (double) delay);
+4 -1
View File
@@ -29,6 +29,9 @@
*
* History
* $Log$
* Revision 1.9 1997/08/05 00:37:06 jhill
* removed warnings
*
* Revision 1.8 1997/06/25 05:45:54 jhill
* cleaned up pc port
*
@@ -247,7 +250,7 @@ osiTime osiTimerQueue::delayToFirstExpire() const
//
// no timer in the queue - return a long delay - 30 min
//
delay = osiTime(30u * secPerMin, 0u);
delay = osiTime (30u * osiTime::secPerMin, 0u);
}
#ifdef DEBUG
printf("delay to first item on the queue %f\n", (double) delay);