6#include <sys/syscall.h>
8static int self_placement(
void) {
11 for (
int round = 0; round < 3 * sc_count; ++round) {
12 int cpu = sc_cpus[round % sc_count];
18 CHECK(sc_register_syscall(SYS_sched_setaffinity, 0,
sizeof(mask), (
long)&mask, &result) == 0);
19 CHECK(result == 0 && sc_tls == 0xb1759e2 && errno == 271);
20 CHECK(sc_sample(cpu) == 0 && sc_mask(0, cpu) == 0);
22 CHECK(sc_sample(cpu) == 0 && sc_tls == 0xb1759e2);
25 if (sched_setaffinity(0,
sizeof(sc_allowed), &sc_allowed))
30 atomic_uint ready, command, ack, stop;
35static void* running_entry(
void* argument) {
37 peer->tid = (pid_t)syscall(SYS_gettid);
38 sc_tls = peer->identity;
39 errno = (int)peer->identity;
40 atomic_store_explicit(&peer->ready, 1, memory_order_release);
41 unsigned acknowledged = 0;
43 while (!atomic_load_explicit(&peer->stop, memory_order_acquire)) {
44 unsigned generation = atomic_load_explicit(&peer->command, memory_order_acquire);
45 unsigned cpu = UINT32_MAX, node = UINT32_MAX;
47 damaged |= sc_register_syscall(SYS_getcpu, (
long)&cpu, (
long)&node, 0, &result) != 0 ||
48 result || node || sc_tls != peer->identity || errno != (int)peer->identity;
49 if (generation != acknowledged) {
52 peer->failed = damaged;
53 acknowledged = generation;
54 atomic_store_explicit(&peer->ack, generation, memory_order_release);
57 return (
void*)(intptr_t)damaged;
59static int peer_placement(
void) {
60 int failed = 0, created = 0;
61 struct running_peer peers[2] = {{.identity = 731}, {.identity = 829}};
63 for (
int i = 0; i < 2; ++i) {
64 CHECK(pthread_create(&threads[i], NULL, running_entry, &peers[i]) == 0);
66 CHECK(sc_wait(&peers[i].ready, 1) == 0);
67 CHECK(peers[i].tid > 0 && peers[i].tid != (pid_t)syscall(SYS_gettid));
69 for (
unsigned round = 1; round <= (unsigned)(6 * sc_count); ++round) {
70 int expected[2] = {sc_cpus[round % (unsigned)sc_count],
71 sc_cpus[(
unsigned)(sc_count - 1) - round % (
unsigned)sc_count]};
72 for (
int i = 0; i < 2; ++i) {
73 CHECK(sc_pin(peers[i].tid, expected[i]) == 0);
74 CHECK(sc_mask(peers[i].tid, expected[i]) == 0);
77 atomic_store_explicit(&peers[i].command, round, memory_order_release);
79 for (
int i = 0; i < 2; ++i) {
80 CHECK(sc_wait(&peers[i].ack, round) == 0);
81 CHECK(!peers[i].failed && peers[i].cpu == (
unsigned)expected[i] && !peers[i].node);
84 for (
int i = 0; i < 2; ++i) {
86 CHECK(pthread_setaffinity_np(threads[i],
sizeof(sc_allowed), &sc_allowed) == 0);
87 CHECK(pthread_getaffinity_np(threads[i],
sizeof(got), &got) == 0 &&
88 CPU_EQUAL(&got, &sc_allowed));
91 for (
int i = 0; i < created; ++i)
92 atomic_store_explicit(&peers[i].stop, 1, memory_order_release);
93 for (
int i = 0; i < created; ++i) {
95 if (pthread_join(threads[i], &result) || result)
100int sc_placement(
void) {
101 return self_placement() || peer_placement();