cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
worker_affinity.h
Go to the documentation of this file.
1
#ifndef CWIST_APP_WORKER_AFFINITY_H
2
#define CWIST_APP_WORKER_AFFINITY_H
3
4
/* Private Linux startup helper; callers must enable GNU affinity APIs. */
5
#include <errno.h>
6
#include <sched.h>
7
#include <stddef.h>
8
9
#include <stdio.h>
10
11
#ifndef CWIST_APP_CPU_SYSFS
12
#define CWIST_APP_CPU_SYSFS "/sys/devices/system/cpu"
13
#endif
14
15
/* Parse a sysfs cpulist ("0,6" or "0-1,8-9") into @p out. Returns 0, or -1
16
* on an unreadable or malformed file. */
17
static
inline
int
cwist_app_read_cpulist(
const
char
*path,
cpu_set_t
*out) {
18
FILE
*
f
=
fopen
(path,
"re"
);
19
if
(!
f
)
return
-1;
20
CPU_ZERO
(out);
21
int
rc
= -1, lo, hi;
22
char
sep
;
23
for
(;;) {
24
if
(
fscanf
(
f
,
"%d"
, &lo) != 1)
break
;
25
hi = lo;
26
int
n
=
fscanf
(
f
,
"%c"
, &
sep
);
27
if
(
n
== 1 &&
sep
==
'-'
) {
28
if
(
fscanf
(
f
,
"%d"
, &hi) != 1)
break
;
29
n
=
fscanf
(
f
,
"%c"
, &
sep
);
30
}
31
if
(lo < 0 ||
hi < lo || hi >
=
CPU_SETSIZE
)
break
;
32
for
(
int
cpu
= lo;
cpu
<= hi;
cpu
++)
CPU_SET
(
cpu
, out);
33
if
(
n
!= 1 ||
sep
==
'\n'
) {
34
rc
= 0;
35
break
;
36
}
37
if
(
sep
!=
','
)
break
;
38
}
39
fclose
(
f
);
40
return
rc
;
41
}
42
43
/* SMT siblings of @p cpu, @p cpu included. Falls back to {cpu} when the
44
* topology is not exposed (containers without sysfs, odd kernels), which
45
* keeps the plain ascending order. */
46
static
inline
void
cwist_app_cpu_siblings(
int
cpu
,
cpu_set_t
*out) {
47
char
path[512];
48
snprintf
(path,
sizeof
(path),
"%s/cpu%d/topology/core_cpus_list"
,
CWIST_APP_CPU_SYSFS
,
cpu
);
49
if
(cwist_app_read_cpulist(path, out) == 0 &&
CPU_ISSET
(
cpu
, out))
return
;
50
snprintf
(path,
sizeof
(path),
"%s/cpu%d/topology/thread_siblings_list"
,
CWIST_APP_CPU_SYSFS
,
51
cpu
);
52
if
(cwist_app_read_cpulist(path, out) == 0 &&
CPU_ISSET
(
cpu
, out))
return
;
53
CPU_ZERO
(out);
54
CPU_SET
(
cpu
, out);
55
}
56
76
static
inline
int
cwist_app_pin_worker(
size_t
worker_index
) {
77
cpu_set_t
allowed
;
78
if
(
sched_getaffinity
(0,
sizeof
(
allowed
), &
allowed
) < 0)
return
-1;
79
int
count
=
CPU_COUNT
(&
allowed
);
80
if
(
count
== 0) {
81
errno
=
EINVAL
;
82
return
-1;
83
}
84
size_t
ordinal
=
worker_index
% (
size_t
)
count
;
85
/* rank[cpu]: allowed siblings below cpu. Only allowed CPUs are filled. */
86
unsigned
short
rank
[
CPU_SETSIZE
];
87
int
max_rank
= 0;
88
for
(
int
cpu
= 0;
cpu
<
CPU_SETSIZE
;
cpu
++) {
89
if
(!
CPU_ISSET
(
cpu
, &
allowed
))
continue
;
90
cpu_set_t
sib
;
91
cwist_app_cpu_siblings(
cpu
, &
sib
);
92
CPU_AND
(&
sib
, &
sib
, &
allowed
);
93
int
r = 0;
94
for
(
int
other
= 0;
other
<
cpu
;
other
++)
95
if
(
CPU_ISSET
(
other
, &
sib
)) r++;
96
rank
[
cpu
] = (
unsigned
short
)r;
97
if
(r >
max_rank
)
max_rank
= r;
98
}
99
for
(
int
r = 0; r <=
max_rank
; r++) {
100
for
(
int
cpu
= 0;
cpu
<
CPU_SETSIZE
;
cpu
++) {
101
if
(!
CPU_ISSET
(
cpu
, &
allowed
) ||
rank
[
cpu
] != r)
continue
;
102
if
(
ordinal
!= 0) {
103
ordinal
--;
104
continue
;
105
}
106
cpu_set_t
selected
;
107
CPU_ZERO
(&
selected
);
108
CPU_SET
(
cpu
, &
selected
);
109
return
sched_setaffinity
(0,
sizeof
(
selected
), &
selected
);
110
}
111
}
112
errno
=
EINVAL
;
113
return
-1;
114
}
115
116
#endif
count
size_t count
Definition
otel.c:58
cap
size_t cap
Definition
otel.c:56
CWIST_APP_CPU_SYSFS
#define CWIST_APP_CPU_SYSFS
Definition
worker_affinity.h:12
src
sys
app
worker_affinity.h
Generated by
1.9.8