xref: /spdk/lib/env_dpdk/threads.c (revision f71d1c112a0a7ac6fb9676fcde95a76e63a78e62)
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 void
89 spdk_env_get_cpuset(struct spdk_cpuset *cpuset)
90 {
91 	uint32_t i;
92 
93 	spdk_cpuset_zero(cpuset);
94 	SPDK_ENV_FOREACH_CORE(i) {
95 		spdk_cpuset_set_cpu(cpuset, i, true);
96 	}
97 }
98 
99 static bool
100 env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core)
101 {
102 #ifdef __linux__
103 	struct spdk_cpuset smt_siblings;
104 	char path[PATH_MAX];
105 	FILE *f;
106 	char *line = NULL;
107 	size_t len = 0;
108 	ssize_t read;
109 	bool valid = false;
110 
111 	snprintf(path, sizeof(path), THREAD_SIBLINGS_FILE, core);
112 	f = fopen(path, "r");
113 	if (f == NULL) {
114 		SPDK_ERRLOG("Could not fopen('%s'): %s\n", path, spdk_strerror(errno));
115 		return false;
116 	}
117 	read = getline(&line, &len, f);
118 	if (read == -1) {
119 		SPDK_ERRLOG("Could not getline() for '%s': %s\n", path, spdk_strerror(errno));
120 		goto ret;
121 	}
122 
123 	/* Remove trailing newline */
124 	line[strlen(line) - 1] = 0;
125 	if (spdk_cpuset_parse(&smt_siblings, line)) {
126 		SPDK_ERRLOG("Could not parse '%s' from '%s'\n", line, path);
127 		goto ret;
128 	}
129 
130 	valid = true;
131 	spdk_cpuset_or(cpuset, &smt_siblings);
132 ret:
133 	free(line);
134 	fclose(f);
135 	return valid;
136 #else
137 	return false;
138 #endif
139 }
140 
141 bool
142 spdk_env_core_get_smt_cpuset(struct spdk_cpuset *cpuset, uint32_t core)
143 {
144 	uint32_t i;
145 
146 	spdk_cpuset_zero(cpuset);
147 
148 	if (core != UINT32_MAX) {
149 		return env_core_get_smt_cpuset(cpuset, core);
150 	}
151 
152 	SPDK_ENV_FOREACH_CORE(i) {
153 		if (!env_core_get_smt_cpuset(cpuset, i)) {
154 			return false;
155 		}
156 	}
157 
158 	return true;
159 }
160 
161 int
162 spdk_env_thread_launch_pinned(uint32_t core, thread_start_fn fn, void *arg)
163 {
164 	int rc;
165 
166 	rc = rte_eal_remote_launch(fn, arg, core);
167 
168 	return rc;
169 }
170 
171 void
172 spdk_env_thread_wait_all(void)
173 {
174 	rte_eal_mp_wait_lcore();
175 }
176