This is Unofficial EPICS BASE Doxygen Site
currentTime Class Reference

Public Member Functions

 currentTime ()
 
 ~currentTime ()
 
void getCurrentTime (epicsTimeStamp &dest)
 
void startPLL ()
 

Friends

unsigned __stdcall _pllThreadEntry (void *pCurrentTimeIn)
 

Detailed Description

Definition at line 67 of file osdTime.cpp.

Constructor & Destructor Documentation

currentTime::currentTime ( )

Definition at line 154 of file osdTime.cpp.

154  :
155  lastPerfCounter ( 0 ),
156  perfCounterFreq ( 0 ),
157  epicsTimeLast ( 0 ),
158  perfCounterFreqPLL ( 0 ),
159  lastPerfCounterPLL ( 0 ),
160  lastFileTimePLL ( 0 ),
161  threadHandle ( 0 ),
162  threadId ( 0 ),
163  perfCtrPresent ( false ),
164  threadShutdownCmd ( false ),
165  threadHasExited ( false )
166 {
167  InitializeCriticalSection ( & this->mutex );
168 
169  // avoid interruptions by briefly becoming a time critical thread
170  int originalPriority = GetThreadPriority ( GetCurrentThread () );
171  SetThreadPriority ( GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL );
172 
173  FILETIME ft;
174  GetSystemTimeAsFileTime ( & ft );
175  LARGE_INTEGER tmp;
176  QueryPerformanceCounter ( & tmp );
177  this->lastPerfCounter = tmp.QuadPart;
178  // if no high resolution counters then default to low res file time
179  if ( QueryPerformanceFrequency ( & tmp ) ) {
180  this->perfCounterFreq = tmp.QuadPart;
181  this->perfCtrPresent = true;
182  }
183  SetThreadPriority ( GetCurrentThread (), originalPriority );
184 
185  LARGE_INTEGER liFileTime;
186  liFileTime.LowPart = ft.dwLowDateTime;
187  liFileTime.HighPart = ft.dwHighDateTime;
188 
189  if ( liFileTime.QuadPart >= epicsEpochInFileTime ) {
190  // the windows file time has a maximum resolution of 100 nS
191  // and a nominal resolution of 10 mS - 16 mS
192  this->epicsTimeLast =
193  ( liFileTime.QuadPart - epicsEpochInFileTime ) *
194  ET_TICKS_PER_FT_TICK;
195  }
196  else {
197  errlogPrintf (
198  "win32 osdTime.cpp init detected questionable "
199  "system date prior to EPICS epoch, epics time will not advance\n" );
200  this->epicsTimeLast = 0;
201  }
202 
203  this->perfCounterFreqPLL = this->perfCounterFreq;
204  this->lastPerfCounterPLL = this->lastPerfCounter;
205  this->lastFileTimePLL = liFileTime.QuadPart;
206 }
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
currentTime::~currentTime ( )

Definition at line 225 of file osdTime.cpp.

226 {
227  EnterCriticalSection ( & this->mutex );
228  this->threadShutdownCmd = true;
229  while ( ! this->threadHasExited ) {
230  LeaveCriticalSection ( & this->mutex );
231  Sleep ( 250 /* mS */ );
232  EnterCriticalSection ( & this->mutex );
233  }
234  LeaveCriticalSection ( & this->mutex );
235  DeleteCriticalSection ( & this->mutex );
236 }

Member Function Documentation

void currentTime::getCurrentTime ( epicsTimeStamp dest)

Definition at line 238 of file osdTime.cpp.

