1 #ifndef __MONOTONIC_H
2 #define __MONOTONIC_H
3 /* The monotonic clock is an always increasing clock source.  It is unrelated to
4  * the actual time of day and should only be used for relative timings.  The
5  * monotonic clock is also not guaranteed to be chronologically precise; there
6  * may be slight skew/shift from a precise clock.
7  *
8  * Depending on system architecture, the monotonic time may be able to be
9  * retrieved much faster than a normal clock source by using an instruction
10  * counter on the CPU.  On x86 architectures (for example), the RDTSC
11  * instruction is a very fast clock source for this purpose.
12  */
13 
14 #include "fmacros.h"
15 #include <stdint.h>
16 #include <unistd.h>
17 
18 /* A counter in micro-seconds.  The 'monotime' type is provided for variables
19  * holding a monotonic time.  This will help distinguish & document that the
20  * variable is associated with the monotonic clock and should not be confused
21  * with other types of time.*/
22 typedef uint64_t monotime;
23 
24 /* Retrieve counter of micro-seconds relative to an arbitrary point in time.  */
25 extern monotime (*getMonotonicUs)(void);
26 
27 
28 /* Call once at startup to initialize the monotonic clock.  Though this only
29  * needs to be called once, it may be called additional times without impact.
30  * Returns a printable string indicating the type of clock initialized.
31  * (The returned string is static and doesn't need to be freed.)  */
32 const char * monotonicInit();
33 
34 
35 /* Functions to measure elapsed time.  Example:
36  *     monotime myTimer;
37  *     elapsedStart(&myTimer);
38  *     while (elapsedMs(myTimer) < 10) {} // loops for 10ms
39  */
elapsedStart(monotime * start_time)40 static inline void elapsedStart(monotime *start_time) {
41     *start_time = getMonotonicUs();
42 }
43 
elapsedUs(monotime start_time)44 static inline uint64_t elapsedUs(monotime start_time) {
45     return getMonotonicUs() - start_time;
46 }
47 
elapsedMs(monotime start_time)48 static inline uint64_t elapsedMs(monotime start_time) {
49     return elapsedUs(start_time) / 1000;
50 }
51 
52 #endif
53