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
|
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>
#include <sys/types.h>
#include <sys/processor.h>
#include <sys/procset.h>
#include <sys/pset.h>
=pod
Prior to Solaris 11.2, the two methods for manipulating CPU
affinity were the processor_bind(2) function and the pset_XXX
suite of functions. The limitation of processor_bind is that
it only allows you to bind a process to either a single core
or to all of them. The limitation of the pset_XXX functions
is that they generally require privileged access. After Solaris 11.2,
users should prefer the processor_affinity(2) function,
This file implements manipulating CPU affinity through
processor_bind(2). See solaris_processor_affinity.xs for
functions using processor_affinity(2) that can be used on
later versions of Solaris.
=cut
int setaffinity_processor_unbind(int pid)
{
int r;
r = processor_bind(P_PID, (id_t) pid, PBIND_NONE, NULL);
if (r != 0) {
if (errno == EFAULT) {
fprintf(stderr,"setaffinity_processor_unbind: error code EFAULT\n");
return 0;
} else if (errno == EINVAL) {
fprintf(stderr,"setaffinity_processor_unbind: error code EINVAL\n");
return 0;
} else if (errno == EPERM) {
fprintf(stderr,"setaffinity_processor_unbind: no permission to bind %d\n",
pid);
return 0;
} else if (errno == ESRCH) {
fprintf(stderr,"setaffinity_processor_unbind: no such PID %d\n", pid);
return 0;
} else {
fprintf(stderr,"setaffinity_processor_unbind: unknown error %d\n", errno);
return 0;
}
}
return 1;
}
int setaffinity_processor_bind(int pid,AV* mask)
{
int r,z;
idtype_t idtype = P_PID;
id_t id = (id_t) pid;
processorid_t processorid = (processorid_t) mask;
processorid_t obind = (processorid_t) mask;
int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
int len_mask = av_len(mask) + 1;
if (len_mask > ncpus) {
fprintf(stderr,"setaffinity_processor_bind: too many items in cpu mask!\n");
return 0;
}
if (len_mask == ncpus || len_mask == 0) { /* unbind */
return setaffinity_processor_unbind(pid);
}
if (len_mask > 1) {
fprintf(stderr,"setaffinity_processor_bind: processor_bind() can only bind a process to a single cpu. Your complete set of desired CPU affinities will not be respected.\n");
}
z = SvIV(*av_fetch(mask, 0, 0));
if (z < 0 || z >= ncpus) {
fprintf(stderr,"setaffinity_processor_bind: invalid cpu spec %d\n", z);
return 0;
}
r = processor_bind(P_PID, (id_t) pid, (processorid_t) z, NULL);
if (r != 0) {
if (errno == EFAULT) {
fprintf(stderr,"setaffinity_processor_bind: error code EFAULT\n");
return 0;
} else if (errno == EINVAL) {
fprintf(stderr,"setaffinity_processor_bind: error code EINVAL\n");
return 0;
} else if (errno == EPERM) {
fprintf(stderr,"setaffinity_processor_bind: no permission to bind %d\n",
pid);
return 0;
} else if (errno == ESRCH) {
fprintf(stderr,"setaffinity_processor_bind: no such PID %d\n", pid);
return 0;
} else {
fprintf(stderr,"setaffinity_processor_bind: unknown error %d\n", errno);
return 0;
}
}
return 1;
}
int getaffinity_processor_bind(int pid, AV* mask)
{
int r,z;
processorid_t obind;
r = processor_bind(P_PID, (id_t) pid, PBIND_QUERY, &obind);
if (r != 0) {
if (errno == EFAULT) {
fprintf(stderr,"getaffinity_processor_bind: error code EFAULT %d\n",r);
return 0;
} else if (errno == EINVAL) {
fprintf(stderr,"getaffinity_processor_bind: error code EINVAL %d\n",r);
return 0;
} else if (errno == EPERM) {
fprintf(stderr,
"getaffinity_processor_bind: no permission to pbind %d (%d)\n",
pid, r);
return 0;
} else if (errno == ESRCH) {
fprintf(stderr,"getaffinity_processor_bind: no such PID %d (%d)\n",
pid, r);
return 0;
} else {
fprintf(stderr,"getaffinity_processor_bind: unknown error %d %d\n",
errno, r);
return 0;
}
}
if (obind == PBIND_NONE) {
/* process is unboud */
int i, n;
n = sysconf(_SC_NPROCESSORS_ONLN);
av_clear(mask);
for (i=0; i<n; i++) {
av_push(mask, newSvIV(i));
}
return 1;
}
av_clear(mask);
av_push(mask, newSvIV(obind));
return 1;
}
MODULE = Sys::CpuAffinity PACKAGE = Sys::CpuAffinity
int
xs_getaffinity_processor_bind(pid,mask)
int pid
AV *mask
CODE:
RETVAL = getaffinity_processor_bind(pid);
OUTPUT:
RETVAL
int
xs_setaffinity_processor_bind(pid,mask)
int pid
AV *mask
CODE:
/* Bind a process to a single CPU. For Solaris. */
RETVAL = setaffinity_processor_bind(pid,mask);
OUTPUT:
RETVAL
int
xs_setaffinity_processor_unbind(pid)
int pid
CODE:
/* Allow a process to run on all CPUs. For Solaris. */
RETVAL = setaffinity_processor_unbind(pid);
OUTPUT:
RETVAL
|