2 * Copyright 2014, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
6 #define _GNU_SOURCE /* For CPU_ZERO etc. */
18 int pick_online_cpu(void)
25 if (sched_getaffinity(0, sizeof(mask
), &mask
)) {
26 perror("sched_getaffinity");
30 /* We prefer a primary thread, but skip 0 */
31 for (cpu
= 8; cpu
< CPU_SETSIZE
; cpu
+= 8)
32 if (CPU_ISSET(cpu
, &mask
))
35 /* Search for anything, but in reverse */
36 for (cpu
= CPU_SETSIZE
- 1; cpu
>= 0; cpu
--)
37 if (CPU_ISSET(cpu
, &mask
))
40 printf("No cpus in affinity mask?!\n");
44 int bind_to_cpu(int cpu
)
48 printf("Binding to cpu %d\n", cpu
);
53 return sched_setaffinity(0, sizeof(mask
), &mask
);
56 #define PARENT_TOKEN 0xAA
57 #define CHILD_TOKEN 0x55
59 int sync_with_child(union pipe read_pipe
, union pipe write_pipe
)
61 char c
= PARENT_TOKEN
;
63 FAIL_IF(write(write_pipe
.write_fd
, &c
, 1) != 1);
64 FAIL_IF(read(read_pipe
.read_fd
, &c
, 1) != 1);
65 if (c
!= CHILD_TOKEN
) /* sometimes expected */
71 int wait_for_parent(union pipe read_pipe
)
75 FAIL_IF(read(read_pipe
.read_fd
, &c
, 1) != 1);
76 FAIL_IF(c
!= PARENT_TOKEN
);
81 int notify_parent(union pipe write_pipe
)
85 FAIL_IF(write(write_pipe
.write_fd
, &c
, 1) != 1);
90 int notify_parent_of_error(union pipe write_pipe
)
92 char c
= ~CHILD_TOKEN
;
94 FAIL_IF(write(write_pipe
.write_fd
, &c
, 1) != 1);
99 int wait_for_child(pid_t child_pid
)
103 if (waitpid(child_pid
, &rc
, 0) == -1) {
109 rc
= WEXITSTATUS(rc
);
111 rc
= 1; /* Signal or other */
116 int kill_child_and_wait(pid_t child_pid
)
118 kill(child_pid
, SIGTERM
);
120 return wait_for_child(child_pid
);
123 static int eat_cpu_child(union pipe read_pipe
, union pipe write_pipe
)
128 * We are just here to eat cpu and die. So make sure we can be killed,
129 * and also don't do any custom SIGTERM handling.
131 signal(SIGTERM
, SIG_DFL
);
133 notify_parent(write_pipe
);
134 wait_for_parent(read_pipe
);
136 /* Soak up cpu forever */
142 pid_t
eat_cpu(int (test_function
)(void))
144 union pipe read_pipe
, write_pipe
;
148 cpu
= pick_online_cpu();
150 FAIL_IF(bind_to_cpu(cpu
));
152 if (pipe(read_pipe
.fds
) == -1)
155 if (pipe(write_pipe
.fds
) == -1)
160 exit(eat_cpu_child(write_pipe
, read_pipe
));
162 if (sync_with_child(read_pipe
, write_pipe
)) {
167 printf("main test running as pid %d\n", getpid());
169 rc
= test_function();
176 struct addr_range libc
, vdso
;
178 int parse_proc_maps(void)
180 unsigned long start
, end
;
181 char execute
, name
[128];
185 f
= fopen("/proc/self/maps", "r");
192 /* This skips line with no executable which is what we want */
193 rc
= fscanf(f
, "%lx-%lx %*c%*c%c%*c %*x %*d:%*d %*d %127s\n",
194 &start
, &end
, &execute
, name
);
201 if (strstr(name
, "libc")) {
204 } else if (strstr(name
, "[vdso]")) {
215 #define PARANOID_PATH "/proc/sys/kernel/perf_event_paranoid"
217 bool require_paranoia_below(int level
)
219 unsigned long current
;
226 f
= fopen(PARANOID_PATH
, "r");
232 if (!fgets(buf
, sizeof(buf
), f
)) {
233 printf("Couldn't read " PARANOID_PATH
"?\n");
237 current
= strtoul(buf
, &end
, 10);
240 printf("Couldn't parse " PARANOID_PATH
"?\n");
244 if (current
>= level
)