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