File: solaris_processor_bind.xs

package info (click to toggle)
libsys-cpuaffinity-perl 1.13~03-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 252 kB
  • sloc: perl: 1,261; makefile: 3
file content (178 lines) | stat: -rw-r--r-- 4,953 bytes parent folder | download | duplicates (2)
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