1 /*
2 * Check decoding of sched_getaffinity and sched_setaffinity syscalls.
3 *
4 * Copyright (c) 2016-2018 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2016-2023 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include "scno.h"
13 #include "pidns.h"
14 #include <sched.h>
15
16 #if defined CPU_ISSET_S && defined CPU_ZERO_S && defined CPU_SET_S
17
18 # include <assert.h>
19 # include <errno.h>
20 # include <stdio.h>
21 # include <unistd.h>
22
23 static const char *errstr;
24
25 static int
26 getaffinity(unsigned long pid, unsigned long size, void *set)
27 {
28 int rc = syscall(__NR_sched_getaffinity, pid, size, set);
29 errstr = sprintrc(rc);
30 return rc;
31 }
32
33 static int
34 setaffinity(unsigned long pid, unsigned long size, void *set)
35 {
36 int rc = syscall(__NR_sched_setaffinity, pid, size, set);
37 errstr = sprintrc(rc);
38 return rc;
39 }
40
41 int
42 main(void)
43 {
44 PIDNS_TEST_INIT;
45
46 unsigned int cpuset_size = 1;
47 const pid_t pid = getpid();
48 const char *pid_str = pidns_pid2str(PT_TGID);
49
50 while (cpuset_size) {
51 assert(getaffinity(pid, cpuset_size, NULL) == -1);
52 if (EFAULT == errno)
53 break;
54 if (EINVAL != errno)
55 perror_msg_and_skip("sched_getaffinity");
56 pidns_print_leader();
57 printf("sched_getaffinity(%d%s, %u, NULL) = %s\n",
58 pid, pid_str, cpuset_size, errstr);
59 cpuset_size <<= 1;
60 }
61 assert(cpuset_size);
62 pidns_print_leader();
63 printf("sched_getaffinity(%d%s, %u, NULL) = %s\n",
64 pid, pid_str, cpuset_size, errstr);
65
66 cpu_set_t *cpuset = tail_alloc(cpuset_size);
67 getaffinity(pid, cpuset_size, cpuset + 1);
68 pidns_print_leader();
69 printf("sched_getaffinity(%d%s, %u, %p) = %s\n",
70 pid, pid_str, cpuset_size, cpuset + 1, errstr);
71
72 int ret_size = getaffinity(pid, cpuset_size, cpuset);
73 if (ret_size < 0)
74 perror_msg_and_fail("sched_getaffinity(%d, %u, %p) = %s\n",
75 pid, (unsigned) cpuset_size, cpuset, errstr);
76 assert(ret_size <= (int) cpuset_size);
77
78 pidns_print_leader();
79 printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, cpuset_size);
80 const char *sep;
81 unsigned int i, cpu;
82 unsigned int first_cpu = -1U;
83 unsigned int first_crop_cpu = -1U;
84 for (i = 0, cpu = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) {
85 if (CPU_ISSET_S(i, (unsigned) ret_size, cpuset)) {
86 printf("%s%u", sep, i);
87 sep = " ";
88 cpu = i;
89 if (first_cpu == -1U)
90 first_cpu = i;
91 if (first_crop_cpu == -1U && i >= 8)
92 first_crop_cpu = i;
93 }
94 }
95 printf("]) = %s\n", errstr);
96
97 long rc = setaffinity(pid, 0, ((char *) cpuset) + cpuset_size);
98 pidns_print_leader();
99 printf("sched_setaffinity(%d%s, 0, []) = %s\n",
100 pid, pid_str, sprintrc(rc));
101
102 rc = setaffinity(pid, 1, ((char *) cpuset) + cpuset_size);
103 pidns_print_leader();
104 printf("sched_setaffinity(%d%s, 1, %p) = %s\n",
105 pid, pid_str, ((char *) cpuset) + cpuset_size, sprintrc(rc));
106
107 static const uint8_t first_oob = BE_LE(SIZEOF_LONG == 4 ? 39 : 7, 56);
108 const unsigned int crop_size = 8;
109 cpu_set_t *crop_cpuset = tail_alloc(crop_size);
110 if (first_crop_cpu != -1U && first_crop_cpu < 56) {
111 CPU_ZERO_S(crop_size, crop_cpuset);
112 CPU_SET_S(first_crop_cpu, crop_size, crop_cpuset);
113 CPU_SET_S(first_oob, crop_size, crop_cpuset);
114 if (setaffinity(pid, crop_size - 1, crop_cpuset))
115 perror_msg_and_skip("sched_setaffinity()");
116 pidns_print_leader();
117 printf("sched_setaffinity(%d%s, 7, [%u]) = 0\n",
118 pid, pid_str, first_crop_cpu);
119 }
120
121 CPU_ZERO_S(cpuset_size, cpuset);
122 CPU_SET_S(cpu, cpuset_size, cpuset);
123 if (setaffinity(pid, cpuset_size, cpuset))
124 perror_msg_and_skip("sched_setaffinity");
125 pidns_print_leader();
126 printf("sched_setaffinity(%d%s, %u, [%u]) = 0\n",
127 pid, pid_str, cpuset_size, cpu);
128
129 const unsigned int big_size = cpuset_size < 128 ? 128 : cpuset_size * 2;
130 cpuset = tail_alloc(big_size);
131 ret_size = getaffinity(pid, big_size, cpuset);
132 if (ret_size < 0)
133 perror_msg_and_fail("sched_getaffinity(%d, %u, %p) = %s\n",
134 pid, big_size, cpuset, errstr);
135 assert(ret_size <= (int) big_size);
136 pidns_print_leader();
137 printf("sched_getaffinity(%d%s, %u, [", pid, pid_str, big_size);
138 for (i = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) {
139 if (CPU_ISSET_S(i, (unsigned) ret_size, cpuset)) {
140 printf("%s%u", sep, i);
141 sep = " ";
142 }
143 }
144 printf("]) = %s\n", errstr);
145
146 pidns_print_leader();
147 puts("+++ exited with 0 +++");
148 return 0;
149 }
150
151 #else
152
153 SKIP_MAIN_UNDEFINED("CPU_ISSET_S && CPU_ZERO_S && CPU_SET_S")
154
155 #endif