xref: /spdk/lib/env_dpdk/threads.c (revision 8a4b722644b813f499cc1ee74dfd5b8f50eedf94)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2017 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "env_internal.h"
7 
8 #include <rte_config.h>
9 #include <rte_lcore.h>
10 
11 #include "spdk/cpuset.h"
12 #include "spdk/log.h"
13 #include "spdk/string.h"
14 
15 #define THREAD_SIBLINGS_FILE \
16 	"/sys/devices/system/cpu/cpu%d/topology/thread_siblings"
17 
18 uint32_t
19 spdk_env_get_core_count(void)
20 {
21 	return rte_lcore_count();
22 }
23 
24 uint32_t
25 spdk_env_get_current_core(void)
26 {
27 	return rte_lcore_id();
28 }
29 
30 uint32_t
31 spdk_env_get_main_core(void)
32 {
33 	return rte_get_main_lcore();
34 }
35 
36 uint32_t
37 spdk_env_get_first_core(void)
38 {
39 	return rte_get_next_lcore(-1, 0, 0);
40 }
41 
42 uint32_t
43 spdk_env_get_last_core(void)
44 {
45 	uint32_t i;
46 	uint32_t last_core = UINT32_MAX;
47 
48 	SPDK_ENV_FOREACH_CORE(i) {
49 		last_core = i;
50 	}
51 
52 	assert(last_core != UINT32_MAX);
53 
54 	return last_core;
55 }
56 
57 uint32_t
58 spdk_env_get_next_core(uint32_t prev_core)
59 {
60 	unsigned lcore;
61 
62 	lcore = rte_get_next_lcore(prev_core, 0, 0);
63 	if (lcore == RTE_MAX_LCORE) {
64 		return UINT32_MAX;
65 	}
66 	return lcore;
67 }
68 
69 int32_t
70 spdk_env_get_numa_id(uint32_t core)
71 {
72 	if (core >= RTE_MAX_LCORE) {
73 		return SPDK_ENV_NUMA_ID_ANY;
74 	}
75 
76 	return rte_lcore_to_socket_id(core);
77 }
78 
79 SPDK_LOG_DEPRECATION_REGISTER(env_socket_id, "spdk_env_get_socket_id", "v25.05", 0);
80 
81 uint32_t
82 spdk_env_get_socket_id(uint32_t core)
83 {
84 	SPDK_LOG_DEPRECATED(env_socket_id);
85 	return spdk_env_get_numa_id(core);
86 }
87 
88 int32_t
89 spdk_env_get_first_numa_id(void)
90 {
91 	assert(rte_socket_count() > 0);
92 
93 	return rte_socket_id_by_idx(0);
94 }
95 
96 int32_t
97 spdk_env_get_last_numa_id(void)
98 {
99 	assert(rte_socket_count() > 0);
100 
101 	return rte_socket_id_by_idx(rte_socket_count() - 1);
102 }
103 
104 int32_t
105 spdk_env_get_next_numa_id(int32_t prev_numa_id)
106 {
107 	uint32_t i;
108 
109 	for (i = 0; i < rte_socket_count(); i++) {
110 		if (rte_socket_id_by_idx(i) == prev_numa_id) {
111 			break;
112 		}
113 	}
114 
115 	if ((i + 1) < rte_socket_count()) {
116 		return rte_socket_id_by_idx(i + 1);
117 	} else {
118 		return INT32_MAX;
119 	}
120 }
121 
122 void
123 spdk_env_get_cpuset(struct spdk_cpuset *cpuset)
124 {
125 	uint32_t i;
126 
127 	spdk_cpuset_zero(cpuset);
128 	SPDK_ENV_FOREACH_CORE(i) {
129 		spdk_cpuset_set_cpu(cpuset, i, true);
130 	}
131 }
132 
133 static bool
134 env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core)
135 {
136 #ifdef __linux__
137 	struct spdk_cpuset smt_siblings;
138 	char path[PATH_MAX];
139 	FILE *f;
140 	char *line = NULL;
141 	size_t len = 0;
142 	ssize_t read;
143 	bool valid = false;
144 
145 	snprintf(path, sizeof(path), THREAD_SIBLINGS_FILE, core);
146 	f = fopen(path, "r");
147 	if (f == NULL) {
148 		SPDK_ERRLOG("Could not fopen('%s'): %s\n", path, spdk_strerror(errno));
149 		return false;
150 	}
151 	read = getline(&line, &len, f);
152 	if (read == -1) {
153 		SPDK_ERRLOG("Could not getline() for '%s': %s\n", path, spdk_strerror(errno));
154 		goto ret;
155 	}
156 
157 	/* Remove trailing newline */
158 	line[strlen(line) - 1] = 0;
159 	if (spdk_cpuset_parse(&smt_siblings, line)) {
160 		SPDK_ERRLOG("Could not parse '%s' from '%s'\n", line, path);
161 		goto ret;
162 	}
163 
164 	valid = true;
165 	spdk_cpuset_or(cpuset, &smt_siblings);
166 ret:
167 	free(line);
168 	fclose(f);
169 	return valid;
170 #else
171 	return false;
172 #endif
173 }
174 
175 bool
176 spdk_env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core)
177 {
178 	uint32_t i;
179 
180 	spdk_cpuset_zero(cpuset);
181 
182 	if (core != UINT32_MAX) {
183 		return env_core_get_smt_cpuset(cpuset, core);
184 	}
185 
186 	SPDK_ENV_FOREACH_CORE(i) {
187 		if (!env_core_get_smt_cpuset(cpuset, i)) {
188 			return false;
189 		}
190 	}
191 
192 	return true;
193 }
194 
195 int
196 spdk_env_thread_launch_pinned(uint32_t core, thread_start_fn fn, void *arg)
197 {
198 	int rc;
199 
200 	rc = rte_eal_remote_launch(fn, arg, core);
201 
202 	return rc;
203 }
204 
205 void
206 spdk_env_thread_wait_all(void)
207 {
208 	rte_eal_mp_wait_lcore();
209 }
210