xref: /dpdk/lib/eal/unix/rte_thread.c (revision 1c1abf1786a6de044bd396da4cc316961e3fd812)
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 
1699a2dd95SBruce Richardson struct eal_tls_key {
1799a2dd95SBruce Richardson 	pthread_key_t thread_index;
1899a2dd95SBruce Richardson };
1999a2dd95SBruce Richardson 
20b28c6196STyler Retzlaff struct thread_start_context {
21ce6e911dSTyler Retzlaff 	rte_thread_func thread_func;
22b28c6196STyler Retzlaff 	void *thread_args;
23b28c6196STyler Retzlaff 	const rte_thread_attr_t *thread_attr;
24b28c6196STyler Retzlaff 	pthread_mutex_t wrapper_mutex;
25b28c6196STyler Retzlaff 	pthread_cond_t wrapper_cond;
26b28c6196STyler Retzlaff 	int wrapper_ret;
27b28c6196STyler Retzlaff 	bool wrapper_done;
28ce6e911dSTyler Retzlaff };
29ce6e911dSTyler Retzlaff 
30ca04c78bSTyler Retzlaff static int
31ca04c78bSTyler Retzlaff thread_map_priority_to_os_value(enum rte_thread_priority eal_pri, int *os_pri,
32ca04c78bSTyler Retzlaff 	int *pol)
33ca04c78bSTyler Retzlaff {
34ca04c78bSTyler Retzlaff 	/* Clear the output parameters. */
35ca04c78bSTyler Retzlaff 	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
36ca04c78bSTyler Retzlaff 	*pol = -1;
37ca04c78bSTyler Retzlaff 
38ca04c78bSTyler Retzlaff 	switch (eal_pri) {
39ca04c78bSTyler Retzlaff 	case RTE_THREAD_PRIORITY_NORMAL:
40ca04c78bSTyler Retzlaff 		*pol = SCHED_OTHER;
41ca04c78bSTyler Retzlaff 
42ca04c78bSTyler Retzlaff 		/*
43ca04c78bSTyler Retzlaff 		 * Choose the middle of the range to represent the priority
44ca04c78bSTyler Retzlaff 		 * 'normal'.
45ca04c78bSTyler Retzlaff 		 * On Linux, this should be 0, since both
46ca04c78bSTyler Retzlaff 		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
47ca04c78bSTyler Retzlaff 		 */
48ca04c78bSTyler Retzlaff 		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
49ca04c78bSTyler Retzlaff 			sched_get_priority_max(SCHED_OTHER)) / 2;
50ca04c78bSTyler Retzlaff 		break;
51ca04c78bSTyler Retzlaff 	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
52ca04c78bSTyler Retzlaff 		*pol = SCHED_RR;
53ca04c78bSTyler Retzlaff 		*os_pri = sched_get_priority_max(SCHED_RR);
54ca04c78bSTyler Retzlaff 		break;
55ca04c78bSTyler Retzlaff 	default:
56ca04c78bSTyler Retzlaff 		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
57ca04c78bSTyler Retzlaff 		return EINVAL;
58ca04c78bSTyler Retzlaff 	}
59ca04c78bSTyler Retzlaff 
60ca04c78bSTyler Retzlaff 	return 0;
61ca04c78bSTyler Retzlaff }
62ca04c78bSTyler Retzlaff 
63ca04c78bSTyler Retzlaff static int
64ca04c78bSTyler Retzlaff thread_map_os_priority_to_eal_priority(int policy, int os_pri,
65ca04c78bSTyler Retzlaff 	enum rte_thread_priority *eal_pri)
66ca04c78bSTyler Retzlaff {
67ca04c78bSTyler Retzlaff 	switch (policy) {
68ca04c78bSTyler Retzlaff 	case SCHED_OTHER:
69ca04c78bSTyler Retzlaff 		if (os_pri == (sched_get_priority_min(SCHED_OTHER) +
70ca04c78bSTyler Retzlaff 				sched_get_priority_max(SCHED_OTHER)) / 2) {
71ca04c78bSTyler Retzlaff 			*eal_pri = RTE_THREAD_PRIORITY_NORMAL;
72ca04c78bSTyler Retzlaff 			return 0;
73ca04c78bSTyler Retzlaff 		}
74ca04c78bSTyler Retzlaff 		break;
75ca04c78bSTyler Retzlaff 	case SCHED_RR:
76ca04c78bSTyler Retzlaff 		if (os_pri == sched_get_priority_max(SCHED_RR)) {
77ca04c78bSTyler Retzlaff 			*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
78ca04c78bSTyler Retzlaff 			return 0;
79ca04c78bSTyler Retzlaff 		}
80ca04c78bSTyler Retzlaff 		break;
81ca04c78bSTyler Retzlaff 	default:
82ca04c78bSTyler Retzlaff 		RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
83ca04c78bSTyler Retzlaff 		return EINVAL;
84ca04c78bSTyler Retzlaff 	}
85ca04c78bSTyler Retzlaff 
86ca04c78bSTyler Retzlaff 	return 0;
87ca04c78bSTyler Retzlaff }
88ca04c78bSTyler Retzlaff 
89ce6e911dSTyler Retzlaff static void *
90b28c6196STyler Retzlaff thread_start_wrapper(void *arg)
91ce6e911dSTyler Retzlaff {
92b28c6196STyler Retzlaff 	struct thread_start_context *ctx = (struct thread_start_context *)arg;
93b28c6196STyler Retzlaff 	rte_thread_func thread_func = ctx->thread_func;
94b28c6196STyler Retzlaff 	void *thread_args = ctx->thread_args;
95b28c6196STyler Retzlaff 	int ret = 0;
96ce6e911dSTyler Retzlaff 
97b28c6196STyler Retzlaff 	if (ctx->thread_attr != NULL && CPU_COUNT(&ctx->thread_attr->cpuset) > 0) {
98b28c6196STyler Retzlaff 		ret = rte_thread_set_affinity_by_id(rte_thread_self(), &ctx->thread_attr->cpuset);
99b28c6196STyler Retzlaff 		if (ret != 0)
100b28c6196STyler Retzlaff 			RTE_LOG(DEBUG, EAL, "rte_thread_set_affinity_by_id failed\n");
101b28c6196STyler Retzlaff 	}
102ce6e911dSTyler Retzlaff 
103b28c6196STyler Retzlaff 	pthread_mutex_lock(&ctx->wrapper_mutex);
104b28c6196STyler Retzlaff 	ctx->wrapper_ret = ret;
105b28c6196STyler Retzlaff 	ctx->wrapper_done = true;
106b28c6196STyler Retzlaff 	pthread_cond_signal(&ctx->wrapper_cond);
107b28c6196STyler Retzlaff 	pthread_mutex_unlock(&ctx->wrapper_mutex);
108b28c6196STyler Retzlaff 
109b28c6196STyler Retzlaff 	if (ret != 0)
110b28c6196STyler Retzlaff 		return NULL;
111b28c6196STyler Retzlaff 
112b28c6196STyler Retzlaff 	return (void *)(uintptr_t)thread_func(thread_args);
113ce6e911dSTyler Retzlaff }
114ce6e911dSTyler Retzlaff 
115ce6e911dSTyler Retzlaff int
116ce6e911dSTyler Retzlaff rte_thread_create(rte_thread_t *thread_id,
117ce6e911dSTyler Retzlaff 		const rte_thread_attr_t *thread_attr,
118ce6e911dSTyler Retzlaff 		rte_thread_func thread_func, void *args)
119ce6e911dSTyler Retzlaff {
120ce6e911dSTyler Retzlaff 	int ret = 0;
121ce6e911dSTyler Retzlaff 	pthread_attr_t attr;
122ce6e911dSTyler Retzlaff 	pthread_attr_t *attrp = NULL;
123ce6e911dSTyler Retzlaff 	struct sched_param param = {
124ce6e911dSTyler Retzlaff 		.sched_priority = 0,
125ce6e911dSTyler Retzlaff 	};
126ce6e911dSTyler Retzlaff 	int policy = SCHED_OTHER;
127b28c6196STyler Retzlaff 	struct thread_start_context ctx = {
128b28c6196STyler Retzlaff 		.thread_func = thread_func,
129b28c6196STyler Retzlaff 		.thread_args = args,
130b28c6196STyler Retzlaff 		.thread_attr = thread_attr,
131b28c6196STyler Retzlaff 		.wrapper_done = false,
132b28c6196STyler Retzlaff 		.wrapper_mutex = PTHREAD_MUTEX_INITIALIZER,
133b28c6196STyler Retzlaff 		.wrapper_cond = PTHREAD_COND_INITIALIZER,
134b28c6196STyler Retzlaff 	};
135ce6e911dSTyler Retzlaff 
136ce6e911dSTyler Retzlaff 	if (thread_attr != NULL) {
137ce6e911dSTyler Retzlaff 		ret = pthread_attr_init(&attr);
138ce6e911dSTyler Retzlaff 		if (ret != 0) {
139ce6e911dSTyler Retzlaff 			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
140ce6e911dSTyler Retzlaff 			goto cleanup;
141ce6e911dSTyler Retzlaff 		}
142ce6e911dSTyler Retzlaff 
143ce6e911dSTyler Retzlaff 		attrp = &attr;
144ce6e911dSTyler Retzlaff 
145ce6e911dSTyler Retzlaff 		/*
146ce6e911dSTyler Retzlaff 		 * Set the inherit scheduler parameter to explicit,
147ce6e911dSTyler Retzlaff 		 * otherwise the priority attribute is ignored.
148ce6e911dSTyler Retzlaff 		 */
149ce6e911dSTyler Retzlaff 		ret = pthread_attr_setinheritsched(attrp,
150ce6e911dSTyler Retzlaff 				PTHREAD_EXPLICIT_SCHED);
151ce6e911dSTyler Retzlaff 		if (ret != 0) {
152ce6e911dSTyler Retzlaff 			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
153ce6e911dSTyler Retzlaff 			goto cleanup;
154ce6e911dSTyler Retzlaff 		}
155ce6e911dSTyler Retzlaff 
156ce6e911dSTyler Retzlaff 		if (thread_attr->priority ==
157ce6e911dSTyler Retzlaff 				RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
158ce6e911dSTyler Retzlaff 			ret = ENOTSUP;
159ce6e911dSTyler Retzlaff 			goto cleanup;
160ce6e911dSTyler Retzlaff 		}
161ce6e911dSTyler Retzlaff 		ret = thread_map_priority_to_os_value(thread_attr->priority,
162ce6e911dSTyler Retzlaff 				&param.sched_priority, &policy);
163ce6e911dSTyler Retzlaff 		if (ret != 0)
164ce6e911dSTyler Retzlaff 			goto cleanup;
165ce6e911dSTyler Retzlaff 
166ce6e911dSTyler Retzlaff 		ret = pthread_attr_setschedpolicy(attrp, policy);
167ce6e911dSTyler Retzlaff 		if (ret != 0) {
168ce6e911dSTyler Retzlaff 			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
169ce6e911dSTyler Retzlaff 			goto cleanup;
170ce6e911dSTyler Retzlaff 		}
171ce6e911dSTyler Retzlaff 
172ce6e911dSTyler Retzlaff 		ret = pthread_attr_setschedparam(attrp, &param);
173ce6e911dSTyler Retzlaff 		if (ret != 0) {
174ce6e911dSTyler Retzlaff 			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
175ce6e911dSTyler Retzlaff 			goto cleanup;
176ce6e911dSTyler Retzlaff 		}
177ce6e911dSTyler Retzlaff 	}
178ce6e911dSTyler Retzlaff 
179ce6e911dSTyler Retzlaff 	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
180b28c6196STyler Retzlaff 		thread_start_wrapper, &ctx);
181ce6e911dSTyler Retzlaff 	if (ret != 0) {
182ce6e911dSTyler Retzlaff 		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
183ce6e911dSTyler Retzlaff 		goto cleanup;
184ce6e911dSTyler Retzlaff 	}
185ce6e911dSTyler Retzlaff 
186b28c6196STyler Retzlaff 	pthread_mutex_lock(&ctx.wrapper_mutex);
187b28c6196STyler Retzlaff 	while (!ctx.wrapper_done)
188b28c6196STyler Retzlaff 		pthread_cond_wait(&ctx.wrapper_cond, &ctx.wrapper_mutex);
189b28c6196STyler Retzlaff 	ret = ctx.wrapper_ret;
190b28c6196STyler Retzlaff 	pthread_mutex_unlock(&ctx.wrapper_mutex);
191ce6e911dSTyler Retzlaff 
192b28c6196STyler Retzlaff 	if (ret != 0)
193*1c1abf17SThomas Monjalon 		rte_thread_join(*thread_id, NULL);
194b28c6196STyler Retzlaff 
195ce6e911dSTyler Retzlaff cleanup:
196ce6e911dSTyler Retzlaff 	if (attrp != NULL)
197ce6e911dSTyler Retzlaff 		pthread_attr_destroy(&attr);
198ce6e911dSTyler Retzlaff 
199ce6e911dSTyler Retzlaff 	return ret;
200ce6e911dSTyler Retzlaff }
201ce6e911dSTyler Retzlaff 
202ce6e911dSTyler Retzlaff int
203ce6e911dSTyler Retzlaff rte_thread_join(rte_thread_t thread_id, uint32_t *value_ptr)
204ce6e911dSTyler Retzlaff {
205ce6e911dSTyler Retzlaff 	int ret = 0;
206ce6e911dSTyler Retzlaff 	void *res = (void *)(uintptr_t)0;
207ce6e911dSTyler Retzlaff 	void **pres = NULL;
208ce6e911dSTyler Retzlaff 
209ce6e911dSTyler Retzlaff 	if (value_ptr != NULL)
210ce6e911dSTyler Retzlaff 		pres = &res;
211ce6e911dSTyler Retzlaff 
212ce6e911dSTyler Retzlaff 	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
213ce6e911dSTyler Retzlaff 	if (ret != 0) {
214ce6e911dSTyler Retzlaff 		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
215ce6e911dSTyler Retzlaff 		return ret;
216ce6e911dSTyler Retzlaff 	}
217ce6e911dSTyler Retzlaff 
218ce6e911dSTyler Retzlaff 	if (value_ptr != NULL)
219ce6e911dSTyler Retzlaff 		*value_ptr = (uint32_t)(uintptr_t)res;
220ce6e911dSTyler Retzlaff 
221ce6e911dSTyler Retzlaff 	return 0;
222ce6e911dSTyler Retzlaff }
223ce6e911dSTyler Retzlaff 
224ce6e911dSTyler Retzlaff int
225ce6e911dSTyler Retzlaff rte_thread_detach(rte_thread_t thread_id)
226ce6e911dSTyler Retzlaff {
227ce6e911dSTyler Retzlaff 	return pthread_detach((pthread_t)thread_id.opaque_id);
228ce6e911dSTyler Retzlaff }
229ce6e911dSTyler Retzlaff 
230a2e94ca8STyler Retzlaff int
231a2e94ca8STyler Retzlaff rte_thread_equal(rte_thread_t t1, rte_thread_t t2)
232a2e94ca8STyler Retzlaff {
233a2e94ca8STyler Retzlaff 	return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);
234a2e94ca8STyler Retzlaff }
235a2e94ca8STyler Retzlaff 
23656539289STyler Retzlaff rte_thread_t
23756539289STyler Retzlaff rte_thread_self(void)
23856539289STyler Retzlaff {
23956539289STyler Retzlaff 	RTE_BUILD_BUG_ON(sizeof(pthread_t) > sizeof(uintptr_t));
24056539289STyler Retzlaff 
24156539289STyler Retzlaff 	rte_thread_t thread_id;
24256539289STyler Retzlaff 
24356539289STyler Retzlaff 	thread_id.opaque_id = (uintptr_t)pthread_self();
24456539289STyler Retzlaff 
24556539289STyler Retzlaff 	return thread_id;
24656539289STyler Retzlaff }
24756539289STyler Retzlaff 
24899a2dd95SBruce Richardson int
249ca04c78bSTyler Retzlaff rte_thread_get_priority(rte_thread_t thread_id,
250ca04c78bSTyler Retzlaff 	enum rte_thread_priority *priority)
251ca04c78bSTyler Retzlaff {
252ca04c78bSTyler Retzlaff 	struct sched_param param;
253ca04c78bSTyler Retzlaff 	int policy;
254ca04c78bSTyler Retzlaff 	int ret;
255ca04c78bSTyler Retzlaff 
256ca04c78bSTyler Retzlaff 	ret = pthread_getschedparam((pthread_t)thread_id.opaque_id, &policy,
257ca04c78bSTyler Retzlaff 		&param);
258ca04c78bSTyler Retzlaff 	if (ret != 0) {
259ca04c78bSTyler Retzlaff 		RTE_LOG(DEBUG, EAL, "pthread_getschedparam failed\n");
260ca04c78bSTyler Retzlaff 		goto cleanup;
261ca04c78bSTyler Retzlaff 	}
262ca04c78bSTyler Retzlaff 
263ca04c78bSTyler Retzlaff 	return thread_map_os_priority_to_eal_priority(policy,
264ca04c78bSTyler Retzlaff 		param.sched_priority, priority);
265ca04c78bSTyler Retzlaff 
266ca04c78bSTyler Retzlaff cleanup:
267ca04c78bSTyler Retzlaff 	return ret;
268ca04c78bSTyler Retzlaff }
269ca04c78bSTyler Retzlaff 
270ca04c78bSTyler Retzlaff int
271ca04c78bSTyler Retzlaff rte_thread_set_priority(rte_thread_t thread_id,
272ca04c78bSTyler Retzlaff 	enum rte_thread_priority priority)
273ca04c78bSTyler Retzlaff {
274ca04c78bSTyler Retzlaff 	struct sched_param param;
275ca04c78bSTyler Retzlaff 	int policy;
276ca04c78bSTyler Retzlaff 	int ret;
277ca04c78bSTyler Retzlaff 
278ca04c78bSTyler Retzlaff 	/* Realtime priority can cause crashes on non-Windows platforms. */
279ca04c78bSTyler Retzlaff 	if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL)
280ca04c78bSTyler Retzlaff 		return ENOTSUP;
281ca04c78bSTyler Retzlaff 
282ca04c78bSTyler Retzlaff 	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
283ca04c78bSTyler Retzlaff 		&policy);
284ca04c78bSTyler Retzlaff 	if (ret != 0)
285ca04c78bSTyler Retzlaff 		return ret;
286ca04c78bSTyler Retzlaff 
287ca04c78bSTyler Retzlaff 	return pthread_setschedparam((pthread_t)thread_id.opaque_id, policy,
288ca04c78bSTyler Retzlaff 		&param);
289ca04c78bSTyler Retzlaff }
290ca04c78bSTyler Retzlaff 
291ca04c78bSTyler Retzlaff int
29299a2dd95SBruce Richardson rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
29399a2dd95SBruce Richardson {
29499a2dd95SBruce Richardson 	int err;
29599a2dd95SBruce Richardson 
29699a2dd95SBruce Richardson 	*key = malloc(sizeof(**key));
29799a2dd95SBruce Richardson 	if ((*key) == NULL) {
29899a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
29999a2dd95SBruce Richardson 		rte_errno = ENOMEM;
30099a2dd95SBruce Richardson 		return -1;
30199a2dd95SBruce Richardson 	}
30299a2dd95SBruce Richardson 	err = pthread_key_create(&((*key)->thread_index), destructor);
30399a2dd95SBruce Richardson 	if (err) {
30499a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
30599a2dd95SBruce Richardson 			strerror(err));
30699a2dd95SBruce Richardson 		free(*key);
30799a2dd95SBruce Richardson 		rte_errno = ENOEXEC;
30899a2dd95SBruce Richardson 		return -1;
30999a2dd95SBruce Richardson 	}
31099a2dd95SBruce Richardson 	return 0;
31199a2dd95SBruce Richardson }
31299a2dd95SBruce Richardson 
31399a2dd95SBruce Richardson int
31499a2dd95SBruce Richardson rte_thread_key_delete(rte_thread_key key)
31599a2dd95SBruce Richardson {
31699a2dd95SBruce Richardson 	int err;
31799a2dd95SBruce Richardson 
31899a2dd95SBruce Richardson 	if (!key) {
31999a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
32099a2dd95SBruce Richardson 		rte_errno = EINVAL;
32199a2dd95SBruce Richardson 		return -1;
32299a2dd95SBruce Richardson 	}
32399a2dd95SBruce Richardson 	err = pthread_key_delete(key->thread_index);
32499a2dd95SBruce Richardson 	if (err) {
32599a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
32699a2dd95SBruce Richardson 			strerror(err));
32799a2dd95SBruce Richardson 		free(key);
32899a2dd95SBruce Richardson 		rte_errno = ENOEXEC;
32999a2dd95SBruce Richardson 		return -1;
33099a2dd95SBruce Richardson 	}
33199a2dd95SBruce Richardson 	free(key);
33299a2dd95SBruce Richardson 	return 0;
33399a2dd95SBruce Richardson }
33499a2dd95SBruce Richardson 
33599a2dd95SBruce Richardson int
33699a2dd95SBruce Richardson rte_thread_value_set(rte_thread_key key, const void *value)
33799a2dd95SBruce Richardson {
33899a2dd95SBruce Richardson 	int err;
33999a2dd95SBruce Richardson 
34099a2dd95SBruce Richardson 	if (!key) {
34199a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
34299a2dd95SBruce Richardson 		rte_errno = EINVAL;
34399a2dd95SBruce Richardson 		return -1;
34499a2dd95SBruce Richardson 	}
34599a2dd95SBruce Richardson 	err = pthread_setspecific(key->thread_index, value);
34699a2dd95SBruce Richardson 	if (err) {
34799a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
34899a2dd95SBruce Richardson 			strerror(err));
34999a2dd95SBruce Richardson 		rte_errno = ENOEXEC;
35099a2dd95SBruce Richardson 		return -1;
35199a2dd95SBruce Richardson 	}
35299a2dd95SBruce Richardson 	return 0;
35399a2dd95SBruce Richardson }
35499a2dd95SBruce Richardson 
35599a2dd95SBruce Richardson void *
35699a2dd95SBruce Richardson rte_thread_value_get(rte_thread_key key)
35799a2dd95SBruce Richardson {
35899a2dd95SBruce Richardson 	if (!key) {
35999a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
36099a2dd95SBruce Richardson 		rte_errno = EINVAL;
36199a2dd95SBruce Richardson 		return NULL;
36299a2dd95SBruce Richardson 	}
36399a2dd95SBruce Richardson 	return pthread_getspecific(key->thread_index);
36499a2dd95SBruce Richardson }
365b70a9b78STyler Retzlaff 
366b70a9b78STyler Retzlaff int
367b70a9b78STyler Retzlaff rte_thread_set_affinity_by_id(rte_thread_t thread_id,
368b70a9b78STyler Retzlaff 		const rte_cpuset_t *cpuset)
369b70a9b78STyler Retzlaff {
370b70a9b78STyler Retzlaff 	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
371b70a9b78STyler Retzlaff 		sizeof(*cpuset), cpuset);
372b70a9b78STyler Retzlaff }
373b70a9b78STyler Retzlaff 
374b70a9b78STyler Retzlaff int
375b70a9b78STyler Retzlaff rte_thread_get_affinity_by_id(rte_thread_t thread_id,
376b70a9b78STyler Retzlaff 		rte_cpuset_t *cpuset)
377b70a9b78STyler Retzlaff {
378b70a9b78STyler Retzlaff 	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
379b70a9b78STyler Retzlaff 		sizeof(*cpuset), cpuset);
380b70a9b78STyler Retzlaff }
381