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