1 /*
2 ** GNU Pth - The GNU Portable Threads
3 ** Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
4 **
5 ** This file is part of GNU Pth, a non-preemptive thread scheduling
6 ** library which can be found at http://www.gnu.org/software/pth/.
7 **
8 ** This library is free software; you can redistribute it and/or
9 ** modify it under the terms of the GNU Lesser General Public
10 ** License as published by the Free Software Foundation; either
11 ** version 2.1 of the License, or (at your option) any later version.
12 **
13 ** This library is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ** Lesser General Public License for more details.
17 **
18 ** You should have received a copy of the GNU Lesser General Public
19 ** License along with this library; if not, write to the Free Software
20 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 ** USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
22 **
23 ** pthread.c: POSIX Thread ("Pthread") API for Pth
24 */
25 /* ``The nice thing about standards is that
26 there are so many to choose from. And if
27 you really don't like all the standards you
28 just have to wait another year until the one
29 arises you are looking for''
30 -- Tannenbaum, 'Introduction
31 to Computer Networks' */
32
33 /*
34 ** HEADER STUFF
35 */
36
37 /*
38 * Include our own Pthread and then the private Pth header.
39 * The order here is very important to get correct namespace hiding!
40 */
41 #define _PTHREAD_PRIVATE
42 #include "pthread.h"
43 #include "pth_p.h"
44 #undef _PTHREAD_PRIVATE
45
46 /* general success return value */
47 #ifdef OK
48 #undef OK
49 #endif
50 #define OK 0
51
52 /*
53 ** GLOBAL STUFF
54 */
55
pthread_shutdown(void)56 static void pthread_shutdown(void)
57 {
58 pth_kill();
59 return;
60 }
61
62 static int pthread_initialized = FALSE;
63
64 #define pthread_initialize() \
65 do { \
66 if (pthread_initialized == FALSE) { \
67 pthread_initialized = TRUE; \
68 pth_init(); \
69 atexit(pthread_shutdown); \
70 } \
71 } while (0)
72
73 /*
74 ** THREAD ATTRIBUTE ROUTINES
75 */
76
pthread_attr_init(pthread_attr_t * attr)77 int pthread_attr_init(pthread_attr_t *attr)
78 {
79 pth_attr_t na;
80
81 pthread_initialize();
82 if (attr == NULL)
83 return pth_error(EINVAL, EINVAL);
84 if ((na = pth_attr_new()) == NULL)
85 return errno;
86 (*attr) = (pthread_attr_t)na;
87 return OK;
88 }
89
pthread_attr_destroy(pthread_attr_t * attr)90 int pthread_attr_destroy(pthread_attr_t *attr)
91 {
92 pth_attr_t na;
93
94 if (attr == NULL || *attr == NULL)
95 return pth_error(EINVAL, EINVAL);
96 na = (pth_attr_t)(*attr);
97 pth_attr_destroy(na);
98 *attr = NULL;
99 return OK;
100 }
101
pthread_attr_setinheritsched(pthread_attr_t * attr,int inheritsched)102 int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched)
103 {
104 if (attr == NULL)
105 return pth_error(EINVAL, EINVAL);
106 /* not supported */
107 return pth_error(ENOSYS, ENOSYS);
108 }
109
pthread_attr_getinheritsched(const pthread_attr_t * attr,int * inheritsched)110 int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched)
111 {
112 if (attr == NULL || inheritsched == NULL)
113 return pth_error(EINVAL, EINVAL);
114 /* not supported */
115 return pth_error(ENOSYS, ENOSYS);
116 }
117
pthread_attr_setschedparam(pthread_attr_t * attr,const struct sched_param * schedparam)118 int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *schedparam)
119 {
120 if (attr == NULL)
121 return pth_error(EINVAL, EINVAL);
122 /* not supported */
123 return pth_error(ENOSYS, ENOSYS);
124 }
125
pthread_attr_getschedparam(const pthread_attr_t * attr,struct sched_param * schedparam)126 int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *schedparam)
127 {
128 if (attr == NULL || schedparam == NULL)
129 return pth_error(EINVAL, EINVAL);
130 /* not supported */
131 return pth_error(ENOSYS, ENOSYS);
132 }
133
pthread_attr_setschedpolicy(pthread_attr_t * attr,int schedpolicy)134 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int schedpolicy)
135 {
136 if (attr == NULL)
137 return pth_error(EINVAL, EINVAL);
138 /* not supported */
139 return pth_error(ENOSYS, ENOSYS);
140 }
141
pthread_attr_getschedpolicy(const pthread_attr_t * attr,int * schedpolicy)142 int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *schedpolicy)
143 {
144 if (attr == NULL || schedpolicy == NULL)
145 return pth_error(EINVAL, EINVAL);
146 /* not supported */
147 return pth_error(ENOSYS, ENOSYS);
148 }
149
pthread_attr_setscope(pthread_attr_t * attr,int scope)150 int pthread_attr_setscope(pthread_attr_t *attr, int scope)
151 {
152 if (attr == NULL)
153 return pth_error(EINVAL, EINVAL);
154 /* not supported */
155 return pth_error(ENOSYS, ENOSYS);
156 }
157
pthread_attr_getscope(const pthread_attr_t * attr,int * scope)158 int pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
159 {
160 if (attr == NULL || scope == NULL)
161 return pth_error(EINVAL, EINVAL);
162 /* not supported */
163 return pth_error(ENOSYS, ENOSYS);
164 }
165
pthread_attr_setstacksize(pthread_attr_t * attr,size_t stacksize)166 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
167 {
168 if (attr == NULL)
169 return pth_error(EINVAL, EINVAL);
170 if (!pth_attr_set((pth_attr_t)(*attr), PTH_ATTR_STACK_SIZE, (unsigned int)stacksize))
171 return errno;
172 return OK;
173 }
174
pthread_attr_getstacksize(const pthread_attr_t * attr,size_t * stacksize)175 int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
176 {
177 if (attr == NULL || stacksize == NULL)
178 return pth_error(EINVAL, EINVAL);
179 if (!pth_attr_get((pth_attr_t)(*attr), PTH_ATTR_STACK_SIZE, (unsigned int *)stacksize))
180 return errno;
181 return OK;
182 }
183
pthread_attr_setstackaddr(pthread_attr_t * attr,void * stackaddr)184 int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
185 {
186 if (attr == NULL)
187 return pth_error(EINVAL, EINVAL);
188 if (!pth_attr_set((pth_attr_t)(*attr), PTH_ATTR_STACK_ADDR, (char *)stackaddr))
189 return errno;
190 return OK;
191 }
192
pthread_attr_getstackaddr(const pthread_attr_t * attr,void ** stackaddr)193 int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
194 {
195 if (attr == NULL || stackaddr == NULL)
196 return pth_error(EINVAL, EINVAL);
197 if (!pth_attr_get((pth_attr_t)(*attr), PTH_ATTR_STACK_ADDR, (char **)stackaddr))
198 return errno;
199 return OK;
200 }
201
pthread_attr_setdetachstate(pthread_attr_t * attr,int detachstate)202 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
203 {
204 int s;
205
206 if (attr == NULL)
207 return pth_error(EINVAL, EINVAL);
208 if (detachstate == PTHREAD_CREATE_DETACHED)
209 s = FALSE;
210 else if (detachstate == PTHREAD_CREATE_JOINABLE)
211 s = TRUE;
212 else
213 return pth_error(EINVAL, EINVAL);
214 if (!pth_attr_set((pth_attr_t)(*attr), PTH_ATTR_JOINABLE, s))
215 return errno;
216 return OK;
217 }
218
pthread_attr_getdetachstate(const pthread_attr_t * attr,int * detachstate)219 int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
220 {
221 int s;
222
223 if (attr == NULL || detachstate == NULL)
224 return pth_error(EINVAL, EINVAL);
225 if (!pth_attr_get((pth_attr_t)(*attr), PTH_ATTR_JOINABLE, &s))
226 return errno;
227 if (s == TRUE)
228 *detachstate = PTHREAD_CREATE_JOINABLE;
229 else
230 *detachstate = PTHREAD_CREATE_DETACHED;
231 return OK;
232 }
233
pthread_attr_setguardsize(pthread_attr_t * attr,int stacksize)234 int pthread_attr_setguardsize(pthread_attr_t *attr, int stacksize)
235 {
236 if (attr == NULL || stacksize < 0)
237 return pth_error(EINVAL, EINVAL);
238 /* not supported */
239 return pth_error(ENOSYS, ENOSYS);
240 }
241
pthread_attr_getguardsize(const pthread_attr_t * attr,int * stacksize)242 int pthread_attr_getguardsize(const pthread_attr_t *attr, int *stacksize)
243 {
244 if (attr == NULL || stacksize == NULL)
245 return pth_error(EINVAL, EINVAL);
246 /* not supported */
247 return pth_error(ENOSYS, ENOSYS);
248 }
249
pthread_attr_setname_np(pthread_attr_t * attr,char * name)250 int pthread_attr_setname_np(pthread_attr_t *attr, char *name)
251 {
252 if (attr == NULL || name == NULL)
253 return pth_error(EINVAL, EINVAL);
254 if (!pth_attr_set((pth_attr_t)(*attr), PTH_ATTR_NAME, name))
255 return errno;
256 return OK;
257 }
258
pthread_attr_getname_np(const pthread_attr_t * attr,char ** name)259 int pthread_attr_getname_np(const pthread_attr_t *attr, char **name)
260 {
261 if (attr == NULL || name == NULL)
262 return pth_error(EINVAL, EINVAL);
263 if (!pth_attr_get((pth_attr_t)(*attr), PTH_ATTR_NAME, name))
264 return errno;
265 return OK;
266 }
267
pthread_attr_setprio_np(pthread_attr_t * attr,int prio)268 int pthread_attr_setprio_np(pthread_attr_t *attr, int prio)
269 {
270 if (attr == NULL || (prio < PTH_PRIO_MIN || prio > PTH_PRIO_MAX))
271 return pth_error(EINVAL, EINVAL);
272 if (!pth_attr_set((pth_attr_t)(*attr), PTH_ATTR_PRIO, prio))
273 return errno;
274 return OK;
275 }
276
pthread_attr_getprio_np(const pthread_attr_t * attr,int * prio)277 int pthread_attr_getprio_np(const pthread_attr_t *attr, int *prio)
278 {
279 if (attr == NULL || prio == NULL)
280 return pth_error(EINVAL, EINVAL);
281 if (!pth_attr_get((pth_attr_t)(*attr), PTH_ATTR_PRIO, prio))
282 return errno;
283 return OK;
284 }
285
286 /*
287 ** THREAD ROUTINES
288 */
289
pthread_create(pthread_t * thread,const pthread_attr_t * attr,void * (* start_routine)(void *),void * arg)290 int pthread_create(
291 pthread_t *thread, const pthread_attr_t *attr,
292 void *(*start_routine)(void *), void *arg)
293 {
294 pth_attr_t na;
295
296 pthread_initialize();
297 if (thread == NULL || start_routine == NULL)
298 return pth_error(EINVAL, EINVAL);
299 if (pth_ctrl(PTH_CTRL_GETTHREADS) >= PTHREAD_THREADS_MAX)
300 return pth_error(EAGAIN, EAGAIN);
301 if (attr != NULL)
302 na = (pth_attr_t)(*attr);
303 else
304 na = PTH_ATTR_DEFAULT;
305 *thread = (pthread_t)pth_spawn(na, start_routine, arg);
306 if (*thread == NULL)
307 return pth_error(EAGAIN, EAGAIN);
308 return OK;
309 }
310
__pthread_detach(pthread_t thread)311 int __pthread_detach(pthread_t thread)
312 {
313 pth_attr_t na;
314
315 if (thread == NULL)
316 return pth_error(EINVAL, EINVAL);
317 if ((na = pth_attr_of((pth_t)thread)) == NULL)
318 return errno;
319 if (!pth_attr_set(na, PTH_ATTR_JOINABLE, FALSE))
320 return errno;
321 pth_attr_destroy(na);
322 return OK;
323 }
324
pthread_self(void)325 pthread_t pthread_self(void)
326 {
327 pthread_initialize();
328 return (pthread_t)pth_self();
329 }
330
pthread_equal(pthread_t t1,pthread_t t2)331 int pthread_equal(pthread_t t1, pthread_t t2)
332 {
333 return (t1 == t2);
334 }
335
pthread_yield_np(void)336 int pthread_yield_np(void)
337 {
338 pthread_initialize();
339 pth_yield(NULL);
340 return OK;
341 }
342
pthread_exit(void * value_ptr)343 void pthread_exit(void *value_ptr)
344 {
345 pthread_initialize();
346 pth_exit(value_ptr);
347 return;
348 }
349
pthread_join(pthread_t thread,void ** value_ptr)350 int pthread_join(pthread_t thread, void **value_ptr)
351 {
352 pthread_initialize();
353 if (!pth_join((pth_t)thread, value_ptr))
354 return errno;
355 if (value_ptr != NULL)
356 if (*value_ptr == PTH_CANCELED)
357 *value_ptr = PTHREAD_CANCELED;
358 return OK;
359 }
360
pthread_once(pthread_once_t * once_control,void (* init_routine)(void))361 int pthread_once(
362 pthread_once_t *once_control, void (*init_routine)(void))
363 {
364 pthread_initialize();
365 if (once_control == NULL || init_routine == NULL)
366 return pth_error(EINVAL, EINVAL);
367 if (*once_control != 1)
368 init_routine();
369 *once_control = 1;
370 return OK;
371 }
372
pthread_sigmask(int how,const sigset_t * set,sigset_t * oset)373 int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
374 {
375 pthread_initialize();
376 return pth_sigmask(how, set, oset);
377 }
378
pthread_kill(pthread_t thread,int sig)379 int pthread_kill(pthread_t thread, int sig)
380 {
381 if (!pth_raise((pth_t)thread, sig))
382 return errno;
383 return OK;
384 }
385
386 /*
387 ** CONCURRENCY ROUTINES
388 **
389 ** We just have to provide the interface, because SUSv2 says:
390 ** "The pthread_setconcurrency() function allows an application to
391 ** inform the threads implementation of its desired concurrency
392 ** level, new_level. The actual level of concurrency provided by the
393 ** implementation as a result of this function call is unspecified."
394 */
395
396 static int pthread_concurrency = 0;
397
pthread_getconcurrency(void)398 int pthread_getconcurrency(void)
399 {
400 return pthread_concurrency;
401 }
402
pthread_setconcurrency(int new_level)403 int pthread_setconcurrency(int new_level)
404 {
405 if (new_level < 0)
406 return pth_error(EINVAL, EINVAL);
407 pthread_concurrency = new_level;
408 return OK;
409 }
410
411 /*
412 ** CONTEXT ROUTINES
413 */
414
pthread_key_create(pthread_key_t * key,void (* destructor)(void *))415 int pthread_key_create(pthread_key_t *key, void (*destructor)(void *))
416 {
417 pthread_initialize();
418 if (!pth_key_create((pth_key_t *)key, destructor))
419 return errno;
420 return OK;
421 }
422
pthread_key_delete(pthread_key_t key)423 int pthread_key_delete(pthread_key_t key)
424 {
425 if (!pth_key_delete((pth_key_t)key))
426 return errno;
427 return OK;
428 }
429
pthread_setspecific(pthread_key_t key,const void * value)430 int pthread_setspecific(pthread_key_t key, const void *value)
431 {
432 if (!pth_key_setdata((pth_key_t)key, value))
433 return errno;
434 return OK;
435 }
436
pthread_getspecific(pthread_key_t key)437 void *pthread_getspecific(pthread_key_t key)
438 {
439 return pth_key_getdata((pth_key_t)key);
440 }
441
442 /*
443 ** CANCEL ROUTINES
444 */
445
pthread_cancel(pthread_t thread)446 int pthread_cancel(pthread_t thread)
447 {
448 if (!pth_cancel((pth_t)thread))
449 return errno;
450 return OK;
451 }
452
pthread_testcancel(void)453 void pthread_testcancel(void)
454 {
455 pth_cancel_point();
456 return;
457 }
458
pthread_setcancelstate(int state,int * oldstate)459 int pthread_setcancelstate(int state, int *oldstate)
460 {
461 int s, os;
462
463 if (oldstate != NULL) {
464 pth_cancel_state(0, &os);
465 if (os & PTH_CANCEL_ENABLE)
466 *oldstate = PTHREAD_CANCEL_ENABLE;
467 else
468 *oldstate = PTHREAD_CANCEL_DISABLE;
469 }
470 if (state != 0) {
471 pth_cancel_state(0, &s);
472 if (state == PTHREAD_CANCEL_ENABLE) {
473 s |= PTH_CANCEL_ENABLE;
474 s &= ~(PTH_CANCEL_DISABLE);
475 }
476 else {
477 s |= PTH_CANCEL_DISABLE;
478 s &= ~(PTH_CANCEL_ENABLE);
479 }
480 pth_cancel_state(s, NULL);
481 }
482 return OK;
483 }
484
pthread_setcanceltype(int type,int * oldtype)485 int pthread_setcanceltype(int type, int *oldtype)
486 {
487 int t, ot;
488
489 if (oldtype != NULL) {
490 pth_cancel_state(0, &ot);
491 if (ot & PTH_CANCEL_DEFERRED)
492 *oldtype = PTHREAD_CANCEL_DEFERRED;
493 else
494 *oldtype = PTHREAD_CANCEL_ASYNCHRONOUS;
495 }
496 if (type != 0) {
497 pth_cancel_state(0, &t);
498 if (type == PTHREAD_CANCEL_DEFERRED) {
499 t |= PTH_CANCEL_DEFERRED;
500 t &= ~(PTH_CANCEL_ASYNCHRONOUS);
501 }
502 else {
503 t |= PTH_CANCEL_ASYNCHRONOUS;
504 t &= ~(PTH_CANCEL_DEFERRED);
505 }
506 pth_cancel_state(t, NULL);
507 }
508 return OK;
509 }
510
511 /*
512 ** SCHEDULER ROUTINES
513 */
514
pthread_setschedparam(pthread_t pthread,int policy,const struct sched_param * param)515 int pthread_setschedparam(pthread_t pthread, int policy, const struct sched_param *param)
516 {
517 /* not supported */
518 return pth_error(ENOSYS, ENOSYS);
519 }
520
pthread_getschedparam(pthread_t pthread,int * policy,struct sched_param * param)521 int pthread_getschedparam(pthread_t pthread, int *policy, struct sched_param *param)
522 {
523 /* not supported */
524 return pth_error(ENOSYS, ENOSYS);
525 }
526
527 /*
528 ** CLEANUP ROUTINES
529 */
530
pthread_cleanup_push(void (* routine)(void *),void * arg)531 void pthread_cleanup_push(void (*routine)(void *), void *arg)
532 {
533 pthread_initialize();
534 pth_cleanup_push(routine, arg);
535 return;
536 }
537
pthread_cleanup_pop(int execute)538 void pthread_cleanup_pop(int execute)
539 {
540 pth_cleanup_pop(execute);
541 return;
542 }
543
544 /*
545 ** AT-FORK SUPPORT
546 */
547
548 struct pthread_atfork_st {
549 void (*prepare)(void);
550 void (*parent)(void);
551 void (*child)(void);
552 };
553 static struct pthread_atfork_st pthread_atfork_info[PTH_ATFORK_MAX];
554 static int pthread_atfork_idx = 0;
555
pthread_atfork_cb_prepare(void * _info)556 static void pthread_atfork_cb_prepare(void *_info)
557 {
558 struct pthread_atfork_st *info = (struct pthread_atfork_st *)_info;
559 info->prepare();
560 return;
561 }
pthread_atfork_cb_parent(void * _info)562 static void pthread_atfork_cb_parent(void *_info)
563 {
564 struct pthread_atfork_st *info = (struct pthread_atfork_st *)_info;
565 info->parent();
566 return;
567 }
pthread_atfork_cb_child(void * _info)568 static void pthread_atfork_cb_child(void *_info)
569 {
570 struct pthread_atfork_st *info = (struct pthread_atfork_st *)_info;
571 info->child();
572 return;
573 }
574
pthread_atfork(void (* prepare)(void),void (* parent)(void),void (* child)(void))575 int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
576 {
577 struct pthread_atfork_st *info;
578
579 if (pthread_atfork_idx > PTH_ATFORK_MAX-1)
580 return pth_error(ENOMEM, ENOMEM);
581 info = &pthread_atfork_info[pthread_atfork_idx++];
582 info->prepare = prepare;
583 info->parent = parent;
584 info->child = child;
585 if (!pth_atfork_push(pthread_atfork_cb_prepare,
586 pthread_atfork_cb_parent,
587 pthread_atfork_cb_child, info))
588 return errno;
589 return OK;
590 }
591
592 /*
593 ** MUTEX ATTRIBUTE ROUTINES
594 */
595
pthread_mutexattr_init(pthread_mutexattr_t * attr)596 int pthread_mutexattr_init(pthread_mutexattr_t *attr)
597 {
598 pthread_initialize();
599 if (attr == NULL)
600 return pth_error(EINVAL, EINVAL);
601 /* nothing to do for us */
602 return OK;
603 }
604
pthread_mutexattr_destroy(pthread_mutexattr_t * attr)605 int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
606 {
607 if (attr == NULL)
608 return pth_error(EINVAL, EINVAL);
609 /* nothing to do for us */
610 return OK;
611 }
612
pthread_mutexattr_setprioceiling(pthread_mutexattr_t * attr,int prioceiling)613 int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling)
614 {
615 if (attr == NULL)
616 return pth_error(EINVAL, EINVAL);
617 /* not supported */
618 return pth_error(ENOSYS, ENOSYS);
619 }
620
pthread_mutexattr_getprioceiling(pthread_mutexattr_t * attr,int * prioceiling)621 int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *attr, int *prioceiling)
622 {
623 if (attr == NULL)
624 return pth_error(EINVAL, EINVAL);
625 /* not supported */
626 return pth_error(ENOSYS, ENOSYS);
627 }
628
pthread_mutexattr_setprotocol(pthread_mutexattr_t * attr,int protocol)629 int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol)
630 {
631 if (attr == NULL)
632 return pth_error(EINVAL, EINVAL);
633 /* not supported */
634 return pth_error(ENOSYS, ENOSYS);
635 }
636
pthread_mutexattr_getprotocol(pthread_mutexattr_t * attr,int * protocol)637 int pthread_mutexattr_getprotocol(pthread_mutexattr_t *attr, int *protocol)
638 {
639 if (attr == NULL)
640 return pth_error(EINVAL, EINVAL);
641 /* not supported */
642 return pth_error(ENOSYS, ENOSYS);
643 }
644
pthread_mutexattr_setpshared(pthread_mutexattr_t * attr,int pshared)645 int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
646 {
647 if (attr == NULL)
648 return pth_error(EINVAL, EINVAL);
649 /* not supported */
650 return pth_error(ENOSYS, ENOSYS);
651 }
652
pthread_mutexattr_getpshared(pthread_mutexattr_t * attr,int * pshared)653 int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared)
654 {
655 if (attr == NULL)
656 return pth_error(EINVAL, EINVAL);
657 /* not supported */
658 return pth_error(ENOSYS, ENOSYS);
659 }
660
pthread_mutexattr_settype(pthread_mutexattr_t * attr,int type)661 int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
662 {
663 if (attr == NULL)
664 return pth_error(EINVAL, EINVAL);
665 /* not supported */
666 return pth_error(ENOSYS, ENOSYS);
667 }
668
pthread_mutexattr_gettype(pthread_mutexattr_t * attr,int * type)669 int pthread_mutexattr_gettype(pthread_mutexattr_t *attr, int *type)
670 {
671 if (attr == NULL)
672 return pth_error(EINVAL, EINVAL);
673 /* not supported */
674 return pth_error(ENOSYS, ENOSYS);
675 }
676
677 /*
678 ** MUTEX ROUTINES
679 */
680
pthread_mutex_init(pthread_mutex_t * mutex,const pthread_mutexattr_t * attr)681 int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
682 {
683 pth_mutex_t *m;
684
685 pthread_initialize();
686 if (mutex == NULL)
687 return pth_error(EINVAL, EINVAL);
688 if ((m = (pth_mutex_t *)malloc(sizeof(pth_mutex_t))) == NULL)
689 return errno;
690 if (!pth_mutex_init(m))
691 return errno;
692 (*mutex) = (pthread_mutex_t)m;
693 return OK;
694 }
695
pthread_mutex_destroy(pthread_mutex_t * mutex)696 int pthread_mutex_destroy(pthread_mutex_t *mutex)
697 {
698 if (mutex == NULL)
699 return pth_error(EINVAL, EINVAL);
700 free(*mutex);
701 *mutex = NULL;
702 return OK;
703 }
704
pthread_mutex_setprioceiling(pthread_mutex_t * mutex,int prioceiling,int * old_ceiling)705 int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, int *old_ceiling)
706 {
707 if (mutex == NULL)
708 return pth_error(EINVAL, EINVAL);
709 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
710 if (pthread_mutex_init(mutex, NULL) != OK)
711 return errno;
712 /* not supported */
713 return pth_error(ENOSYS, ENOSYS);
714 }
715
pthread_mutex_getprioceiling(pthread_mutex_t * mutex,int * prioceiling)716 int pthread_mutex_getprioceiling(pthread_mutex_t *mutex, int *prioceiling)
717 {
718 if (mutex == NULL)
719 return pth_error(EINVAL, EINVAL);
720 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
721 if (pthread_mutex_init(mutex, NULL) != OK)
722 return errno;
723 /* not supported */
724 return pth_error(ENOSYS, ENOSYS);
725 }
726
pthread_mutex_lock(pthread_mutex_t * mutex)727 int pthread_mutex_lock(pthread_mutex_t *mutex)
728 {
729 if (mutex == NULL)
730 return pth_error(EINVAL, EINVAL);
731 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
732 if (pthread_mutex_init(mutex, NULL) != OK)
733 return errno;
734 if (!pth_mutex_acquire((pth_mutex_t *)(*mutex), FALSE, NULL))
735 return errno;
736 return OK;
737 }
738
pthread_mutex_trylock(pthread_mutex_t * mutex)739 int pthread_mutex_trylock(pthread_mutex_t *mutex)
740 {
741 if (mutex == NULL)
742 return pth_error(EINVAL, EINVAL);
743 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
744 if (pthread_mutex_init(mutex, NULL) != OK)
745 return errno;
746 if (!pth_mutex_acquire((pth_mutex_t *)(*mutex), TRUE, NULL))
747 return errno;
748 return OK;
749 }
750
pthread_mutex_unlock(pthread_mutex_t * mutex)751 int pthread_mutex_unlock(pthread_mutex_t *mutex)
752 {
753 if (mutex == NULL)
754 return pth_error(EINVAL, EINVAL);
755 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
756 if (pthread_mutex_init(mutex, NULL) != OK)
757 return errno;
758 if (!pth_mutex_release((pth_mutex_t *)(*mutex)))
759 return errno;
760 return OK;
761 }
762
763 /*
764 ** LOCK ATTRIBUTE ROUTINES
765 */
766
pthread_rwlockattr_init(pthread_rwlockattr_t * attr)767 int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
768 {
769 pthread_initialize();
770 if (attr == NULL)
771 return pth_error(EINVAL, EINVAL);
772 /* nothing to do for us */
773 return OK;
774 }
775
pthread_rwlockattr_destroy(pthread_rwlockattr_t * attr)776 int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
777 {
778 if (attr == NULL)
779 return pth_error(EINVAL, EINVAL);
780 /* nothing to do for us */
781 return OK;
782 }
783
pthread_rwlockattr_setpshared(pthread_rwlockattr_t * attr,int pshared)784 int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared)
785 {
786 if (attr == NULL)
787 return pth_error(EINVAL, EINVAL);
788 /* not supported */
789 return pth_error(ENOSYS, ENOSYS);
790 }
791
pthread_rwlockattr_getpshared(const pthread_rwlockattr_t * attr,int * pshared)792 int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, int *pshared)
793 {
794 if (attr == NULL)
795 return pth_error(EINVAL, EINVAL);
796 /* not supported */
797 return pth_error(ENOSYS, ENOSYS);
798 }
799
800 /*
801 ** LOCK ROUTINES
802 */
803
pthread_rwlock_init(pthread_rwlock_t * rwlock,const pthread_rwlockattr_t * attr)804 int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
805 {
806 pth_rwlock_t *rw;
807
808 pthread_initialize();
809 if (rwlock == NULL)
810 return pth_error(EINVAL, EINVAL);
811 if ((rw = (pth_rwlock_t *)malloc(sizeof(pth_rwlock_t))) == NULL)
812 return errno;
813 if (!pth_rwlock_init(rw))
814 return errno;
815 (*rwlock) = (pthread_rwlock_t)rw;
816 return OK;
817 }
818
pthread_rwlock_destroy(pthread_rwlock_t * rwlock)819 int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
820 {
821 if (rwlock == NULL)
822 return pth_error(EINVAL, EINVAL);
823 free(*rwlock);
824 *rwlock = NULL;
825 return OK;
826 }
827
pthread_rwlock_rdlock(pthread_rwlock_t * rwlock)828 int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
829 {
830 if (rwlock == NULL)
831 return pth_error(EINVAL, EINVAL);
832 if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
833 if (pthread_rwlock_init(rwlock, NULL) != OK)
834 return errno;
835 if (!pth_rwlock_acquire((pth_rwlock_t *)(*rwlock), PTH_RWLOCK_RD, FALSE, NULL))
836 return errno;
837 return OK;
838 }
839
pthread_rwlock_tryrdlock(pthread_rwlock_t * rwlock)840 int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
841 {
842 if (rwlock == NULL)
843 return pth_error(EINVAL, EINVAL);
844 if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
845 if (pthread_rwlock_init(rwlock, NULL) != OK)
846 return errno;
847 if (!pth_rwlock_acquire((pth_rwlock_t *)(*rwlock), PTH_RWLOCK_RD, TRUE, NULL))
848 return errno;
849 return OK;
850 }
851
pthread_rwlock_wrlock(pthread_rwlock_t * rwlock)852 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
853 {
854 if (rwlock == NULL)
855 return pth_error(EINVAL, EINVAL);
856 if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
857 if (pthread_rwlock_init(rwlock, NULL) != OK)
858 return errno;
859 if (!pth_rwlock_acquire((pth_rwlock_t *)(*rwlock), PTH_RWLOCK_RW, FALSE, NULL))
860 return errno;
861 return OK;
862 }
863
pthread_rwlock_trywrlock(pthread_rwlock_t * rwlock)864 int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
865 {
866 if (rwlock == NULL)
867 return pth_error(EINVAL, EINVAL);
868 if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
869 if (pthread_rwlock_init(rwlock, NULL) != OK)
870 return errno;
871 if (!pth_rwlock_acquire((pth_rwlock_t *)(*rwlock), PTH_RWLOCK_RW, TRUE, NULL))
872 return errno;
873 return OK;
874 }
875
pthread_rwlock_unlock(pthread_rwlock_t * rwlock)876 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
877 {
878 if (rwlock == NULL)
879 return pth_error(EINVAL, EINVAL);
880 if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
881 if (pthread_rwlock_init(rwlock, NULL) != OK)
882 return errno;
883 if (!pth_rwlock_release((pth_rwlock_t *)(*rwlock)))
884 return errno;
885 return OK;
886 }
887
888 /*
889 ** CONDITION ATTRIBUTE ROUTINES
890 */
891
pthread_condattr_init(pthread_condattr_t * attr)892 int pthread_condattr_init(pthread_condattr_t *attr)
893 {
894 pthread_initialize();
895 if (attr == NULL)
896 return pth_error(EINVAL, EINVAL);
897 /* nothing to do for us */
898 return OK;
899 }
900
pthread_condattr_destroy(pthread_condattr_t * attr)901 int pthread_condattr_destroy(pthread_condattr_t *attr)
902 {
903 if (attr == NULL)
904 return pth_error(EINVAL, EINVAL);
905 /* nothing to do for us */
906 return OK;
907 }
908
pthread_condattr_setpshared(pthread_condattr_t * attr,int pshared)909 int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared)
910 {
911 if (attr == NULL)
912 return pth_error(EINVAL, EINVAL);
913 /* not supported */
914 return pth_error(ENOSYS, ENOSYS);
915 }
916
pthread_condattr_getpshared(pthread_condattr_t * attr,int * pshared)917 int pthread_condattr_getpshared(pthread_condattr_t *attr, int *pshared)
918 {
919 if (attr == NULL)
920 return pth_error(EINVAL, EINVAL);
921 /* not supported */
922 return pth_error(ENOSYS, ENOSYS);
923 }
924
925 /*
926 ** CONDITION ROUTINES
927 */
928
pthread_cond_init(pthread_cond_t * cond,const pthread_condattr_t * attr)929 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
930 {
931 pth_cond_t *cn;
932
933 pthread_initialize();
934 if (cond == NULL)
935 return pth_error(EINVAL, EINVAL);
936 if ((cn = (pth_cond_t *)malloc(sizeof(pth_cond_t))) == NULL)
937 return errno;
938 if (!pth_cond_init(cn))
939 return errno;
940 (*cond) = (pthread_cond_t)cn;
941 return OK;
942 }
943
pthread_cond_destroy(pthread_cond_t * cond)944 int pthread_cond_destroy(pthread_cond_t *cond)
945 {
946 if (cond == NULL)
947 return pth_error(EINVAL, EINVAL);
948 free(*cond);
949 *cond = NULL;
950 return OK;
951 }
952
pthread_cond_broadcast(pthread_cond_t * cond)953 int pthread_cond_broadcast(pthread_cond_t *cond)
954 {
955 if (cond == NULL)
956 return pth_error(EINVAL, EINVAL);
957 if (*cond == PTHREAD_COND_INITIALIZER)
958 if (pthread_cond_init(cond, NULL) != OK)
959 return errno;
960 if (!pth_cond_notify((pth_cond_t *)(*cond), TRUE))
961 return errno;
962 return OK;
963 }
964
pthread_cond_signal(pthread_cond_t * cond)965 int pthread_cond_signal(pthread_cond_t *cond)
966 {
967 if (cond == NULL)
968 return pth_error(EINVAL, EINVAL);
969 if (*cond == PTHREAD_COND_INITIALIZER)
970 if (pthread_cond_init(cond, NULL) != OK)
971 return errno;
972 if (!pth_cond_notify((pth_cond_t *)(*cond), FALSE))
973 return errno;
974 return OK;
975 }
976
pthread_cond_wait(pthread_cond_t * cond,pthread_mutex_t * mutex)977 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
978 {
979 if (cond == NULL || mutex == NULL)
980 return pth_error(EINVAL, EINVAL);
981 if (*cond == PTHREAD_COND_INITIALIZER)
982 if (pthread_cond_init(cond, NULL) != OK)
983 return errno;
984 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
985 if (pthread_mutex_init(mutex, NULL) != OK)
986 return errno;
987 if (!pth_cond_await((pth_cond_t *)(*cond), (pth_mutex_t *)(*mutex), NULL))
988 return errno;
989 return OK;
990 }
991
pthread_cond_timedwait(pthread_cond_t * cond,pthread_mutex_t * mutex,const struct timespec * abstime)992 int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
993 const struct timespec *abstime)
994 {
995 pth_event_t ev;
996 static pth_key_t ev_key = PTH_KEY_INIT;
997
998 if (cond == NULL || mutex == NULL || abstime == NULL)
999 return pth_error(EINVAL, EINVAL);
1000 #ifdef __amigaos__
1001 if (abstime->ts_sec < 0 || abstime->ts_nsec < 0 || abstime->ts_nsec >= 1000000000)
1002 #else
1003 if (abstime->tv_sec < 0 || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
1004 #endif
1005 return pth_error(EINVAL, EINVAL);
1006 if (*cond == PTHREAD_COND_INITIALIZER)
1007 if (pthread_cond_init(cond, NULL) != OK)
1008 return errno;
1009 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
1010 if (pthread_mutex_init(mutex, NULL) != OK)
1011 return errno;
1012 ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key,
1013 #ifdef __amigaos__
1014 pth_time(abstime->ts_sec, (abstime->ts_nsec)/1000)
1015 #else
1016 pth_time(abstime->tv_sec, (abstime->tv_nsec)/1000)
1017 #endif
1018 );
1019 if (!pth_cond_await((pth_cond_t *)(*cond), (pth_mutex_t *)(*mutex), ev))
1020 return errno;
1021 if (pth_event_status(ev) == PTH_STATUS_OCCURRED)
1022 return ETIMEDOUT;
1023 return OK;
1024 }
1025
1026 /*
1027 ** POSIX 1003.1j
1028 */
1029
pthread_abort(pthread_t thread)1030 int pthread_abort(pthread_t thread)
1031 {
1032 if (!pth_abort((pth_t)thread))
1033 return errno;
1034 return OK;
1035 }
1036
1037 /*
1038 ** THREAD-SAFE REPLACEMENT FUNCTIONS
1039 */
1040
__pthread_fork(void)1041 pid_t __pthread_fork(void)
1042 {
1043 pthread_initialize();
1044 return pth_fork();
1045 }
1046
__pthread_sleep(unsigned int sec)1047 unsigned int __pthread_sleep(unsigned int sec)
1048 {
1049 pthread_initialize();
1050 return pth_sleep(sec);
1051 }
1052
__pthread_system(const char * cmd)1053 int __pthread_system(const char *cmd)
1054 {
1055 pthread_initialize();
1056 return pth_system(cmd);
1057 }
1058
__pthread_nanosleep(const struct timespec * rqtp,struct timespec * rmtp)1059 int __pthread_nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
1060 {
1061 pthread_initialize();
1062 return pth_nanosleep(rqtp, rmtp);
1063 }
1064
__pthread_usleep(unsigned int sec)1065 int __pthread_usleep(unsigned int sec)
1066 {
1067 pthread_initialize();
1068 return pth_usleep(sec);
1069 }
1070
__pthread_sigwait(const sigset_t * set,int * sig)1071 int __pthread_sigwait(const sigset_t *set, int *sig)
1072 {
1073 pthread_initialize();
1074 return pth_sigwait(set, sig);
1075 }
1076
__pthread_waitpid(pid_t pid,int * status,int options)1077 pid_t __pthread_waitpid(pid_t pid, int *status, int options)
1078 {
1079 pthread_initialize();
1080 return pth_waitpid(pid, status, options);
1081 }
1082
__pthread_connect(int s,struct sockaddr * addr,socklen_t addrlen)1083 int __pthread_connect(int s, struct sockaddr *addr, socklen_t addrlen)
1084 {
1085 pthread_initialize();
1086 return pth_connect(s, addr, addrlen);
1087 }
1088
__pthread_accept(int s,struct sockaddr * addr,socklen_t * addrlen)1089 int __pthread_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1090 {
1091 pthread_initialize();
1092 return pth_accept(s, addr, addrlen);
1093 }
1094
__pthread_select(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout)1095 int __pthread_select(int nfds, fd_set *readfds, fd_set *writefds,
1096 fd_set *exceptfds, struct timeval *timeout)
1097 {
1098 pthread_initialize();
1099 return pth_select(nfds, readfds, writefds, exceptfds, timeout);
1100 }
1101
__pthread_poll(struct pollfd * pfd,nfds_t nfd,int timeout)1102 int __pthread_poll(struct pollfd *pfd, nfds_t nfd, int timeout)
1103 {
1104 pthread_initialize();
1105 return pth_poll(pfd, nfd, timeout);
1106 }
1107
__pthread_read(int fd,void * buf,size_t nbytes)1108 ssize_t __pthread_read(int fd, void *buf, size_t nbytes)
1109 {
1110 pthread_initialize();
1111 return pth_read(fd, buf, nbytes);
1112 }
1113
__pthread_write(int fd,const void * buf,size_t nbytes)1114 ssize_t __pthread_write(int fd, const void *buf, size_t nbytes)
1115 {
1116 pthread_initialize();
1117 return pth_write(fd, buf, nbytes);
1118 }
1119
__pthread_readv(int fd,const struct iovec * piovec,int iocnt)1120 ssize_t __pthread_readv(int fd, const struct iovec *piovec, int iocnt)
1121 {
1122 pthread_initialize();
1123 return pth_readv(fd, piovec, iocnt);
1124 }
1125
__pthread_writev(int fd,const struct iovec * piovec,int iocnt)1126 ssize_t __pthread_writev(int fd, const struct iovec *piovec, int iocnt)
1127 {
1128 pthread_initialize();
1129 return pth_writev(fd, piovec, iocnt);
1130 }
1131
__pthread_recv(int fd,void * buf,size_t nbytes,int flags)1132 ssize_t __pthread_recv(int fd, void *buf, size_t nbytes, int flags)
1133 {
1134 pthread_initialize();
1135 return pth_recv(fd, buf, nbytes, flags);
1136 }
1137
__pthread_send(int fd,const void * buf,size_t nbytes,int flags)1138 ssize_t __pthread_send(int fd, const void *buf, size_t nbytes, int flags)
1139 {
1140 pthread_initialize();
1141 return pth_send(fd, buf, nbytes, flags);
1142 }
1143
__pthread_recvfrom(int fd,void * buf,size_t nbytes,int flags,struct sockaddr * from,socklen_t * fromlen)1144 ssize_t __pthread_recvfrom(int fd, void *buf, size_t nbytes, int flags, struct sockaddr *from, socklen_t *fromlen)
1145 {
1146 pthread_initialize();
1147 return pth_recvfrom(fd, buf, nbytes, flags, from, fromlen);
1148 }
1149
__pthread_sendto(int fd,const void * buf,size_t nbytes,int flags,const struct sockaddr * to,socklen_t tolen)1150 ssize_t __pthread_sendto(int fd, const void *buf, size_t nbytes, int flags, const struct sockaddr *to, socklen_t tolen)
1151 {
1152 pthread_initialize();
1153 return pth_sendto(fd, buf, nbytes, flags, to, tolen);
1154 }
1155
__pthread_pread(int fd,void * buf,size_t nbytes,off_t offset)1156 ssize_t __pthread_pread(int fd, void *buf, size_t nbytes, off_t offset)
1157 {
1158 pthread_initialize();
1159 return pth_pread(fd, buf, nbytes, offset);
1160 }
1161
__pthread_pwrite(int fd,const void * buf,size_t nbytes,off_t offset)1162 ssize_t __pthread_pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
1163 {
1164 pthread_initialize();
1165 return pth_pwrite(fd, buf, nbytes, offset);
1166 }
1167
1168