This is Unofficial EPICS BASE Doxygen Site
osdMonotonic.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * EPICS BASE is distributed subject to a Software License Agreement found
5 * in file LICENSE that is included with this distribution.
6 \*************************************************************************/
7 
8 #define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h>
9 
10 #include <vxWorks.h>
11 #include <stdio.h>
12 #include <sysLib.h>
13 #include <taskLib.h>
14 
15 #define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE
16 #include "epicsTypes.h"
17 #include "epicsTime.h"
18 #include "cantProceed.h"
19 
20 
21 #define NS_PER_SEC 1000000000
22 
23 union timebase {
24  UINT32 u32[2]; /* vxTimeBaseGet() */
25  INT64 i64; /* pentiumTscGet64() */
26  UINT64 u64; /* epicsMonotonicGet() */
27 };
28 
29 static void measureTickRate(void);
30 
31 #if CPU_FAMILY == PPC
32 #include <arch/ppc/vxPpcLib.h>
33 #include "epicsFindSymbol.h"
34 
35 /* On PowerPC the timebase counter runs at a rate related to the
36  * bus clock and its frequency should always fit into a UINT32.
37  */
38 
39 static epicsUInt32 ticksPerSec;
40 
41 #define TIMEBASEGET(TB) \
42  vxTimeBaseGet(&TB.u32[0], &TB.u32[1])
43 
44 void osdMonotonicInit(void)
45 {
46  typedef epicsUInt32 (*sysTimeBaseFreq_t)(void);
47  sysTimeBaseFreq_t sysTimeBaseFreq =
48  (sysTimeBaseFreq_t) epicsFindSymbol("_sysTimeBaseFreq");
49 
50  if (sysTimeBaseFreq) {
51  ticksPerSec = sysTimeBaseFreq();
52 
53  if (ticksPerSec)
54  return;
55 
56  /* This should never happen */
57  printf("Warning: sysTimeBaseFreq() present but returned zero.\n");
58  }
59 
60  /* Fall back to measuring */
61  measureTickRate();
62 }
63 
64 
65 #elif CPU_FAMILY == I80X86
66 
67 #include <arch/i86/pentiumLib.h>
68 #include <hwif/cpu/arch/i86/vxCpuIdLib.h>
69 
70 /* On Intel the timebase counter frequency is returned by the OS as a
71  * UINT64. Some CPUs may count at multi-GHz rates so we need 64 bits.
72  */
73 
74 static epicsUInt64 ticksPerSec;
75 
76 #define TIMEBASEGET(TB) \
77  pentiumTscGet64(&TB.i64)
78 
79 void osdMonotonicInit(void)
80 {
81  ticksPerSec = vxCpuIdGetFreq();
82 
83  if (ticksPerSec)
84  return;
85 
86  /* This should never happen */
87  printf("Warning: vxCpuIdGetFreq() returned zero.\n");
88 
89  /* Fall back to measuring */
90  measureTickRate();
91 }
92 
93 
94 #else
95  #error This CPU family not supported yet!
96 #endif
97 
98 
100 {
101  if (!ticksPerSec)
102  return 0;
103 
104  return NS_PER_SEC / ticksPerSec;
105 }
106 
108 {
109  union timebase tbNow;
110 
111  if (!ticksPerSec) {
112  cantProceed("Monotonic time source not available.\n");
113  }
114 
115  TIMEBASEGET(tbNow);
116  /* Using a long double for the calculation below to preserve
117  * as many bits in the mantissa as possible.
118  */
119  return ((long double) tbNow.u64) * NS_PER_SEC / ticksPerSec;
120 }
121 
122 static void measureTickRate(void)
123 {
124  union timebase start, end;
125  int sysTicks = sysClkRateGet(); /* 1 second */
126 
127  printf("osdMonotonicInit: Measuring CPU time-base frequency ...");
128  fflush(stdout);
129 
130  taskDelay(1);
131  TIMEBASEGET(start);
132  taskDelay(sysTicks);
133  TIMEBASEGET(end);
134  ticksPerSec = end.u64 - start.u64;
135 
136  printf(" %llu ticks/sec.\n", (unsigned long long) ticksPerSec);
137 }
int sysClkRateGet(void)
UINT64 u64
Definition: osdMonotonic.c:26
#define printf
Definition: epicsStdio.h:41
void osdMonotonicInit(void)
Definition: osdMonotonic.c:19
epicsUInt64 epicsMonotonicGet(void)
Fetch monotonic counter, returns the number of nanoseconds since some unspecified time...
Definition: osdMonotonic.c:29
unsigned int epicsUInt32
Definition: epicsTypes.h:43
unsigned long long epicsUInt64
Definition: epicsTypes.h:45
epicsUInt64 epicsMonotonicResolution(void)
Monotonic time resolution, may not be accurate. Returns the minimum non-zero time difference between ...
Definition: osdMonotonic.c:24
#define NS_PER_SEC
Definition: osdMonotonic.c:21
#define stdout
Definition: epicsStdio.h:30
LIBCOM_API void *epicsStdCall epicsFindSymbol(const char *name)
Definition: osdFindSymbol.c:23
LIBCOM_API void cantProceed(const char *msg,...)
Definition: cantProceed.c:54
INT64 i64
Definition: osdMonotonic.c:25
Routines for code that can&#39;t continue or return after an error.
EPICS time-stamps (epicsTimeStamp), epicsTime C++ class and C functions for handling wall-clock times...
UINT32 u32[2]
Definition: osdMonotonic.c:24
#define TIMEBASEGET(TB)
Definition: osdMonotonic.c:41