]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/numa-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
6 #include "alloc-util.h"
7 #include "cpu-set-util.h"
10 #include "missing_syscall.h"
11 #include "numa-util.h"
12 #include "stdio-util.h"
13 #include "string-table.h"
15 bool numa_policy_is_valid(const NUMAPolicy
*policy
) {
18 if (!mpol_is_valid(numa_policy_get_type(policy
)))
21 if (!policy
->nodes
.set
&&
22 !IN_SET(numa_policy_get_type(policy
), MPOL_DEFAULT
, MPOL_LOCAL
, MPOL_PREFERRED
))
25 if (policy
->nodes
.set
&&
26 numa_policy_get_type(policy
) == MPOL_PREFERRED
&&
27 CPU_COUNT_S(policy
->nodes
.allocated
, policy
->nodes
.set
) != 1)
33 static int numa_policy_to_mempolicy(const NUMAPolicy
*policy
, unsigned long *ret_maxnode
, unsigned long **ret_nodes
) {
34 unsigned node
, bits
= 0, ulong_bits
;
35 _cleanup_free_
unsigned long *out
= NULL
;
41 if (IN_SET(numa_policy_get_type(policy
), MPOL_DEFAULT
, MPOL_LOCAL
) ||
42 (numa_policy_get_type(policy
) == MPOL_PREFERRED
&& !policy
->nodes
.set
)) {
48 bits
= policy
->nodes
.allocated
* 8;
49 ulong_bits
= sizeof(unsigned long) * 8;
51 out
= new0(unsigned long, DIV_ROUND_UP(policy
->nodes
.allocated
, sizeof(unsigned long)));
55 /* We don't make any assumptions about internal type libc is using to store NUMA node mask.
56 Hence we need to convert the node mask to the representation expected by set_mempolicy() */
57 for (node
= 0; node
< bits
; node
++)
58 if (CPU_ISSET_S(node
, policy
->nodes
.allocated
, policy
->nodes
.set
))
59 out
[node
/ ulong_bits
] |= 1ul << (node
% ulong_bits
);
61 *ret_nodes
= TAKE_PTR(out
);
62 *ret_maxnode
= bits
+ 1;
66 int apply_numa_policy(const NUMAPolicy
*policy
) {
68 _cleanup_free_
unsigned long *nodes
= NULL
;
69 unsigned long maxnode
;
73 if (get_mempolicy(NULL
, NULL
, 0, 0, 0) < 0 && errno
== ENOSYS
)
76 if (!numa_policy_is_valid(policy
))
79 r
= numa_policy_to_mempolicy(policy
, &maxnode
, &nodes
);
83 r
= set_mempolicy(numa_policy_get_type(policy
), nodes
, maxnode
);
90 int numa_to_cpu_set(const NUMAPolicy
*policy
, CPUSet
*ret
) {
93 _cleanup_(cpu_set_reset
) CPUSet s
= {};
98 for (i
= 0; i
< policy
->nodes
.allocated
* 8; i
++) {
99 _cleanup_free_
char *l
= NULL
;
100 char p
[STRLEN("/sys/devices/system/node/node//cpulist") + DECIMAL_STR_MAX(size_t) + 1];
101 _cleanup_(cpu_set_reset
) CPUSet part
= {};
103 if (!CPU_ISSET_S(i
, policy
->nodes
.allocated
, policy
->nodes
.set
))
106 xsprintf(p
, "/sys/devices/system/node/node%zu/cpulist", i
);
108 r
= read_one_line_file(p
, &l
);
112 r
= parse_cpu_set(l
, &part
);
116 r
= cpu_set_add_all(&s
, &part
);
127 static const char* const mpol_table
[] = {
128 [MPOL_DEFAULT
] = "default",
129 [MPOL_PREFERRED
] = "preferred",
130 [MPOL_BIND
] = "bind",
131 [MPOL_INTERLEAVE
] = "interleave",
132 [MPOL_LOCAL
] = "local",
135 DEFINE_STRING_TABLE_LOOKUP(mpol
, int);