1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include <errno.h>
38 #define __USE_GNU
39 #include <sched.h>
40 #include <dlfcn.h>
41 
42 #include <rte_log.h>
43 
44 #include "lthread_api.h"
45 #include "pthread_shim.h"
46 
47 #define RTE_LOGTYPE_PTHREAD_SHIM RTE_LOGTYPE_USER3
48 
49 #define POSIX_ERRNO(x)  (x)
50 
51 /* some releases of FreeBSD 10, e.g. 10.0, don't have CPU_COUNT macro */
52 #ifndef CPU_COUNT
53 #define CPU_COUNT(x) __cpu_count(x)
54 
55 static inline unsigned int
56 __cpu_count(const rte_cpuset_t *cpuset)
57 {
58 	unsigned int i, count = 0;
59 	for (i = 0; i < RTE_MAX_LCORE; i++)
60 		if (CPU_ISSET(i, cpuset))
61 			count++;
62 	return count;
63 }
64 #endif
65 
66 /*
67  * this flag determines at run time if we override pthread
68  * calls and map then to equivalent lthread calls
69  * or of we call the standard pthread function
70  */
71 static __thread int override;
72 
73 
74 /*
75  * this structures contains function pointers that will be
76  * initialised to the loaded address of the real
77  * pthread library API functions
78  */
79 struct pthread_lib_funcs {
80 int (*f_pthread_barrier_destroy)
81 	(pthread_barrier_t *);
82 int (*f_pthread_barrier_init)
83 	(pthread_barrier_t *, const pthread_barrierattr_t *, unsigned);
84 int (*f_pthread_barrier_wait)
85 	(pthread_barrier_t *);
86 int (*f_pthread_cond_broadcast)
87 	(pthread_cond_t *);
88 int (*f_pthread_cond_destroy)
89 	(pthread_cond_t *);
90 int (*f_pthread_cond_init)
91 	(pthread_cond_t *, const pthread_condattr_t *);
92 int (*f_pthread_cond_signal)
93 	(pthread_cond_t *);
94 int (*f_pthread_cond_timedwait)
95 	(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
96 int (*f_pthread_cond_wait)
97 	(pthread_cond_t *, pthread_mutex_t *);
98 int (*f_pthread_create)
99 	(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
100 int (*f_pthread_detach)
101 	(pthread_t);
102 int (*f_pthread_equal)
103 	(pthread_t, pthread_t);
104 void (*f_pthread_exit)
105 	(void *);
106 void * (*f_pthread_getspecific)
107 	(pthread_key_t);
108 int (*f_pthread_getcpuclockid)
109 	(pthread_t, clockid_t *);
110 int (*f_pthread_join)
111 	(pthread_t, void **);
112 int (*f_pthread_key_create)
113 	(pthread_key_t *, void (*) (void *));
114 int (*f_pthread_key_delete)
115 	(pthread_key_t);
116 int (*f_pthread_mutex_destroy)
117 	(pthread_mutex_t *__mutex);
118 int (*f_pthread_mutex_init)
119 	(pthread_mutex_t *__mutex, const pthread_mutexattr_t *);
120 int (*f_pthread_mutex_lock)
121 	(pthread_mutex_t *__mutex);
122 int (*f_pthread_mutex_trylock)
123 	(pthread_mutex_t *__mutex);
124 int (*f_pthread_mutex_timedlock)
125 	(pthread_mutex_t *__mutex, const struct timespec *);
126 int (*f_pthread_mutex_unlock)
127 	(pthread_mutex_t *__mutex);
128 int (*f_pthread_once)
129 	(pthread_once_t *, void (*) (void));
130 int (*f_pthread_rwlock_destroy)
131 	(pthread_rwlock_t *__rwlock);
132 int (*f_pthread_rwlock_init)
133 	(pthread_rwlock_t *__rwlock, const pthread_rwlockattr_t *);
134 int (*f_pthread_rwlock_rdlock)
135 	(pthread_rwlock_t *__rwlock);
136 int (*f_pthread_rwlock_timedrdlock)
137 	(pthread_rwlock_t *__rwlock, const struct timespec *);
138 int (*f_pthread_rwlock_timedwrlock)
139 	(pthread_rwlock_t *__rwlock, const struct timespec *);
140 int (*f_pthread_rwlock_tryrdlock)
141 	(pthread_rwlock_t *__rwlock);
142 int (*f_pthread_rwlock_trywrlock)
143 	(pthread_rwlock_t *__rwlock);
144 int (*f_pthread_rwlock_unlock)
145 	(pthread_rwlock_t *__rwlock);
146 int (*f_pthread_rwlock_wrlock)
147 	(pthread_rwlock_t *__rwlock);
148 pthread_t (*f_pthread_self)
149 	(void);
150 int (*f_pthread_setspecific)
151 	(pthread_key_t, const void *);
152 int (*f_pthread_spin_init)
153 	(pthread_spinlock_t *__spin, int);
154 int (*f_pthread_spin_destroy)
155 	(pthread_spinlock_t *__spin);
156 int (*f_pthread_spin_lock)
157 	(pthread_spinlock_t *__spin);
158 int (*f_pthread_spin_trylock)
159 	(pthread_spinlock_t *__spin);
160 int (*f_pthread_spin_unlock)
161 	(pthread_spinlock_t *__spin);
162 int (*f_pthread_cancel)
163 	(pthread_t);
164 int (*f_pthread_setcancelstate)
165 	(int, int *);
166 int (*f_pthread_setcanceltype)
167 	(int, int *);
168 void (*f_pthread_testcancel)
169 	(void);
170 int (*f_pthread_getschedparam)
171 	(pthread_t pthread, int *, struct sched_param *);
172 int (*f_pthread_setschedparam)
173 	(pthread_t, int, const struct sched_param *);
174 int (*f_pthread_yield)
175 	(void);
176 int (*f_pthread_setaffinity_np)
177 	(pthread_t thread, size_t cpusetsize, const rte_cpuset_t *cpuset);
178 int (*f_nanosleep)
179 	(const struct timespec *req, struct timespec *rem);
180 } _sys_pthread_funcs = {
181 	.f_pthread_barrier_destroy = NULL,
182 };
183 
184 
185 /*
186  * this macro obtains the loaded address of a library function
187  * and saves it.
188  */
189 static void *__libc_dl_handle = RTLD_NEXT;
190 
191 #define get_addr_of_loaded_symbol(name) do {				\
192 	char *error_str;						\
193 	_sys_pthread_funcs.f_##name = dlsym(__libc_dl_handle, (#name));	\
194 	error_str = dlerror();						\
195 	if (error_str != NULL) {					\
196 		fprintf(stderr, "%s\n", error_str);			\
197 	}								\
198 } while (0)
199 
200 
201 /*
202  * The constructor function initialises the
203  * function pointers for pthread library functions
204  */
205 RTE_INIT(pthread_intercept_ctor)
206 {
207 	override = 0;
208 	/*
209 	 * Get the original functions
210 	 */
211 	get_addr_of_loaded_symbol(pthread_barrier_destroy);
212 	get_addr_of_loaded_symbol(pthread_barrier_init);
213 	get_addr_of_loaded_symbol(pthread_barrier_wait);
214 	get_addr_of_loaded_symbol(pthread_cond_broadcast);
215 	get_addr_of_loaded_symbol(pthread_cond_destroy);
216 	get_addr_of_loaded_symbol(pthread_cond_init);
217 	get_addr_of_loaded_symbol(pthread_cond_signal);
218 	get_addr_of_loaded_symbol(pthread_cond_timedwait);
219 	get_addr_of_loaded_symbol(pthread_cond_wait);
220 	get_addr_of_loaded_symbol(pthread_create);
221 	get_addr_of_loaded_symbol(pthread_detach);
222 	get_addr_of_loaded_symbol(pthread_equal);
223 	get_addr_of_loaded_symbol(pthread_exit);
224 	get_addr_of_loaded_symbol(pthread_getspecific);
225 	get_addr_of_loaded_symbol(pthread_getcpuclockid);
226 	get_addr_of_loaded_symbol(pthread_join);
227 	get_addr_of_loaded_symbol(pthread_key_create);
228 	get_addr_of_loaded_symbol(pthread_key_delete);
229 	get_addr_of_loaded_symbol(pthread_mutex_destroy);
230 	get_addr_of_loaded_symbol(pthread_mutex_init);
231 	get_addr_of_loaded_symbol(pthread_mutex_lock);
232 	get_addr_of_loaded_symbol(pthread_mutex_trylock);
233 	get_addr_of_loaded_symbol(pthread_mutex_timedlock);
234 	get_addr_of_loaded_symbol(pthread_mutex_unlock);
235 	get_addr_of_loaded_symbol(pthread_once);
236 	get_addr_of_loaded_symbol(pthread_rwlock_destroy);
237 	get_addr_of_loaded_symbol(pthread_rwlock_init);
238 	get_addr_of_loaded_symbol(pthread_rwlock_rdlock);
239 	get_addr_of_loaded_symbol(pthread_rwlock_timedrdlock);
240 	get_addr_of_loaded_symbol(pthread_rwlock_timedwrlock);
241 	get_addr_of_loaded_symbol(pthread_rwlock_tryrdlock);
242 	get_addr_of_loaded_symbol(pthread_rwlock_trywrlock);
243 	get_addr_of_loaded_symbol(pthread_rwlock_unlock);
244 	get_addr_of_loaded_symbol(pthread_rwlock_wrlock);
245 	get_addr_of_loaded_symbol(pthread_self);
246 	get_addr_of_loaded_symbol(pthread_setspecific);
247 	get_addr_of_loaded_symbol(pthread_spin_init);
248 	get_addr_of_loaded_symbol(pthread_spin_destroy);
249 	get_addr_of_loaded_symbol(pthread_spin_lock);
250 	get_addr_of_loaded_symbol(pthread_spin_trylock);
251 	get_addr_of_loaded_symbol(pthread_spin_unlock);
252 	get_addr_of_loaded_symbol(pthread_cancel);
253 	get_addr_of_loaded_symbol(pthread_setcancelstate);
254 	get_addr_of_loaded_symbol(pthread_setcanceltype);
255 	get_addr_of_loaded_symbol(pthread_testcancel);
256 	get_addr_of_loaded_symbol(pthread_getschedparam);
257 	get_addr_of_loaded_symbol(pthread_setschedparam);
258 	get_addr_of_loaded_symbol(pthread_yield);
259 	get_addr_of_loaded_symbol(pthread_setaffinity_np);
260 	get_addr_of_loaded_symbol(nanosleep);
261 }
262 
263 
264 /*
265  * Enable/Disable pthread override
266  * state
267  *  0 disable
268  *  1 enable
269  */
270 void pthread_override_set(int state)
271 {
272 	override = state;
273 }
274 
275 
276 /*
277  * Return pthread override state
278  * return
279  *  0 disable
280  *  1 enable
281  */
282 int pthread_override_get(void)
283 {
284 	return override;
285 }
286 
287 /*
288  * This macro is used to catch and log
289  * invocation of stubs for unimplemented pthread
290  * API functions.
291  */
292 #define NOT_IMPLEMENTED do {				\
293 	if (override) {					\
294 		RTE_LOG(WARNING,			\
295 			PTHREAD_SHIM,			\
296 			"WARNING %s NOT IMPLEMENTED\n",	\
297 			__func__);			\
298 	}						\
299 } while (0)
300 
301 /*
302  * pthread API override functions follow
303  * Note in this example code only a subset of functions are
304  * implemented.
305  *
306  * The stub functions provided will issue a warning log
307  * message if an unimplemented function is invoked
308  *
309  */
310 
311 int pthread_barrier_destroy(pthread_barrier_t *a)
312 {
313 	NOT_IMPLEMENTED;
314 	return _sys_pthread_funcs.f_pthread_barrier_destroy(a);
315 }
316 
317 int
318 pthread_barrier_init(pthread_barrier_t *a,
319 		     const pthread_barrierattr_t *b, unsigned c)
320 {
321 	NOT_IMPLEMENTED;
322 	return _sys_pthread_funcs.f_pthread_barrier_init(a, b, c);
323 }
324 
325 int pthread_barrier_wait(pthread_barrier_t *a)
326 {
327 	NOT_IMPLEMENTED;
328 	return _sys_pthread_funcs.f_pthread_barrier_wait(a);
329 }
330 
331 int pthread_cond_broadcast(pthread_cond_t *cond)
332 {
333 	if (override) {
334 
335 		lthread_cond_broadcast(*(struct lthread_cond **)cond);
336 		return 0;
337 	}
338 	return _sys_pthread_funcs.f_pthread_cond_broadcast(cond);
339 }
340 
341 int pthread_mutex_destroy(pthread_mutex_t *mutex)
342 {
343 	if (override)
344 		return lthread_mutex_destroy(*(struct lthread_mutex **)mutex);
345 	return _sys_pthread_funcs.f_pthread_mutex_destroy(mutex);
346 }
347 
348 int pthread_cond_destroy(pthread_cond_t *cond)
349 {
350 	if (override)
351 		return lthread_cond_destroy(*(struct lthread_cond **)cond);
352 	return _sys_pthread_funcs.f_pthread_cond_destroy(cond);
353 }
354 
355 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
356 {
357 	if (override)
358 		return lthread_cond_init(NULL,
359 				(struct lthread_cond **)cond,
360 				(const struct lthread_condattr *) attr);
361 	return _sys_pthread_funcs.f_pthread_cond_init(cond, attr);
362 }
363 
364 int pthread_cond_signal(pthread_cond_t *cond)
365 {
366 	if (override) {
367 		lthread_cond_signal(*(struct lthread_cond **)cond);
368 		return 0;
369 	}
370 	return _sys_pthread_funcs.f_pthread_cond_signal(cond);
371 }
372 
373 int
374 pthread_cond_timedwait(pthread_cond_t *__restrict cond,
375 		       pthread_mutex_t *__restrict mutex,
376 		       const struct timespec *__restrict time)
377 {
378 	NOT_IMPLEMENTED;
379 	return _sys_pthread_funcs.f_pthread_cond_timedwait(cond, mutex, time);
380 }
381 
382 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
383 {
384 	if (override) {
385 		pthread_mutex_unlock(mutex);
386 		int rv = lthread_cond_wait(*(struct lthread_cond **)cond, 0);
387 
388 		pthread_mutex_lock(mutex);
389 		return rv;
390 	}
391 	return _sys_pthread_funcs.f_pthread_cond_wait(cond, mutex);
392 }
393 
394 int
395 pthread_create(pthread_t *__restrict tid,
396 		const pthread_attr_t *__restrict attr,
397 		lthread_func_t func,
398 	       void *__restrict arg)
399 {
400 	if (override) {
401 		int lcore = -1;
402 
403 		if (attr != NULL) {
404 			/* determine CPU being requested */
405 			rte_cpuset_t cpuset;
406 
407 			CPU_ZERO(&cpuset);
408 			pthread_attr_getaffinity_np(attr,
409 						sizeof(rte_cpuset_t),
410 						&cpuset);
411 
412 			if (CPU_COUNT(&cpuset) != 1)
413 				return POSIX_ERRNO(EINVAL);
414 
415 			for (lcore = 0; lcore < LTHREAD_MAX_LCORES; lcore++) {
416 				if (!CPU_ISSET(lcore, &cpuset))
417 					continue;
418 				break;
419 			}
420 		}
421 		return lthread_create((struct lthread **)tid, lcore,
422 				      func, arg);
423 	}
424 	return _sys_pthread_funcs.f_pthread_create(tid, attr, func, arg);
425 }
426 
427 int pthread_detach(pthread_t tid)
428 {
429 	if (override) {
430 		struct lthread *lt = (struct lthread *)tid;
431 
432 		if (lt == lthread_current()) {
433 			lthread_detach();
434 			return 0;
435 		}
436 		NOT_IMPLEMENTED;
437 	}
438 	return _sys_pthread_funcs.f_pthread_detach(tid);
439 }
440 
441 int pthread_equal(pthread_t a, pthread_t b)
442 {
443 	NOT_IMPLEMENTED;
444 	return _sys_pthread_funcs.f_pthread_equal(a, b);
445 }
446 
447 void pthread_exit_override(void *v)
448 {
449 	if (override) {
450 		lthread_exit(v);
451 		return;
452 	}
453 	_sys_pthread_funcs.f_pthread_exit(v);
454 }
455 
456 void
457 *pthread_getspecific(pthread_key_t key)
458 {
459 	if (override)
460 		return lthread_getspecific((unsigned int) key);
461 	return _sys_pthread_funcs.f_pthread_getspecific(key);
462 }
463 
464 int pthread_getcpuclockid(pthread_t a, clockid_t *b)
465 {
466 	NOT_IMPLEMENTED;
467 	return _sys_pthread_funcs.f_pthread_getcpuclockid(a, b);
468 }
469 
470 int pthread_join(pthread_t tid, void **val)
471 {
472 	if (override)
473 		return lthread_join((struct lthread *)tid, val);
474 	return _sys_pthread_funcs.f_pthread_join(tid, val);
475 }
476 
477 int pthread_key_create(pthread_key_t *keyptr, void (*dtor) (void *))
478 {
479 	if (override)
480 		return lthread_key_create((unsigned int *)keyptr, dtor);
481 	return _sys_pthread_funcs.f_pthread_key_create(keyptr, dtor);
482 }
483 
484 int pthread_key_delete(pthread_key_t key)
485 {
486 	if (override) {
487 		lthread_key_delete((unsigned int) key);
488 		return 0;
489 	}
490 	return _sys_pthread_funcs.f_pthread_key_delete(key);
491 }
492 
493 
494 int
495 pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
496 {
497 	if (override)
498 		return lthread_mutex_init(NULL,
499 				(struct lthread_mutex **)mutex,
500 				(const struct lthread_mutexattr *)attr);
501 	return _sys_pthread_funcs.f_pthread_mutex_init(mutex, attr);
502 }
503 
504 int pthread_mutex_lock(pthread_mutex_t *mutex)
505 {
506 	if (override)
507 		return lthread_mutex_lock(*(struct lthread_mutex **)mutex);
508 	return _sys_pthread_funcs.f_pthread_mutex_lock(mutex);
509 }
510 
511 int pthread_mutex_trylock(pthread_mutex_t *mutex)
512 {
513 	if (override)
514 		return lthread_mutex_trylock(*(struct lthread_mutex **)mutex);
515 	return _sys_pthread_funcs.f_pthread_mutex_trylock(mutex);
516 }
517 
518 int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *b)
519 {
520 	NOT_IMPLEMENTED;
521 	return _sys_pthread_funcs.f_pthread_mutex_timedlock(mutex, b);
522 }
523 
524 int pthread_mutex_unlock(pthread_mutex_t *mutex)
525 {
526 	if (override)
527 		return lthread_mutex_unlock(*(struct lthread_mutex **)mutex);
528 	return _sys_pthread_funcs.f_pthread_mutex_unlock(mutex);
529 }
530 
531 int pthread_once(pthread_once_t *a, void (b) (void))
532 {
533 	NOT_IMPLEMENTED;
534 	return _sys_pthread_funcs.f_pthread_once(a, b);
535 }
536 
537 int pthread_rwlock_destroy(pthread_rwlock_t *a)
538 {
539 	NOT_IMPLEMENTED;
540 	return _sys_pthread_funcs.f_pthread_rwlock_destroy(a);
541 }
542 
543 int pthread_rwlock_init(pthread_rwlock_t *a, const pthread_rwlockattr_t *b)
544 {
545 	NOT_IMPLEMENTED;
546 	return _sys_pthread_funcs.f_pthread_rwlock_init(a, b);
547 }
548 
549 int pthread_rwlock_rdlock(pthread_rwlock_t *a)
550 {
551 	NOT_IMPLEMENTED;
552 	return _sys_pthread_funcs.f_pthread_rwlock_rdlock(a);
553 }
554 
555 int pthread_rwlock_timedrdlock(pthread_rwlock_t *a, const struct timespec *b)
556 {
557 	NOT_IMPLEMENTED;
558 	return _sys_pthread_funcs.f_pthread_rwlock_timedrdlock(a, b);
559 }
560 
561 int pthread_rwlock_timedwrlock(pthread_rwlock_t *a, const struct timespec *b)
562 {
563 	NOT_IMPLEMENTED;
564 	return _sys_pthread_funcs.f_pthread_rwlock_timedwrlock(a, b);
565 }
566 
567 int pthread_rwlock_tryrdlock(pthread_rwlock_t *a)
568 {
569 	NOT_IMPLEMENTED;
570 	return _sys_pthread_funcs.f_pthread_rwlock_tryrdlock(a);
571 }
572 
573 int pthread_rwlock_trywrlock(pthread_rwlock_t *a)
574 {
575 	NOT_IMPLEMENTED;
576 	return _sys_pthread_funcs.f_pthread_rwlock_trywrlock(a);
577 }
578 
579 int pthread_rwlock_unlock(pthread_rwlock_t *a)
580 {
581 	NOT_IMPLEMENTED;
582 	return _sys_pthread_funcs.f_pthread_rwlock_unlock(a);
583 }
584 
585 int pthread_rwlock_wrlock(pthread_rwlock_t *a)
586 {
587 	NOT_IMPLEMENTED;
588 	return _sys_pthread_funcs.f_pthread_rwlock_wrlock(a);
589 }
590 
591 #ifdef RTE_EXEC_ENV_LINUXAPP
592 int
593 pthread_yield(void)
594 {
595 	if (override) {
596 		lthread_yield();
597 		return 0;
598 	}
599 	return _sys_pthread_funcs.f_pthread_yield();
600 }
601 #else
602 void
603 pthread_yield(void)
604 {
605 	if (override)
606 		lthread_yield();
607 	else
608 		_sys_pthread_funcs.f_pthread_yield();
609 }
610 #endif
611 
612 pthread_t pthread_self(void)
613 {
614 	if (override)
615 		return (pthread_t) lthread_current();
616 	return _sys_pthread_funcs.f_pthread_self();
617 }
618 
619 int pthread_setspecific(pthread_key_t key, const void *data)
620 {
621 	if (override) {
622 		int rv =  lthread_setspecific((unsigned int)key, data);
623 		return rv;
624 	}
625 	return _sys_pthread_funcs.f_pthread_setspecific(key, data);
626 }
627 
628 int pthread_spin_init(pthread_spinlock_t *a, int b)
629 {
630 	NOT_IMPLEMENTED;
631 	return _sys_pthread_funcs.f_pthread_spin_init(a, b);
632 }
633 
634 int pthread_spin_destroy(pthread_spinlock_t *a)
635 {
636 	NOT_IMPLEMENTED;
637 	return _sys_pthread_funcs.f_pthread_spin_destroy(a);
638 }
639 
640 int pthread_spin_lock(pthread_spinlock_t *a)
641 {
642 	NOT_IMPLEMENTED;
643 	return _sys_pthread_funcs.f_pthread_spin_lock(a);
644 }
645 
646 int pthread_spin_trylock(pthread_spinlock_t *a)
647 {
648 	NOT_IMPLEMENTED;
649 	return _sys_pthread_funcs.f_pthread_spin_trylock(a);
650 }
651 
652 int pthread_spin_unlock(pthread_spinlock_t *a)
653 {
654 	NOT_IMPLEMENTED;
655 	return _sys_pthread_funcs.f_pthread_spin_unlock(a);
656 }
657 
658 int pthread_cancel(pthread_t tid)
659 {
660 	if (override) {
661 		lthread_cancel(*(struct lthread **)tid);
662 		return 0;
663 	}
664 	return _sys_pthread_funcs.f_pthread_cancel(tid);
665 }
666 
667 int pthread_setcancelstate(int a, int *b)
668 {
669 	NOT_IMPLEMENTED;
670 	return _sys_pthread_funcs.f_pthread_setcancelstate(a, b);
671 }
672 
673 int pthread_setcanceltype(int a, int *b)
674 {
675 	NOT_IMPLEMENTED;
676 	return _sys_pthread_funcs.f_pthread_setcanceltype(a, b);
677 }
678 
679 void pthread_testcancel(void)
680 {
681 	NOT_IMPLEMENTED;
682 	return _sys_pthread_funcs.f_pthread_testcancel();
683 }
684 
685 
686 int pthread_getschedparam(pthread_t tid, int *a, struct sched_param *b)
687 {
688 	NOT_IMPLEMENTED;
689 	return _sys_pthread_funcs.f_pthread_getschedparam(tid, a, b);
690 }
691 
692 int pthread_setschedparam(pthread_t a, int b, const struct sched_param *c)
693 {
694 	NOT_IMPLEMENTED;
695 	return _sys_pthread_funcs.f_pthread_setschedparam(a, b, c);
696 }
697 
698 
699 int nanosleep(const struct timespec *req, struct timespec *rem)
700 {
701 	if (override) {
702 		uint64_t ns = req->tv_sec * 1000000000 + req->tv_nsec;
703 
704 		lthread_sleep(ns);
705 		return 0;
706 	}
707 	return _sys_pthread_funcs.f_nanosleep(req, rem);
708 }
709 
710 int
711 pthread_setaffinity_np(pthread_t thread, size_t cpusetsize,
712 		       const rte_cpuset_t *cpuset)
713 {
714 	if (override) {
715 		/* we only allow affinity with a single CPU */
716 		if (CPU_COUNT(cpuset) != 1)
717 			return POSIX_ERRNO(EINVAL);
718 
719 		/* we only allow the current thread to sets its own affinity */
720 		struct lthread *lt = (struct lthread *)thread;
721 
722 		if (lthread_current() != lt)
723 			return POSIX_ERRNO(EINVAL);
724 
725 		/* determine the CPU being requested */
726 		int i;
727 
728 		for (i = 0; i < LTHREAD_MAX_LCORES; i++) {
729 			if (!CPU_ISSET(i, cpuset))
730 				continue;
731 			break;
732 		}
733 		/* check requested core is allowed */
734 		if (i == LTHREAD_MAX_LCORES)
735 			return POSIX_ERRNO(EINVAL);
736 
737 		/* finally we can set affinity to the requested lcore */
738 		lthread_set_affinity(i);
739 		return 0;
740 	}
741 	return _sys_pthread_funcs.f_pthread_setaffinity_np(thread, cpusetsize,
742 							   cpuset);
743 }
744