_M procs start up at _start/hart_entry for vcore0
[akaros.git] / kern / src / timer.c
1
2 // zra: why is this in the kernel?
3
4 #ifdef __SHARC__
5 #pragma nosharc
6 #endif
7
8 #include <arch/arch.h>
9 #include <ros/timer.h>
10
11 /* timing_overhead
12  * Any user space process that links to this file will get its own copy.  
13  * This means it will manually have to call tune_timing itself before it 
14  * makes its first measurement.
15  */
16 uint64_t timing_overhead = 0;
17
18 /* start_timing()
19  * This function simply reads the tsc in a serialized fashion and returns its
20  * value.  It is pusposefully annotated with a noinline so that the overheads 
21  * assocaited with calling it are as deterministic as possible.
22  */
23 uint64_t start_timing()
24 {
25     return read_tsc_serialized();
26 }
27
28 /* stop_timing()
29  * This function reads the tsc in a serialized fashion and subtracts the value
30  * it reads from the value passed in as a paramter in order to determine the 
31  * difference between the two values.  A global timing_overhead value is also 
32  * subtracted to compensate for the overhead associated with calling both
33  * start and stop timing and returning their values.
34  * This function is purposefully annotated with a noinline so that 
35  * the overheads assocaited with calling it are as deterministic as possible.
36  */
37 uint64_t stop_timing(uint64_t val)
38 {
39     uint64_t diff = (read_tsc_serialized() - val - timing_overhead);
40         if ((int64_t) diff < 0) 
41                 return 1;
42         return diff;
43 }
44
45 /* train_timing()
46  * This function is intended to train the timing_overhead variable for use by
47  * stop_timing().  It runs through a loop calling start/stop and averaging the 
48  * overhead of calling them without doing any useful work in between.
49  */
50 void train_timing() 
51 {
52         int i;
53         // set training overhead to be something large
54         register uint64_t training_overhead = 0xffffffff;
55         register uint64_t time, diff;
56
57         //Do this 3 times outside the loop to warm up cpuid
58         time = start_timing();
59         diff = stop_timing(time);
60         time = start_timing();
61         diff = stop_timing(time);
62         time = start_timing();
63         diff = stop_timing(time);
64         for(i=0; i<10000; i++) {
65                 time = start_timing();
66                 diff = stop_timing(time);
67                 
68                 /* In case diff was negative, I want to add its absolute value
69                  * to the cumulative error, otherwise, just diff itself
70                  */
71                 if((int64_t)diff < 0)
72                         diff = (uint64_t)(~0) - diff + 1;
73                 training_overhead = MIN(training_overhead, diff);
74         }
75         timing_overhead = training_overhead;
76 }