subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 1 | /******************************************************************************/ |
| 2 | /* */ |
| 3 | /* Paul Mackerras <paulus@samba.org>, 2009 */ |
| 4 | /* */ |
| 5 | /* This program is free software; you can redistribute it and/or modify */ |
| 6 | /* it under the terms of the GNU General Public License as published by */ |
| 7 | /* the Free Software Foundation; either version 2 of the License, or */ |
| 8 | /* (at your option) any later version. */ |
| 9 | /* */ |
| 10 | /* This program is distributed in the hope that it will be useful, */ |
| 11 | /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ |
| 12 | /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ |
| 13 | /* the GNU General Public License for more details. */ |
| 14 | /* */ |
| 15 | /* You should have received a copy of the GNU General Public License */ |
| 16 | /* along with this program; if not, write to the Free Software */ |
Wanlong Gao | 4548c6c | 2012-10-19 18:03:36 +0800 | [diff] [blame] | 17 | /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 18 | /* */ |
| 19 | /******************************************************************************/ |
| 20 | /* |
| 21 | Here's a little test program that checks whether software counters |
| 22 | (specifically, the task clock counter) work correctly when they're in |
| 23 | a group with hardware counters. |
| 24 | |
| 25 | What it does is to create several groups, each with one hardware |
| 26 | counter, counting instructions, plus a task clock counter. It needs |
| 27 | to know an upper bound N on the number of hardware counters you have |
| 28 | (N defaults to 8), and it creates N+4 groups to force them to be |
| 29 | multiplexed. It also creates an overall task clock counter. |
| 30 | |
| 31 | Then it spins for a while, and then stops all the counters and reads |
| 32 | them. It takes the total of the task clock counters in the groups and |
| 33 | computes the ratio of that total to the overall execution time from |
| 34 | the overall task clock counter. |
| 35 | |
| 36 | That ratio should be equal to the number of actual hardware counters |
| 37 | that can count instructions. If the task clock counters in the groups |
| 38 | don't stop when their group gets taken off the PMU, the ratio will |
| 39 | instead be close to N+4. The program will declare that the test fails |
| 40 | if the ratio is greater than N (actually, N + 0.0001 to allow for FP |
| 41 | rounding errors). |
| 42 | |
| 43 | Could someone run this on x86 on the latest PCL tree and let me know |
| 44 | what happens? I don't have an x86 crash box easily to hand. On |
| 45 | powerpc, it passes, but I think that is because I am missing setting |
| 46 | counter->prev_count in arch/powerpc/kernel/perf_counter.c, and I think |
| 47 | that means that enabling/disabling a group with a task clock counter |
| 48 | in it won't work correctly (I'll do a test program for that next). |
| 49 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 50 | Usage is: ./performance_counter02 [-v] |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 51 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 52 | The -v flag makes it print out the values of each counter. |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 53 | */ |
| 54 | |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 55 | #include <stdio.h> |
| 56 | #include <stddef.h> |
| 57 | #include <stdlib.h> |
| 58 | #include <string.h> |
| 59 | #include <fcntl.h> |
| 60 | #include <poll.h> |
| 61 | #include <unistd.h> |
| 62 | #include <errno.h> |
yaberauneya | ef77253 | 2009-10-09 17:55:43 +0000 | [diff] [blame] | 63 | #include "config.h" |
| 64 | #include <sys/prctl.h> |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 65 | #include <sys/types.h> |
| 66 | #include <linux/types.h> |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 67 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 68 | #if HAVE_PERF_EVENT_ATTR |
| 69 | # include <linux/perf_event.h> |
| 70 | #endif |
| 71 | |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 72 | #include "test.h" |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 73 | #include "safe_macros.h" |
subrata_modak | d076204 | 2009-06-23 14:21:32 +0000 | [diff] [blame] | 74 | #include "linux_syscall_numbers.h" |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 75 | |
Xing Gu | 166c45f | 2014-08-07 10:05:01 +0800 | [diff] [blame] | 76 | char *TCID = "perf_event_open02"; |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 77 | int TST_TOTAL = 1; |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 78 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 79 | #if HAVE_PERF_EVENT_ATTR |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 80 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 81 | #define MAX_CTRS 1000 |
| 82 | #define LOOPS 1000000000 |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 83 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 84 | static int count_hardware_counters(void); |
| 85 | static void setup(void); |
| 86 | static void verify(void); |
| 87 | static void cleanup(void); |
| 88 | static void help(void); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 89 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 90 | static int n, nhw; |
| 91 | static int verbose; |
| 92 | static option_t options[] = { |
| 93 | {"v", &verbose, NULL}, |
| 94 | {NULL, NULL, NULL}, |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 95 | }; |
| 96 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 97 | static int tsk0; |
| 98 | static int hwfd[MAX_CTRS], tskfd[MAX_CTRS]; |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 99 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 100 | int main(int ac, char **av) |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 101 | { |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 102 | int lc; |
Cyril Hrubis | 0b9589f | 2014-05-27 17:40:33 +0200 | [diff] [blame] | 103 | const char *msg; |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 104 | |
| 105 | msg = parse_opts(ac, av, options, help); |
| 106 | if (msg != NULL) |
| 107 | tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
| 108 | |
| 109 | setup(); |
| 110 | |
| 111 | for (lc = 0; TEST_LOOPING(lc); lc++) { |
| 112 | tst_count = 0; |
| 113 | verify(); |
| 114 | } |
| 115 | |
| 116 | cleanup(); |
| 117 | tst_exit(); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 118 | } |
| 119 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 120 | static int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, |
| 121 | int cpu, int group_fd, unsigned long flags) |
| 122 | { |
| 123 | int ret; |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 124 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 125 | ret = ltp_syscall(__NR_perf_event_open, hw_event, pid, cpu, |
| 126 | group_fd, flags); |
| 127 | return ret; |
| 128 | } |
| 129 | |
| 130 | |
| 131 | static void do_work(void) |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 132 | { |
| 133 | int i; |
| 134 | |
| 135 | for (i = 0; i < LOOPS; ++i) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 136 | asm volatile (""::"g" (i)); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 137 | } |
| 138 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 139 | struct read_format { |
| 140 | unsigned long long value; |
| 141 | /* if PERF_FORMAT_TOTAL_TIME_ENABLED */ |
| 142 | unsigned long long time_enabled; |
| 143 | /* if PERF_FORMAT_TOTAL_TIME_RUNNING */ |
| 144 | unsigned long long time_running; |
| 145 | }; |
yaberauneya | 1a1b1fb | 2009-11-27 08:15:35 +0000 | [diff] [blame] | 146 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 147 | static int count_hardware_counters(void) |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 148 | { |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 149 | struct perf_event_attr hw_event; |
| 150 | int i, hwctrs = 0; |
| 151 | int fdarry[MAX_CTRS]; |
| 152 | struct read_format buf; |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 153 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 154 | memset(&hw_event, 0, sizeof(struct perf_event_attr)); |
| 155 | |
| 156 | hw_event.type = PERF_TYPE_HARDWARE; |
| 157 | hw_event.size = sizeof(struct perf_event_attr); |
| 158 | hw_event.disabled = 1; |
| 159 | hw_event.config = PERF_COUNT_HW_INSTRUCTIONS; |
| 160 | hw_event.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | |
| 161 | PERF_FORMAT_TOTAL_TIME_RUNNING; |
| 162 | |
| 163 | for (i = 0; i < MAX_CTRS; i++) { |
| 164 | fdarry[i] = perf_event_open(&hw_event, 0, -1, -1, 0); |
| 165 | if (fdarry[i] == -1) { |
Cyril Hrubis | adedb78 | 2014-08-21 11:20:12 +0200 | [diff] [blame] | 166 | if (errno == ENOENT) { |
| 167 | tst_brkm(TCONF, cleanup, |
| 168 | "PERF_COUNT_HW_INSTRUCTIONS not supported"); |
| 169 | } |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 170 | tst_brkm(TBROK | TERRNO, cleanup, |
| 171 | "perf_event_open failed at iteration:%d", i); |
| 172 | } |
| 173 | |
| 174 | if (prctl(PR_TASK_PERF_EVENTS_ENABLE) == -1) { |
| 175 | tst_brkm(TBROK | TERRNO, cleanup, |
| 176 | "prctl(PR_TASK_PERF_EVENTS_ENABLE) failed"); |
| 177 | } |
| 178 | |
| 179 | do_work(); |
| 180 | |
| 181 | if (prctl(PR_TASK_PERF_EVENTS_DISABLE) == -1) { |
| 182 | tst_brkm(TBROK | TERRNO, cleanup, |
| 183 | "prctl(PR_TASK_PERF_EVENTS_DISABLE) failed"); |
| 184 | } |
| 185 | |
| 186 | if (read(fdarry[i], &buf, sizeof(buf)) != sizeof(buf)) { |
| 187 | tst_brkm(TBROK | TERRNO, cleanup, |
| 188 | "error reading counter(s)"); |
| 189 | } |
| 190 | |
| 191 | if (verbose == 1) { |
| 192 | printf("at iteration:%d value:%lld time_enabled:%lld " |
| 193 | "time_running:%lld\n", i, buf.value, |
| 194 | buf.time_enabled, buf.time_running); |
| 195 | } |
| 196 | |
| 197 | /* |
| 198 | * Normally time_enabled and time_running are the same value. |
| 199 | * But if more events are started than available counter slots |
| 200 | * on the PMU, then multiplexing happens and events run only |
| 201 | * part of the time. Time_enabled and time_running's values |
| 202 | * will be different. In this case the time_enabled and time_ |
| 203 | * running values can be used to scale an estimated value for |
| 204 | * the count. So if buf.time_enabled and buf.time_running are |
| 205 | * not equal, we can think that PMU hardware counters |
| 206 | * multiplexing happens and the number of the opened events |
| 207 | * are the number of max available hardware counters. |
| 208 | */ |
| 209 | if (buf.time_enabled != buf.time_running) { |
| 210 | hwctrs = i; |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 211 | break; |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 212 | } |
| 213 | } |
| 214 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 215 | for (i = 0; i <= hwctrs; i++) |
| 216 | SAFE_CLOSE(cleanup, fdarry[i]); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 217 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 218 | return hwctrs; |
| 219 | } |
| 220 | |
| 221 | static void setup(void) |
| 222 | { |
| 223 | int i; |
| 224 | struct perf_event_attr tsk_event, hw_event; |
| 225 | |
| 226 | /* |
| 227 | * According to perf_event_open's manpage, the official way of |
| 228 | * knowing if perf_event_open() support is enabled is checking for |
| 229 | * the existence of the file /proc/sys/kernel/perf_event_paranoid. |
| 230 | */ |
| 231 | if (access("/proc/sys/kernel/perf_event_paranoid", F_OK) == -1) |
| 232 | tst_brkm(TCONF, NULL, "Kernel doesn't have perf_event support"); |
| 233 | |
| 234 | tst_sig(NOFORK, DEF_HANDLER, cleanup); |
| 235 | |
| 236 | TEST_PAUSE; |
| 237 | |
| 238 | nhw = count_hardware_counters(); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 239 | n = nhw + 4; |
| 240 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 241 | memset(&hw_event, 0, sizeof(struct perf_event_attr)); |
| 242 | memset(&tsk_event, 0, sizeof(struct perf_event_attr)); |
| 243 | |
| 244 | tsk_event.type = PERF_TYPE_SOFTWARE; |
| 245 | tsk_event.size = sizeof(struct perf_event_attr); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 246 | tsk_event.disabled = 1; |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 247 | tsk_event.config = PERF_COUNT_SW_TASK_CLOCK; |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 248 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 249 | hw_event.type = PERF_TYPE_HARDWARE; |
| 250 | hw_event.size = sizeof(struct perf_event_attr); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 251 | hw_event.disabled = 1; |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 252 | hw_event.config = PERF_COUNT_HW_INSTRUCTIONS; |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 253 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 254 | tsk0 = perf_event_open(&tsk_event, 0, -1, -1, 0); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 255 | if (tsk0 == -1) { |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 256 | tst_brkm(TBROK | TERRNO, cleanup, "perf_event_open failed"); |
yaberauneya | 1a1b1fb | 2009-11-27 08:15:35 +0000 | [diff] [blame] | 257 | } else { |
yaberauneya | 1a1b1fb | 2009-11-27 08:15:35 +0000 | [diff] [blame] | 258 | tsk_event.disabled = 0; |
| 259 | for (i = 0; i < n; ++i) { |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 260 | hwfd[i] = perf_event_open(&hw_event, 0, -1, -1, 0); |
| 261 | tskfd[i] = perf_event_open(&tsk_event, 0, -1, |
| 262 | hwfd[i], 0); |
yaberauneya | 1a1b1fb | 2009-11-27 08:15:35 +0000 | [diff] [blame] | 263 | if (tskfd[i] == -1 || hwfd[i] == -1) { |
| 264 | tst_brkm(TBROK | TERRNO, cleanup, |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 265 | "perf_event_open failed"); |
yaberauneya | 1a1b1fb | 2009-11-27 08:15:35 +0000 | [diff] [blame] | 266 | } |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 267 | } |
| 268 | } |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 269 | } |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 270 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 271 | static void cleanup(void) |
| 272 | { |
| 273 | int i; |
| 274 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 275 | for (i = 0; i < n; i++) { |
| 276 | if (hwfd[i] > 0 && close(hwfd[i]) == -1) |
| 277 | tst_resm(TWARN | TERRNO, "close(%d) failed", hwfd[i]); |
| 278 | if (tskfd[i] > 0 && close(tskfd[i]) == -1) |
| 279 | tst_resm(TWARN | TERRNO, "close(%d) failed", tskfd[i]); |
| 280 | } |
| 281 | |
| 282 | if (tsk0 > 0 && close(tsk0) == -1) |
| 283 | tst_resm(TWARN | TERRNO, "close(%d) failed", tsk0); |
| 284 | } |
| 285 | |
| 286 | static void verify(void) |
| 287 | { |
| 288 | unsigned long long vt0, vt[MAX_CTRS], vh[MAX_CTRS]; |
| 289 | unsigned long long vtsum = 0, vhsum = 0; |
| 290 | int i; |
| 291 | double ratio; |
| 292 | |
| 293 | if (prctl(PR_TASK_PERF_EVENTS_ENABLE) == -1) { |
| 294 | tst_brkm(TBROK | TERRNO, cleanup, |
| 295 | "prctl(PR_TASK_PERF_EVENTS_ENABLE) failed"); |
| 296 | } |
| 297 | |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 298 | do_work(); |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 299 | |
| 300 | if (prctl(PR_TASK_PERF_EVENTS_DISABLE) == -1) { |
| 301 | tst_brkm(TBROK | TERRNO, cleanup, |
| 302 | "prctl(PR_TASK_PERF_EVENTS_DISABLE) failed"); |
| 303 | } |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 304 | |
| 305 | if (read(tsk0, &vt0, sizeof(vt0)) != sizeof(vt0)) { |
yaberauneya | 1a1b1fb | 2009-11-27 08:15:35 +0000 | [diff] [blame] | 306 | tst_brkm(TBROK | TERRNO, cleanup, |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 307 | "error reading task clock counter"); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 308 | } |
| 309 | |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 310 | for (i = 0; i < n; ++i) { |
| 311 | if (read(tskfd[i], &vt[i], sizeof(vt[i])) != sizeof(vt[i]) || |
| 312 | read(hwfd[i], &vh[i], sizeof(vh[i])) != sizeof(vh[i])) { |
yaberauneya | 1a1b1fb | 2009-11-27 08:15:35 +0000 | [diff] [blame] | 313 | tst_brkm(TBROK | TERRNO, cleanup, |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 314 | "error reading counter(s)"); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 315 | } |
| 316 | vtsum += vt[i]; |
| 317 | vhsum += vh[i]; |
| 318 | } |
| 319 | |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 320 | tst_resm(TINFO, "overall task clock: %llu", vt0); |
| 321 | tst_resm(TINFO, "hw sum: %llu, task clock sum: %llu", vhsum, vtsum); |
| 322 | |
| 323 | if (verbose == 1) { |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 324 | printf("hw counters:"); |
| 325 | for (i = 0; i < n; ++i) |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 326 | printf(" %llu", vh[i]); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 327 | printf("\ntask clock counters:"); |
| 328 | for (i = 0; i < n; ++i) |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 329 | printf(" %llu", vt[i]); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 330 | printf("\n"); |
| 331 | } |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 332 | |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 333 | ratio = (double)vtsum / vt0; |
yaberauneya | 1a1b1fb | 2009-11-27 08:15:35 +0000 | [diff] [blame] | 334 | tst_resm(TINFO, "ratio: %.2f", ratio); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 335 | if (ratio > nhw + 0.0001) { |
yaberauneya | 1a1b1fb | 2009-11-27 08:15:35 +0000 | [diff] [blame] | 336 | tst_resm(TFAIL, "test failed (ratio was greater than )"); |
| 337 | } else { |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 338 | tst_resm(TPASS, "test passed"); |
subrata_modak | 89823fe | 2009-04-02 06:48:41 +0000 | [diff] [blame] | 339 | } |
Garrett Cooper | 49f7622 | 2010-12-19 10:22:13 -0800 | [diff] [blame] | 340 | } |
Xiaoguang Wang | f40983c | 2014-04-10 12:08:46 +0800 | [diff] [blame] | 341 | |
| 342 | static void help(void) |
| 343 | { |
| 344 | printf("-v print verbose infomation\n"); |
| 345 | } |
| 346 | |
| 347 | #else |
| 348 | |
| 349 | int main(void) |
| 350 | { |
| 351 | tst_brkm(TCONF, NULL, "This system doesn't have " |
| 352 | "header file:<linux/perf_event.h> or " |
| 353 | "no struct perf_event_attr defined"); |
| 354 | } |
| 355 | #endif |