line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#define PERL_NO_GET_CONTEXT |
2
|
|
|
|
|
|
|
#include "EXTERN.h" |
3
|
|
|
|
|
|
|
#include "perl.h" |
4
|
|
|
|
|
|
|
#include "XSUB.h" |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
#include |
7
|
|
|
|
|
|
|
#include |
8
|
|
|
|
|
|
|
#include |
9
|
|
|
|
|
|
|
//#include |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
struct xs_state { |
12
|
|
|
|
|
|
|
cpu_set_t *set; |
13
|
|
|
|
|
|
|
size_t size; |
14
|
|
|
|
|
|
|
}; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
typedef struct xs_state Linux_Sys_CPU_Affinity; |
17
|
|
|
|
|
|
|
|
18
|
6
|
|
|
|
|
|
void init_set (Linux_Sys_CPU_Affinity *cpuset, AV *av) { |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
static int available_cpus_cnt = 0; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
/* get available amount of CPU cores */ |
23
|
6
|
100
|
|
|
|
|
if (available_cpus_cnt == 0) |
24
|
1
|
|
|
|
|
|
available_cpus_cnt = get_nprocs(); // sysconf(_SC_NPROCESSORS_ONLN); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
/* if we're failed, then use constant, mostly it equals to 1024 */ |
27
|
6
|
50
|
|
|
|
|
if (available_cpus_cnt == -1) |
28
|
0
|
|
|
|
|
|
available_cpus_cnt = CPU_SETSIZE; |
29
|
|
|
|
|
|
|
|
30
|
6
|
100
|
|
|
|
|
if (cpuset->set != NULL) |
31
|
4
|
|
|
|
|
|
CPU_FREE(cpuset->set); |
32
|
|
|
|
|
|
|
|
33
|
6
|
|
|
|
|
|
cpuset->size = CPU_ALLOC_SIZE(available_cpus_cnt); |
34
|
6
|
|
|
|
|
|
cpuset->set = CPU_ALLOC(available_cpus_cnt); |
35
|
|
|
|
|
|
|
|
36
|
6
|
50
|
|
|
|
|
if (cpuset->set == NULL) { |
37
|
0
|
|
|
|
|
|
SV *msg = sv_2mortal( newSVpvf("Failed to allocate memory for %i CPUs", available_cpus_cnt) ); |
38
|
0
|
0
|
|
|
|
|
Perl_croak(pTHX_ (char *) SvPV_nolen(msg)); |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
6
|
|
|
|
|
|
CPU_ZERO_S(cpuset->size, cpuset->set); |
42
|
|
|
|
|
|
|
|
43
|
6
|
100
|
|
|
|
|
if (av != NULL) { |
44
|
|
|
|
|
|
|
SSize_t i; |
45
|
3
|
|
|
|
|
|
SSize_t av_len = av_len(av) + 1; |
46
|
14
|
100
|
|
|
|
|
for (i = 0; i < av_len; i++) { |
47
|
11
|
50
|
|
|
|
|
size_t cpu = SvIV((SV*)*av_fetch(av, i, 0)); // SvIVX to coerce value into IV |
48
|
|
|
|
|
|
|
//Perl_warner_nocontext(aTHX_ packWARN(WARN_QW), "value = %i\n", cpu); |
49
|
11
|
50
|
|
|
|
|
CPU_SET_S(cpu, cpuset->size, cpuset->set); |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
} |
52
|
6
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
3
|
|
|
|
|
|
AV* _extract_and_validate_av(SV *sv) { |
55
|
|
|
|
|
|
|
|
56
|
3
|
50
|
|
|
|
|
if (!SvOK(sv)) |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
57
|
0
|
|
|
|
|
|
Perl_croak(aTHX_ "the CPU's list can't be undefined"); |
58
|
|
|
|
|
|
|
|
59
|
3
|
50
|
|
|
|
|
if (SvTIED_mg(sv, PERL_MAGIC_tied)) |
|
|
0
|
|
|
|
|
|
60
|
0
|
|
|
|
|
|
Perl_croak(aTHX_ "tied objects aren't supported"); |
61
|
|
|
|
|
|
|
|
62
|
3
|
50
|
|
|
|
|
if (!SvROK(sv)) |
63
|
0
|
|
|
|
|
|
Perl_croak(aTHX_ "the CPU's list must be an array reference"); |
64
|
|
|
|
|
|
|
|
65
|
3
|
|
|
|
|
|
SV *ref = SvRV(sv); |
66
|
|
|
|
|
|
|
AV *av; |
67
|
|
|
|
|
|
|
|
68
|
3
|
50
|
|
|
|
|
switch (SvTYPE(ref)) { |
69
|
|
|
|
|
|
|
case SVt_PVAV: // $ref eq "ARRAY" |
70
|
3
|
|
|
|
|
|
av = (AV *) ref; |
71
|
3
|
|
|
|
|
|
break; |
72
|
|
|
|
|
|
|
default: // $ref ne "ARRAY" |
73
|
0
|
|
|
|
|
|
Perl_croak(aTHX_ "the CPU's list must be an array reference"); |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
SSize_t i; |
77
|
3
|
|
|
|
|
|
SSize_t bad_arg = -1; |
78
|
|
|
|
|
|
|
// SV **arr = AvARRAY(av); |
79
|
|
|
|
|
|
|
|
80
|
14
|
100
|
|
|
|
|
for (i = av_len(av); i >= 0; i--) { |
81
|
11
|
|
|
|
|
|
SV *val = (SV *) *av_fetch(av, i, 0); |
82
|
|
|
|
|
|
|
// SV *val = arr[i]; |
83
|
11
|
50
|
|
|
|
|
if (!SvOK(val) || !SvIOK(val)) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
84
|
0
|
|
|
|
|
|
bad_arg = i; |
85
|
0
|
|
|
|
|
|
break; |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
3
|
50
|
|
|
|
|
if (bad_arg != -1) { |
90
|
|
|
|
|
|
|
// postpone SvREFCNT_dec(sv) |
91
|
0
|
|
|
|
|
|
SV *msg = sv_2mortal( newSVpvf("Not an integer at position %i", bad_arg) ); |
92
|
0
|
0
|
|
|
|
|
Perl_croak(pTHX_ (char *) SvPV_nolen(msg)); |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
3
|
|
|
|
|
|
return av; |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
MODULE = Linux::Sys::CPU::Affinity PACKAGE = Linux::Sys::CPU::Affinity |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
PROTOTYPES: DISABLE |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Linux_Sys_CPU_Affinity* new(class_name, sv = &PL_sv_undef) |
103
|
|
|
|
|
|
|
char *class_name |
104
|
|
|
|
|
|
|
SV *sv |
105
|
|
|
|
|
|
|
PREINIT: |
106
|
|
|
|
|
|
|
Linux_Sys_CPU_Affinity *cpuset; |
107
|
2
|
|
|
|
|
|
AV* av = NULL; |
108
|
|
|
|
|
|
|
CODE: |
109
|
|
|
|
|
|
|
|
110
|
2
|
100
|
|
|
|
|
if (SvOK(sv)) |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
111
|
1
|
|
|
|
|
|
av = _extract_and_validate_av(sv); |
112
|
|
|
|
|
|
|
|
113
|
2
|
|
|
|
|
|
cpuset = (Linux_Sys_CPU_Affinity *) malloc(sizeof(Linux_Sys_CPU_Affinity)); |
114
|
|
|
|
|
|
|
|
115
|
2
|
|
|
|
|
|
cpuset->set = NULL; |
116
|
|
|
|
|
|
|
|
117
|
2
|
|
|
|
|
|
init_set(cpuset, av); |
118
|
|
|
|
|
|
|
|
119
|
2
|
|
|
|
|
|
RETVAL = cpuset; |
120
|
|
|
|
|
|
|
OUTPUT: |
121
|
|
|
|
|
|
|
RETVAL |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
SV* cpu_zero(cpuset) |
125
|
|
|
|
|
|
|
Linux_Sys_CPU_Affinity *cpuset |
126
|
|
|
|
|
|
|
CODE: |
127
|
1
|
|
|
|
|
|
init_set(cpuset, NULL); |
128
|
1
|
|
|
|
|
|
XSRETURN_UNDEF; |
129
|
|
|
|
|
|
|
OUTPUT: |
130
|
|
|
|
|
|
|
RETVAL |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
SV* reset(cpuset, sv = &PL_sv_undef) |
134
|
|
|
|
|
|
|
Linux_Sys_CPU_Affinity *cpuset |
135
|
|
|
|
|
|
|
SV *sv |
136
|
|
|
|
|
|
|
PREINIT: |
137
|
3
|
|
|
|
|
|
AV* av = NULL; |
138
|
|
|
|
|
|
|
CODE: |
139
|
3
|
100
|
|
|
|
|
if (SvOK(sv)) |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
140
|
2
|
|
|
|
|
|
av = _extract_and_validate_av(sv); |
141
|
3
|
|
|
|
|
|
init_set(cpuset, av); |
142
|
3
|
|
|
|
|
|
XSRETURN_UNDEF; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
IV cpu_isset (cpuset, cpu) |
146
|
|
|
|
|
|
|
Linux_Sys_CPU_Affinity *cpuset |
147
|
|
|
|
|
|
|
UV cpu |
148
|
|
|
|
|
|
|
PPCODE: |
149
|
4
|
50
|
|
|
|
|
int res = CPU_ISSET_S((uint32_t) cpu, cpuset->size, cpuset->set); |
|
|
100
|
|
|
|
|
|
150
|
4
|
50
|
|
|
|
|
mXPUSHu( res ); |
151
|
4
|
|
|
|
|
|
XSRETURN(1); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
IV cpu_set (cpuset, cpu) |
155
|
|
|
|
|
|
|
Linux_Sys_CPU_Affinity *cpuset |
156
|
|
|
|
|
|
|
UV cpu |
157
|
|
|
|
|
|
|
PPCODE: |
158
|
1
|
50
|
|
|
|
|
CPU_SET_S((uint32_t) cpu, cpuset->size, cpuset->set); |
159
|
1
|
|
|
|
|
|
XSRETURN_UNDEF; |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
IV cpu_clr (cpuset, cpu) |
163
|
|
|
|
|
|
|
Linux_Sys_CPU_Affinity *cpuset |
164
|
|
|
|
|
|
|
UV cpu |
165
|
|
|
|
|
|
|
PPCODE: |
166
|
1
|
50
|
|
|
|
|
CPU_CLR_S((uint32_t) cpu, cpuset->size, cpuset->set); |
167
|
1
|
|
|
|
|
|
XSRETURN_UNDEF; |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
UV cpu_count(cpuset) |
171
|
|
|
|
|
|
|
Linux_Sys_CPU_Affinity *cpuset |
172
|
|
|
|
|
|
|
PPCODE: |
173
|
7
|
|
|
|
|
|
int cpu_count = CPU_COUNT_S(cpuset->size, cpuset->set); |
174
|
7
|
50
|
|
|
|
|
mXPUSHu( cpu_count ); // PUSHs(sv_2mortal(newSVuv(cpu_count))); |
175
|
7
|
|
|
|
|
|
XSRETURN(1); |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
IV set_affinity(cpuset, pid) |
179
|
|
|
|
|
|
|
Linux_Sys_CPU_Affinity *cpuset |
180
|
|
|
|
|
|
|
UV pid |
181
|
|
|
|
|
|
|
PPCODE: |
182
|
1
|
|
|
|
|
|
int res = sched_setaffinity((pid_t) pid, cpuset->size, cpuset->set); |
183
|
1
|
50
|
|
|
|
|
if (res == -1) { |
184
|
0
|
|
|
|
|
|
SV *error = sv_2mortal(newSV(0)); |
185
|
0
|
|
|
|
|
|
switch (errno) { |
186
|
|
|
|
|
|
|
case EFAULT: |
187
|
0
|
|
|
|
|
|
sv_setpv(error, "A supplied memory address was invalid"); |
188
|
0
|
|
|
|
|
|
break; |
189
|
|
|
|
|
|
|
case EINVAL: |
190
|
0
|
|
|
|
|
|
sv_setpv(error, "The affinity bit mask mask contains no processors that are currently physically on the system and permitted to the thread"); |
191
|
0
|
|
|
|
|
|
break; |
192
|
|
|
|
|
|
|
case EPERM: |
193
|
0
|
|
|
|
|
|
sv_setpv(error, "The calling thread does not have appropriate privileges"); |
194
|
0
|
|
|
|
|
|
break; |
195
|
|
|
|
|
|
|
case ESRCH: |
196
|
0
|
|
|
|
|
|
sv_setpv(error, "The thread whose ID is pid could not be found"); |
197
|
0
|
|
|
|
|
|
break; |
198
|
|
|
|
|
|
|
default: |
199
|
0
|
|
|
|
|
|
sv_setpv(error, "Unknown error has occurred"); |
200
|
|
|
|
|
|
|
} |
201
|
0
|
0
|
|
|
|
|
Perl_croak(pTHX_ (char *) SvPV_nolen(error)); |
202
|
|
|
|
|
|
|
} |
203
|
1
|
50
|
|
|
|
|
mXPUSHi( res ); |
204
|
1
|
|
|
|
|
|
XSRETURN(1); |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
void DESTROY (cpuset) |
208
|
|
|
|
|
|
|
Linux_Sys_CPU_Affinity *cpuset |
209
|
|
|
|
|
|
|
PPCODE: |
210
|
2
|
|
|
|
|
|
CPU_FREE(cpuset->set); |
211
|
2
|
|
|
|
|
|
free(cpuset); |
212
|
2
|
|
|
|
|
|
XSRETURN_UNDEF; |