Skip to content

Commit 6bf08e3

Browse files
committed
Fix and enhance decoding of sched_[gs]etaffinity syscalls
Print cpu_set_t as a set of integers, similar to the way fd_set is printed as a set of descriptors. * affinity.c: Include <sched.h>. (get_cpuset_size): New function. (print_affinitylist): Rewrite using get_cpuset_size and next_set_bit. (sched_getaffinity, sched_setaffinity): Print first two args as ints. * NEWS: Mention this enhancement. * tests/sched_xetaffinity.c: New file. * tests/sched_xetaffinity.test: New test. * tests/Makefile.am (check_PROGRAMS): Add sched_xetaffinity. (TESTS): Add sched_xetaffinity.test. * tests/.gitignore: Add sched_xetaffinity. Reported-by: Joe Korty <[email protected]>
1 parent 6267e4b commit 6bf08e3

File tree

6 files changed

+186
-28
lines changed

6 files changed

+186
-28
lines changed

NEWS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ Noteworthy changes in release ?.?? (????-??-??)
22
===============================================
33

44
* Improvements
5-
* Enhanced decoding of personality syscall.
5+
* Enhanced decoding of personality, sched_getaffinity,
6+
and sched_setaffinity syscalls.
67

78
* Bug fixes
89
* Fixed build on arc, metag, nios2, or1k, and tile architectures.

affinity.c

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright (c) 2002-2004 Roland McGrath <[email protected]>
3-
* Copyright (c) 2009-2015 Dmitry V. Levin <[email protected]>
3+
* Copyright (c) 2009-2016 Dmitry V. Levin <[email protected]>
44
* All rights reserved.
55
*
66
* Redistribution and use in source and binary forms, with or without
@@ -27,56 +27,82 @@
2727
*/
2828

2929
#include "defs.h"
30+
#include <sched.h>
31+
32+
static unsigned int
33+
get_cpuset_size(void)
34+
{
35+
static unsigned int cpuset_size;
36+
37+
if (!cpuset_size) {
38+
pid_t pid = getpid();
39+
cpuset_size = 128;
40+
while (cpuset_size &&
41+
sched_getaffinity(pid, cpuset_size, NULL) == -1 &&
42+
EINVAL == errno) {
43+
cpuset_size <<= 1;
44+
}
45+
if (!cpuset_size)
46+
cpuset_size = 128;
47+
}
48+
49+
return cpuset_size;
50+
}
3051

3152
static void
3253
print_affinitylist(struct tcb *tcp, const unsigned long addr, const unsigned int len)
3354
{
34-
unsigned long w;
35-
const unsigned int size = len * sizeof(w);
36-
const unsigned long end = addr + size;
37-
unsigned long cur, abbrev_end;
55+
const unsigned int max_size = get_cpuset_size();
56+
const unsigned int umove_size = len < max_size ? len : max_size;
57+
const unsigned int size =
58+
(umove_size + current_wordsize - 1) & -current_wordsize;
59+
const unsigned int ncpu = size * 8;
60+
void *cpu;
3861

3962
if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
40-
!addr || !len || size / sizeof(w) != len || end < addr) {
63+
!addr || !len || !(cpu = calloc(size, 1))) {
4164
printaddr(addr);
4265
return;
4366
}
4467

