eal: register non-EAL threads as lcores
[dpdk.git] / lib / librte_eal / common / eal_common_lcore.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <unistd.h>
6 #include <limits.h>
7 #include <string.h>
8
9 #include <rte_common.h>
10 #include <rte_debug.h>
11 #include <rte_eal.h>
12 #include <rte_errno.h>
13 #include <rte_lcore.h>
14 #include <rte_log.h>
15 #include <rte_spinlock.h>
16
17 #include "eal_memcfg.h"
18 #include "eal_private.h"
19 #include "eal_thread.h"
20
21 unsigned int rte_get_master_lcore(void)
22 {
23         return rte_eal_get_configuration()->master_lcore;
24 }
25
26 unsigned int rte_lcore_count(void)
27 {
28         return rte_eal_get_configuration()->lcore_count;
29 }
30
31 int rte_lcore_index(int lcore_id)
32 {
33         if (unlikely(lcore_id >= RTE_MAX_LCORE))
34                 return -1;
35
36         if (lcore_id < 0) {
37                 if (rte_lcore_id() == LCORE_ID_ANY)
38                         return -1;
39
40                 lcore_id = (int)rte_lcore_id();
41         }
42
43         return lcore_config[lcore_id].core_index;
44 }
45
46 int rte_lcore_to_cpu_id(int lcore_id)
47 {
48         if (unlikely(lcore_id >= RTE_MAX_LCORE))
49                 return -1;
50
51         if (lcore_id < 0) {
52                 if (rte_lcore_id() == LCORE_ID_ANY)
53                         return -1;
54
55                 lcore_id = (int)rte_lcore_id();
56         }
57
58         return lcore_config[lcore_id].core_id;
59 }
60
61 rte_cpuset_t rte_lcore_cpuset(unsigned int lcore_id)
62 {
63         return lcore_config[lcore_id].cpuset;
64 }
65
66 enum rte_lcore_role_t
67 rte_eal_lcore_role(unsigned int lcore_id)
68 {
69         struct rte_config *cfg = rte_eal_get_configuration();
70
71         if (lcore_id >= RTE_MAX_LCORE)
72                 return ROLE_OFF;
73         return cfg->lcore_role[lcore_id];
74 }
75
76 int
77 rte_lcore_has_role(unsigned int lcore_id, enum rte_lcore_role_t role)
78 {
79         struct rte_config *cfg = rte_eal_get_configuration();
80
81         if (lcore_id >= RTE_MAX_LCORE)
82                 return -EINVAL;
83
84         return cfg->lcore_role[lcore_id] == role;
85 }
86
87 int rte_lcore_is_enabled(unsigned int lcore_id)
88 {
89         struct rte_config *cfg = rte_eal_get_configuration();
90
91         if (lcore_id >= RTE_MAX_LCORE)
92                 return 0;
93         return cfg->lcore_role[lcore_id] == ROLE_RTE;
94 }
95
96 unsigned int rte_get_next_lcore(unsigned int i, int skip_master, int wrap)
97 {
98         i++;
99         if (wrap)
100                 i %= RTE_MAX_LCORE;
101
102         while (i < RTE_MAX_LCORE) {
103                 if (!rte_lcore_is_enabled(i) ||
104                     (skip_master && (i == rte_get_master_lcore()))) {
105                         i++;
106                         if (wrap)
107                                 i %= RTE_MAX_LCORE;
108                         continue;
109                 }
110                 break;
111         }
112         return i;
113 }
114
115 unsigned int
116 rte_lcore_to_socket_id(unsigned int lcore_id)
117 {
118         return lcore_config[lcore_id].socket_id;
119 }
120
121 static int
122 socket_id_cmp(const void *a, const void *b)
123 {
124         const int *lcore_id_a = a;
125         const int *lcore_id_b = b;
126
127         if (*lcore_id_a < *lcore_id_b)
128                 return -1;
129         if (*lcore_id_a > *lcore_id_b)
130                 return 1;
131         return 0;
132 }
133
134 /*
135  * Parse /sys/devices/system/cpu to get the number of physical and logical
136  * processors on the machine. The function will fill the cpu_info
137  * structure.
138  */
139 int
140 rte_eal_cpu_init(void)
141 {
142         /* pointer to global configuration */
143         struct rte_config *config = rte_eal_get_configuration();
144         unsigned lcore_id;
145         unsigned count = 0;
146         unsigned int socket_id, prev_socket_id;
147         int lcore_to_socket_id[RTE_MAX_LCORE];
148
149         /*
150          * Parse the maximum set of logical cores, detect the subset of running
151          * ones and enable them by default.
152          */
153         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
154                 lcore_config[lcore_id].core_index = count;
155
156                 /* init cpuset for per lcore config */
157                 CPU_ZERO(&lcore_config[lcore_id].cpuset);
158
159                 /* find socket first */
160                 socket_id = eal_cpu_socket_id(lcore_id);
161                 lcore_to_socket_id[lcore_id] = socket_id;
162
163                 if (eal_cpu_detected(lcore_id) == 0) {
164                         config->lcore_role[lcore_id] = ROLE_OFF;
165                         lcore_config[lcore_id].core_index = -1;
166                         continue;
167                 }
168
169                 /* By default, lcore 1:1 map to cpu id */
170                 CPU_SET(lcore_id, &lcore_config[lcore_id].cpuset);
171
172                 /* By default, each detected core is enabled */
173                 config->lcore_role[lcore_id] = ROLE_RTE;
174                 lcore_config[lcore_id].core_role = ROLE_RTE;
175                 lcore_config[lcore_id].core_id = eal_cpu_core_id(lcore_id);
176                 lcore_config[lcore_id].socket_id = socket_id;
177                 RTE_LOG(DEBUG, EAL, "Detected lcore %u as "
178                                 "core %u on socket %u\n",
179                                 lcore_id, lcore_config[lcore_id].core_id,
180                                 lcore_config[lcore_id].socket_id);
181                 count++;
182         }
183         for (; lcore_id < CPU_SETSIZE; lcore_id++) {
184                 if (eal_cpu_detected(lcore_id) == 0)
185                         continue;
186                 RTE_LOG(DEBUG, EAL, "Skipped lcore %u as core %u on socket %u\n",
187                         lcore_id, eal_cpu_core_id(lcore_id),
188                         eal_cpu_socket_id(lcore_id));
189         }
190
191         /* Set the count of enabled logical cores of the EAL configuration */
192         config->lcore_count = count;
193         RTE_LOG(DEBUG, EAL,
194                 "Support maximum %u logical core(s) by configuration.\n",
195                 RTE_MAX_LCORE);
196         RTE_LOG(INFO, EAL, "Detected %u lcore(s)\n", config->lcore_count);
197
198         /* sort all socket id's in ascending order */
199         qsort(lcore_to_socket_id, RTE_DIM(lcore_to_socket_id),
200                         sizeof(lcore_to_socket_id[0]), socket_id_cmp);
201
202         prev_socket_id = -1;
203         config->numa_node_count = 0;
204         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
205                 socket_id = lcore_to_socket_id[lcore_id];
206                 if (socket_id != prev_socket_id)
207                         config->numa_nodes[config->numa_node_count++] =
208                                         socket_id;
209                 prev_socket_id = socket_id;
210         }
211         RTE_LOG(INFO, EAL, "Detected %u NUMA nodes\n", config->numa_node_count);
212
213         return 0;
214 }
215
216 unsigned int
217 rte_socket_count(void)
218 {
219         const struct rte_config *config = rte_eal_get_configuration();
220         return config->numa_node_count;
221 }
222
223 int
224 rte_socket_id_by_idx(unsigned int idx)
225 {
226         const struct rte_config *config = rte_eal_get_configuration();
227         if (idx >= config->numa_node_count) {
228                 rte_errno = EINVAL;
229                 return -1;
230         }
231         return config->numa_nodes[idx];
232 }
233
234 static rte_spinlock_t lcore_lock = RTE_SPINLOCK_INITIALIZER;
235
236 unsigned int
237 eal_lcore_non_eal_allocate(void)
238 {
239         struct rte_config *cfg = rte_eal_get_configuration();
240         unsigned int lcore_id;
241
242         rte_spinlock_lock(&lcore_lock);
243         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
244                 if (cfg->lcore_role[lcore_id] != ROLE_OFF)
245                         continue;
246                 cfg->lcore_role[lcore_id] = ROLE_NON_EAL;
247                 cfg->lcore_count++;
248                 break;
249         }
250         if (lcore_id == RTE_MAX_LCORE)
251                 RTE_LOG(DEBUG, EAL, "No lcore available.\n");
252         rte_spinlock_unlock(&lcore_lock);
253         return lcore_id;
254 }
255
256 void
257 eal_lcore_non_eal_release(unsigned int lcore_id)
258 {
259         struct rte_config *cfg = rte_eal_get_configuration();
260
261         rte_spinlock_lock(&lcore_lock);
262         if (cfg->lcore_role[lcore_id] == ROLE_NON_EAL) {
263                 cfg->lcore_role[lcore_id] = ROLE_OFF;
264                 cfg->lcore_count--;
265         }
266         rte_spinlock_unlock(&lcore_lock);
267 }