many improvements to osiTime
This commit is contained in:
@@ -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
@@ -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 (¤tTimeFT);
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 (¤tTimeFT);
|
||||
// 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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user