BNX2X: disables TPA
[akaros.git] / kern / src / time.c
index 1815258..f298ba7 100644 (file)
@@ -1,85 +1,62 @@
 #include <arch/arch.h>
-#include <ros/time.h>
+#include <time.h>
 #include <stdio.h>
 #include <schedule.h>
 #include <multiboot.h>
 #include <pmap.h>
 #include <smp.h>
 
-/* timing_overhead
- * Any user space process that links to this file will get its own copy.  
- * This means it will manually have to call tune_timing itself before it 
- * makes its first measurement.
- */
-uint64_t timing_overhead = 0;
-
-/* start_timing()
- * This function simply reads the tsc in a serialized fashion and returns its
- * value.  It is pusposefully annotated with a noinline so that the overheads 
- * assocaited with calling it are as deterministic as possible.
- */
-uint64_t start_timing()
-{
-    return read_tsc_serialized();
-}
-
-/* stop_timing()
- * This function reads the tsc in a serialized fashion and subtracts the value
- * it reads from the value passed in as a paramter in order to determine the 
- * difference between the two values.  A global timing_overhead value is also 
- * subtracted to compensate for the overhead associated with calling both
- * start and stop timing and returning their values.
- * This function is purposefully annotated with a noinline so that 
- * the overheads assocaited with calling it are as deterministic as possible.
- */
-uint64_t stop_timing(uint64_t val)
-{
-    uint64_t diff = (read_tsc_serialized() - val - timing_overhead);
-       if ((int64_t) diff < 0) 
-               return 1;
-       return diff;
-}
-
-/* train_timing()
- * This function is intended to train the timing_overhead variable for use by
- * stop_timing().  It runs through a loop calling start/stop and averaging the 
- * overhead of calling them without doing any useful work in between.
- */
+/* Determines the overhead of tsc timing.  Note the start/stop calls are
+ * inlined, so we're trying to determine the lowest amount of overhead
+ * attainable by using the TSC (or whatever timing source).
+ *
+ * For more detailed TSC measurements, use test_rdtsc() in k/a/i/rdtsc_test.c */
 void train_timing() 
 {
-       int i;
-       // set training overhead to be something large
-       register uint64_t training_overhead = 0xffffffff;
-       register uint64_t time, diff;
+       uint64_t min_overhead = UINT64_MAX;
+       uint64_t max_overhead = 0;
+       uint64_t time, diff;
+       int8_t irq_state = 0;
 
-       //Do this 3 times outside the loop to warm up cpuid
+       /* Reset this, in case we run it again.  The use of start/stop to determine
+        * the overhead relies on timing_overhead being 0. */
+       system_timing.timing_overhead = 0;
+       /* timing might use cpuid, in which case we warm it up to avoid some extra
+        * variance */
        time = start_timing();
        diff = stop_timing(time);
        time = start_timing();
        diff = stop_timing(time);
        time = start_timing();
        diff = stop_timing(time);
-       for(i=0; i<10000; i++) {
+       disable_irqsave(&irq_state);
+       for (int i = 0; i < 10000; i++) {
                time = start_timing();
                diff = stop_timing(time);
-               
-               /* In case diff was negative, I want to add its absolute value
-                * to the cumulative error, otherwise, just diff itself
-                */
-               if((int64_t)diff < 0)
-                       diff = (uint64_t)(~0) - diff + 1;
-               training_overhead = MIN(training_overhead, diff);
+               min_overhead = MIN(min_overhead, diff);
+               max_overhead = MAX(max_overhead, diff);
        }
-       timing_overhead = training_overhead;
+       enable_irqsave(&irq_state);
+       system_timing.timing_overhead = min_overhead;
+       printk("TSC overhead (Min: %llu, Max: %llu)\n", min_overhead, max_overhead);
+}
+
+void udelay_sched(uint64_t usec)
+{
+       struct timer_chain *tchain = &per_cpu_info[core_id()].tchain;
+       struct alarm_waiter a_waiter;
+       init_awaiter(&a_waiter, 0);
+       set_awaiter_rel(&a_waiter, usec);
+       set_alarm(tchain, &a_waiter);
+       sleep_on_awaiter(&a_waiter);
 }
 
 /* Convenience wrapper called when a core's timer interrupt goes off.  Not to be
  * confused with global timers (like the PIC).  Do not put your code here.  If
  * you want something to happen in the future, set an alarm. */
-void timer_interrupt(struct trapframe *tf, void *data)
+void timer_interrupt(struct hw_trapframe *hw_tf, void *data)
 {
-       struct timer_chain *pcpui_tchain = &per_cpu_info[core_id()].tchain;
-       trigger_tchain(pcpui_tchain);
+       __trigger_tchain(&per_cpu_info[core_id()].tchain, hw_tf);
 }
 
 /* We can overflow/wraparound when we multiply up, but we have to divide last,
@@ -150,3 +127,39 @@ uint64_t nsec2tsc(uint64_t nsec)
        else
                return (nsec * system_timing.tsc_freq) / 1000000000;
 }
+
+/* TODO: figure out what epoch time TSC == 0 is and store that as boot_tsc */
+static uint64_t boot_sec = 1242129600; /* nanwan's birthday */
+
+uint64_t epoch_tsc(void)
+{
+       return read_tsc() + sec2tsc(boot_sec);
+}
+
+uint64_t epoch_sec(void)
+{
+       return tsc2sec(epoch_tsc());
+}
+
+uint64_t epoch_msec(void)
+{
+       return tsc2msec(epoch_tsc());
+}
+
+uint64_t epoch_usec(void)
+{
+       return tsc2usec(epoch_tsc());
+}
+
+uint64_t epoch_nsec(void)
+{
+       return tsc2nsec(epoch_tsc());
+}
+
+void tsc2timespec(uint64_t tsc_time, struct timespec *ts)
+{
+       ts->tv_sec = tsc2sec(tsc_time);
+       /* subtract off everything but the remainder */
+       tsc_time -= sec2tsc(ts->tv_sec);
+       ts->tv_nsec = tsc2nsec(tsc_time);
+}