eal: add function to create control threads
[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 <sched.h>
11 #include <assert.h>
12 #include <string.h>
13
14 #include <rte_lcore.h>
15 #include <rte_memory.h>
16 #include <rte_log.h>
17
18 #include "eal_thread.h"
19
20 RTE_DECLARE_PER_LCORE(unsigned , _socket_id);
21
22 unsigned rte_socket_id(void)
23 {
24         return RTE_PER_LCORE(_socket_id);
25 }
26
27 int
28 rte_lcore_has_role(unsigned int lcore_id, enum rte_lcore_role_t role)
29 {
30         struct rte_config *cfg = rte_eal_get_configuration();
31
32         if (lcore_id >= RTE_MAX_LCORE)
33                 return -EINVAL;
34
35         if (cfg->lcore_role[lcore_id] == role)
36                 return 0;
37
38         return -EINVAL;
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 __rte_experimental int
145 rte_ctrl_thread_create(pthread_t *thread,
146                         const pthread_attr_t *attr,
147                         void *(*start_routine)(void *), void *arg)
148 {
149         return pthread_create(thread, attr, start_routine, arg);
150 }