xref: /dpdk/lib/eal/include/rte_thread.h (revision 665b49c51639a10c553433bc2bcd85c7331c631e)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2021 Mellanox Technologies, Ltd
3  * Copyright (C) 2022 Microsoft Corporation
4  */
5 
6 #include <stdint.h>
7 
8 #include <rte_os.h>
9 #include <rte_compat.h>
10 
11 #ifndef _RTE_THREAD_H_
12 #define _RTE_THREAD_H_
13 
14 /**
15  * @file
16  *
17  * Threading functions
18  *
19  * Simple threads functionality supplied by EAL.
20  */
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 /**
27  * Thread id descriptor.
28  */
29 typedef struct {
30 	uintptr_t opaque_id; /**< thread identifier */
31 } rte_thread_t;
32 
33 /**
34  * Thread function
35  *
36  * Function pointer to thread start routine.
37  *
38  * @param arg
39  *   Argument passed to rte_thread_create().
40  * @return
41  *   Thread function exit value.
42  */
43 typedef uint32_t (*rte_thread_func) (void *arg);
44 
45 /**
46  * Thread priority values.
47  */
48 enum rte_thread_priority {
49 	RTE_THREAD_PRIORITY_NORMAL            = 0,
50 	/**< normal thread priority, the default */
51 	RTE_THREAD_PRIORITY_REALTIME_CRITICAL = 1,
52 	/**< highest thread priority allowed */
53 };
54 
55 /**
56  * Representation for thread attributes.
57  */
58 typedef struct {
59 	enum rte_thread_priority priority; /**< thread priority */
60 #ifdef RTE_HAS_CPUSET
61 	rte_cpuset_t cpuset; /**< thread affinity */
62 #endif
63 } rte_thread_attr_t;
64 
65 /**
66  * TLS key type, an opaque pointer.
67  */
68 typedef struct eal_tls_key *rte_thread_key;
69 
70 /**
71  * @warning
72  * @b EXPERIMENTAL: this API may change without prior notice.
73  *
74  * Create a new thread that will invoke the 'thread_func' routine.
75  *
76  * @param thread_id
77  *    A pointer that will store the id of the newly created thread.
78  *
79  * @param thread_attr
80  *    Attributes that are used at the creation of the new thread.
81  *
82  * @param thread_func
83  *    The routine that the new thread will invoke when starting execution.
84  *
85  * @param arg
86  *    Argument to be passed to the 'thread_func' routine.
87  *
88  * @return
89  *   On success, return 0.
90  *   On failure, return a positive errno-style error number.
91  */
92 __rte_experimental
93 int rte_thread_create(rte_thread_t *thread_id,
94 		const rte_thread_attr_t *thread_attr,
95 		rte_thread_func thread_func, void *arg);
96 
97 /**
98  * @warning
99  * @b EXPERIMENTAL: this API may change without prior notice.
100  *
101  * Create a control thread.
102  *
103  * Creates a control thread with the given name and attributes. The
104  * affinity of the new thread is based on the CPU affinity retrieved
105  * at the time rte_eal_init() was called, the EAL threads are then
106  * excluded. If setting the name of the thread fails, the error is
107  * ignored and a debug message is logged.
108  *
109  * @param thread
110  *   Filled with the thread id of the new created thread.
111  * @param name
112  *   The name of the control thread
113  *   (max RTE_MAX_THREAD_NAME_LEN characters including '\0').
114  * @param thread_attr
115  *   Attributes for the new thread.
116  * @param thread_func
117  *   Function to be executed by the new thread.
118  * @param arg
119  *   Argument passed to start_routine.
120  * @return
121  *   On success, returns 0; on error, it returns a negative value
122  *   corresponding to the error number.
123  */
124 __rte_experimental
125 int
126 rte_thread_create_control(rte_thread_t *thread, const char *name,
127 	const rte_thread_attr_t *thread_attr, rte_thread_func thread_func,
128 	void *arg);
129 
130 /**
131  * @warning
132  * @b EXPERIMENTAL: this API may change without prior notice.
133  *
134  * Waits for the thread identified by 'thread_id' to terminate
135  *
136  * @param thread_id
137  *    The identifier of the thread.
138  *
139  * @param value_ptr
140  *    Stores the exit status of the thread.
141  *
142  * @return
143  *   On success, return 0.
144  *   On failure, return a positive errno-style error number.
145  */
146 __rte_experimental
147 int rte_thread_join(rte_thread_t thread_id, uint32_t *value_ptr);
148 
149 /**
150  * @warning
151  * @b EXPERIMENTAL: this API may change without prior notice.
152  *
153  * Indicate that the return value of the thread is not needed and
154  * all thread resources should be release when the thread terminates.
155  *
156  * @param thread_id
157  *    The id of the thread to be detached.
158  *
159  * @return
160  *   On success, return 0.
161  *   On failure, return a positive errno-style error number.
162  */
163 __rte_experimental
164 int rte_thread_detach(rte_thread_t thread_id);
165 
166 /**
167  * @warning
168  * @b EXPERIMENTAL: this API may change without prior notice.
169  *
170  * Get the id of the calling thread.
171  *
172  * @return
173  *   Return the thread id of the calling thread.
174  */
175 __rte_experimental
176 rte_thread_t rte_thread_self(void);
177 
178 /**
179  * @warning
180  * @b EXPERIMENTAL: this API may change without prior notice.
181  *
182  * Set the name of the thread.
183  * This API is a noop if the underlying platform does not
184  * support setting the thread name or the platform-specific
185  * API used to set the thread name fails.
186  *
187  * @param thread_id
188  *    The id of the thread to set name.
189  *
190  * @param thread_name
191  *    The name to set. Truncated to RTE_MAX_THREAD_NAME_LEN,
192  *    including terminating NUL if necessary.
193  */
194 __rte_experimental
195 void
196 rte_thread_set_name(rte_thread_t thread_id, const char *thread_name);
197 
198 /**
199  * @warning
200  * @b EXPERIMENTAL: this API may change without prior notice.
201  *
202  * Check if 2 thread ids are equal.
203  *
204  * @param t1
205  *   First thread id.
206  *
207  * @param t2
208  *   Second thread id.
209  *
210  * @return
211  *   If the ids are equal, return nonzero.
212  *   Otherwise, return 0.
213  */
214 __rte_experimental
215 int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);
216 
217 /**
218  * @warning
219  * @b EXPERIMENTAL: this API may change without prior notice.
220  *
221  * Initialize the attributes of a thread.
222  * These attributes can be passed to the rte_thread_create() function
223  * that will create a new thread and set its attributes according to attr.
224  *
225  * @param attr
226  *   Thread attributes to initialize.
227  *
228  * @return
229  *   On success, return 0.
230  *   On failure, return a positive errno-style error number.
231  */
232 __rte_experimental
233 int rte_thread_attr_init(rte_thread_attr_t *attr);
234 
235 /**
236  * @warning
237  * @b EXPERIMENTAL: this API may change without prior notice.
238  *
239  * Set the thread priority value in the thread attributes pointed to
240  * by 'thread_attr'.
241  *
242  * @param thread_attr
243  *   Points to the thread attributes in which priority will be updated.
244  *
245  * @param priority
246  *   Points to the value of the priority to be set.
247  *
248  * @return
249  *   On success, return 0.
250  *   On failure, return a positive errno-style error number.
251  */
252 __rte_experimental
253 int rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr,
254 		enum rte_thread_priority priority);
255 
256 #ifdef RTE_HAS_CPUSET
257 
258 /**
259  * @warning
260  * @b EXPERIMENTAL: this API may change without prior notice.
261  *
262  * Set the CPU affinity value in the thread attributes pointed to
263  * by 'thread_attr'.
264  *
265  * @param thread_attr
266  *   Points to the thread attributes in which affinity will be updated.
267  *
268  * @param cpuset
269  *   Points to the value of the affinity to be set.
270  *
271  * @return
272  *   On success, return 0.
273  *   On failure, return a positive errno-style error number.
274  */
275 __rte_experimental
276 int rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr,
277 		rte_cpuset_t *cpuset);
278 
279 /**
280  * @warning
281  * @b EXPERIMENTAL: this API may change without prior notice.
282  *
283  * Get the value of CPU affinity that is set in the thread attributes pointed
284  * to by 'thread_attr'.
285  *
286  * @param thread_attr
287  *   Points to the thread attributes from which affinity will be retrieved.
288  *
289  * @param cpuset
290  *   Pointer to the memory that will store the affinity.
291  *
292  * @return
293  *   On success, return 0.
294  *   On failure, return a positive errno-style error number.
295  */
296 __rte_experimental
297 int rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr,
298 		rte_cpuset_t *cpuset);
299 
300 /**
301  * @warning
302  * @b EXPERIMENTAL: this API may change without prior notice.
303  *
304  * Set the affinity of thread 'thread_id' to the cpu set
305  * specified by 'cpuset'.
306  *
307  * @param thread_id
308  *    Id of the thread for which to set the affinity.
309  *
310  * @param cpuset
311  *   Pointer to CPU affinity to set.
312  *
313  * @return
314  *   On success, return 0.
315  *   On failure, return a positive errno-style error number.
316  */
317 __rte_experimental
318 int rte_thread_set_affinity_by_id(rte_thread_t thread_id,
319 		const rte_cpuset_t *cpuset);
320 
321 /**
322  * @warning
323  * @b EXPERIMENTAL: this API may change without prior notice.
324  *
325  * Get the affinity of thread 'thread_id' and store it
326  * in 'cpuset'.
327  *
328  * @param thread_id
329  *    Id of the thread for which to get the affinity.
330  *
331  * @param cpuset
332  *   Pointer for storing the affinity value.
333  *
334  * @return
335  *   On success, return 0.
336  *   On failure, return a positive errno-style error number.
337  */
338 __rte_experimental
339 int rte_thread_get_affinity_by_id(rte_thread_t thread_id,
340 		rte_cpuset_t *cpuset);
341 
342 /**
343  * Set core affinity of the current thread.
344  * Support both EAL and non-EAL thread and update TLS.
345  *
346  * @param cpusetp
347  *   Pointer to CPU affinity to set.
348  * @return
349  *   On success, return 0; otherwise return -1;
350  */
351 int rte_thread_set_affinity(rte_cpuset_t *cpusetp);
352 
353 /**
354  * Get core affinity of the current thread.
355  *
356  * @param cpusetp
357  *   Pointer to CPU affinity of current thread.
358  *   It presumes input is not NULL, otherwise it causes panic.
359  *
360  */
361 void rte_thread_get_affinity(rte_cpuset_t *cpusetp);
362 
363 #endif /* RTE_HAS_CPUSET */
364 
365 /**
366  * @warning
367  * @b EXPERIMENTAL: this API may change without prior notice.
368  *
369  * Get the priority of a thread.
370  *
371  * @param thread_id
372  *   Id of the thread for which to get priority.
373  *
374  * @param priority
375  *   Location to store the retrieved priority.
376  *
377  * @return
378  *   On success, return 0.
379  *   On failure, return a positive errno-style error number.
380  */
381 __rte_experimental
382 int rte_thread_get_priority(rte_thread_t thread_id,
383 		enum rte_thread_priority *priority);
384 
385 /**
386  * @warning
387  * @b EXPERIMENTAL: this API may change without prior notice.
388  *
389  * Set the priority of a thread.
390  *
391  * @param thread_id
392  *   Id of the thread for which to set priority.
393  *
394  * @param priority
395  *   Priority value to be set.
396  *
397  * @return
398  *   On success, return 0.
399  *   On failure, return a positive errno-style error number.
400  */
401 __rte_experimental
402 int rte_thread_set_priority(rte_thread_t thread_id,
403 		enum rte_thread_priority priority);
404 
405 /**
406  * Create a TLS data key visible to all threads in the process.
407  * the created key is later used to get/set a value.
408  * and optional destructor can be set to be called when a thread exits.
409  *
410  * @param key
411  *   Pointer to store the allocated key.
412  * @param destructor
413  *   The function to be called when the thread exits.
414  *   Ignored on Windows OS.
415  *
416  * @return
417  *   On success, zero.
418  *   On failure, a negative number and an error number is set in rte_errno.
419  *   rte_errno can be: ENOMEM  - Memory allocation error.
420  *                     ENOEXEC - Specific OS error.
421  */
422 
423 __rte_experimental
424 int rte_thread_key_create(rte_thread_key *key,
425 			void (*destructor)(void *));
426 
427 /**
428  * Delete a TLS data key visible to all threads in the process.
429  *
430  * @param key
431  *   The key allocated by rte_thread_key_create().
432  *
433  * @return
434  *   On success, zero.
435  *   On failure, a negative number and an error number is set in rte_errno.
436  *   rte_errno can be: EINVAL  - Invalid parameter passed.
437  *                     ENOEXEC - Specific OS error.
438  */
439 __rte_experimental
440 int rte_thread_key_delete(rte_thread_key key);
441 
442 /**
443  * Set value bound to the TLS key on behalf of the calling thread.
444  *
445  * @param key
446  *   The key allocated by rte_thread_key_create().
447  * @param value
448  *   The value bound to the rte_thread_key key for the calling thread.
449  *
450  * @return
451  *   On success, zero.
452  *   On failure, a negative number and an error number is set in rte_errno.
453  *   rte_errno can be: EINVAL  - Invalid parameter passed.
454  *                     ENOEXEC - Specific OS error.
455  */
456 __rte_experimental
457 int rte_thread_value_set(rte_thread_key key, const void *value);
458 
459 /**
460  * Get value bound to the TLS key on behalf of the calling thread.
461  *
462  * @param key
463  *   The key allocated by rte_thread_key_create().
464  *
465  * @return
466  *   On success, value data pointer (can also be NULL).
467  *   On failure, NULL and an error number is set in rte_errno.
468  *   rte_errno can be: EINVAL  - Invalid parameter passed.
469  *                     ENOEXEC - Specific OS error.
470  */
471 __rte_experimental
472 void *rte_thread_value_get(rte_thread_key key);
473 
474 #ifdef __cplusplus
475 }
476 #endif
477 
478 #endif /* _RTE_THREAD_H_ */
479