1/* 2 * libbenchtsc is a simple benchmarking library that uses the rdtsc 3 * x86 instruction. 4 * Copyright (c) 2014, Simon Gerber <gesimu@gmail.com> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19*/ 20 21#ifndef BENCH_RDTSC_H 22#define BENCH_RDTSC_H 23#include <math.h> 24#include <stdbool.h> 25#include <inttypes.h> 26#include <stdlib.h> 27 28extern bool rdtscp_flag; 29extern double ticks_per_nano; 30 31static inline uint64_t rdtscp(void) 32{ 33 uint32_t eax, edx; 34 __asm volatile ("rdtscp" : "=a" (eax), "=d" (edx) :: "ecx"); 35 return ((uint64_t)edx << 32) | eax; 36} 37 38static inline uint64_t rdtsc(void) 39{ 40 uint32_t eax, edx; 41 __asm volatile ("rdtsc" : "=a" (eax), "=d" (edx)); 42 return ((uint64_t)edx << 32) | eax; 43} 44 45 46static inline uint64_t bench_tsc() 47{ 48 if (rdtscp_flag) { 49 return rdtscp(); 50 } else { 51 return rdtsc(); 52 } 53} 54 55static inline void cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx, 56 uint32_t *ecx, uint32_t *edx) 57{ 58 // make it possible to omit certain return registers 59 uint32_t a, b, c, d; 60 if (eax == NULL) { 61 eax = &a; 62 } 63 if (ebx == NULL) { 64 ebx = &b; 65 } 66 if (ecx == NULL) { 67 ecx = &c; 68 } 69 if (edx == NULL) { 70 edx = &d; 71 } 72 __asm volatile("cpuid" 73 : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) 74 : "a" (function) 75 ); 76} 77 78static inline double bench_tsc_to_ms(uint64_t tsc) 79{ 80 return tsc / (ticks_per_nano * 1e6); 81} 82 83void bench_init(void); 84 85struct bench_calc_st; 86double bench_avg(double *measurements, int runs, struct bench_calc_st *st); 87double bench_sdev(double *measurements, int runs, struct bench_calc_st *st); 88size_t bench_calc_st_sz(void); 89 90#endif // BENCH_RDTSC_H 91