45-
if (abbrev(tcp)) {
46-
abbrev_end = addr + max_strlen * sizeof(w);
47-
if (abbrev_end < addr)
48-
abbrev_end = end;
49-
} else {
50-
abbrev_end = end;
51-
}
68+
if (!umoven_or_printaddr(tcp, addr, umove_size, cpu)) {
69+
int i = 0;
70+
const char *sep = "";
5271

53-
tprints("[");
54-
for (cur = addr; cur < end; cur += sizeof(w)) {
55-
if (cur > addr)
56-
tprints(", ");
57-
if (cur >= abbrev_end) {
58-
tprints("...");
59-
break;
72+
tprints("[");
73+
for (;; i++) {
74+
i = next_set_bit(cpu, i, ncpu);
75+
if (i < 0)
76+
break;
77+
tprintf("%s%d", sep, i);
78+
sep = " ";
6079
}
61-
if (umove_or_printaddr(tcp, cur, &w))
62-
break;
63-
tprintf("%lx", w);
80+
if (size < len)
81+
tprintf("%s...", sep);
82+
tprints("]");
6483
}
65-
tprints("]");
84+
85+
free(cpu);
6686
}
6787

6888
SYS_FUNC(sched_setaffinity)
6989
{
70-
tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
71-
print_affinitylist(tcp, tcp->u_arg[2], tcp->u_arg[1]);
90+
const int pid = tcp->u_arg[0];
91+
const unsigned int len = tcp->u_arg[1];
92+
93+
tprintf("%d, %u, ", pid, len);
94+
print_affinitylist(tcp, tcp->u_arg[2], len);
7295

7396
return RVAL_DECODED;
7497
}
7598

7699
SYS_FUNC(sched_getaffinity)
77100
{
101+
const int pid = tcp->u_arg[0];
102+
const unsigned int len = tcp->u_arg[1];
103+
78104
if (entering(tcp)) {
79-
tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
105+
tprintf("%d, %u, ", pid, len);
80106
} else {
81107
print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval);
82108
}

tests/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ readlink
6868
readlinkat
6969
restart_syscall
7070
rt_sigqueueinfo
71+
sched_xetaffinity
7172
sched_xetattr
7273
scm_rights
7374
seccomp

tests/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ check_PROGRAMS = \
112112
readlinkat \
113113
restart_syscall \
114114
rt_sigqueueinfo \
115+
sched_xetaffinity \
115116
sched_xetattr \
116117
scm_rights \
117118
seccomp \
@@ -245,6 +246,7 @@ TESTS = \
245246
readlink.test \
246247
readlinkat.test \
247248
rt_sigqueueinfo.test \
249+
sched_xetaffinity.test \
248250
sched_xetattr.test \
249251
scm_rights-fd.test \
250252
seccomp.test \

tests/sched_xetaffinity.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright (c) 2016 Dmitry V. Levin <[email protected]>
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
* 1. Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* 2. Redistributions in binary form must reproduce the above copyright
11+
* notice, this list of conditions and the following disclaimer in the
12+
* documentation and/or other materials provided with the distribution.
13+
* 3. The name of the author may not be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18+
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19+
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25+
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
28+
#include "tests.h"
29+
#include <sys/syscall.h>
30+
#include <sched.h>
31+
32+
#if defined __NR_sched_getaffinity && defined __NR_sched_setaffinity \
33+
&& defined CPU_ISSET_S && defined CPU_ZERO_S && defined CPU_SET_S
34+
35+
# include <assert.h>
36+
# include <errno.h>
37+
# include <stdio.h>
38+
# include <unistd.h>
39+
40+
static int
41+
getaffinity(unsigned long pid, unsigned long size, void *set)
42+
{
43+
return syscall(__NR_sched_getaffinity, pid, size, set);
44+
}
45+
46+
static int
47+
setaffinity(unsigned long pid, unsigned long size, void *set)
48+
{
49+
return syscall(__NR_sched_setaffinity, pid, size, set);
50+
}
51+
52+
int
53+
main(void)
54+
{
55+
unsigned int cpuset_size = 1;
56+
pid_t pid = getpid();
57+
58+
while (cpuset_size) {
59+
assert(getaffinity(pid, cpuset_size, NULL) == -1);
60+
if (EFAULT == errno)
61+
break;
62+
if (EINVAL != errno)
63+
perror_msg_and_skip("sched_getaffinity");
64+
printf("sched_getaffinity(%d, %u, NULL) = -1 EINVAL (%m)\n",
65+
pid, cpuset_size);
66+
cpuset_size <<= 1;
67+
}
68+
assert(cpuset_size);
69+
printf("sched_getaffinity(%d, %u, NULL) = -1 EFAULT (%m)\n",
70+
pid, cpuset_size);
71+
72+
cpu_set_t *cpuset = tail_alloc(cpuset_size);
73+
assert(getaffinity(pid, cpuset_size, cpuset) == (int) cpuset_size);
74+
printf("sched_getaffinity(%d, %u, [", pid, cpuset_size);
75+
const char *sep;
76+
unsigned int i, cpu;
77+
for (i = 0, cpu = 0, sep = ""; i < cpuset_size * 8; ++i) {
78+
if (CPU_ISSET_S(i, cpuset_size, cpuset)) {
79+
printf("%s%u", sep, i);
80+
sep = " ";
81+
cpu = i;
82+
}
83+
}
84+
printf("]) = %u\n", cpuset_size);
85+
86+
CPU_ZERO_S(cpuset_size, cpuset);
87+
CPU_SET_S(cpu, cpuset_size, cpuset);
88+
if (setaffinity(pid, cpuset_size, cpuset))
89+
perror_msg_and_skip("sched_setaffinity");
90+
printf("sched_setaffinity(%d, %u, [%u]) = 0\n",
91+
pid, cpuset_size, cpu);
92+
93+
const unsigned int big_size = cpuset_size < 128 ? 128 : cpuset_size * 2;
94+
cpuset = tail_alloc(big_size);
95+
const int ret_size = getaffinity(pid, big_size, cpuset);
96+
assert(ret_size >= (int) cpuset_size && ret_size <= (int) big_size);
97+
printf("sched_getaffinity(%d, %u, [", pid, big_size);
98+
for (i = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) {
99+
if (CPU_ISSET_S(i, (unsigned) ret_size, cpuset)) {
100+
printf("%s%u", sep, i);
101+
sep = " ";
102+
}
103+
}
104+
printf("]) = %d\n", ret_size);
105+
106+
puts("+++ exited with 0 +++");
107+
return 0;
108+
}
109+
110+
#else
111+
112+
SKIP_MAIN_UNDEFINED("__NR_sched_getaffinity && __NR_sched_setaffinity"
113+
" && CPU_ISSET_S && CPU_ZERO_S && CPU_SET_S")
114+
115+
#endif

tests/sched_xetaffinity.test

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/sh
2+
3+
# Check sched_getaffinity and sched_setaffinity syscalls decoding.
4+
5+
. "${srcdir=.}/init.sh"
6+
7+
run_prog > /dev/null
8+
OUT="$LOG.out"
9+
run_strace -a28 -esched_getaffinity,sched_setaffinity $args > "$OUT"
10+
match_diff "$LOG" "$OUT"
11+
rm -f "$OUT"
12+
13+
exit 0

0 commit comments

Comments
 (0)