WiscSort / wiscSort / RSW / nano_time.c
nano_time.c
Raw
#include <stdbool.h>
#include <stdio.h>
#include <time.h>
#include "nano_time.h"
//#include <x86intrin.h>
#define USE_RDTSC
#define NS_IN_SECOND 1000000000

#ifdef __MACH__
#include <mach/mach_time.h>
static uint64_t mach_gethrtime() {
	static bool scale = true;
	static double scaling_factor = 1.0;
	static mach_timebase_info_data_t timebase = {0, 0};
	uint64_t time;

	/* This function call is very expensive so it must
	 * be done only once. That being said, this implementation
	 * is not thread safe. We don't really care, because any
	 * number of calls to this function will produce the same
	 * result, so we don't care if one thread overwrites another.
	 */
	if (timebase.denom == 0) {
		mach_timebase_info(&timebase);
		scaling_factor = ((double)timebase.numer)/
			((double)timebase.denom);
		if (scaling_factor == 1.0 || scaling_factor == 0)
			scale = false;
	}

	time = mach_absolute_time();
	if (scale)
		return ((double)time) * scaling_factor;
	else
		return time;
}
#endif

#ifdef __i386
extern __inline__ uint64_t rdtsc(void) {
	uint64_t x;
	__asm__ volatile ("rdtsc" : "=A" (x));
	return x;
}
#elif defined __amd64
extern __inline__ uint64_t rdtsc(void) {
	uint64_t a, d;
//        uint64_t cput_clock_ticks_per_ns = 2600000000000LL;
        double cput_clock_ticks_per_ns = 2.6; //2.6 Ghz TSC
//        _mm_lfence();
//	__asm__ volatile ("lfence; rdtsc" : "=a" (a), "=d" (d));
//        _mm_lfence();
        // Using rdtscp
        uint64_t c;
        __asm__ volatile ("rdtscp" : "=a" (a), "=c" (c), "=d" (d) : : "memory");
        return ((d<<32) | a)/cput_clock_ticks_per_ns;
}
#endif


uint64_t
nano_time(void) {

#ifdef USE_RDTSC
	return rdtsc();
#else
#ifdef __linux__
	struct timespec ts;
	if( clock_gettime(CLOCK_REALTIME, &ts) == 0)
	    return ts.tv_sec * NS_IN_SECOND + ts.tv_nsec;
	else
		return 0;
#elif defined __MACH__
	return mach_gethrtime();
#endif
#endif
}