2 * Copyright 2013, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
11 #include <sys/prctl.h>
16 extern void thirty_two_instruction_loop(u64 loops
);
18 static void setup_event(struct event
*e
, u64 config
, char *name
)
20 event_init_opts(e
, config
, PERF_TYPE_HARDWARE
, name
);
23 e
->attr
.exclude_kernel
= 1;
24 e
->attr
.exclude_hv
= 1;
25 e
->attr
.exclude_idle
= 1;
28 static int do_count_loop(struct event
*events
, u64 instructions
,
29 u64 overhead
, bool report
)
31 s64 difference
, expected
;
34 prctl(PR_TASK_PERF_EVENTS_ENABLE
);
36 /* Run for 1M instructions */
37 thirty_two_instruction_loop(instructions
>> 5);
39 prctl(PR_TASK_PERF_EVENTS_DISABLE
);
41 event_read(&events
[0]);
42 event_read(&events
[1]);
44 expected
= instructions
+ overhead
;
45 difference
= events
[0].result
.value
- expected
;
46 percentage
= (double)difference
/ events
[0].result
.value
* 100;
49 event_report(&events
[0]);
50 event_report(&events
[1]);
52 printf("Looped for %llu instructions, overhead %llu\n", instructions
, overhead
);
53 printf("Expected %llu\n", expected
);
54 printf("Actual %llu\n", events
[0].result
.value
);
55 printf("Delta %lld, %f%%\n", difference
, percentage
);
58 event_reset(&events
[0]);
59 event_reset(&events
[1]);
62 difference
= -difference
;
64 /* Tolerate a difference below 0.0001 % */
65 difference
*= 10000 * 100;
66 if (difference
/ events
[0].result
.value
)
72 /* Count how many instructions it takes to do a null loop */
73 static u64
determine_overhead(struct event
*events
)
75 u64 current
, overhead
;
78 do_count_loop(events
, 0, 0, false);
79 overhead
= events
[0].result
.value
;
81 for (i
= 0; i
< 100; i
++) {
82 do_count_loop(events
, 0, 0, false);
83 current
= events
[0].result
.value
;
84 if (current
< overhead
) {
85 printf("Replacing overhead %llu with %llu\n", overhead
, current
);
93 static int count_instructions(void)
95 struct event events
[2];
98 setup_event(&events
[0], PERF_COUNT_HW_INSTRUCTIONS
, "instructions");
99 setup_event(&events
[1], PERF_COUNT_HW_CPU_CYCLES
, "cycles");
101 if (event_open(&events
[0])) {
102 perror("perf_event_open");
106 if (event_open_with_group(&events
[1], events
[0].fd
)) {
107 perror("perf_event_open");
111 overhead
= determine_overhead(events
);
112 printf("Overhead of null loop: %llu instructions\n", overhead
);
114 /* Run for 1M instructions */
115 FAIL_IF(do_count_loop(events
, 0x100000, overhead
, true));
117 /* Run for 10M instructions */
118 FAIL_IF(do_count_loop(events
, 0xa00000, overhead
, true));
120 /* Run for 100M instructions */
121 FAIL_IF(do_count_loop(events
, 0x6400000, overhead
, true));
123 /* Run for 1G instructions */
124 FAIL_IF(do_count_loop(events
, 0x40000000, overhead
, true));
126 event_close(&events
[0]);
127 event_close(&events
[1]);
134 return test_harness(count_instructions
, "count_instructions");