#ifndef _CORE_TIMER_H_ #define _CORE_TIMER_H_ template class CoreTimer { CoreTimer() { index_ = 0; freq_in_100mhz_ = MeasureTSCFreqHz(); } ~CoreTimer() { if (index_ >= Size) { printf("ERROR: memory corruption: out of timer data"); abort(); } } // retrieve time double Get() { double n = 0; // AMD Linux timing unsigned int unused; n = __rdtscp(&unused); data_[index_] = 10 * n / freq_in_100mhz_; // unit is ns index_ += 1; } double Print() private : // timer data double data_[Size]; // data index uint32_t index_; // frequency double freq_in_100mhz_; // timing methods uint64_t CoreTimer::CoarseTimestampUs() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC_RAW, &ts); return uint64_t(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000; } uint64_t CoreTimer::MeasureTSCFreqHz() { // Make a coarse interval measurement of TSC ticks for 1 gigacycles. unsigned int unused; uint64_t tscTicksEnd; uint64_t coarseBeginUs = CoarseTimestampUs(); uint64_t tscTicksBegin = __rdtscp(&unused); do { tscTicksEnd = __rdtscp(&unused); } while (tscTicksEnd - tscTicksBegin < 1000000000); uint64_t coarseEndUs = CoarseTimestampUs(); // Compute the TSC frequency and round to nearest 100MHz. uint64_t coarseIntervalNs = (coarseEndUs - coarseBeginUs) * 1000; uint64_t tscIntervalTicks = tscTicksEnd - tscTicksBegin; return (tscIntervalTicks * 10 + (coarseIntervalNs / 2)) / coarseIntervalNs; } }; #endif // _CORE_TIMER_H_