0001
0002
0003
0004
0005
0006
0007
0008 #define NR_LOOPS 10000000
0009
0010 #include <string.h>
0011 #include <stdio.h>
0012 #include <stdlib.h>
0013 #include <unistd.h>
0014 #include <time.h>
0015 #include <sys/types.h>
0016 #include <sys/time.h>
0017 #include <sys/syscall.h>
0018 #include <signal.h>
0019
0020 static volatile int soak_done;
0021 unsigned long long clock_frequency;
0022 unsigned long long timebase_frequency;
0023 double timebase_multiplier;
0024
0025 static inline unsigned long mftb(void)
0026 {
0027 unsigned long low;
0028
0029 asm volatile("mftb %0" : "=r" (low));
0030
0031 return low;
0032 }
0033
0034 static void sigalrm_handler(int unused)
0035 {
0036 soak_done = 1;
0037 }
0038
0039
0040
0041
0042
0043 static void cpu_soak_usecs(unsigned long usecs)
0044 {
0045 struct itimerval val;
0046
0047 memset(&val, 0, sizeof(val));
0048 val.it_value.tv_usec = usecs;
0049
0050 signal(SIGALRM, sigalrm_handler);
0051 setitimer(ITIMER_REAL, &val, NULL);
0052
0053 while (1) {
0054 if (soak_done)
0055 break;
0056 }
0057
0058 signal(SIGALRM, SIG_DFL);
0059 }
0060
0061
0062
0063
0064
0065 static void get_proc_frequency(void)
0066 {
0067 FILE *f;
0068 char line[128];
0069 char *p, *end;
0070 unsigned long v;
0071 double d;
0072 char *override;
0073
0074
0075 cpu_soak_usecs(0.25 * 1000000);
0076
0077 f = fopen("/proc/cpuinfo", "r");
0078 if (f == NULL)
0079 return;
0080
0081 timebase_frequency = 0;
0082
0083 while (fgets(line, sizeof(line), f) != NULL) {
0084 if (strncmp(line, "timebase", 8) == 0) {
0085 p = strchr(line, ':');
0086 if (p != NULL) {
0087 v = strtoull(p + 1, &end, 0);
0088 if (end != p + 1)
0089 timebase_frequency = v;
0090 }
0091 }
0092
0093 if (((strncmp(line, "clock", 5) == 0) ||
0094 (strncmp(line, "cpu MHz", 7) == 0))) {
0095 p = strchr(line, ':');
0096 if (p != NULL) {
0097 d = strtod(p + 1, &end);
0098 if (end != p + 1) {
0099
0100 if ((d * 1000000ULL) > clock_frequency)
0101 clock_frequency = d * 1000000ULL;
0102 }
0103 }
0104 }
0105 }
0106
0107 fclose(f);
0108
0109 override = getenv("FREQUENCY");
0110 if (override)
0111 clock_frequency = strtoull(override, NULL, 10);
0112
0113 if (timebase_frequency)
0114 timebase_multiplier = (double)clock_frequency
0115 / timebase_frequency;
0116 else
0117 timebase_multiplier = 1;
0118 }
0119
0120 static void do_null_syscall(unsigned long nr)
0121 {
0122 unsigned long i;
0123
0124 for (i = 0; i < nr; i++)
0125 syscall(__NR_gettid);
0126 }
0127
0128 #define TIME(A, STR) \
0129
0130 int main(void)
0131 {
0132 unsigned long tb_start, tb_now;
0133 struct timespec tv_start, tv_now;
0134 unsigned long long elapsed_ns, elapsed_tb;
0135
0136 get_proc_frequency();
0137
0138 clock_gettime(CLOCK_MONOTONIC, &tv_start);
0139 tb_start = mftb();
0140
0141 do_null_syscall(NR_LOOPS);
0142
0143 clock_gettime(CLOCK_MONOTONIC, &tv_now);
0144 tb_now = mftb();
0145
0146 elapsed_ns = (tv_now.tv_sec - tv_start.tv_sec) * 1000000000ULL +
0147 (tv_now.tv_nsec - tv_start.tv_nsec);
0148 elapsed_tb = tb_now - tb_start;
0149
0150 printf("%10.2f ns %10.2f cycles\n", (float)elapsed_ns / NR_LOOPS,
0151 (float)elapsed_tb * timebase_multiplier / NR_LOOPS);
0152
0153 return 0;
0154 }