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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>
#include <sys/param.h>
#include <sys/cpuset.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sched.h>
#include <stdio.h>
=pod
Manipulate CPU affinity of FreeBSD processes with
cpuset_getaffinity() and cpuset_setaffinity()
system calls.
=cut
int num_cpus_sysctl()
{
int mib[2], ncpu;
size_t len;
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
len = sizeof(ncpu);
sysctl(mib, 2, &ncpu, &len, NULL, 0);
return ncpu;
}
int getaffinity_freebsd(int pid, AV *mask, int debug)
{
cpulevel_t level = CPU_LEVEL_WHICH;
cpuwhich_t which = CPU_WHICH_PID;
id_t id = (id_t) pid;
size_t setsize;
cpuset_t cpumask;
int i, r;
setsize = sizeof(cpumask);
if (debug) {
fprintf(stderr,"calling cpuset_getaffinity(%d,%d,%d,%d,&cpumask)\n",
(int) level, (int) which, (int) id, (int) setsize);
}
r = cpuset_getaffinity(level, which, id, setsize, &cpumask);
if (debug) {
fprintf(stderr,"cpuset_getaffinity return value: %d\n", r);
}
if (r != 0) {
if (errno == EINVAL) {
fprintf(stderr, "cpuset_getaffinity: invalid level or which arg\n");
} else if (errno == EDEADLK) {
fprintf(stderr, "cpuset_getaffinity: EDEADLK encountered\n");
} else if (errno == EFAULT) {
fprintf(stderr, "cpuset_getaffinity: EFAULT - invalid cpu mask\n");
} else if (errno == ESRCH) {
fprintf(stderr, "cpuset_getaffinity: ESRCH - invalid pid\n");
} else if (errno == ERANGE) {
fprintf(stderr, "cpuset_getaffinity: ERANGE - invalid cpusetsize\n");
} else if (errno == EPERM) {
fprintf(stderr, "cpuset_getaffinity: EPERM - "
"no permission to get affinity for pid=%d\n", pid);
} else {
fprintf(stderr, "cpuset_getaffinity: unknown error %d\n", errno);
}
return 0;
} else {
int ncpu = num_cpus_sysctl();
int nset = 0;
if (debug) {
fprintf(stderr,"num_cpus_sysctl() returned: %d\n", ncpu);
}
if (ncpu <= 0) {
fprintf(stderr, "getaffinity_freebsd: "
"failed to get num cpus from sysctl\n");
ncpu = 32;
}
for (i = 0; i < ncpu; i++) {
if (CPU_ISSET(i, &cpumask)) {
nset++;
av_push(mask, newSViv(i));
if (debug) {
fprintf(stderr,"cpu #%d is set\n", i);
}
} else if (debug) {
fprintf(stderr,"cpu #%d is clear\n", i);
}
}
if (nset == 0) {
fprintf(stderr, "getaffinity_freebsd: no cpu set in cpumask\n");
for (i = 0; i < ncpu; i++) {
av_push(mask, newSViv(i));
}
}
return 1;
}
}
int setaffinity_freebsd(int pid, AV *mask)
{
cpulevel_t level = CPU_LEVEL_WHICH;
cpuwhich_t which = CPU_WHICH_PID;
id_t id = (id_t) pid;
size_t setsize;
cpuset_t cpumask;
int i, r;
int n = av_len(mask) + 1;
int ncpu = num_cpus_sysctl();
CPU_ZERO(&cpumask);
if (ncpu > 0 && n > ncpu) {
fprintf(stderr, "setaffinity_freebsd: "
"mask is larger than the number of cpus!\n");
}
setsize = sizeof(cpumask);
for (i = 0; i < n; i++) {
int proc_id = SvIV(*av_fetch(mask, i, 0));
if (ncpu <= 0 || proc_id < ncpu) {
CPU_SET(proc_id, &cpumask);
} else {
fprintf(stderr, "setaffinity_freebsd: ignoring request to set "
"processor %d which exceeds known num cpus %d\n",
proc_id, ncpu);
}
}
r = cpuset_setaffinity(level, which, id, setsize, &cpumask);
if (r != 0) {
if (errno == EINVAL) {
fprintf(stderr, "cpuset_setaffinity: EINVAL - "
"bad level, which, or mask arg\n");
} else if (errno == EDEADLK) {
fprintf(stderr, "cpuset_setaffinity: EDEADLK found\n");
} else if (errno == EFAULT) {
fprintf(stderr, "cpuset_setaffinity: EFAULT - invalid mask pointer\n");
} else if (errno == ESRCH) {
fprintf(stderr, "cpuset_setaffinity: ESRCH - invalid pid\n");
} else if (errno == ERANGE) {
fprintf(stderr, "cpuset_setaffinity: ERANGE - bad cpusetsize\n");
} else if (errno == EPERM) {
fprintf(stderr, "cpuset_setaffinity: EPERM - "
"no permission to set affinity on pid=%d\n", pid);
} else {
fprintf(stderr, "cpuset_setaffinity: unexpected error no=%d\n", errno);
}
return 0;
} else {
return 1;
}
}
MODULE = Sys::CpuAffinity PACKAGE = Sys::CpuAffinity
int
xs_getaffinity_freebsd(pid,mask,debug)
int pid
AV *mask
int debug
CODE:
RETVAL = getaffinity_freebsd(pid,mask,debug);
OUTPUT:
RETVAL
int
xs_setaffinity_freebsd(pid,mask)
int pid
AV *mask
CODE:
RETVAL = setaffinity_freebsd(pid,mask);
OUTPUT:
RETVAL
int
xs_num_cpus_freebsd()
CODE:
RETVAL = num_cpus_sysctl();
OUTPUT:
RETVAL
|