]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | } |