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