root/tools/testing/selftests/powerpc/benchmarks/null_syscall.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mftb
  2. sigalrm_handler
  3. cpu_soak_usecs
  4. get_proc_frequency
  5. do_null_syscall
  6. main

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Test null syscall performance
   4  *
   5  * Copyright (C) 2009-2015 Anton Blanchard, IBM
   6  */
   7 
   8 #define NR_LOOPS 10000000
   9 
  10 #include <string.h>
  11 #include <stdio.h>
  12 #include <stdlib.h>
  13 #include <unistd.h>
  14 #include <time.h>
  15 #include <sys/types.h>
  16 #include <sys/time.h>
  17 #include <signal.h>
  18 
  19 static volatile int soak_done;
  20 unsigned long long clock_frequency;
  21 unsigned long long timebase_frequency;
  22 double timebase_multiplier;
  23 
  24 static inline unsigned long mftb(void)
  25 {
  26         unsigned long low;
  27 
  28         asm volatile("mftb %0" : "=r" (low));
  29 
  30         return low;
  31 }
  32 
  33 static void sigalrm_handler(int unused)
  34 {
  35         soak_done = 1;
  36 }
  37 
  38 /*
  39  * Use a timer instead of busy looping on clock_gettime() so we don't
  40  * pollute profiles with glibc and VDSO hits.
  41  */
  42 static void cpu_soak_usecs(unsigned long usecs)
  43 {
  44         struct itimerval val;
  45 
  46         memset(&val, 0, sizeof(val));
  47         val.it_value.tv_usec = usecs;
  48 
  49         signal(SIGALRM, sigalrm_handler);
  50         setitimer(ITIMER_REAL, &val, NULL);
  51 
  52         while (1) {
  53                 if (soak_done)
  54                         break;
  55         }
  56 
  57         signal(SIGALRM, SIG_DFL);
  58 }
  59 
  60 /*
  61  * This only works with recent kernels where cpufreq modifies
  62  * /proc/cpuinfo dynamically.
  63  */
  64 static void get_proc_frequency(void)
  65 {
  66         FILE *f;
  67         char line[128];
  68         char *p, *end;
  69         unsigned long v;
  70         double d;
  71         char *override;
  72 
  73         /* Try to get out of low power/low frequency mode */
  74         cpu_soak_usecs(0.25 * 1000000);
  75 
  76         f = fopen("/proc/cpuinfo", "r");
  77         if (f == NULL)
  78                 return;
  79 
  80         timebase_frequency = 0;
  81 
  82         while (fgets(line, sizeof(line), f) != NULL) {
  83                 if (strncmp(line, "timebase", 8) == 0) {
  84                         p = strchr(line, ':');
  85                         if (p != NULL) {
  86                                 v = strtoull(p + 1, &end, 0);
  87                                 if (end != p + 1)
  88                                         timebase_frequency = v;
  89                         }
  90                 }
  91 
  92                 if (((strncmp(line, "clock", 5) == 0) ||
  93                      (strncmp(line, "cpu MHz", 7) == 0))) {
  94                         p = strchr(line, ':');
  95                         if (p != NULL) {
  96                                 d = strtod(p + 1, &end);
  97                                 if (end != p + 1) {
  98                                         /* Find fastest clock frequency */
  99                                         if ((d * 1000000ULL) > clock_frequency)
 100                                                 clock_frequency = d * 1000000ULL;
 101                                 }
 102                         }
 103                 }
 104         }
 105 
 106         fclose(f);
 107 
 108         override = getenv("FREQUENCY");
 109         if (override)
 110                 clock_frequency = strtoull(override, NULL, 10);
 111 
 112         if (timebase_frequency)
 113                 timebase_multiplier = (double)clock_frequency
 114                                         / timebase_frequency;
 115         else
 116                 timebase_multiplier = 1;
 117 }
 118 
 119 static void do_null_syscall(unsigned long nr)
 120 {
 121         unsigned long i;
 122 
 123         for (i = 0; i < nr; i++)
 124                 getppid();
 125 }
 126 
 127 #define TIME(A, STR) \
 128 
 129 int main(void)
 130 {
 131         unsigned long tb_start, tb_now;
 132         struct timespec tv_start, tv_now;
 133         unsigned long long elapsed_ns, elapsed_tb;
 134 
 135         get_proc_frequency();
 136 
 137         clock_gettime(CLOCK_MONOTONIC, &tv_start);
 138         tb_start = mftb();
 139 
 140         do_null_syscall(NR_LOOPS);
 141 
 142         clock_gettime(CLOCK_MONOTONIC, &tv_now);
 143         tb_now = mftb();
 144 
 145         elapsed_ns = (tv_now.tv_sec - tv_start.tv_sec) * 1000000000ULL +
 146                         (tv_now.tv_nsec - tv_start.tv_nsec);
 147         elapsed_tb = tb_now - tb_start;
 148 
 149         printf("%10.2f ns %10.2f cycles\n", (float)elapsed_ns / NR_LOOPS,
 150                         (float)elapsed_tb * timebase_multiplier / NR_LOOPS);
 151 
 152         return 0;
 153 }

/* [<][>][^][v][top][bottom][index][help] */