~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/powerpc/pmu/count_instructions.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Copyright 2013, Michael Ellerman, IBM Corp.
  4  */
  5 
  6 #define _GNU_SOURCE
  7 
  8 #include <stdio.h>
  9 #include <stdbool.h>
 10 #include <string.h>
 11 #include <sys/prctl.h>
 12 
 13 #include "event.h"
 14 #include "utils.h"
 15 #include "lib.h"
 16 
 17 extern void thirty_two_instruction_loop(u64 loops);
 18 
 19 static void setup_event(struct event *e, u64 config, char *name)
 20 {
 21         event_init_opts(e, config, PERF_TYPE_HARDWARE, name);
 22 
 23         e->attr.disabled = 1;
 24         e->attr.exclude_kernel = 1;
 25         e->attr.exclude_hv = 1;
 26         e->attr.exclude_idle = 1;
 27 }
 28 
 29 static int do_count_loop(struct event *events, u64 instructions,
 30                          u64 overhead, bool report)
 31 {
 32         s64 difference, expected;
 33         double percentage;
 34 
 35         prctl(PR_TASK_PERF_EVENTS_ENABLE);
 36 
 37         /* Run for 1M instructions */
 38         thirty_two_instruction_loop(instructions >> 5);
 39 
 40         prctl(PR_TASK_PERF_EVENTS_DISABLE);
 41 
 42         event_read(&events[0]);
 43         event_read(&events[1]);
 44 
 45         expected = instructions + overhead;
 46         difference = events[0].result.value - expected;
 47         percentage = (double)difference / events[0].result.value * 100;
 48 
 49         if (report) {
 50                 event_report(&events[0]);
 51                 event_report(&events[1]);
 52 
 53                 printf("Looped for %llu instructions, overhead %llu\n", instructions, overhead);
 54                 printf("Expected %llu\n", expected);
 55                 printf("Actual   %llu\n", events[0].result.value);
 56                 printf("Delta    %lld, %f%%\n", difference, percentage);
 57         }
 58 
 59         event_reset(&events[0]);
 60         event_reset(&events[1]);
 61 
 62         if (difference < 0)
 63                 difference = -difference;
 64 
 65         /* Tolerate a difference below 0.0001 % */
 66         difference *= 10000 * 100;
 67         if (difference / events[0].result.value)
 68                 return -1;
 69 
 70         return 0;
 71 }
 72 
 73 /* Count how many instructions it takes to do a null loop */
 74 static u64 determine_overhead(struct event *events)
 75 {
 76         u64 current, overhead;
 77         int i;
 78 
 79         do_count_loop(events, 0, 0, false);
 80         overhead = events[0].result.value;
 81 
 82         for (i = 0; i < 100; i++) {
 83                 do_count_loop(events, 0, 0, false);
 84                 current = events[0].result.value;
 85                 if (current < overhead) {
 86                         printf("Replacing overhead %llu with %llu\n", overhead, current);
 87                         overhead = current;
 88                 }
 89         }
 90 
 91         return overhead;
 92 }
 93 
 94 static int test_body(void)
 95 {
 96         struct event events[2];
 97         u64 overhead;
 98 
 99         setup_event(&events[0], PERF_COUNT_HW_INSTRUCTIONS, "instructions");
100         setup_event(&events[1], PERF_COUNT_HW_CPU_CYCLES, "cycles");
101 
102         if (event_open(&events[0])) {
103                 perror("perf_event_open");
104                 return -1;
105         }
106 
107         if (event_open_with_group(&events[1], events[0].fd)) {
108                 perror("perf_event_open");
109                 return -1;
110         }
111 
112         overhead = determine_overhead(events);
113         printf("Overhead of null loop: %llu instructions\n", overhead);
114 
115         /* Run for 1Mi instructions */
116         FAIL_IF(do_count_loop(events, 1000000, overhead, true));
117 
118         /* Run for 10Mi instructions */
119         FAIL_IF(do_count_loop(events, 10000000, overhead, true));
120 
121         /* Run for 100Mi instructions */
122         FAIL_IF(do_count_loop(events, 100000000, overhead, true));
123 
124         /* Run for 1Bi instructions */
125         FAIL_IF(do_count_loop(events, 1000000000, overhead, true));
126 
127         /* Run for 16Bi instructions */
128         FAIL_IF(do_count_loop(events, 16000000000, overhead, true));
129 
130         /* Run for 64Bi instructions */
131         FAIL_IF(do_count_loop(events, 64000000000, overhead, true));
132 
133         event_close(&events[0]);
134         event_close(&events[1]);
135 
136         return 0;
137 }
138 
139 static int count_instructions(void)
140 {
141         return eat_cpu(test_body);
142 }
143 
144 int main(void)
145 {
146         return test_harness(count_instructions, "count_instructions");
147 }
148 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php