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