xref: /dpdk/lib/eal/unix/rte_thread.c (revision ce6e911d20f6c9af0fe717f6769b804c444aa228)
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>
899a2dd95SBruce Richardson #include <stdlib.h>
999a2dd95SBruce Richardson #include <string.h>
1099a2dd95SBruce Richardson 
1199a2dd95SBruce Richardson #include <rte_errno.h>
1299a2dd95SBruce Richardson #include <rte_log.h>
1399a2dd95SBruce Richardson #include <rte_thread.h>
1499a2dd95SBruce Richardson 
1599a2dd95SBruce Richardson struct eal_tls_key {
1699a2dd95SBruce Richardson 	pthread_key_t thread_index;
1799a2dd95SBruce Richardson };
1899a2dd95SBruce Richardson 
19*ce6e911dSTyler Retzlaff struct thread_routine_ctx {
20*ce6e911dSTyler Retzlaff 	rte_thread_func thread_func;
21*ce6e911dSTyler Retzlaff 	void *routine_args;
22*ce6e911dSTyler Retzlaff };
23*ce6e911dSTyler Retzlaff 
24ca04c78bSTyler Retzlaff static int
25ca04c78bSTyler Retzlaff thread_map_priority_to_os_value(enum rte_thread_priority eal_pri, int *os_pri,
26ca04c78bSTyler Retzlaff 	int *pol)
27ca04c78bSTyler Retzlaff {
28ca04c78bSTyler Retzlaff 	/* Clear the output parameters. */
29ca04c78bSTyler Retzlaff 	*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;
30ca04c78bSTyler Retzlaff 	*pol = -1;
31ca04c78bSTyler Retzlaff 
32ca04c78bSTyler Retzlaff 	switch (eal_pri) {
33ca04c78bSTyler Retzlaff 	case RTE_THREAD_PRIORITY_NORMAL:
34ca04c78bSTyler Retzlaff 		*pol = SCHED_OTHER;
35ca04c78bSTyler Retzlaff 
36ca04c78bSTyler Retzlaff 		/*
37ca04c78bSTyler Retzlaff 		 * Choose the middle of the range to represent the priority
38ca04c78bSTyler Retzlaff 		 * 'normal'.
39ca04c78bSTyler Retzlaff 		 * On Linux, this should be 0, since both
40ca04c78bSTyler Retzlaff 		 * sched_get_priority_min/_max return 0 for SCHED_OTHER.
41ca04c78bSTyler Retzlaff 		 */
42ca04c78bSTyler Retzlaff 		*os_pri = (sched_get_priority_min(SCHED_OTHER) +
43ca04c78bSTyler Retzlaff 			sched_get_priority_max(SCHED_OTHER)) / 2;
44ca04c78bSTyler Retzlaff 		break;
45ca04c78bSTyler Retzlaff 	case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
46ca04c78bSTyler Retzlaff 		*pol = SCHED_RR;
47ca04c78bSTyler Retzlaff 		*os_pri = sched_get_priority_max(SCHED_RR);
48ca04c78bSTyler Retzlaff 		break;
49ca04c78bSTyler Retzlaff 	default:
50ca04c78bSTyler Retzlaff 		RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
51ca04c78bSTyler Retzlaff 		return EINVAL;
52ca04c78bSTyler Retzlaff 	}
53ca04c78bSTyler Retzlaff 
54ca04c78bSTyler Retzlaff 	return 0;
55ca04c78bSTyler Retzlaff }
56ca04c78bSTyler Retzlaff 
57ca04c78bSTyler Retzlaff static int
58ca04c78bSTyler Retzlaff thread_map_os_priority_to_eal_priority(int policy, int os_pri,
59ca04c78bSTyler Retzlaff 	enum rte_thread_priority *eal_pri)
60ca04c78bSTyler Retzlaff {
61ca04c78bSTyler Retzlaff 	switch (policy) {
62ca04c78bSTyler Retzlaff 	case SCHED_OTHER:
63ca04c78bSTyler Retzlaff 		if (os_pri == (sched_get_priority_min(SCHED_OTHER) +
64ca04c78bSTyler Retzlaff 				sched_get_priority_max(SCHED_OTHER)) / 2) {
65ca04c78bSTyler Retzlaff 			*eal_pri = RTE_THREAD_PRIORITY_NORMAL;
66ca04c78bSTyler Retzlaff 			return 0;
67ca04c78bSTyler Retzlaff 		}
68ca04c78bSTyler Retzlaff 		break;
69ca04c78bSTyler Retzlaff 	case SCHED_RR:
70ca04c78bSTyler Retzlaff 		if (os_pri == sched_get_priority_max(SCHED_RR)) {
71ca04c78bSTyler Retzlaff 			*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
72ca04c78bSTyler Retzlaff 			return 0;
73ca04c78bSTyler Retzlaff 		}
74ca04c78bSTyler Retzlaff 		break;
75ca04c78bSTyler Retzlaff 	default:
76ca04c78bSTyler Retzlaff 		RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
77ca04c78bSTyler Retzlaff 		return EINVAL;
78ca04c78bSTyler Retzlaff 	}
79ca04c78bSTyler Retzlaff 
80ca04c78bSTyler Retzlaff 	return 0;
81ca04c78bSTyler Retzlaff }
82ca04c78bSTyler Retzlaff 
83*ce6e911dSTyler Retzlaff static void *
84*ce6e911dSTyler Retzlaff thread_func_wrapper(void *arg)
85*ce6e911dSTyler Retzlaff {
86*ce6e911dSTyler Retzlaff 	struct thread_routine_ctx ctx = *(struct thread_routine_ctx *)arg;
87*ce6e911dSTyler Retzlaff 
88*ce6e911dSTyler Retzlaff 	free(arg);
89*ce6e911dSTyler Retzlaff 
90*ce6e911dSTyler Retzlaff 	return (void *)(uintptr_t)ctx.thread_func(ctx.routine_args);
91*ce6e911dSTyler Retzlaff }
92*ce6e911dSTyler Retzlaff 
93*ce6e911dSTyler Retzlaff int
94*ce6e911dSTyler Retzlaff rte_thread_create(rte_thread_t *thread_id,
95*ce6e911dSTyler Retzlaff 		const rte_thread_attr_t *thread_attr,
96*ce6e911dSTyler Retzlaff 		rte_thread_func thread_func, void *args)
97*ce6e911dSTyler Retzlaff {
98*ce6e911dSTyler Retzlaff 	int ret = 0;
99*ce6e911dSTyler Retzlaff 	pthread_attr_t attr;
100*ce6e911dSTyler Retzlaff 	pthread_attr_t *attrp = NULL;
101*ce6e911dSTyler Retzlaff 	struct thread_routine_ctx *ctx;
102*ce6e911dSTyler Retzlaff 	struct sched_param param = {
103*ce6e911dSTyler Retzlaff 		.sched_priority = 0,
104*ce6e911dSTyler Retzlaff 	};
105*ce6e911dSTyler Retzlaff 	int policy = SCHED_OTHER;
106*ce6e911dSTyler Retzlaff 
107*ce6e911dSTyler Retzlaff 	ctx = calloc(1, sizeof(*ctx));
108*ce6e911dSTyler Retzlaff 	if (ctx == NULL) {
109*ce6e911dSTyler Retzlaff 		RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n");
110*ce6e911dSTyler Retzlaff 		ret = ENOMEM;
111*ce6e911dSTyler Retzlaff 		goto cleanup;
112*ce6e911dSTyler Retzlaff 	}
113*ce6e911dSTyler Retzlaff 	ctx->routine_args = args;
114*ce6e911dSTyler Retzlaff 	ctx->thread_func = thread_func;
115*ce6e911dSTyler Retzlaff 
116*ce6e911dSTyler Retzlaff 	if (thread_attr != NULL) {
117*ce6e911dSTyler Retzlaff 		ret = pthread_attr_init(&attr);
118*ce6e911dSTyler Retzlaff 		if (ret != 0) {
119*ce6e911dSTyler Retzlaff 			RTE_LOG(DEBUG, EAL, "pthread_attr_init failed\n");
120*ce6e911dSTyler Retzlaff 			goto cleanup;
121*ce6e911dSTyler Retzlaff 		}
122*ce6e911dSTyler Retzlaff 
123*ce6e911dSTyler Retzlaff 		attrp = &attr;
124*ce6e911dSTyler Retzlaff 
125*ce6e911dSTyler Retzlaff 		/*
126*ce6e911dSTyler Retzlaff 		 * Set the inherit scheduler parameter to explicit,
127*ce6e911dSTyler Retzlaff 		 * otherwise the priority attribute is ignored.
128*ce6e911dSTyler Retzlaff 		 */
129*ce6e911dSTyler Retzlaff 		ret = pthread_attr_setinheritsched(attrp,
130*ce6e911dSTyler Retzlaff 				PTHREAD_EXPLICIT_SCHED);
131*ce6e911dSTyler Retzlaff 		if (ret != 0) {
132*ce6e911dSTyler Retzlaff 			RTE_LOG(DEBUG, EAL, "pthread_attr_setinheritsched failed\n");
133*ce6e911dSTyler Retzlaff 			goto cleanup;
134*ce6e911dSTyler Retzlaff 		}
135*ce6e911dSTyler Retzlaff 
136*ce6e911dSTyler Retzlaff 
137*ce6e911dSTyler Retzlaff 		if (thread_attr->priority ==
138*ce6e911dSTyler Retzlaff 				RTE_THREAD_PRIORITY_REALTIME_CRITICAL) {
139*ce6e911dSTyler Retzlaff 			ret = ENOTSUP;
140*ce6e911dSTyler Retzlaff 			goto cleanup;
141*ce6e911dSTyler Retzlaff 		}
142*ce6e911dSTyler Retzlaff 		ret = thread_map_priority_to_os_value(thread_attr->priority,
143*ce6e911dSTyler Retzlaff 				&param.sched_priority, &policy);
144*ce6e911dSTyler Retzlaff 		if (ret != 0)
145*ce6e911dSTyler Retzlaff 			goto cleanup;
146*ce6e911dSTyler Retzlaff 
147*ce6e911dSTyler Retzlaff 		ret = pthread_attr_setschedpolicy(attrp, policy);
148*ce6e911dSTyler Retzlaff 		if (ret != 0) {
149*ce6e911dSTyler Retzlaff 			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedpolicy failed\n");
150*ce6e911dSTyler Retzlaff 			goto cleanup;
151*ce6e911dSTyler Retzlaff 		}
152*ce6e911dSTyler Retzlaff 
153*ce6e911dSTyler Retzlaff 		ret = pthread_attr_setschedparam(attrp, &param);
154*ce6e911dSTyler Retzlaff 		if (ret != 0) {
155*ce6e911dSTyler Retzlaff 			RTE_LOG(DEBUG, EAL, "pthread_attr_setschedparam failed\n");
156*ce6e911dSTyler Retzlaff 			goto cleanup;
157*ce6e911dSTyler Retzlaff 		}
158*ce6e911dSTyler Retzlaff 	}
159*ce6e911dSTyler Retzlaff 
160*ce6e911dSTyler Retzlaff 	ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp,
161*ce6e911dSTyler Retzlaff 		thread_func_wrapper, ctx);
162*ce6e911dSTyler Retzlaff 	if (ret != 0) {
163*ce6e911dSTyler Retzlaff 		RTE_LOG(DEBUG, EAL, "pthread_create failed\n");
164*ce6e911dSTyler Retzlaff 		goto cleanup;
165*ce6e911dSTyler Retzlaff 	}
166*ce6e911dSTyler Retzlaff 
167*ce6e911dSTyler Retzlaff 	if (thread_attr != NULL && CPU_COUNT(&thread_attr->cpuset) > 0) {
168*ce6e911dSTyler Retzlaff 		ret = rte_thread_set_affinity_by_id(*thread_id,
169*ce6e911dSTyler Retzlaff 			&thread_attr->cpuset);
170*ce6e911dSTyler Retzlaff 		if (ret != 0) {
171*ce6e911dSTyler Retzlaff 			RTE_LOG(DEBUG, EAL, "rte_thread_set_affinity_by_id failed\n");
172*ce6e911dSTyler Retzlaff 			goto cleanup;
173*ce6e911dSTyler Retzlaff 		}
174*ce6e911dSTyler Retzlaff 	}
175*ce6e911dSTyler Retzlaff 
176*ce6e911dSTyler Retzlaff 	ctx = NULL;
177*ce6e911dSTyler Retzlaff cleanup:
178*ce6e911dSTyler Retzlaff 	free(ctx);
179*ce6e911dSTyler Retzlaff 	if (attrp != NULL)
180*ce6e911dSTyler Retzlaff 		pthread_attr_destroy(&attr);
181*ce6e911dSTyler Retzlaff 
182*ce6e911dSTyler Retzlaff 	return ret;
183*ce6e911dSTyler Retzlaff }
184*ce6e911dSTyler Retzlaff 
185*ce6e911dSTyler Retzlaff int
186*ce6e911dSTyler Retzlaff rte_thread_join(rte_thread_t thread_id, uint32_t *value_ptr)
187*ce6e911dSTyler Retzlaff {
188*ce6e911dSTyler Retzlaff 	int ret = 0;
189*ce6e911dSTyler Retzlaff 	void *res = (void *)(uintptr_t)0;
190*ce6e911dSTyler Retzlaff 	void **pres = NULL;
191*ce6e911dSTyler Retzlaff 
192*ce6e911dSTyler Retzlaff 	if (value_ptr != NULL)
193*ce6e911dSTyler Retzlaff 		pres = &res;
194*ce6e911dSTyler Retzlaff 
195*ce6e911dSTyler Retzlaff 	ret = pthread_join((pthread_t)thread_id.opaque_id, pres);
196*ce6e911dSTyler Retzlaff 	if (ret != 0) {
197*ce6e911dSTyler Retzlaff 		RTE_LOG(DEBUG, EAL, "pthread_join failed\n");
198*ce6e911dSTyler Retzlaff 		return ret;
199*ce6e911dSTyler Retzlaff 	}
200*ce6e911dSTyler Retzlaff 
201*ce6e911dSTyler Retzlaff 	if (value_ptr != NULL)
202*ce6e911dSTyler Retzlaff 		*value_ptr = (uint32_t)(uintptr_t)res;
203*ce6e911dSTyler Retzlaff 
204*ce6e911dSTyler Retzlaff 	return 0;
205*ce6e911dSTyler Retzlaff }
206*ce6e911dSTyler Retzlaff 
207*ce6e911dSTyler Retzlaff int
208*ce6e911dSTyler Retzlaff rte_thread_detach(rte_thread_t thread_id)
209*ce6e911dSTyler Retzlaff {
210*ce6e911dSTyler Retzlaff 	return pthread_detach((pthread_t)thread_id.opaque_id);
211*ce6e911dSTyler Retzlaff }
212*ce6e911dSTyler Retzlaff 
21356539289STyler Retzlaff rte_thread_t
21456539289STyler Retzlaff rte_thread_self(void)
21556539289STyler Retzlaff {
21656539289STyler Retzlaff 	RTE_BUILD_BUG_ON(sizeof(pthread_t) > sizeof(uintptr_t));
21756539289STyler Retzlaff 
21856539289STyler Retzlaff 	rte_thread_t thread_id;
21956539289STyler Retzlaff 
22056539289STyler Retzlaff 	thread_id.opaque_id = (uintptr_t)pthread_self();
22156539289STyler Retzlaff 
22256539289STyler Retzlaff 	return thread_id;
22356539289STyler Retzlaff }
22456539289STyler Retzlaff 
22599a2dd95SBruce Richardson int
226ca04c78bSTyler Retzlaff rte_thread_get_priority(rte_thread_t thread_id,
227ca04c78bSTyler Retzlaff 	enum rte_thread_priority *priority)
228ca04c78bSTyler Retzlaff {
229ca04c78bSTyler Retzlaff 	struct sched_param param;
230ca04c78bSTyler Retzlaff 	int policy;
231ca04c78bSTyler Retzlaff 	int ret;
232ca04c78bSTyler Retzlaff 
233ca04c78bSTyler Retzlaff 	ret = pthread_getschedparam((pthread_t)thread_id.opaque_id, &policy,
234ca04c78bSTyler Retzlaff 		&param);
235ca04c78bSTyler Retzlaff 	if (ret != 0) {
236ca04c78bSTyler Retzlaff 		RTE_LOG(DEBUG, EAL, "pthread_getschedparam failed\n");
237ca04c78bSTyler Retzlaff 		goto cleanup;
238ca04c78bSTyler Retzlaff 	}
239ca04c78bSTyler Retzlaff 
240ca04c78bSTyler Retzlaff 	return thread_map_os_priority_to_eal_priority(policy,
241ca04c78bSTyler Retzlaff 		param.sched_priority, priority);
242ca04c78bSTyler Retzlaff 
243ca04c78bSTyler Retzlaff cleanup:
244ca04c78bSTyler Retzlaff 	return ret;
245ca04c78bSTyler Retzlaff }
246ca04c78bSTyler Retzlaff 
247ca04c78bSTyler Retzlaff int
248ca04c78bSTyler Retzlaff rte_thread_set_priority(rte_thread_t thread_id,
249ca04c78bSTyler Retzlaff 	enum rte_thread_priority priority)
250ca04c78bSTyler Retzlaff {
251ca04c78bSTyler Retzlaff 	struct sched_param param;
252ca04c78bSTyler Retzlaff 	int policy;
253ca04c78bSTyler Retzlaff 	int ret;
254ca04c78bSTyler Retzlaff 
255ca04c78bSTyler Retzlaff 	/* Realtime priority can cause crashes on non-Windows platforms. */
256ca04c78bSTyler Retzlaff 	if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL)
257ca04c78bSTyler Retzlaff 		return ENOTSUP;
258ca04c78bSTyler Retzlaff 
259ca04c78bSTyler Retzlaff 	ret = thread_map_priority_to_os_value(priority, &param.sched_priority,
260ca04c78bSTyler Retzlaff 		&policy);
261ca04c78bSTyler Retzlaff 	if (ret != 0)
262ca04c78bSTyler Retzlaff 		return ret;
263ca04c78bSTyler Retzlaff 
264ca04c78bSTyler Retzlaff 	return pthread_setschedparam((pthread_t)thread_id.opaque_id, policy,
265ca04c78bSTyler Retzlaff 		&param);
266ca04c78bSTyler Retzlaff }
267ca04c78bSTyler Retzlaff 
268ca04c78bSTyler Retzlaff int
26999a2dd95SBruce Richardson rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))
27099a2dd95SBruce Richardson {
27199a2dd95SBruce Richardson 	int err;
27299a2dd95SBruce Richardson 
27399a2dd95SBruce Richardson 	*key = malloc(sizeof(**key));
27499a2dd95SBruce Richardson 	if ((*key) == NULL) {
27599a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
27699a2dd95SBruce Richardson 		rte_errno = ENOMEM;
27799a2dd95SBruce Richardson 		return -1;
27899a2dd95SBruce Richardson 	}
27999a2dd95SBruce Richardson 	err = pthread_key_create(&((*key)->thread_index), destructor);
28099a2dd95SBruce Richardson 	if (err) {
28199a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n",
28299a2dd95SBruce Richardson 			strerror(err));
28399a2dd95SBruce Richardson 		free(*key);
28499a2dd95SBruce Richardson 		rte_errno = ENOEXEC;
28599a2dd95SBruce Richardson 		return -1;
28699a2dd95SBruce Richardson 	}
28799a2dd95SBruce Richardson 	return 0;
28899a2dd95SBruce Richardson }
28999a2dd95SBruce Richardson 
29099a2dd95SBruce Richardson int
29199a2dd95SBruce Richardson rte_thread_key_delete(rte_thread_key key)
29299a2dd95SBruce Richardson {
29399a2dd95SBruce Richardson 	int err;
29499a2dd95SBruce Richardson 
29599a2dd95SBruce Richardson 	if (!key) {
29699a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
29799a2dd95SBruce Richardson 		rte_errno = EINVAL;
29899a2dd95SBruce Richardson 		return -1;
29999a2dd95SBruce Richardson 	}
30099a2dd95SBruce Richardson 	err = pthread_key_delete(key->thread_index);
30199a2dd95SBruce Richardson 	if (err) {
30299a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n",
30399a2dd95SBruce Richardson 			strerror(err));
30499a2dd95SBruce Richardson 		free(key);
30599a2dd95SBruce Richardson 		rte_errno = ENOEXEC;
30699a2dd95SBruce Richardson 		return -1;
30799a2dd95SBruce Richardson 	}
30899a2dd95SBruce Richardson 	free(key);
30999a2dd95SBruce Richardson 	return 0;
31099a2dd95SBruce Richardson }
31199a2dd95SBruce Richardson 
31299a2dd95SBruce Richardson int
31399a2dd95SBruce Richardson rte_thread_value_set(rte_thread_key key, const void *value)
31499a2dd95SBruce Richardson {
31599a2dd95SBruce Richardson 	int err;
31699a2dd95SBruce Richardson 
31799a2dd95SBruce Richardson 	if (!key) {
31899a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
31999a2dd95SBruce Richardson 		rte_errno = EINVAL;
32099a2dd95SBruce Richardson 		return -1;
32199a2dd95SBruce Richardson 	}
32299a2dd95SBruce Richardson 	err = pthread_setspecific(key->thread_index, value);
32399a2dd95SBruce Richardson 	if (err) {
32499a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n",
32599a2dd95SBruce Richardson 			strerror(err));
32699a2dd95SBruce Richardson 		rte_errno = ENOEXEC;
32799a2dd95SBruce Richardson 		return -1;
32899a2dd95SBruce Richardson 	}
32999a2dd95SBruce Richardson 	return 0;
33099a2dd95SBruce Richardson }
33199a2dd95SBruce Richardson 
33299a2dd95SBruce Richardson void *
33399a2dd95SBruce Richardson rte_thread_value_get(rte_thread_key key)
33499a2dd95SBruce Richardson {
33599a2dd95SBruce Richardson 	if (!key) {
33699a2dd95SBruce Richardson 		RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
33799a2dd95SBruce Richardson 		rte_errno = EINVAL;
33899a2dd95SBruce Richardson 		return NULL;
33999a2dd95SBruce Richardson 	}
34099a2dd95SBruce Richardson 	return pthread_getspecific(key->thread_index);
34199a2dd95SBruce Richardson }
342b70a9b78STyler Retzlaff 
343b70a9b78STyler Retzlaff int
344b70a9b78STyler Retzlaff rte_thread_set_affinity_by_id(rte_thread_t thread_id,
345b70a9b78STyler Retzlaff 		const rte_cpuset_t *cpuset)
346b70a9b78STyler Retzlaff {
347b70a9b78STyler Retzlaff 	return pthread_setaffinity_np((pthread_t)thread_id.opaque_id,
348b70a9b78STyler Retzlaff 		sizeof(*cpuset), cpuset);
349b70a9b78STyler Retzlaff }
350b70a9b78STyler Retzlaff 
351b70a9b78STyler Retzlaff int
352b70a9b78STyler Retzlaff rte_thread_get_affinity_by_id(rte_thread_t thread_id,
353b70a9b78STyler Retzlaff 		rte_cpuset_t *cpuset)
354b70a9b78STyler Retzlaff {
355b70a9b78STyler Retzlaff 	return pthread_getaffinity_np((pthread_t)thread_id.opaque_id,
356b70a9b78STyler Retzlaff 		sizeof(*cpuset), cpuset);
357b70a9b78STyler Retzlaff }
358