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