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