resetting manifest requested domain to floor
[platform/upstream/pth.git] / pthread.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
325 pthread_t pthread_self(void)
326 {
327     pthread_initialize();
328     return (pthread_t)pth_self();
329 }
330
331 int pthread_equal(pthread_t t1, pthread_t t2)
332 {
333     return (t1 == t2);
334 }
335
336 int pthread_yield_np(void)
337 {
338     pthread_initialize();
339     pth_yield(NULL);
340     return OK;
341 }
342
343 void pthread_exit(void *value_ptr)
344 {
345     pthread_initialize();
346     pth_exit(value_ptr);
347     return;
348 }
349
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
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
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
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
398 int pthread_getconcurrency(void)
399 {
400     return pthread_concurrency;
401 }
402
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
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
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
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
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
446 int pthread_cancel(pthread_t thread)
447 {
448     if (!pth_cancel((pth_t)thread))
449         return errno;
450     return OK;
451 }
452
453 void pthread_testcancel(void)
454 {
455     pth_cancel_point();
456     return;
457 }
458
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
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
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
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
531 void pthread_cleanup_push(void (*routine)(void *), void *arg)
532 {
533     pthread_initialize();
534     pth_cleanup_push(routine, arg);
535     return;
536 }
537
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
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 }
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 }
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1041 pid_t __pthread_fork(void)
1042 {
1043     pthread_initialize();
1044     return pth_fork();
1045 }
1046
1047 unsigned int __pthread_sleep(unsigned int sec)
1048 {
1049     pthread_initialize();
1050     return pth_sleep(sec);
1051 }
1052
1053 int __pthread_system(const char *cmd)
1054 {
1055     pthread_initialize();
1056     return pth_system(cmd);
1057 }
1058
1059 int __pthread_nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
1060 {
1061     pthread_initialize();
1062     return pth_nanosleep(rqtp, rmtp);
1063 }
1064
1065 int __pthread_usleep(unsigned int sec)
1066 {
1067     pthread_initialize();
1068     return pth_usleep(sec);
1069 }
1070
1071 int __pthread_sigwait(const sigset_t *set, int *sig)
1072 {
1073     pthread_initialize();
1074     return pth_sigwait(set, sig);
1075 }
1076
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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