File Coverage

lib/Sys/CpuAffinity.xs
Criterion Covered Total %
statement 30 39 76.9
branch 30 48 62.5
condition n/a
subroutine n/a
pod n/a
total 60 87 68.9


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4             #include
5             #include
6              
7              
8              
9              
10             =pod
11            
12             linux-sched_getaffinity.xs: return CPU affinity with the Linux
13             sched_getaffinity(2) system call. See also:
14             linux-sched_setaffinity.xs .
15              
16              
17             /*
18             * This declaration isn't used and looks useless. But for some
19             * reason I don't understand at all, for some versions of perl
20             * with some build configurations running on some systems,
21             * this declaration is the difference between XS code that works
22             * (specifically, passing t/11-exercise-all.t) and code that
23             * segfaults. For the same reason, the cpu_set_t variables
24             * in xs_sched_getaffinity_get_affinity() below are declared
25             * static .
26             *
27             * Any insights into this issue would be profoundly appreciated.
28             */
29              
30             =cut
31            
32             char ___linux_sched_getaffinity_dummy[4096];
33              
34 0           void diag()
35             {
36 0           fprintf(stderr,"---\n");
37 0           fprintf(stderr,"diag CPU_SETSIZE=%d\n", CPU_SETSIZE);
38 0           fprintf(stderr,"diag sizeof(__cpu_mask)=%d\n", (int) sizeof(__cpu_mask));
39 0           fprintf(stderr,"diag __NCPUBITS=%d\n", (int) __NCPUBITS);
40 0           fprintf(stderr,"diag sizeof(cpu_set_t)=%d\n", (int) sizeof(cpu_set_t));
41 0           fprintf(stderr,"diag sizeof(pid_t)=%d\n", (int) sizeof(pid_t));
42 0           }
43              
44              
45              
46              
47             =pod
48              
49             linux-sched_setaffinity.xs: update CPU affinity with the Linux
50             sched_setaffinity(2) system call. See also:
51             linux-sched_getaffinity.xs .
52              
53             =cut
54              
55              
56              
57              
58             MODULE = Sys::CpuAffinity PACKAGE = Sys::CpuAffinity
59              
60             int
61             xs_fortytwo()
62             CODE:
63             /* The purpose of this trivial code snippet is to
64             see whether you can compile something, anything,
65             during this build process.
66              
67             If this doesn't compile, then you probably don't have
68             a compiler or it is badly misconfigured, and you
69             won't be able to generate any XS code with this
70             distribution. This would not necessarily mean that
71             this module wouldn't work -- it may still be possible
72             to manipulate CPU affinities on your system with Pure
73             Perl calls or with external utilities available on
74             your system.
75              
76             If this is the ONLY thing that compiles, then your
77             system-specific snippets might be incorrect, or your
78             system might be obscure enough that no system-specific
79             snippets have been developed for it yet. */
80             RETVAL = 42;
81             OUTPUT:
82             RETVAL
83              
84              
85              
86              
87              
88              
89              
90              
91             int
92             xs_sched_getaffinity_get_affinity(pid,maskarray,debug_flag)
93             int pid
94             AV *maskarray
95             int debug_flag
96             CODE:
97             int i, z;
98             int r = 0;
99             int ncpus = __NCPUBITS;
100             static cpu_set_t _set2, *_set1;
101              
102 50 50         if(debug_flag) diag();
103 50 50         if(debug_flag) fprintf(stderr,"getaffinity0\n");
104 50           _set1 = &_set2;
105 50 50         if(debug_flag) {
106 0           fprintf(stderr,"getaffinity1 pid=%d size=%d %d ncpu=%d cpuset=%p %d\n",
107             (int) pid, (int) CPU_SETSIZE, (int) sizeof(cpu_set_t),
108             ncpus, (void *) _set1, ncpus);
109             }
110             /* RT 94560: CPU_SETSIZE might be less than sizeof(cpu_set_t) ? */
111 50           z = sched_getaffinity((pid_t) pid, sizeof(cpu_set_t), _set1);
112             #ifdef CPU_COUNT
113             /* CPU_COUNT() can undercount the number of cpus? And __NCPUBITS can
114             * overcount. I don't know if there's any harm in that.
115             */
116             #endif
117 50 50         if(debug_flag) fprintf(stderr,"getaffinity2 ncpus=%d\n", ncpus);
118 50 100         if (z) {
119 6 50         if(debug_flag) fprintf(stderr,"getaffinity3 z=%d err=%d\n", z, errno);
120             r = 0;
121             } else {
122             int nn = ncpus * 4;
123             if (nn > __NCPUBITS) nn = __NCPUBITS;
124            
125 44           av_clear(maskarray);
126 44 50         if(debug_flag) fprintf(stderr,"getaffinity5\n");
127             /* tests.reproducible-builds.org/debian/rb-pkg/unstable/i386/
128             libsys-cpuaffinity-perl.html:
129             __NCPUBITS=32 but taskset,/proc/cpuinfo say there are 34 cpus */
130 2860 100         for (i = 0, r = 0; i < nn; i++) {
131 2816 50         if(debug_flag) fprintf(stderr,"getaffinity6 i=%d r=%d\n", i, r);
132 2816 50         if (CPU_ISSET(i, &_set2)) {
    100          
    100          
133             r |= 1;
134 400           av_push(maskarray, newSViv(i));
135 400 50         if(debug_flag) fprintf(stderr,"getaffinity8 add %d to mask\n", i);
136             }
137             }
138 44 50         if(debug_flag) fprintf(stderr,"getaffinitya r=%d\n",r);
139             }
140             RETVAL = r;
141             OUTPUT:
142             RETVAL
143              
144              
145              
146              
147              
148             int
149             xs_sched_setaffinity_set_affinity(pid,mask,debug_flag)
150             int pid
151             AV *mask
152             int debug_flag
153             CODE:
154             static cpu_set_t cpumask;
155             int i,r;
156            
157 16           CPU_ZERO(&cpumask);
158 168 100         for (i=0; i <= av_len(mask); i++) {
159 152 50         int c = SvIV(*av_fetch(mask,i,0));
160 152 50         if (debug_flag) fprintf(stderr,"sched_setaffinity%d = %d\n", i, c);
161 152 50         CPU_SET(c, &cpumask);
162             }
163 16           r = sched_setaffinity(pid, sizeof(cpu_set_t), &cpumask);
164 16 50         if (debug_flag) fprintf(stderr,"sched_setaffinity(%d,%d,...) = %d\n", pid, sizeof(cpu_set_t), r);
165 16 100         if (r != 0) {
166 4 50         fprintf(stderr,"result: %d %d %s\n", r, errno,
167 4           errno==EFAULT ? "EFAULT" /* a supplied memory address was invalid */
168             : errno==EINVAL ? "EINVAL" /* the affinity bitmask contains no
169             processors that are physically on the
170             system, or _cpusetsize_ is smaller than
171             the size of the affinity mask used by
172             the kernel */
173 4 50         : errno==EPERM ? "EPERM" /* the calling process does not have
174             appropriate privilieges. The process
175             calling *sched_setaffinity()* needs an
176             effective user ID equal to the user ID
177             or effective user ID of the process
178             identified by _pid_, or it must possess
179             the _CAP_SYS_NICE_ capability. */
180 4 50         : errno==ESRCH ? "ESRCH" /* the process whose ID is _pid_ could not
181             be found */
182 4 50         :"E_WTF");
183             }
184 16           RETVAL = !r;
185             OUTPUT:
186             RETVAL
187              
188              
189              
190              
191              
192              
193