239 {
240  if ( this->perfCtrPresent ) {
241  EnterCriticalSection ( & this->mutex );
242 
243  LARGE_INTEGER curPerfCounter;
244  QueryPerformanceCounter ( & curPerfCounter );
245 
246  LONGLONG offset;
247  if ( curPerfCounter.QuadPart >= this->lastPerfCounter ) {
248  offset = curPerfCounter.QuadPart - this->lastPerfCounter;
249  }
250  else {
251  //
252  // must have been a timer roll-over event
253  //
254  // It takes 9.223372036855e+18/perf_freq sec to roll over this
255  // counter. This is currently about 245118 years using the perf
256  // counter freq value on my system (1193182). Nevertheless, I
257  // have code for this situation because the performance
258  // counter resolution will more than likely improve over time.
259  //
260  offset = ( MAXLONGLONG - this->lastPerfCounter )
261  + ( curPerfCounter.QuadPart - MINLONGLONG ) + 1;
262  }
263  if ( offset < MAXLONGLONG / EPICS_TIME_TICKS_PER_SEC ) {
264  offset *= EPICS_TIME_TICKS_PER_SEC;
265  offset /= this->perfCounterFreq;
266  }
267  else {
268  double fpOffset = static_cast < double > ( offset );
269  fpOffset *= EPICS_TIME_TICKS_PER_SEC;
270  fpOffset /= static_cast < double > ( this->perfCounterFreq );
271  offset = static_cast < LONGLONG > ( fpOffset );
272  }
273  LONGLONG epicsTimeCurrent = this->epicsTimeLast + offset;
274  if ( this->epicsTimeLast > epicsTimeCurrent ) {
275  double diff = static_cast < double >
276  ( this->epicsTimeLast - epicsTimeCurrent ) / EPICS_TIME_TICKS_PER_SEC;
277  errlogPrintf (
278  "currentTime::getCurrentTime(): %f sec "
279  "time discontinuity detected\n",
280  diff );
281  }
282  this->epicsTimeLast = epicsTimeCurrent;
283  this->lastPerfCounter = curPerfCounter.QuadPart;
284 
285  LeaveCriticalSection ( & this->mutex );
286 
287  dest.secPastEpoch = static_cast < epicsUInt32 >
288  ( epicsTimeCurrent / EPICS_TIME_TICKS_PER_SEC );
289  dest.nsec = static_cast < epicsUInt32 >
290  ( epicsTimeCurrent % EPICS_TIME_TICKS_PER_SEC );
291  }
292  else {
293  // if high resolution performance counters are not supported then
294  // fall back to low res file time
295  FILETIME ft;
296  GetSystemTimeAsFileTime ( & ft );
297  dest = epicsTime ( ft );
298  }
299 }
unsigned int epicsUInt32
Definition: epicsTypes.h:43
epicsUInt32 secPastEpoch
seconds since 0000 Jan 1, 1990
Definition: epicsTime.h:34
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
#define MAXLONGLONG
Definition: osdTime.cpp:54
#define MINLONGLONG
Definition: osdTime.cpp:57
epicsUInt32 nsec
nanoseconds within second
Definition: epicsTime.h:35
void currentTime::startPLL ( )

Definition at line 208 of file osdTime.cpp.

209 {
210  // create frequency estimation thread when needed
211  if ( this->perfCtrPresent && ! this->threadHandle ) {
212  this->threadHandle = (HANDLE)
213  _beginthreadex ( 0, 4096, _pllThreadEntry, this,
214  CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,
215  & this->threadId );
216  assert ( this->threadHandle );
217  BOOL bstat = SetThreadPriority (
218  this->threadHandle, THREAD_PRIORITY_HIGHEST );
219  assert ( bstat );
220  DWORD wstat = ResumeThread ( this->threadHandle );
221  assert ( wstat != 0xFFFFFFFF );
222  }
223 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
#define STACK_SIZE_PARAM_IS_A_RESERVATION
Definition: osdTime.cpp:60
friend unsigned __stdcall _pllThreadEntry(void *pCurrentTimeIn)
Definition: osdTime.cpp:494

Friends And Related Function Documentation

unsigned __stdcall _pllThreadEntry ( void *  pCurrentTimeIn)
friend

Definition at line 494 of file osdTime.cpp.

495 {
496  currentTime * pCT =
497  reinterpret_cast < currentTime * > ( pCurrentTimeIn );
498  setThreadName ( pCT->threadId, "EPICS Time PLL" );
499  while ( ! pCT->threadShutdownCmd ) {
500  Sleep ( currentTime :: pllDelay * 1000 /* mS */ );
501  pCT->updatePLL ();
502  }
503  EnterCriticalSection ( & pCT->mutex );
504  pCT->threadHasExited = true;
505  LeaveCriticalSection ( & pCT->mutex );
506  return 1;
507 }
void setThreadName(DWORD dwThreadID, LPCSTR szThreadName)

The documentation for this class was generated from the following file: