Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2002-2004 Roland McGrath <roland@redhat.com>
3 : : * Copyright (c) 2009-2016 Dmitry V. Levin <ldv@altlinux.org>
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions
8 : : * are met:
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : * 3. The name of the author may not be used to endorse or promote products
15 : : * derived from this software without specific prior written permission.
16 : : *
17 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 : : */
28 : :
29 : : #include "defs.h"
30 : : #include <sched.h>
31 : :
32 : : static unsigned int
33 : 94 : get_cpuset_size(void)
34 : : {
35 : : static unsigned int cpuset_size;
36 : :
37 [ + + ]: 94 : if (!cpuset_size) {
38 : : /*
39 : : * If the cpuset size passed to sched_getaffinity is less
40 : : * than necessary to store the bitmask, the kernel does not
41 : : * look at the mask pointer and fails with EINVAL.
42 : : *
43 : : * If the cpuset size is large enough, the kernel fails with
44 : : * EFAULT on inaccessible mask pointers.
45 : : *
46 : : * This undocumented kernel feature can be used to probe
47 : : * the kernel and find out the minimal valid cpuset size
48 : : * without allocating any memory for the CPU affinity mask.
49 : : */
50 : 12 : cpuset_size = 128;
51 [ + - + - ]: 24 : while (cpuset_size &&
52 [ - + ]: 24 : sched_getaffinity(0, cpuset_size, NULL) == -1 &&
53 : 12 : EINVAL == errno) {
54 : 0 : cpuset_size <<= 1;
55 : : }
56 [ - + ]: 12 : if (!cpuset_size)
57 : 0 : cpuset_size = 128;
58 : : }
59 : :
60 : 94 : return cpuset_size;
61 : : }
62 : :
63 : : static void
64 : 94 : print_affinitylist(struct tcb *const tcp, const kernel_ulong_t addr,
65 : : const unsigned int len)
66 : : {
67 : 94 : const unsigned int max_size = get_cpuset_size();
68 : 94 : const unsigned int umove_size = len < max_size ? len : max_size;
69 : 94 : const unsigned int size =
70 : 94 : (umove_size + current_wordsize - 1) & -current_wordsize;
71 : 94 : const unsigned int ncpu = size * 8;
72 : : void *cpu;
73 : :
74 [ + - ][ + + ]: 94 : if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
[ + + ][ + - ]
75 [ + - ][ - + ]: 36 : !addr || !len || !(cpu = calloc(size, 1))) {
76 : 58 : printaddr(addr);
77 : 58 : return;
78 : : }
79 : :
80 [ + - ]: 36 : if (!umoven_or_printaddr(tcp, addr, umove_size, cpu)) {
81 : 36 : int i = 0;
82 : 36 : const char *sep = "";
83 : :
84 : 36 : tprints("[");
85 : 120 : for (;; i++) {
86 : 156 : i = next_set_bit(cpu, i, ncpu);
87 [ + + ]: 156 : if (i < 0)
88 : 36 : break;
89 : 120 : tprintf("%s%d", sep, i);
90 : 120 : sep = ", ";
91 : : }
92 [ - + ]: 36 : if (size < len)
93 : 0 : tprintf("%s...", sep);
94 : 36 : tprints("]");
95 : : }
96 : :
97 : 36 : free(cpu);
98 : : }
99 : :
100 : 12 : SYS_FUNC(sched_setaffinity)
101 : : {
102 : 12 : const int pid = tcp->u_arg[0];
103 : 12 : const unsigned int len = tcp->u_arg[1];
104 : :
105 : 12 : tprintf("%d, %u, ", pid, len);
106 : 12 : print_affinitylist(tcp, tcp->u_arg[2], len);
107 : :
108 : 12 : return RVAL_DECODED;
109 : : }
110 : :
111 : 164 : SYS_FUNC(sched_getaffinity)
112 : : {
113 : 164 : const int pid = tcp->u_arg[0];
114 : 164 : const unsigned int len = tcp->u_arg[1];
115 : :
116 [ + + ]: 164 : if (entering(tcp)) {
117 : 82 : tprintf("%d, %u, ", pid, len);
118 : : } else {
119 : 82 : print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval);
120 : : }
121 : 164 : return 0;
122 : : }
|