Free Electron
SystemTicker.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __platform_SystemTicker_h__
8 #define __platform_SystemTicker_h__
9 
10 #if FE_OS==FE_LINUX
11 //#define FE_HAS_TIMES
12 //#include <sys/times.h>
13 #endif
14 
15 #if FE_OS==FE_OSX
16 #define FE_HAS_TIMES
17 #include <sys/times.h>
18 #endif
19 
20 namespace fe
21 {
22 
23 /**************************************************************************//**
24  @brief Sleep the current process for the given number of milliseconds
25 
26  @ingroup platform
27 
28  This can sleep all the threads for the process.
29 *//***************************************************************************/
30 void FE_DL_EXPORT milliSleep(long milliseconds);
31 
32 /**************************************************************************//**
33  @brief Sleep the current process for the given number of microseconds
34 
35  @ingroup platform
36 
37  This can sleep all the threads for the process.
38 *//***************************************************************************/
39 void FE_DL_EXPORT microSleep(long microseconds);
40 
41 /**************************************************************************//**
42  @brief Sleep the current process for the given number of microseconds
43  or the minimum that the OS can resolve, whichever is larger
44 
45  @ingroup platform
46 
47  This can sleep all the threads for the process.
48 *//***************************************************************************/
49 void FE_DL_EXPORT minimumSleep(long microseconds=1);
50 
51 /**************************************************************************//**
52  @brief Delay the current thread for the given number of nanoseconds
53 
54  @ingroup platform
55 
56  This function may involve an active polling of clock ticks.
57 
58  This should not sleep other threads.
59 *//***************************************************************************/
60 void FE_DL_EXPORT nanoSpin(long nanoseconds);
61 
62 /**************************************************************************//**
63  @brief Sleep the current thread for the given number of
64  seconds and nanoseconds
65 
66  @ingroup platform
67 
68  This should not sleep other threads.
69 *//***************************************************************************/
70 #if 0
71 inline void nanoSleep(long seconds,long nanoseconds)
72 {
73  FE_SLEEP(seconds, nanoseconds);
74 }
75 #endif
76 
77 /**************************************************************************//**
78  @brief Yield the current thread
79 
80  @ingroup platform
81 
82  This should not yield other threads.
83 *//***************************************************************************/
84 #if 0
85 inline void yield(void)
86 {
87  FE_YIELD();
88 }
89 #endif
90 
91 /**************************************************************************//**
92  @fn unsigned long systemTick(void)
93 
94  @brief Get the high precision tick count from the processor
95 
96  @ingroup platform
97 
98  See fe::SystemTicker for utilities and interpreted results,
99  including calibration.
100 *//***************************************************************************/
101 
102 #if FE_HW==FE_X86 || FE_HW==FE_ARM
103 //* no return value and we know it (asm sets the return value)
104 #if FE_COMPILER==FE_MICROSOFT || FE_COMPILER==FE_INTEL
105 #if FE_COMPILER==FE_MICROSOFT
106 #if FE_OS==FE_WIN64
107 inline unsigned long systemTick(void)
108 {
109  LARGE_INTEGER tick;
110  BOOL success=QueryPerformanceCounter(&tick);
111  return success? tick.LowPart: 0;
112 }
113 #else
114 #pragma warning( push )
115 #pragma warning( disable : 4035 )
116 inline unsigned long systemTick(void) { __asm { rdtsc } };
117 #pragma warning( pop )
118 #endif // FE_OS
119 #else // FE_COMPILER
120 
121 #ifdef FE_HAS_TIMES
122 inline unsigned long systemTick(void)
123 {
124  tms s_tms;
125  times(s_tms);
126  return s_tms.tms_cutime/* + s_tms.tms_cstime*/;
127 }
128 #elif FE_OS==FE_LINUX && FE_HW==FE_X86
129 inline unsigned long systemTick(void)
130 {
131  unsigned long low;
132  unsigned long high;
133  __asm__ __volatile__ ( "rdtsc" : "=a" (low) , "=d" (high) );
134  return low;
135 };
136 #else
137 inline unsigned long systemTick(void) { __asm { rdtsc }; return 0; };
138 #endif /* FE_OS */
139 #endif /* FE_COMPILER */
140 #elif FE_COMPILER==FE_GNU && FE_OS!=FE_OSX
141 #ifndef FE_SUPPRESS_GetSystemTick
142 #define GetSystemTick2(low,high) __asm__ __volatile__ ( "rdtsc" : "=a" (low) , "=d" (high) )
143 inline unsigned long systemTick(void)
144 {
145  unsigned long low;
146  unsigned long high;
147  __asm__ __volatile__ ( "rdtsc" : "=a" (low) , "=d" (high) );
148  return low;
149 };
150 #else
151 inline unsigned long systemTick(void) { return 0; }
152 #endif /* FE_SUPPRESS_GetSystemTick */
153 #elif defined(FE_HAS_TIMES)
154 // OSX?
155 inline unsigned long systemTick(void)
156 {
157  tms s_tms;
158  times(&s_tms);
159  return s_tms.tms_cutime/* + s_tms.tms_cstime*/;
160 }
161 #else
162 inline unsigned long systemTick(void) { return 0; }
163 #endif /* FE_COMPILER */
164 #else
165 inline unsigned long systemTick(void) { return 0; }
166 #endif /* FE_HW */
167 
168 
169 /**************************************************************************//**
170  @brief High precision timer
171 
172  @ingroup platform
173 *//***************************************************************************/
174 class FE_DL_PUBLIC FE_CORE_PORT SystemTicker
175 {
176  public:
177  SystemTicker(void);
178  SystemTicker(const char *name);
179  SystemTicker(const char *group, const char *name);
180 virtual ~SystemTicker(void) { }
181 
182  /** @brief Returns a time in milliseconds from an
183  arbitrary fixed reference point
184 
185  This number can loop. */
186  unsigned long timeMS(void);
187 
188  /** @brief Perform a self-contained recalibration
189 
190  Must be performed at least once before TicksPerMS
191  can be considered useful. */
192 static void FE_CDECL calibrate(void) { staticInit(); }
193 
194  /** @brief Returns the approximate number of processor
195  clock ticks that occur every millisecond. */
196 static unsigned long ticksPerMS(void) { return ms_ticksPerMS; }
197 
198  /** @brief Return the reltive tick change between
199  two absolute tick values
200 
201  Rollover is corrected.
202  */
203 static unsigned long tickDifference(unsigned long start,
204  unsigned long finish)
205  {
206  if(start<=finish)
207  {
208  return finish - start;
209  }
210  return finish + (UINT_MAX-start);
211  }
212 
213  /** @brief Returns the fractional number of microseonds
214  for each processor clock tick */
215 static float microsecondsPerTick() { return ms_usPerTick; }
216 
217  void log(const char *fmt, ...);
218  void log(void);
219 
220  private:
221 static void staticInit(void);
222 
223 static unsigned long ms_ticksPerMS;
224 static float ms_usPerTick;
225 
226  unsigned long m_lastincl;
227  unsigned long m_lastexcl;
228  String m_name;
229  String m_group;
230  unsigned long m_lasttick;
231  struct timeval m_timer;
232 };
233 
234 /**************************************************************************//**
235  @fn unsigned long systemMicroseconds(void)
236 
237  @brief Get the high precision microsecond timer.
238 
239  @ingroup platform
240 
241  This is a convenience function utilizing fe::systemTick().
242  You must call fe::SystemTicker::calibrate() once prior to use.
243 *//***************************************************************************/
244 inline unsigned long systemMicroseconds(void)
245 {
246  return (unsigned long)(systemTick()*SystemTicker::microsecondsPerTick()); }
247 
248 } /* namespace */
249 
250 #endif /* __platform_SystemTicker_h__ */
kernel
Definition: namespace.dox:3
unsigned long systemTick(void)
Sleep the current thread for the given number of seconds and nanoseconds.
Definition: SystemTicker.h:107
void nanoSpin(long nanoseconds)
Delay the current thread for the given number of nanoseconds.
Definition: SystemTicker.cc:113
void microSleep(long microseconds)
Sleep the current process for the given number of microseconds.
Definition: SystemTicker.cc:59
void minimumSleep(long microseconds)
Sleep the current process for the given number of microseconds or the minimum that the OS can resolve...
Definition: SystemTicker.cc:97
High precision timer.
Definition: SystemTicker.h:174
static float microsecondsPerTick()
Returns the fractional number of microseonds for each processor clock tick.
Definition: SystemTicker.h:215
static unsigned long ticksPerMS(void)
Returns the approximate number of processor clock ticks that occur every millisecond.
Definition: SystemTicker.h:196
Automatically reference-counted string container.
Definition: String.h:128
static unsigned long tickDifference(unsigned long start, unsigned long finish)
Return the reltive tick change between two absolute tick values.
Definition: SystemTicker.h:203
void milliSleep(long milliseconds)
Sleep the current process for the given number of milliseconds.
Definition: SystemTicker.cc:28
unsigned long systemMicroseconds(void)
Get the high precision microsecond timer.
Definition: SystemTicker.h:244