1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
/**
* @file timer.h
*
* @author jeffrey.daily@gmail.com
*
* Copyright 2012 Pacific Northwest National Laboratory. All rights reserved.
*
* Use CPU instructions and inline assembly to query tics and/or wall clock.
*/
#ifndef __TIMER_H__
#define __TIMER_H__
#ifdef __cplusplus
extern "C" {
#endif
/*#define FORCE_SYS_TIME 1*/
#if (defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)) && !defined(_CRAYC) && !defined(FORCE_SYS_TIME)
# define HAVE_RDTSC 1
# if defined(__i386__)
static __inline__ unsigned long long rdtsc(void)
{
unsigned long long int x;
__asm__ volatile(".byte 0x0f, 0x31" : "=A"(x));
return x;
}
# elif defined(__x86_64__)
static __inline__ unsigned long long rdtsc(void)
{
unsigned hi, lo;
__asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
return ((unsigned long long)lo) | (((unsigned long long)hi) << 32);
}
# elif defined(__powerpc__)
static __inline__ unsigned long long rdtsc(void)
{
unsigned long long int result = 0;
unsigned long int upper, lower, tmp;
__asm__ volatile(
"0: \n"
"\tmftbu %0 \n"
"\tmftb %1 \n"
"\tmftbu %2 \n"
"\tcmpw %2,%0 \n"
"\tbne 0b \n"
: "=r"(upper), "=r"(lower), "=r"(tmp)
);
result = upper;
result = result << 32;
result = result | lower;
return (result);
}
# endif
#elif defined(HAVE_SYS_TIME_H) || defined(FORCE_SYS_TIME)
# undef HAVE_SYS_TIME_H
# define HAVE_SYS_TIME_H 1
# include <sys/time.h>
#elif defined(HAVE_WINDOWS_H)
# undef HAVE_WINDOWS_H
# define HAVE_WINDOWS_H 1
# include <windows.h>
static LARGE_INTEGER frequency;
#endif
static unsigned long long timer_start()
{
#if defined(HAVE_RDTSC)
return rdtsc();
#elif defined(HAVE_SYS_TIME_H)
struct timeval timer;
(void)gettimeofday(&timer, NULL);
return timer.tv_sec * 1000000 + timer.tv_usec;
#elif defined(HAVE_WINDOWS_H)
LARGE_INTEGER timer;
QueryPerformanceCounter(&timer);
return timer.QuadPart * 1000 / frequency.QuadPart;
#else
return 0;
#endif
}
/*
static unsigned long long timer_end(unsigned long long begin)
{
return timer_start() - begin;
}
*/
/*
static void timer_init()
{
#if defined(HAVE_RDTSC)
#elif defined(HAVE_SYS_TIME_H)
#elif defined(HAVE_WINDOWS_H)
QueryPerformanceFrequency(&frequency);
#else
#endif
}
*/
/*
static const char *timer_name()
{
#if defined(HAVE_RDTSC)
return "rdtsc";
#elif defined(HAVE_SYS_TIME_H)
return "gettimeofday";
#elif defined(HAVE_WINDOWS_H)
return "windows QueryPerformanceCounter";
#else
return "no timers";
#endif
}
*/
#ifdef __cplusplus
}
#endif
#endif /* __TIMER_H__ */
|