akaros/user/parlib/timing.c
<<
>>
Prefs
   1#include <parlib/arch/arch.h>
   2#include <parlib/common.h>
   3#include <parlib/timing.h>
   4#include <ros/procinfo.h>
   5#include <parlib/stdio.h>
   6
   7uint64_t udelay(uint64_t usec)
   8{
   9        uint64_t start, end, now;
  10
  11        start = read_tsc();
  12        end = start + (get_tsc_freq() * usec) / 1000000;
  13        do {
  14                cpu_relax();
  15                now = read_tsc();
  16        } while (now < end || (now > start && end < start));
  17        return tsc2usec(now);
  18}
  19
  20/* Not super accurate, due to overheads of reading tsc and looping */
  21uint64_t ndelay(uint64_t nsec)
  22{
  23        uint64_t start, end, now;
  24
  25        start = read_tsc();
  26        end = start + (get_tsc_freq() * nsec) / 1000000000;
  27        do {
  28                cpu_relax();
  29                now = read_tsc();
  30        } while (now < end || (now > start && end < start));
  31        return tsc2nsec(now);
  32}
  33
  34/* Difference between the ticks in microseconds */
  35uint64_t udiff(uint64_t begin, uint64_t end)
  36{
  37        return (end - begin) * 1000000 / __procinfo.tsc_freq;
  38}
  39
  40/* Difference between the ticks in nanoseconds */
  41uint64_t ndiff(uint64_t begin, uint64_t end)
  42{
  43        return (end - begin) * 1000000000 / __procinfo.tsc_freq;
  44}
  45
  46/* Conversion btw tsc ticks and time units.  From Akaros's kern/src/time.c */
  47
  48/* We can overflow/wraparound when we multiply up, but we have to divide last,
  49 * or else we lose precision.  If we're too big and will overflow, we'll
  50 * sacrifice precision for correctness, and degrade to the next lower level
  51 * (losing 3 digits worth).  The recursive case shouldn't overflow, since it
  52 * called something that scaled down the tsc_time by more than 1000. */
  53uint64_t tsc2sec(uint64_t tsc_time)
  54{
  55        return tsc_time / get_tsc_freq();
  56}
  57
  58uint64_t tsc2msec(uint64_t tsc_time)
  59{
  60        if (mult_will_overflow_u64(tsc_time, 1000))
  61                return tsc2sec(tsc_time) * 1000;
  62        else
  63                return (tsc_time * 1000) / get_tsc_freq();
  64}
  65
  66uint64_t tsc2usec(uint64_t tsc_time)
  67{
  68        if (mult_will_overflow_u64(tsc_time, 1000000))
  69                return tsc2msec(tsc_time) * 1000;
  70        else
  71                return (tsc_time * 1000000) / get_tsc_freq();
  72}
  73
  74uint64_t tsc2nsec(uint64_t tsc_time)
  75{
  76        if (mult_will_overflow_u64(tsc_time, 1000000000))
  77                return tsc2usec(tsc_time) * 1000;
  78        else
  79                return (tsc_time * 1000000000) / get_tsc_freq();
  80}
  81
  82uint64_t sec2tsc(uint64_t sec)
  83{
  84        if (mult_will_overflow_u64(sec, get_tsc_freq()))
  85                return (uint64_t)(-1);
  86        else
  87                return sec * get_tsc_freq();
  88}
  89
  90uint64_t msec2tsc(uint64_t msec)
  91{
  92        if (mult_will_overflow_u64(msec, get_tsc_freq()))
  93                return sec2tsc(msec / 1000);
  94        else
  95                return (msec * get_tsc_freq()) / 1000;
  96}
  97
  98uint64_t usec2tsc(uint64_t usec)
  99{
 100        if (mult_will_overflow_u64(usec, get_tsc_freq()))
 101                return msec2tsc(usec / 1000);
 102        else
 103                return (usec * get_tsc_freq()) / 1000000;
 104}
 105
 106uint64_t nsec2tsc(uint64_t nsec)
 107{
 108        if (mult_will_overflow_u64(nsec, get_tsc_freq()))
 109                return usec2tsc(nsec / 1000);
 110        else
 111                return (nsec * get_tsc_freq()) / 1000000000;
 112}
 113
 114uint64_t nsec(void)
 115{
 116        return tsc2nsec(read_tsc());
 117}
 118