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