eal: fix multiple definition of per lcore thread id
[dpdk.git] / lib / librte_eal / common / eal_common_thread.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8 #include <unistd.h>
9 #include <pthread.h>
10 #include <signal.h>
11 #include <sched.h>
12 #include <assert.h>
13 #include <string.h>
14
15 #include <rte_lcore.h>
16 #include <rte_memory.h>
17 #include <rte_log.h>
18 #include <rte_trace_point.h>
19
20 #include "eal_internal_cfg.h"
21 #include "eal_private.h"
22 #include "eal_thread.h"
23
24 RTE_DEFINE_PER_LCORE(unsigned int, _lcore_id) = LCORE_ID_ANY;
25 RTE_DEFINE_PER_LCORE(int, _thread_id) = -1;
26 static RTE_DEFINE_PER_LCORE(unsigned int, _socket_id) =
27         (unsigned int)SOCKET_ID_ANY;
28 static RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset);
29
30 unsigned rte_socket_id(void)
31 {
32         return RTE_PER_LCORE(_socket_id);
33 }
34
35 int
36 rte_lcore_has_role(unsigned int lcore_id, enum rte_lcore_role_t role)
37 {
38         struct rte_config *cfg = rte_eal_get_configuration();
39
40         if (lcore_id >= RTE_MAX_LCORE)
41                 return -EINVAL;
42
43         return cfg->lcore_role[lcore_id] == role;
44 }
45
46 static int
47 eal_cpuset_socket_id(rte_cpuset_t *cpusetp)
48 {
49         unsigned cpu = 0;
50         int socket_id = SOCKET_ID_ANY;
51         int sid;
52
53         if (cpusetp == NULL)
54                 return SOCKET_ID_ANY;
55
56         do {
57                 if (!CPU_ISSET(cpu, cpusetp))
58                         continue;
59
60                 if (socket_id == SOCKET_ID_ANY)
61                         socket_id = eal_cpu_socket_id(cpu);
62
63                 sid = eal_cpu_socket_id(cpu);
64                 if (socket_id != sid) {
65                         socket_id = SOCKET_ID_ANY;
66                         break;
67                 }
68
69         } while (++cpu < CPU_SETSIZE);
70
71         return socket_id;
72 }
73
74 int
75 rte_thread_set_affinity(rte_cpuset_t *cpusetp)
76 {
77         int s;
78         unsigned lcore_id;
79         pthread_t tid;
80
81         tid = pthread_self();
82
83         s = pthread_setaffinity_np(tid, sizeof(rte_cpuset_t), cpusetp);
84         if (s != 0) {
85                 RTE_LOG(ERR, EAL, "pthread_setaffinity_np failed\n");
86                 return -1;
87         }
88
89         /* store socket_id in TLS for quick access */
90         RTE_PER_LCORE(_socket_id) =
91                 eal_cpuset_socket_id(cpusetp);
92
93         /* store cpuset in TLS for quick access */
94         memmove(&RTE_PER_LCORE(_cpuset), cpusetp,
95                 sizeof(rte_cpuset_t));
96
97         lcore_id = rte_lcore_id();
98         if (lcore_id != (unsigned)LCORE_ID_ANY) {
99                 /* EAL thread will update lcore_config */
100                 lcore_config[lcore_id].socket_id = RTE_PER_LCORE(_socket_id);
101                 memmove(&lcore_config[lcore_id].cpuset, cpusetp,
102                         sizeof(rte_cpuset_t));
103         }
104
105         return 0;
106 }
107
108 void
109 rte_thread_get_affinity(rte_cpuset_t *cpusetp)
110 {
111         assert(cpusetp);
112         memmove(cpusetp, &RTE_PER_LCORE(_cpuset),
113                 sizeof(rte_cpuset_t));
114 }
115
116 int
117 eal_thread_dump_affinity(char *str, unsigned size)
118 {
119         rte_cpuset_t cpuset;
120         unsigned cpu;
121         int ret;
122         unsigned int out = 0;
123
124         rte_thread_get_affinity(&cpuset);
125
126         for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
127                 if (!CPU_ISSET(cpu, &cpuset))
128                         continue;
129
130                 ret = snprintf(str + out,
131                                size - out, "%u,", cpu);
132                 if (ret < 0 || (unsigned)ret >= size - out) {
133                         /* string will be truncated */
134                         ret = -1;
135                         goto exit;
136                 }
137
138                 out += ret;
139         }
140
141         ret = 0;
142 exit:
143         /* remove the last separator */
144         if (out > 0)
145                 str[out - 1] = '\0';
146
147         return ret;
148 }
149
150
151 struct rte_thread_ctrl_params {
152         void *(*start_routine)(void *);
153         void *arg;
154         pthread_barrier_t configured;
155 };
156
157 static void *rte_thread_init(void *arg)
158 {
159         int ret;
160         struct internal_config *internal_conf =
161                 eal_get_internal_configuration();
162         rte_cpuset_t *cpuset = &internal_conf->ctrl_cpuset;
163         struct rte_thread_ctrl_params *params = arg;
164         void *(*start_routine)(void *) = params->start_routine;
165         void *routine_arg = params->arg;
166
167         /* Store cpuset in TLS for quick access */
168         memmove(&RTE_PER_LCORE(_cpuset), cpuset, sizeof(rte_cpuset_t));
169
170         ret = pthread_barrier_wait(&params->configured);
171         if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
172                 pthread_barrier_destroy(&params->configured);
173                 free(params);
174         }
175
176         __rte_trace_mem_per_thread_alloc();
177
178         return start_routine(routine_arg);
179 }
180
181 int
182 rte_ctrl_thread_create(pthread_t *thread, const char *name,
183                 const pthread_attr_t *attr,
184                 void *(*start_routine)(void *), void *arg)
185 {
186         struct internal_config *internal_conf =
187                 eal_get_internal_configuration();
188         rte_cpuset_t *cpuset = &internal_conf->ctrl_cpuset;
189         struct rte_thread_ctrl_params *params;
190         int ret;
191
192         params = malloc(sizeof(*params));
193         if (!params)
194                 return -ENOMEM;
195
196         params->start_routine = start_routine;
197         params->arg = arg;
198
199         pthread_barrier_init(&params->configured, NULL, 2);
200
201         ret = pthread_create(thread, attr, rte_thread_init, (void *)params);
202         if (ret != 0) {
203                 free(params);
204                 return -ret;
205         }
206
207         if (name != NULL) {
208                 ret = rte_thread_setname(*thread, name);
209                 if (ret < 0)
210                         RTE_LOG(DEBUG, EAL,
211                                 "Cannot set name for ctrl thread\n");
212         }
213
214         ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset);
215         if (ret)
216                 goto fail;
217
218         ret = pthread_barrier_wait(&params->configured);
219         if (ret == PTHREAD_BARRIER_SERIAL_THREAD) {
220                 pthread_barrier_destroy(&params->configured);
221                 free(params);
222         }
223
224         return 0;
225
226 fail:
227         if (PTHREAD_BARRIER_SERIAL_THREAD ==
228             pthread_barrier_wait(&params->configured)) {
229                 pthread_barrier_destroy(&params->configured);
230                 free(params);
231         }
232         pthread_cancel(*thread);
233         pthread_join(*thread, NULL);
234         return -ret;
235 }