From: Dmitry V. Levin Date: Thu, 7 Jan 2016 00:31:33 +0000 (+0000) Subject: Fix and enhance decoding of sched_[gs]etaffinity syscalls X-Git-Tag: v4.12~677 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6bf08e3e4a2f1b249bea566fe3e4dc84fb008c11;p=strace 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 . (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 --- diff --git a/NEWS b/NEWS index f66d3212..03c64a83 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,8 @@ Noteworthy changes in release ?.?? (????-??-??) =============================================== * Improvements - * Enhanced decoding of personality syscall. + * Enhanced decoding of personality, sched_getaffinity, + and sched_setaffinity syscalls. * Bug fixes * Fixed build on arc, metag, nios2, or1k, and tile architectures. diff --git a/affinity.c b/affinity.c index 55bc7e12..6b6eaa33 100644 --- a/affinity.c +++ b/affinity.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2002-2004 Roland McGrath - * Copyright (c) 2009-2015 Dmitry V. Levin + * Copyright (c) 2009-2016 Dmitry V. Levin * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,56 +27,82 @@ */ #include "defs.h" +#include + +static unsigned int +get_cpuset_size(void) +{ + static unsigned int cpuset_size; + + if (!cpuset_size) { + pid_t pid = getpid(); + cpuset_size = 128; + while (cpuset_size && + sched_getaffinity(pid, cpuset_size, NULL) == -1 && + EINVAL == errno) { + cpuset_size <<= 1; + } + if (!cpuset_size) + cpuset_size = 128; + } + + return cpuset_size; +} static void print_affinitylist(struct tcb *tcp, const unsigned long addr, const unsigned int len) { - unsigned long w; - const unsigned int size = len * sizeof(w); - const unsigned long end = addr + size; - unsigned long cur, abbrev_end; + const unsigned int max_size = get_cpuset_size(); + const unsigned int umove_size = len < max_size ? len : max_size; + const unsigned int size = + (umove_size + current_wordsize - 1) & -current_wordsize; + const unsigned int ncpu = size * 8; + void *cpu; if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) || - !addr || !len || size / sizeof(w) != len || end < addr) { + !addr || !len || !(cpu = calloc(size, 1))) { printaddr(addr); return; } - if (abbrev(tcp)) { - abbrev_end = addr + max_strlen * sizeof(w); - if (abbrev_end < addr) - abbrev_end = end; - } else { - abbrev_end = end; - } + if (!umoven_or_printaddr(tcp, addr, umove_size, cpu)) { + int i = 0; + const char *sep = ""; - tprints("["); - for (cur = addr; cur < end; cur += sizeof(w)) { - if (cur > addr) - tprints(", "); - if (cur >= abbrev_end) { - tprints("..."); - break; + tprints("["); + for (;; i++) { + i = next_set_bit(cpu, i, ncpu); + if (i < 0) + break; + tprintf("%s%d", sep, i); + sep = " "; } - if (umove_or_printaddr(tcp, cur, &w)) - break; - tprintf("%lx", w); + if (size < len) + tprintf("%s...", sep); + tprints("]"); } - tprints("]"); + + free(cpu); } SYS_FUNC(sched_setaffinity) { - tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); - print_affinitylist(tcp, tcp->u_arg[2], tcp->u_arg[1]); + const int pid = tcp->u_arg[0]; + const unsigned int len = tcp->u_arg[1]; + + tprintf("%d, %u, ", pid, len); + print_affinitylist(tcp, tcp->u_arg[2], len); return RVAL_DECODED; } SYS_FUNC(sched_getaffinity) { + const int pid = tcp->u_arg[0]; + const unsigned int len = tcp->u_arg[1]; + if (entering(tcp)) { - tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); + tprintf("%d, %u, ", pid, len); } else { print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval); } diff --git a/tests/.gitignore b/tests/.gitignore index d0eb9802..cfe1e9fb 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -68,6 +68,7 @@ readlink readlinkat restart_syscall rt_sigqueueinfo +sched_xetaffinity sched_xetattr scm_rights seccomp diff --git a/tests/Makefile.am b/tests/Makefile.am index 33a975d8..33f76cbc 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -112,6 +112,7 @@ check_PROGRAMS = \ readlinkat \ restart_syscall \ rt_sigqueueinfo \ + sched_xetaffinity \ sched_xetattr \ scm_rights \ seccomp \ @@ -245,6 +246,7 @@ TESTS = \ readlink.test \ readlinkat.test \ rt_sigqueueinfo.test \ + sched_xetaffinity.test \ sched_xetattr.test \ scm_rights-fd.test \ seccomp.test \ diff --git a/tests/sched_xetaffinity.c b/tests/sched_xetaffinity.c new file mode 100644 index 00000000..ef44c59d --- /dev/null +++ b/tests/sched_xetaffinity.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tests.h" +#include +#include + +#if defined __NR_sched_getaffinity && defined __NR_sched_setaffinity \ + && defined CPU_ISSET_S && defined CPU_ZERO_S && defined CPU_SET_S + +# include +# include +# include +# include + +static int +getaffinity(unsigned long pid, unsigned long size, void *set) +{ + return syscall(__NR_sched_getaffinity, pid, size, set); +} + +static int +setaffinity(unsigned long pid, unsigned long size, void *set) +{ + return syscall(__NR_sched_setaffinity, pid, size, set); +} + +int +main(void) +{ + unsigned int cpuset_size = 1; + pid_t pid = getpid(); + + while (cpuset_size) { + assert(getaffinity(pid, cpuset_size, NULL) == -1); + if (EFAULT == errno) + break; + if (EINVAL != errno) + perror_msg_and_skip("sched_getaffinity"); + printf("sched_getaffinity(%d, %u, NULL) = -1 EINVAL (%m)\n", + pid, cpuset_size); + cpuset_size <<= 1; + } + assert(cpuset_size); + printf("sched_getaffinity(%d, %u, NULL) = -1 EFAULT (%m)\n", + pid, cpuset_size); + + cpu_set_t *cpuset = tail_alloc(cpuset_size); + assert(getaffinity(pid, cpuset_size, cpuset) == (int) cpuset_size); + printf("sched_getaffinity(%d, %u, [", pid, cpuset_size); + const char *sep; + unsigned int i, cpu; + for (i = 0, cpu = 0, sep = ""; i < cpuset_size * 8; ++i) { + if (CPU_ISSET_S(i, cpuset_size, cpuset)) { + printf("%s%u", sep, i); + sep = " "; + cpu = i; + } + } + printf("]) = %u\n", cpuset_size); + + CPU_ZERO_S(cpuset_size, cpuset); + CPU_SET_S(cpu, cpuset_size, cpuset); + if (setaffinity(pid, cpuset_size, cpuset)) + perror_msg_and_skip("sched_setaffinity"); + printf("sched_setaffinity(%d, %u, [%u]) = 0\n", + pid, cpuset_size, cpu); + + const unsigned int big_size = cpuset_size < 128 ? 128 : cpuset_size * 2; + cpuset = tail_alloc(big_size); + const int ret_size = getaffinity(pid, big_size, cpuset); + assert(ret_size >= (int) cpuset_size && ret_size <= (int) big_size); + printf("sched_getaffinity(%d, %u, [", pid, big_size); + for (i = 0, sep = ""; i < (unsigned) ret_size * 8; ++i) { + if (CPU_ISSET_S(i, (unsigned) ret_size, cpuset)) { + printf("%s%u", sep, i); + sep = " "; + } + } + printf("]) = %d\n", ret_size); + + puts("+++ exited with 0 +++"); + return 0; +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_sched_getaffinity && __NR_sched_setaffinity" + " && CPU_ISSET_S && CPU_ZERO_S && CPU_SET_S") + +#endif diff --git a/tests/sched_xetaffinity.test b/tests/sched_xetaffinity.test new file mode 100755 index 00000000..b43b5884 --- /dev/null +++ b/tests/sched_xetaffinity.test @@ -0,0 +1,13 @@ +#!/bin/sh + +# Check sched_getaffinity and sched_setaffinity syscalls decoding. + +. "${srcdir=.}/init.sh" + +run_prog > /dev/null +OUT="$LOG.out" +run_strace -a28 -esched_getaffinity,sched_setaffinity $args > "$OUT" +match_diff "$LOG" "$OUT" +rm -f "$OUT" + +exit 0