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