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