2 * Copyright 2013, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
11 #include <sys/prctl.h>
17 extern void thirty_two_instruction_loop(u64 loops
);
19 static void setup_event(struct event
*e
, u64 config
, char *name
)
21 event_init_opts(e
, config
, PERF_TYPE_HARDWARE
, name
);
24 e
->attr
.exclude_kernel
= 1;
25 e
->attr
.exclude_hv
= 1;
26 e
->attr
.exclude_idle
= 1;
29 static int do_count_loop(struct event
*events
, u64 instructions
,
30 u64 overhead
, bool report
)
32 s64 difference
, expected
;
35 prctl(PR_TASK_PERF_EVENTS_ENABLE
);
37 /* Run for 1M instructions */
38 thirty_two_instruction_loop(instructions
>> 5);
40 prctl(PR_TASK_PERF_EVENTS_DISABLE
);
42 event_read(&events
[0]);
43 event_read(&events
[1]);
45 expected
= instructions
+ overhead
;
46 difference
= events
[0].result
.value
- expected
;
47 percentage
= (double)difference
/ events
[0].result
.value
* 100;
50 event_report(&events
[0]);
51 event_report(&events
[1]);
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
);
59 event_reset(&events
[0]);
60 event_reset(&events
[1]);
63 difference
= -difference
;
65 /* Tolerate a difference below 0.0001 % */
66 difference
*= 10000 * 100;
67 if (difference
/ events
[0].result
.value
)
73 /* Count how many instructions it takes to do a null loop */
74 static u64
determine_overhead(struct event
*events
)
76 u64 current
, overhead
;
79 do_count_loop(events
, 0, 0, false);
80 overhead
= events
[0].result
.value
;
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
);
94 static int test_body(void)
96 struct event events
[2];
99 setup_event(&events
[0], PERF_COUNT_HW_INSTRUCTIONS
, "instructions");
100 setup_event(&events
[1], PERF_COUNT_HW_CPU_CYCLES
, "cycles");
102 if (event_open(&events
[0])) {
103 perror("perf_event_open");
107 if (event_open_with_group(&events
[1], events
[0].fd
)) {
108 perror("perf_event_open");
112 overhead
= determine_overhead(events
);
113 printf("Overhead of null loop: %llu instructions\n", overhead
);
115 /* Run for 1Mi instructions */
116 FAIL_IF(do_count_loop(events
, 1000000, overhead
, true));
118 /* Run for 10Mi instructions */
119 FAIL_IF(do_count_loop(events
, 10000000, overhead
, true));
121 /* Run for 100Mi instructions */
122 FAIL_IF(do_count_loop(events
, 100000000, overhead
, true));
124 /* Run for 1Bi instructions */
125 FAIL_IF(do_count_loop(events
, 1000000000, overhead
, true));
127 /* Run for 16Bi instructions */
128 FAIL_IF(do_count_loop(events
, 16000000000, overhead
, true));
130 /* Run for 64Bi instructions */
131 FAIL_IF(do_count_loop(events
, 64000000000, overhead
, true));
133 event_close(&events
[0]);
134 event_close(&events
[1]);
139 static int count_instructions(void)
141 return eat_cpu(test_body
);
146 return test_harness(count_instructions
, "count_instructions");