/* Compile with:  gcc -Wall -o pre pre.c -lrt */
#include <sys/time.h>
#include <sys/resource.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int delay(unsigned long mikros)
  {
  struct timespec ts;
  int err;

  ts.tv_sec = mikros / 1000000L;
  ts.tv_nsec = (mikros % 1000000L) * 1000L;
  err = nanosleep(&ts, (struct timespec *)NULL);
  return (err);
  }

void udelay (unsigned long mikros)
  {
  /* busy wait */
  long int start_time;
  long int time_difference;
  struct timespec gettime_now;

  mikros = mikros * 1000L;
  time_difference = 0;
  clock_gettime(CLOCK_REALTIME, &gettime_now);
  start_time = gettime_now.tv_nsec;  /* Startzeit holen */
  while (time_difference <= mikros)
    {
    clock_gettime(CLOCK_REALTIME, &gettime_now);
    time_difference = gettime_now.tv_nsec - start_time;
    if (time_difference < 0)
      time_difference += 1000000000;  /* Ueberlauf jede Sekunde */
    }
  }

void gettimeofday_benchmark()
  {
  long i;
  struct timespec tv_start, tv_end;
  struct timeval tv_tmp;
  long count = 100001000L;
  clockid_t clockid;

  clock_getcpuclockid(0, &clockid);
  clock_gettime(clockid, &tv_start);
  for(i = 0; i < count; i++)
    gettimeofday(&tv_tmp, NULL);
  clock_gettime(clockid, &tv_end);

  long long diff = (long long)(tv_end.tv_sec - tv_start.tv_sec)*1000000000L;
  diff += (tv_end.tv_nsec - tv_start.tv_nsec);

  printf("%ld cycles in %lld ns = %.1f ns/cycle\n", count, diff, (double)diff / (double)count);
  }


int main ()
  {

  struct timeval t1, t2;
  long long t;

  long microseconds = 999000;

  //nanosleep test
  gettimeofday(&t1, NULL);
  delay(microseconds);
  gettimeofday(&t2, NULL);

  t = ((t2.tv_sec * 1000000) + t2.tv_usec) - ((t1.tv_sec * 1000000) + t1.tv_usec);
  printf("Aufruf von delay(%ld)  dauerte  %lld us\n", microseconds, t);

  //usleep test
  gettimeofday(&t1, NULL);
  usleep(microseconds);
  gettimeofday(&t2, NULL);

  t = ((t2.tv_sec * 1000000) + t2.tv_usec) - ((t1.tv_sec * 1000000) + t1.tv_usec);
  printf("Aufruf von usleep(%ld) dauerte  %lld us\n", microseconds, t);

 //udelay test
  gettimeofday(&t1, NULL);
  udelay(microseconds);
  gettimeofday(&t2, NULL);

  t = ((t2.tv_sec * 1000000) + t2.tv_usec) - ((t1.tv_sec * 1000000) + t1.tv_usec);
  printf("Aufruf von udelay(%ld) dauerte  %lld us\n", microseconds, t);


  //sleep test
  gettimeofday(&t1, NULL);
  sleep(1);
  gettimeofday(&t2, NULL);

  t = ((t2.tv_sec * 1000000) + t2.tv_usec) - ((t1.tv_sec * 1000000) + t1.tv_usec);
  printf("Aufruf von sleep(1)       dauerte %lld us\n", t);

  gettimeofday_benchmark();
  return 0;
  }
