1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>
#include <linux/unistd.h>
#include <sched.h>
=pod
linux-sched_getaffinity.xs: return CPU affinity with the Linux
sched_getaffinity(2) system call. See also:
linux-sched_setaffinity.xs .
/*
* This declaration isn't used and looks useless. But for some
* reason I don't understand at all, for some versions of perl
* with some build configurations running on some systems,
* this declaration is the difference between XS code that works
* (specifically, passing t/11-exercise-all.t) and code that
* segfaults. For the same reason, the cpu_set_t variables
* in xs_sched_getaffinity_get_affinity() below are declared
* static .
*
* Any insights into this issue would be profoundly appreciated.
*/
=cut
char ___linux_sched_getaffinity_dummy[4096];
void diag()
{
fprintf(stderr,"---\n");
fprintf(stderr,"diag CPU_SETSIZE=%d\n", CPU_SETSIZE);
fprintf(stderr,"diag sizeof(__cpu_mask)=%d\n", (int) sizeof(__cpu_mask));
fprintf(stderr,"diag __NCPUBITS=%d\n", (int) __NCPUBITS);
fprintf(stderr,"diag sizeof(cpu_set_t)=%d\n", (int) sizeof(cpu_set_t));
fprintf(stderr,"diag sizeof(pid_t)=%d\n", (int) sizeof(pid_t));
}
MODULE = Sys::CpuAffinity PACKAGE = Sys::CpuAffinity
int
xs_sched_getaffinity_get_affinity(pid,maskarray,debug_flag)
int pid
AV *maskarray
int debug_flag
CODE:
int i, z;
int r = 0;
int ncpus = __NCPUBITS;
static cpu_set_t _set2, *_set1;
if(debug_flag) diag();
if(debug_flag) fprintf(stderr,"getaffinity0\n");
_set1 = &_set2;
if(debug_flag) {
fprintf(stderr,"getaffinity1 pid=%d size=%d %d ncpu=%d cpuset=%p\n",
(int) pid, (int) CPU_SETSIZE, (int) sizeof(cpu_set_t),
ncpus, (void *) _set1);
}
/* RT 94560: CPU_SETSIZE might be less than sizeof(cpu_set_t) ? */
z = sched_getaffinity((pid_t) pid, sizeof(cpu_set_t), _set1);
#ifdef CPU_COUNT
if (debug_flag) fprintf(stderr,"getaffinity2a ncpus=%d\n", ncpus);
ncpus = CPU_COUNT(_set1);
/* CPU_COUNT is not the correct expression to use -- that is the number
of cpus that the process is currently bound to. */
#endif
if (debug_flag) fprintf(stderr,"getaffinity2b ncpus=%d\n", ncpus);
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
if (debug_flag) fprintf(stderr,"getaffinity2c ncpus=%d\n", ncpus);
ncpus = sysconf(_SC_NPROCESSORS_CONF);
if(debug_flag) fprintf(stderr,"getaffinity2d ncpus=%d\n", ncpus);
if (z) {
if(debug_flag) fprintf(stderr,"getaffinity3 z=%d err=%d\n", z, errno);
r = 0;
} else {
av_clear(maskarray);
if(debug_flag) fprintf(stderr,"getaffinity4\n");
/* tests.reproducible-builds.org/debian/rb-pkg/unstable/i386/
libsys-cpuaffinity-perl.html:
__NCPUBITS=32 but taskset,/proc/cpuinfo say there are 34 cpus */
for (i = 0, r = 0; i < ncpus; i++) {
if(debug_flag) fprintf(stderr,"getaffinity5 i=%d r=%d\n", i, r);
if (CPU_ISSET(i, &_set2)) {
r |= 1;
av_push(maskarray, newSViv(i));
if(debug_flag) fprintf(stderr,"getaffinity6 add %d to mask\n", i);
} else if(debug_flag) {
fprintf(stderr,"getaffinity6 don't add %d to mask\n",i);
}
}
if(debug_flag) fprintf(stderr,"getaffinity7 r=%d\n",r);
}
RETVAL = r;
OUTPUT:
RETVAL
|