Treat tabs as having eight spaces instead of four
[akaros.git] / kern / include / time.h
1 #pragma once
2
3 #include <ros/common.h>
4 #include <ros/time.h>
5 #include <arch/time.h>
6 #include <ros/procinfo.h>
7
8 /* Conversion factors */
9 #define NSEC_PER_SEC    1000000000L
10 #define NSEC_PER_MSEC   1000000L
11 #define NSEC_PER_USEC   1000L
12
13 void time_init(void);
14 void udelay(uint64_t usec);     /* done in arch-specific files */
15
16 uint64_t read_persistent_clock(void);   /* arch-specific */
17
18 uint64_t tsc2nsec(uint64_t tsc_time);
19
20 static inline uint64_t tsc2usec(uint64_t tsc_time)
21 {
22         return tsc2nsec(tsc_time) / NSEC_PER_USEC;
23 }
24
25 static inline uint64_t tsc2msec(uint64_t tsc_time)
26 {
27         return tsc2nsec(tsc_time) / NSEC_PER_MSEC;
28 }
29
30 static inline uint64_t tsc2sec(uint64_t tsc_time)
31 {
32         return tsc2nsec(tsc_time) / NSEC_PER_SEC;
33 }
34
35 uint64_t nsec2tsc(uint64_t nsec);
36
37 static inline uint64_t usec2tsc(uint64_t usec)
38 {
39         return nsec2tsc(usec * NSEC_PER_USEC);
40 }
41
42 static inline uint64_t msec2tsc(uint64_t msec)
43 {
44         return nsec2tsc(msec * NSEC_PER_MSEC);
45 }
46
47 static inline uint64_t sec2tsc(uint64_t sec)
48 {
49         return nsec2tsc(sec * NSEC_PER_SEC);
50 }
51
52 uint64_t epoch_nsec(void);
53
54 static inline struct timespec nsec2timespec(uint64_t ns)
55 {
56         return (struct timespec) {
57                 .tv_sec = ns / NSEC_PER_SEC,
58                 .tv_nsec = ns % NSEC_PER_SEC
59         };
60 }
61
62 static inline struct timeval nsec2timeval(uint64_t ns)
63 {
64         return (struct timeval) {
65                 .tv_sec = ns / NSEC_PER_SEC,
66                 .tv_usec = (ns % NSEC_PER_SEC) / NSEC_PER_USEC
67         };
68 }
69
70 static inline struct timespec tsc2timespec(uint64_t tsc_time)
71 {
72         return nsec2timespec(tsc2nsec(tsc_time));
73 }
74
75 /* Just takes a time measurement.  Meant to be paired with stop_timing.  Use
76  * this if you don't want to muck with overheads or subtraction. */
77 static inline __attribute__((always_inline))
78 uint64_t start_timing(void)
79 {
80     return read_tsc_serialized();
81 }
82
83 /* Takes a time measurement and subtracts the start time and timing overhead,
84  * to return the detected elapsed time.  Use this if you don't want to muck
85  * with overheads or subtraction. */
86 static inline __attribute__((always_inline))
87 uint64_t stop_timing(uint64_t start_time)
88 {
89     uint64_t diff = read_tsc_serialized();
90     diff -= start_time;
91     diff -= __proc_global_info.tsc_overhead;
92         if ((int64_t) diff < 0) {
93                 return 1;
94         }
95         return diff;
96 }
97
98 static inline __attribute__((always_inline))
99 uint64_t nsec(void)
100 {
101         return tsc2nsec(read_tsc());
102 }
103
104
105 /* Ancient measurement crap below.  TODO: use or lose it */
106
107 #if 0
108 #include <pool.h>
109 #include <string.h>
110
111 #define TIMER_TAG_SIZE 20
112 #define MAX_TIMERS 20
113 /* timer_t
114  * This struct is used to keep track of counter values as they are spread
115  * throughput code and timing measurements are made calling TAGGED_TIMING_BEGIN
116  * and TAGGED_TIMING_END
117  */
118 typedef struct Timer{
119         uint64_t curr_run;
120         uint64_t aggr_run;
121         char label[TIMER_TAG_SIZE];
122 } timer_t;
123
124 #define TAGGED_TIMING_BEGIN(tag)                    \
125         static timer_t* _timer_##tag = NULL;            \
126         if (_timer_##tag == NULL) {                     \
127                 _timer_##tag = POOL_GET(&timer_pool);       \
128                 strcpy((_timer_##tag->label), #tag);        \
129                 _timer_##tag->aggr_run = 0;                 \
130         }                                               \
131         _timer_##tag->curr_run = start_timing();
132 #define TAGGED_TIMING_END(tag)                                              \
133 ({                                                                          \
134         _timer_##tag->curr_run = stop_timing(_timer_##tag->curr_run);       \
135         _timer_##tag->aggr_run += _timer_##tag->curr_run;                   \
136 })
137
138 #endif