load_elf() uses the FS for dynamics
[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 #include <stdio.h>
11 #include <schedule.h>
12 #include <multiboot.h>
13 #include <pmap.h>
14 #include <arch/perfmon.h>
15
16 /* timing_overhead
17  * Any user space process that links to this file will get its own copy.  
18  * This means it will manually have to call tune_timing itself before it 
19  * makes its first measurement.
20  */
21 uint64_t timing_overhead = 0;
22
23 /* start_timing()
24  * This function simply reads the tsc in a serialized fashion and returns its
25  * value.  It is pusposefully annotated with a noinline so that the overheads 
26  * assocaited with calling it are as deterministic as possible.
27  */
28 uint64_t start_timing()
29 {
30     return read_tsc_serialized();
31 }
32
33 /* stop_timing()
34  * This function reads the tsc in a serialized fashion and subtracts the value
35  * it reads from the value passed in as a paramter in order to determine the 
36  * difference between the two values.  A global timing_overhead value is also 
37  * subtracted to compensate for the overhead associated with calling both
38  * start and stop timing and returning their values.
39  * This function is purposefully annotated with a noinline so that 
40  * the overheads assocaited with calling it are as deterministic as possible.
41  */
42 uint64_t stop_timing(uint64_t val)
43 {
44     uint64_t diff = (read_tsc_serialized() - val - timing_overhead);
45         if ((int64_t) diff < 0) 
46                 return 1;
47         return diff;
48 }
49
50 /* train_timing()
51  * This function is intended to train the timing_overhead variable for use by
52  * stop_timing().  It runs through a loop calling start/stop and averaging the 
53  * overhead of calling them without doing any useful work in between.
54  */
55 void train_timing() 
56 {
57         int i;
58         // set training overhead to be something large
59         register uint64_t training_overhead = 0xffffffff;
60         register uint64_t time, diff;
61
62         //Do this 3 times outside the loop to warm up cpuid
63         time = start_timing();
64         diff = stop_timing(time);
65         time = start_timing();
66         diff = stop_timing(time);
67         time = start_timing();
68         diff = stop_timing(time);
69         for(i=0; i<10000; i++) {
70                 time = start_timing();
71                 diff = stop_timing(time);
72                 
73                 /* In case diff was negative, I want to add its absolute value
74                  * to the cumulative error, otherwise, just diff itself
75                  */
76                 if((int64_t)diff < 0)
77                         diff = (uint64_t)(~0) - diff + 1;
78                 training_overhead = MIN(training_overhead, diff);
79         }
80         timing_overhead = training_overhead;
81 }
82
83 /* Typical per-core timer interrupt handler.  Note that sparc's timer is
84  * periodic by nature, so if you want it to not be periodic, turn off the alarm
85  * in here. */
86 void timer_interrupt(struct trapframe *tf, void *data)
87 {
88 }