xref: /dpdk/lib/eal/unix/rte_thread.c (revision 64f27886b8bf127cd365a8a3ed5c05852a5ae81d)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright 2021 Mellanox Technologies, Ltd
356539289STyler Retzlaff  * Copyright (C) 2022 Microsoft Corporation
499a2dd95SBruce Richardson  */
599a2dd95SBruce Richardson 
699a2dd95SBruce Richardson #include <errno.h>
799a2dd95SBruce Richardson #include <pthread.h>
8b28c6196STyler Retzlaff #include <stdbool.h>
999a2dd95SBruce Richardson #include <stdlib.h>
1099a2dd95SBruce Richardson #include <string.h>
1199a2dd95SBruce Richardson 
1299a2dd95SBruce Richardson #include <rte_errno.h>
1399a2dd95SBruce Richardson #include <rte_log.h>
1499a2dd95SBruce Richardson #include <rte_thread.h>
1599a2dd95SBruce Richardson 
16ae67895bSDavid Marchand #include "eal_private.h"
17ae67895bSDavid Marchand 
1899a2dd95SBruce Richardson struct eal_tls_key {
1999a2dd95SBruce Richardson 	pthread_key_t thread_index;
2099a2dd95SBruce Richardson };
2199a2dd95SBruce Richardson 
22*64f27886SDavid Marchand #ifndef RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP
23b28c6196STyler Retzlaff struct thread_start_context {
24ce6e911dSTyler Retzlaff 	rte_thread_func thread_func;
25b28c6196STyler Retzlaff 	void *thread_args;
26b28c6196STyler Retzlaff 	const rte_thread_attr_t *thread_attr;
27b28c6196STyler Retzlaff 	pthread_mutex_t wrapper_mutex;
28b28c6196STyler Retzlaff 	pthread_cond_t wrapper_cond;
29b28c6196STyler Retzlaff 	int wrapper_ret;
30b28c6196STyler Retzlaff 	bool wrapper_done;
31ce6e911dSTyler Retzlaff };
32*64f27886SDavid Marchand #endif
33ce6e911dSTyler Retzlaff 
34ca04c78bSTyler Retzlaff static int
35ca04c78bSTyler Retzlaff thread_map_priority_to_os_value(enum rte_thread_priority eal_pri, int *os_pri,
36ca04c78bSTyler Retzlaff 	int *pol)
37ca04c78bSTyler Retzlaff {
38ca04c78bSTyler Retzlaff 	/* Clear the output parameters. */
39ca04c78bSTyler Retzlaff 	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
40ca04c78bSTyler Retzlaff 	*pol = -1;
41ca04c78bSTyler Retzlaff 
42ca04c78bSTyler Retzlaff 	switch (eal_pri) {
43ca04c78bSTyler Retzlaff 	case RTE_THREAD_PRIORITY_NORMAL:
44ca04c78bSTyler Retzlaff 		*pol = SCHED_OTHER;
45ca04c78bSTyler Retzlaff 
46ca04c78bSTyler Retzlaff 		/*
47ca04c78bSTyler Retzlaff 		 * Choose the middle of the range to represent the priority
48ca04c78bSTyler Retzlaff 		 * 'normal'.
49ca04c78bSTyler Retzlaff 		 * On Linux, this should be 0, since both
50ca04c78bSTyler Retzlaff 		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
51ca04c78bSTyler Retzlaff 		 */
52ca04c78bSTyler Retzlaff 		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
53ca04c78bSTyler Retzlaff 			sched_get_priority_max(SCHED_OTHER)) / 2;
54ca04c78bSTyler Retzlaff 		break;
55ca04c78bSTyler Retzlaff 	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
56ca04c78bSTyler Retzlaff 		*pol = SCHED_RR;
57ca04c78bSTyler Retzlaff 		*os_pri = sched_get_priority_max(SCHED_RR);
58ca04c78bSTyler Retzlaff 		break;
59ca04c78bSTyler Retzlaff 	default:
60ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "The requested priority value is invalid.");
61ca04c78bSTyler Retzlaff 		return EINVAL;
62ca04c78bSTyler Retzlaff 	}
63ca04c78bSTyler Retzlaff 
64ca04c78bSTyler Retzlaff 	return 0;
65ca04c78bSTyler Retzlaff }
66ca04c78bSTyler Retzlaff 
67ca04c78bSTyler Retzlaff static int
68ca04c78bSTyler Retzlaff thread_map_os_priority_to_eal_priority(int policy, int os_pri,
69ca04c78bSTyler Retzlaff 	enum rte_thread_priority *eal_pri)
70ca04c78bSTyler Retzlaff {
71ca04c78bSTyler Retzlaff 	switch (policy) {
72ca04c78bSTyler Retzlaff 	case SCHED_OTHER:
73ca04c78bSTyler Retzlaff 		if (os_pri == (sched_get_priority_min(SCHED_OTHER) +
74ca04c78bSTyler Retzlaff 				sched_get_priority_max(SCHED_OTHER)) / 2) {
75ca04c78bSTyler Retzlaff 			*eal_pri = RTE_THREAD_PRIORITY_NORMAL;
76ca04c78bSTyler Retzlaff 			return 0;
77ca04c78bSTyler Retzlaff 		}
78ca04c78bSTyler Retzlaff 		break;
79ca04c78bSTyler Retzlaff 	case SCHED_RR:
80ca04c78bSTyler Retzlaff 		if (os_pri == sched_get_priority_max(SCHED_RR)) {
81ca04c78bSTyler Retzlaff 			*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
82ca04c78bSTyler Retzlaff 			return 0;
83ca04c78bSTyler Retzlaff 		}
84ca04c78bSTyler Retzlaff 		break;
85ca04c78bSTyler Retzlaff 	default:
86ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "The OS priority value does not map to an EAL-defined priority.");
87ca04c78bSTyler Retzlaff 		return EINVAL;
88ca04c78bSTyler Retzlaff 	}
89ca04c78bSTyler Retzlaff 
90ca04c78bSTyler Retzlaff 	return 0;
91ca04c78bSTyler Retzlaff }
92ca04c78bSTyler Retzlaff 
93*64f27886SDavid Marchand #ifndef RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP
94ce6e911dSTyler Retzlaff static void *
95b28c6196STyler Retzlaff thread_start_wrapper(void *arg)
96ce6e911dSTyler Retzlaff {
97b28c6196STyler Retzlaff 	struct thread_start_context *ctx = (struct thread_start_context *)arg;
98b28c6196STyler Retzlaff 	rte_thread_func thread_func = ctx->thread_func;
99b28c6196STyler Retzlaff 	void *thread_args = ctx->thread_args;
100b28c6196STyler Retzlaff 	int ret = 0;
101ce6e911dSTyler Retzlaff 
102b28c6196STyler Retzlaff 	if (ctx->thread_attr != NULL && CPU_COUNT(&ctx->thread_attr->cpuset) > 0) {
103b28c6196STyler Retzlaff 		ret = rte_thread_set_affinity_by_id(rte_thread_self(), &ctx->thread_attr->cpuset);
104b28c6196STyler Retzlaff 		if (ret != 0)
105ae67895bSDavid Marchand 			EAL_LOG(DEBUG, "rte_thread_set_affinity_by_id failed");
106b28c6196STyler Retzlaff 	}
107ce6e911dSTyler Retzlaff 
108b28c6196STyler Retzlaff 	pthread_mutex_lock(&ctx->wrapper_mutex);
109b28c6196STyler Retzlaff 	ctx->wrapper_ret = ret;
110b28c6196STyler Retzlaff 	ctx->wrapper_done = true;
111b28c6196STyler Retzlaff 	pthread_cond_signal(&ctx->wrapper_cond);
112b28c6196STyler Retzlaff 	pthread_mutex_unlock(&ctx->wrapper_mutex);
113b28c6196STyler Retzlaff 
114b28c6196STyler Retzlaff 	if (ret != 0)
115b28c6196STyler Retzlaff 		return NULL;
116b28c6196STyler Retzlaff 
117b28c6196STyler Retzlaff 	return (void *)(uintptr_t)thread_func(thread_args);
118ce6e911dSTyler Retzlaff }
119*64f27886SDavid Marchand #endif
120ce6e911dSTyler Retzlaff 
121ce6e911dSTyler Retzlaff int
122ce6e911dSTyler Retzlaff rte_thread_create(rte_thread_t *thread_id,
123ce6e911dSTyler Retzlaff 		const rte_thread_attr_t *thread_attr,
124ce6e911dSTyler Retzlaff 		rte_thread_func thread_func, void *args)
125ce6e911dSTyler Retzlaff {
126ce6e911dSTyler Retzlaff 	int ret = 0;
127ce6e911dSTyler Retzlaff 	pthread_attr_t attr;
128ce6e911dSTyler Retzlaff 	pthread_attr_t *attrp = NULL;
129ce6e911dSTyler Retzlaff 	struct sched_param param = {
130ce6e911dSTyler Retzlaff 		.sched_priority = 0,
131ce6e911dSTyler Retzlaff 	};
132ce6e911dSTyler Retzlaff 	int policy = SCHED_OTHER;
133*64f27886SDavid Marchand #ifndef RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP
134b28c6196STyler Retzlaff 	struct thread_start_context ctx = {
135b28c6196STyler Retzlaff 		.thread_func = thread_func,
136b28c6196STyler Retzlaff 		.thread_args = args,
137b28c6196STyler Retzlaff 		.thread_attr = thread_attr,
138b28c6196STyler Retzlaff 		.wrapper_done = false,
139b28c6196STyler Retzlaff 		.wrapper_mutex = PTHREAD_MUTEX_INITIALIZER,
140b28c6196STyler Retzlaff 		.wrapper_cond = PTHREAD_COND_INITIALIZER,
141b28c6196STyler Retzlaff 	};
142*64f27886SDavid Marchand #endif
143ce6e911dSTyler Retzlaff 
144ce6e911dSTyler Retzlaff 	if (thread_attr != NULL) {
145ce6e911dSTyler Retzlaff 		ret = pthread_attr_init(&attr);
146ce6e911dSTyler Retzlaff 		if (ret != 0) {
147ae67895bSDavid Marchand 			EAL_LOG(DEBUG, "pthread_attr_init failed");
148ce6e911dSTyler Retzlaff 			goto cleanup;
149ce6e911dSTyler Retzlaff 		}
150ce6e911dSTyler Retzlaff 
151ce6e911dSTyler Retzlaff 		attrp = &attr;
152ce6e911dSTyler Retzlaff 
153*64f27886SDavid Marchand #ifdef RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP
154*64f27886SDavid Marchand 		if (CPU_COUNT(&thread_attr->cpuset) > 0) {
155*64f27886SDavid Marchand 			ret = pthread_attr_setaffinity_np(attrp, sizeof(thread_attr->cpuset),
156*64f27886SDavid Marchand 				&thread_attr->cpuset);
157*64f27886SDavid Marchand 			if (ret != 0) {
158*64f27886SDavid Marchand 				EAL_LOG(DEBUG, "pthread_attr_setaffinity_np failed");
159*64f27886SDavid Marchand 				goto cleanup;
160*64f27886SDavid Marchand 			}
161*64f27886SDavid Marchand 		}
162*64f27886SDavid Marchand #endif
163ce6e911dSTyler Retzlaff 		/*
164ce6e911dSTyler Retzlaff 		 * Set the inherit scheduler parameter to explicit,
165ce6e911dSTyler Retzlaff 		 * otherwise the priority attribute is ignored.
166ce6e911dSTyler Retzlaff 		 */
167ce6e911dSTyler Retzlaff 		ret = pthread_attr_setinheritsched(attrp,
168ce6e911dSTyler Retzlaff 				PTHREAD_EXPLICIT_SCHED);
169ce6e911dSTyler Retzlaff 		if (ret != 0) {
170ae67895bSDavid Marchand 			EAL_LOG(DEBUG, "pthread_attr_setinheritsched failed");
171ce6e911dSTyler Retzlaff 			goto cleanup;
172ce6e911dSTyler Retzlaff 		}
173ce6e911dSTyler Retzlaff 
174ce6e911dSTyler Retzlaff 		if (thread_attr->priority ==
175ce6e911dSTyler Retzlaff 				RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
176ce6e911dSTyler Retzlaff 			ret = ENOTSUP;
177ce6e911dSTyler Retzlaff 			goto cleanup;
178ce6e911dSTyler Retzlaff 		}
179ce6e911dSTyler Retzlaff 		ret = thread_map_priority_to_os_value(thread_attr->priority,
180ce6e911dSTyler Retzlaff 				&param.sched_priority, &policy);
181ce6e911dSTyler Retzlaff 		if (ret != 0)
182ce6e911dSTyler Retzlaff 			goto cleanup;
183ce6e911dSTyler Retzlaff 
184ce6e911dSTyler Retzlaff 		ret = pthread_attr_setschedpolicy(attrp, policy);
185ce6e911dSTyler Retzlaff 		if (ret != 0) {
186ae67895bSDavid Marchand 			EAL_LOG(DEBUG, "pthread_attr_setschedpolicy failed");
187ce6e911dSTyler Retzlaff 			goto cleanup;
188ce6e911dSTyler Retzlaff 		}
189ce6e911dSTyler Retzlaff 
190ce6e911dSTyler Retzlaff 		ret = pthread_attr_setschedparam(attrp, &param);
191ce6e911dSTyler Retzlaff 		if (ret != 0) {
192ae67895bSDavid Marchand 			EAL_LOG(DEBUG, "pthread_attr_setschedparam failed");
193ce6e911dSTyler Retzlaff 			goto cleanup;
194ce6e911dSTyler Retzlaff 		}
195ce6e911dSTyler Retzlaff 	}
196ce6e911dSTyler Retzlaff 
197*64f27886SDavid Marchand #ifdef RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP
198*64f27886SDavid Marchand 	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
199*64f27886SDavid Marchand 		(void *)(void *)thread_func, args);
200*64f27886SDavid Marchand 	if (ret != 0) {
201*64f27886SDavid Marchand 		EAL_LOG(DEBUG, "pthread_create failed");
202*64f27886SDavid Marchand 		goto cleanup;
203*64f27886SDavid Marchand 	}
204*64f27886SDavid Marchand #else /* !RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP */
205ce6e911dSTyler Retzlaff 	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
206b28c6196STyler Retzlaff 		thread_start_wrapper, &ctx);
207ce6e911dSTyler Retzlaff 	if (ret != 0) {
208ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "pthread_create failed");
209ce6e911dSTyler Retzlaff 		goto cleanup;
210ce6e911dSTyler Retzlaff 	}
211ce6e911dSTyler Retzlaff 
212b28c6196STyler Retzlaff 	pthread_mutex_lock(&ctx.wrapper_mutex);
213b28c6196STyler Retzlaff 	while (!ctx.wrapper_done)
214b28c6196STyler Retzlaff 		pthread_cond_wait(&ctx.wrapper_cond, &ctx.wrapper_mutex);
215b28c6196STyler Retzlaff 	ret = ctx.wrapper_ret;
216b28c6196STyler Retzlaff 	pthread_mutex_unlock(&ctx.wrapper_mutex);
217ce6e911dSTyler Retzlaff 
218b28c6196STyler Retzlaff 	if (ret != 0)
2191c1abf17SThomas Monjalon 		rte_thread_join(*thread_id, NULL);
220*64f27886SDavid Marchand #endif /* RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP */
221b28c6196STyler Retzlaff 
222ce6e911dSTyler Retzlaff cleanup:
223ce6e911dSTyler Retzlaff 	if (attrp != NULL)
224ce6e911dSTyler Retzlaff 		pthread_attr_destroy(&attr);
225ce6e911dSTyler Retzlaff 
226ce6e911dSTyler Retzlaff 	return ret;
227ce6e911dSTyler Retzlaff }
228ce6e911dSTyler Retzlaff 
229ce6e911dSTyler Retzlaff int
230ce6e911dSTyler Retzlaff rte_thread_join(rte_thread_t thread_id, uint32_t *value_ptr)
231ce6e911dSTyler Retzlaff {
232ce6e911dSTyler Retzlaff 	int ret = 0;
233ce6e911dSTyler Retzlaff 	void *res = (void *)(uintptr_t)0;
234ce6e911dSTyler Retzlaff 	void **pres = NULL;
235ce6e911dSTyler Retzlaff 
236ce6e911dSTyler Retzlaff 	if (value_ptr != NULL)
237ce6e911dSTyler Retzlaff 		pres = &res;
238ce6e911dSTyler Retzlaff 
239ce6e911dSTyler Retzlaff 	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
240ce6e911dSTyler Retzlaff 	if (ret != 0) {
241ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "pthread_join failed");
242ce6e911dSTyler Retzlaff 		return ret;
243ce6e911dSTyler Retzlaff 	}
244ce6e911dSTyler Retzlaff 
245ce6e911dSTyler Retzlaff 	if (value_ptr != NULL)
246ce6e911dSTyler Retzlaff 		*value_ptr = (uint32_t)(uintptr_t)res;
247ce6e911dSTyler Retzlaff 
248ce6e911dSTyler Retzlaff 	return 0;
249ce6e911dSTyler Retzlaff }
250ce6e911dSTyler Retzlaff 
251ce6e911dSTyler Retzlaff int
252ce6e911dSTyler Retzlaff rte_thread_detach(rte_thread_t thread_id)
253ce6e911dSTyler Retzlaff {
254ce6e911dSTyler Retzlaff 	return pthread_detach((pthread_t)thread_id.opaque_id);
255ce6e911dSTyler Retzlaff }
256ce6e911dSTyler Retzlaff 
257a2e94ca8STyler Retzlaff int
258a2e94ca8STyler Retzlaff rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
259a2e94ca8STyler Retzlaff {
260a2e94ca8STyler Retzlaff 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
261a2e94ca8STyler Retzlaff }
262a2e94ca8STyler Retzlaff 
26356539289STyler Retzlaff rte_thread_t
26456539289STyler Retzlaff rte_thread_self(void)
26556539289STyler Retzlaff {
26656539289STyler Retzlaff 	RTE_BUILD_BUG_ON(sizeof(pthread_t) > sizeof(uintptr_t));
26756539289STyler Retzlaff 
26856539289STyler Retzlaff 	rte_thread_t thread_id;
26956539289STyler Retzlaff 
27056539289STyler Retzlaff 	thread_id.opaque_id = (uintptr_t)pthread_self();
27156539289STyler Retzlaff 
27256539289STyler Retzlaff 	return thread_id;
27356539289STyler Retzlaff }
27456539289STyler Retzlaff 
27599a2dd95SBruce Richardson int
276ca04c78bSTyler Retzlaff rte_thread_get_priority(rte_thread_t thread_id,
277ca04c78bSTyler Retzlaff 	enum rte_thread_priority *priority)
278ca04c78bSTyler Retzlaff {
279ca04c78bSTyler Retzlaff 	struct sched_param param;
280ca04c78bSTyler Retzlaff 	int policy;
281ca04c78bSTyler Retzlaff 	int ret;
282ca04c78bSTyler Retzlaff 
283ca04c78bSTyler Retzlaff 	ret = pthread_getschedparam((pthread_t)thread_id.opaque_id, &policy,
284ca04c78bSTyler Retzlaff 		&param);
285ca04c78bSTyler Retzlaff 	if (ret != 0) {
286ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "pthread_getschedparam failed");
287ca04c78bSTyler Retzlaff 		goto cleanup;
288ca04c78bSTyler Retzlaff 	}
289ca04c78bSTyler Retzlaff 
290ca04c78bSTyler Retzlaff 	return thread_map_os_priority_to_eal_priority(policy,
291ca04c78bSTyler Retzlaff 		param.sched_priority, priority);
292ca04c78bSTyler Retzlaff 
293ca04c78bSTyler Retzlaff cleanup:
294ca04c78bSTyler Retzlaff 	return ret;
295ca04c78bSTyler Retzlaff }
296ca04c78bSTyler Retzlaff 
297ca04c78bSTyler Retzlaff int
298ca04c78bSTyler Retzlaff rte_thread_set_priority(rte_thread_t thread_id,
299ca04c78bSTyler Retzlaff 	enum rte_thread_priority priority)
300ca04c78bSTyler Retzlaff {
301ca04c78bSTyler Retzlaff 	struct sched_param param;
302ca04c78bSTyler Retzlaff 	int policy;
303ca04c78bSTyler Retzlaff 	int ret;
304ca04c78bSTyler Retzlaff 
305ca04c78bSTyler Retzlaff 	/* Realtime priority can cause crashes on non-Windows platforms. */
306ca04c78bSTyler Retzlaff 	if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL)
307ca04c78bSTyler Retzlaff 		return ENOTSUP;
308ca04c78bSTyler Retzlaff 
309ca04c78bSTyler Retzlaff 	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
310ca04c78bSTyler Retzlaff 		&policy);
311ca04c78bSTyler Retzlaff 	if (ret != 0)
312ca04c78bSTyler Retzlaff 		return ret;
313ca04c78bSTyler Retzlaff 
314ca04c78bSTyler Retzlaff 	return pthread_setschedparam((pthread_t)thread_id.opaque_id, policy,
315ca04c78bSTyler Retzlaff 		&param);
316ca04c78bSTyler Retzlaff }
317ca04c78bSTyler Retzlaff 
318ca04c78bSTyler Retzlaff int
31999a2dd95SBruce Richardson rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
32099a2dd95SBruce Richardson {
32199a2dd95SBruce Richardson 	int err;
32299a2dd95SBruce Richardson 
32399a2dd95SBruce Richardson 	*key = malloc(sizeof(**key));
32499a2dd95SBruce Richardson 	if ((*key) == NULL) {
325ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "Cannot allocate TLS key.");
32699a2dd95SBruce Richardson 		rte_errno = ENOMEM;
32799a2dd95SBruce Richardson 		return -1;
32899a2dd95SBruce Richardson 	}
32999a2dd95SBruce Richardson 	err = pthread_key_create(&((*key)->thread_index), destructor);
33099a2dd95SBruce Richardson 	if (err) {
331ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "pthread_key_create failed: %s",
33299a2dd95SBruce Richardson 			strerror(err));
33399a2dd95SBruce Richardson 		free(*key);
33499a2dd95SBruce Richardson 		rte_errno = ENOEXEC;
33599a2dd95SBruce Richardson 		return -1;
33699a2dd95SBruce Richardson 	}
33799a2dd95SBruce Richardson 	return 0;
33899a2dd95SBruce Richardson }
33999a2dd95SBruce Richardson 
34099a2dd95SBruce Richardson int
34199a2dd95SBruce Richardson rte_thread_key_delete(rte_thread_key key)
34299a2dd95SBruce Richardson {
34399a2dd95SBruce Richardson 	int err;
34499a2dd95SBruce Richardson 
34599a2dd95SBruce Richardson 	if (!key) {
346ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "Invalid TLS key.");
34799a2dd95SBruce Richardson 		rte_errno = EINVAL;
34899a2dd95SBruce Richardson 		return -1;
34999a2dd95SBruce Richardson 	}
35099a2dd95SBruce Richardson 	err = pthread_key_delete(key->thread_index);
35199a2dd95SBruce Richardson 	if (err) {
352ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "pthread_key_delete failed: %s",
35399a2dd95SBruce Richardson 			strerror(err));
35499a2dd95SBruce Richardson 		free(key);
35599a2dd95SBruce Richardson 		rte_errno = ENOEXEC;
35699a2dd95SBruce Richardson 		return -1;
35799a2dd95SBruce Richardson 	}
35899a2dd95SBruce Richardson 	free(key);
35999a2dd95SBruce Richardson 	return 0;
36099a2dd95SBruce Richardson }
36199a2dd95SBruce Richardson 
36299a2dd95SBruce Richardson int
36399a2dd95SBruce Richardson rte_thread_value_set(rte_thread_key key, const void *value)
36499a2dd95SBruce Richardson {
36599a2dd95SBruce Richardson 	int err;
36699a2dd95SBruce Richardson 
36799a2dd95SBruce Richardson 	if (!key) {
368ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "Invalid TLS key.");
36999a2dd95SBruce Richardson 		rte_errno = EINVAL;
37099a2dd95SBruce Richardson 		return -1;
37199a2dd95SBruce Richardson 	}
37299a2dd95SBruce Richardson 	err = pthread_setspecific(key->thread_index, value);
37399a2dd95SBruce Richardson 	if (err) {
374ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "pthread_setspecific failed: %s",
37599a2dd95SBruce Richardson 			strerror(err));
37699a2dd95SBruce Richardson 		rte_errno = ENOEXEC;
37799a2dd95SBruce Richardson 		return -1;
37899a2dd95SBruce Richardson 	}
37999a2dd95SBruce Richardson 	return 0;
38099a2dd95SBruce Richardson }
38199a2dd95SBruce Richardson 
38299a2dd95SBruce Richardson void *
38399a2dd95SBruce Richardson rte_thread_value_get(rte_thread_key key)
38499a2dd95SBruce Richardson {
38599a2dd95SBruce Richardson 	if (!key) {
386ae67895bSDavid Marchand 		EAL_LOG(DEBUG, "Invalid TLS key.");
38799a2dd95SBruce Richardson 		rte_errno = EINVAL;
38899a2dd95SBruce Richardson 		return NULL;
38999a2dd95SBruce Richardson 	}
39099a2dd95SBruce Richardson 	return pthread_getspecific(key->thread_index);
39199a2dd95SBruce Richardson }
392b70a9b78STyler Retzlaff 
393b70a9b78STyler Retzlaff int
394b70a9b78STyler Retzlaff rte_thread_set_affinity_by_id(rte_thread_t thread_id,
395b70a9b78STyler Retzlaff 		const rte_cpuset_t *cpuset)
396b70a9b78STyler Retzlaff {
397b70a9b78STyler Retzlaff 	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
398b70a9b78STyler Retzlaff 		sizeof(*cpuset), cpuset);
399b70a9b78STyler Retzlaff }
400b70a9b78STyler Retzlaff 
401b70a9b78STyler Retzlaff int
402b70a9b78STyler Retzlaff rte_thread_get_affinity_by_id(rte_thread_t thread_id,
403b70a9b78STyler Retzlaff 		rte_cpuset_t *cpuset)
404b70a9b78STyler Retzlaff {
405b70a9b78STyler Retzlaff 	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
406b70a9b78STyler Retzlaff 		sizeof(*cpuset), cpuset);
407b70a9b78STyler Retzlaff }
408