Merged the timing and measurement stuff together and cleaned it up a bit
[akaros.git] / inc / timer.h
1 #ifndef ROS_INC_TIMER_H
2 #define ROS_INC_TIMER_H
3 #include <inc/pool.h>
4 #include <inc/string.h>
5
6 #define TIMER_TAG_SIZE 20
7 #define MAX_TIMERS 20
8
9 /* start_timing()
10  * This function simply reads the tsc in a serialized fashion and returns its
11  * value.  It is pusposefully annotated with a noinline so that the overheads 
12  * assocaited with calling it are as deterministic as possible.
13  */
14 uint64_t start_timing() __attribute__((noinline));
15
16 /* stop_timing()
17  * This function reads the tsc in a serialized fashion and subtracts the value
18  * it reads from the value passed in as a paramter in order to determine the 
19  * difference between the two values.  A global timing_overhead value is also 
20  * subtracted to compensate for the overhead associated with calling both
21  * start and stop timing and returning their values.
22  * This function is purposefully annotated with a noinline so that 
23  * the overheads assocaited with calling it are as deterministic as possible.
24  */
25 uint64_t stop_timing(uint64_t val) __attribute__((noinline));
26
27 /* train_timing()
28  * This function is intended to train the timing_overhead variable for use by
29  * stop_timing().  It runs through a loop calling start/stop and averaging the 
30  * overhead of calling them without doing any useful work in between.
31  */
32 void train_timing();
33
34 /* timer_t
35  * This struct is used to keep track of counter values as they are spread
36  * throughput code and timing measurements are made calling TAGGED_TIMING_BEGIN
37  * and TAGGED_TIMING_END
38  */
39 typedef struct Timer{
40         uint64_t curr_run;
41         uint64_t aggr_run;
42         char label[TIMER_TAG_SIZE];
43 } timer_t;
44
45 #define TAGGED_TIMING_BEGIN(tag)                    \
46         static timer_t* _timer_##tag = NULL;            \
47         if (_timer_##tag == NULL) {                     \
48                 _timer_##tag = POOL_GET(&timer_pool);       \
49                 strcpy((_timer_##tag->label), #tag);        \
50                 _timer_##tag->aggr_run = 0;                 \
51         }                                               \
52         _timer_##tag->curr_run = start_timing();
53
54 #define TAGGED_TIMING_END(tag)                                              \
55 ({                                                                          \
56         _timer_##tag->curr_run = stop_timing(_timer_##tag->curr_run);           \
57         _timer_##tag->aggr_run += _timer_##tag->curr_run;                       \
58 })
59
60 #endif /* !ROS_INC_TIMER_H */
61