diff options
author | Tor Egge <tegge@FreeBSD.org> | 2003-06-09 03:48:31 +0000 |
---|---|---|
committer | Tor Egge <tegge@FreeBSD.org> | 2003-06-09 03:48:31 +0000 |
commit | f390ff8ee2cd9f3d83e4bd7a724a54fa90b0b83a (patch) | |
tree | 04653183d749220ab7d9c65b9ca3ba277f313bdc /devel/linuxthreads/files/wraputhread.c | |
parent | Mark memgrep as i386 only. (diff) |
Add new experimental option, LINUXTHREADS_WRAP_API, that adds wrapper
functions providing most of the native threads API while avoiding name
clashes by transparently prefixing all function names that directly
provide the linuxthreads API.
Diffstat (limited to 'devel/linuxthreads/files/wraputhread.c')
-rw-r--r-- | devel/linuxthreads/files/wraputhread.c | 1634 |
1 files changed, 1585 insertions, 49 deletions
diff --git a/devel/linuxthreads/files/wraputhread.c b/devel/linuxthreads/files/wraputhread.c index 8f1dafd987ae..0394f53ba07f 100644 --- a/devel/linuxthreads/files/wraputhread.c +++ b/devel/linuxthreads/files/wraputhread.c @@ -23,53 +23,327 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: /tmp/pcvs/ports/devel/linuxthreads/files/wraputhread.c,v 1.2 2001-06-14 01:34:18 tegge Exp $ + * $FreeBSD: /tmp/pcvs/ports/devel/linuxthreads/files/wraputhread.c,v 1.3 2003-06-09 03:48:31 tegge Exp $ */ +#ifdef LINUXTHREADS_WRAP_API +#define COMPILING_WRAPUTHREAD +#endif #include <pthread.h> #include <stdlib.h> #include <sys/errno.h> +#ifdef LINUXTHREADS_WRAP_API +#define __pthread_attr_destroy linuxthreads_pthread_attr_destroy +#define __pthread_attr_getdetachstate linuxthreads_pthread_attr_getdetachstate +#define __pthread_attr_getinheritsched linuxthreads_pthread_attr_getinheritsched +#define __pthread_attr_getschedparam linuxthreads_pthread_attr_getschedparam +#define __pthread_attr_getschedpolicy linuxthreads_pthread_attr_getschedpolicy +#define __pthread_attr_getscope linuxthreads_pthread_attr_getscope +#define __pthread_attr_init linuxthreads_pthread_attr_init +#define __pthread_attr_setdetachstate linuxthreads_pthread_attr_setdetachstate +#define __pthread_attr_setinheritsched linuxthreads_pthread_attr_setinheritsched +#define __pthread_attr_setschedparam linuxthreads_pthread_attr_setschedparam +#define __pthread_attr_setschedpolicy linuxthreads_pthread_attr_setschedpolicy +#define __pthread_attr_setscope linuxthreads_pthread_attr_setscope +#define __pthread_barrier_destroy linuxthreads_pthread_barrier_destroy +#define __pthread_barrier_init linuxthreads_pthread_barrier_init +#define __pthread_barrier_wait linuxthreads_pthread_barrier_wait +#define __pthread_barrierattr_destroy linuxthreads_pthread_barrierattr_destroy +#define __pthread_barrierattr_init linuxthreads_pthread_barrierattr_init +#define __pthread_barrierattr_setpshared linuxthreads_pthread_barrierattr_setpshared +#define __pthread_cancel linuxthreads_pthread_cancel +#define __pthread_condattr_destroy linuxthreads_pthread_condattr_destroy +#define __pthread_condattr_getpshared linuxthreads_pthread_condattr_getpshared +#define __pthread_condattr_init linuxthreads_pthread_condattr_init +#define __pthread_condattr_setpshared linuxthreads_pthread_condattr_setpshared +#define __pthread_cond_broadcast linuxthreads_pthread_cond_broadcast +#define __pthread_cond_destroy linuxthreads_pthread_cond_destroy +#define __pthread_cond_init linuxthreads_pthread_cond_init +#define __pthread_cond_signal linuxthreads_pthread_cond_signal +#define __pthread_cond_timedwait linuxthreads_pthread_cond_timedwait +#define __pthread_cond_wait linuxthreads_pthread_cond_wait +#define __pthread_create linuxthreads_pthread_create +#define __pthread_detach linuxthreads_pthread_detach +#define __pthread_equal linuxthreads_pthread_equal +#define __pthread_exit linuxthreads_pthread_exit +#define __pthread_getcpuclockid linuxthreads_pthread_getcpuclockid +#define __pthread_getschedparam linuxthreads_pthread_getschedparam +#define __pthread_join linuxthreads_pthread_join +#define __pthread_key_delete linuxthreads_pthread_key_delete +#define __pthread_kill linuxthreads_pthread_kill +#define __pthread_rwlockattr_init linuxthreads_pthread_rwlockattr_init +#define __pthread_rwlockattr_getpshared linuxthreads_pthread_rwlockattr_getpshared +#define __pthread_rwlockattr_setpshared linuxthreads_pthread_rwlockattr_setpshared +#define __pthread_rwlockattr_destroy linuxthreads_pthread_rwlockattr_destroy +#define __pthread_self linuxthreads_pthread_self +#define __pthread_setcanceltype linuxthreads_pthread_setcanceltype +#define __pthread_setcancelstate linuxthreads_pthread_setcancelstate +#define __pthread_setschedparam linuxthreads_pthread_setschedparam +#define __pthread_sigmask linuxthreads_pthread_sigmask +#define __pthread_testcancel linuxthreads_pthread_testcancel +#else +#define __pthread_attr_destroy pthread_attr_destroy +#define __pthread_attr_getdetachstate pthread_attr_getdetachstate +#define __pthread_attr_getinheritsched pthread_attr_getinheritsched +#define __pthread_attr_getschedparam pthread_attr_getschedparam +#define __pthread_attr_getschedpolicy pthread_attr_getschedpolicy +#define __pthread_attr_getscope pthread_attr_getscope +#define __pthread_attr_init pthread_attr_init +#define __pthread_attr_setdetachstate pthread_attr_setdetachstate +#define __pthread_attr_setinheritsched pthread_attr_setinheritsched +#define __pthread_attr_setschedparam pthread_attr_setschedparam +#define __pthread_attr_setschedpolicy pthread_attr_setschedpolicy +#define __pthread_attr_setscope pthread_attr_setscope +#define __pthread_barrier_destroy pthread_barrier_destroy +#define __pthread_barrier_init pthread_barrier_init +#define __pthread_barrier_wait pthread_barrier_wait +#define __pthread_barrierattr_destroy pthread_barrierattr_destroy +#define __pthread_barrierattr_init pthread_barrierattr_init +#define __pthread_barrierattr_setpshared pthread_barrierattr_setpshared +#define __pthread_cancel pthread_cancel +#define __pthread_condattr_destroy pthread_condattr_destroy +#define __pthread_condattr_getpshared pthread_condattr_getpshared +#define __pthread_condattr_init pthread_condattr_init +#define __pthread_condattr_setpshared pthread_condattr_setpshared +#define __pthread_cond_broadcast pthread_cond_broadcast +#define __pthread_cond_destroy pthread_cond_destroy +#define __pthread_cond_init pthread_cond_init +#define __pthread_cond_signal pthread_cond_signal +#define __pthread_cond_timedwait pthread_cond_timedwait +#define __pthread_cond_wait pthread_cond_wait +#define __pthread_create pthread_create +#define __pthread_detach pthread_detach +#define __pthread_equal pthread_equal +#define __pthread_exit pthread_exit +#define __pthread_getschedparam pthread_getschedparam +#define __pthread_join pthread_join +#define __pthread_key_delete pthread_key_delete +#define __pthread_kill pthread_kill +#define __pthread_rwlockattr_init pthread_rwlockattr_init +#define __pthread_rwlockattr_getpshared pthread_rwlockattr_getpshared +#define __pthread_rwlockattr_setpshared pthread_rwlockattr_setpshared +#define __pthread_rwlockattr_destroy pthread_rwlockattr_destroy +#define __pthread_self pthread_self +#define __pthread_setcanceltype pthread_setcanceltype +#define __pthread_setcancelstate pthread_setcancelstate +#define __pthread_setschedparam pthread_setschedparam +#define __pthread_sigmask pthread_sigmask +#define __pthread_testcancel pthread_testcancel +#endif + +int __pthread_atfork(void (*)(void), void (*)(void), void (*)(void)); +int __pthread_attr_destroy(pthread_attr_t *); +int __pthread_attr_getdetachstate(const pthread_attr_t *, int *); +int __pthread_attr_getguardsize(const pthread_attr_t *, size_t *); +int __pthread_attr_getinheritsched(const pthread_attr_t *, int *); +int __pthread_attr_getschedparam(const pthread_attr_t *, + struct sched_param *); +int __pthread_attr_getschedpolicy(const pthread_attr_t *, int *); +int __pthread_attr_getscope(const pthread_attr_t *, int *); +int __pthread_attr_getstack(const pthread_attr_t *, void **, size_t *); +int __pthread_attr_getstackaddr(const pthread_attr_t *, void **); +int __pthread_attr_getstacksize(const pthread_attr_t *, size_t *); +int __pthread_attr_init(pthread_attr_t *); +int __pthread_attr_setdetachstate(pthread_attr_t *, int); +int __pthread_attr_setguardsize(pthread_attr_t *, size_t); +int __pthread_attr_setinheritsched(pthread_attr_t *, int); +int __pthread_attr_setschedparam(pthread_attr_t *, + const struct sched_param *); +int __pthread_attr_setschedpolicy(pthread_attr_t *, int); +int __pthread_attr_setscope(pthread_attr_t *, int); +int __pthread_attr_setstack(pthread_attr_t *, void *, size_t); +int __pthread_attr_setstackaddr(pthread_attr_t *, void *); +int __pthread_attr_setstacksize(pthread_attr_t *, size_t); +int __pthread_barrier_destroy(pthread_barrier_t *); +int __pthread_barrier_init(pthread_barrier_t *, + const pthread_barrierattr_t *, + unsigned int); +int __pthread_barrier_wait(pthread_barrier_t *); +int __pthread_barrierattr_destroy(pthread_barrierattr_t *); +int __pthread_barrierattr_getpshared(const pthread_barrierattr_t *, int *); +int __pthread_barrierattr_init(pthread_barrierattr_t *); +int __pthread_barrierattr_setpshared(pthread_barrierattr_t *, int); +int __pthread_cancel(pthread_t); +int __pthread_cond_broadcast(pthread_cond_t *); +int __pthread_cond_destroy(pthread_cond_t *); +int __pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *); +int __pthread_cond_signal(pthread_cond_t *); +int __pthread_cond_timedwait(pthread_cond_t *, + pthread_mutex_t *, + const struct timespec *); +int __pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *); +int __pthread_condattr_destroy(pthread_condattr_t *); +int __pthread_condattr_getpshared(const pthread_condattr_t *, int *); +int __pthread_condattr_init(pthread_condattr_t *); +int __pthread_condattr_setpshared(pthread_condattr_t *, int); +int __pthread_create(pthread_t *, + const pthread_attr_t *, + void *(*)(void *), + void *); +int __pthread_detach(pthread_t); +int __pthread_equal(pthread_t, pthread_t); +void __pthread_exit(void *); +int __pthread_getconcurrency(void); +int __pthread_getschedparam(pthread_t, int *, struct sched_param *); void *__pthread_getspecific(pthread_key_t); -int __pthread_setspecific(pthread_key_t, const void *); +int __pthread_join(pthread_t, void **); int __pthread_key_create(pthread_key_t *, void (*) (void *)); +int __pthread_key_delete(pthread_key_t); +int __pthread_kill(pthread_t, int); int __pthread_mutex_destroy(pthread_mutex_t *); int __pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *); int __pthread_mutex_lock(pthread_mutex_t *); +int __pthread_mutex_timedlock(pthread_mutex_t *, const struct timespec *); int __pthread_mutex_trylock(pthread_mutex_t *); int __pthread_mutex_unlock(pthread_mutex_t *); +int __pthread_mutexattr_destroy(pthread_mutexattr_t *); +int __pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *); +int __pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *); +int __pthread_mutexattr_init(pthread_mutexattr_t *); +int __pthread_mutexattr_setpshared(pthread_mutexattr_t *, int); +int __pthread_mutexattr_settype(pthread_mutexattr_t *, int); +int __pthread_rwlock_destroy(pthread_rwlock_t *); +int __pthread_rwlock_init(pthread_rwlock_t *, + const pthread_rwlockattr_t *); +int __pthread_rwlock_rdlock(pthread_rwlock_t *); +int __pthread_rwlock_timedrdlock(pthread_rwlock_t *, + const struct timespec *); +int __pthread_rwlock_timedwrlock(pthread_rwlock_t *, + const struct timespec *); +int __pthread_rwlock_tryrdlock(pthread_rwlock_t *); +int __pthread_rwlock_trywrlock(pthread_rwlock_t *); +int __pthread_rwlock_unlock(pthread_rwlock_t *); +int __pthread_rwlock_wrlock(pthread_rwlock_t *); +int __pthread_rwlockattr_destroy(pthread_rwlockattr_t *); +int __pthread_rwlockattr_init(pthread_rwlockattr_t *); +int __pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *); +int __pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int); +pthread_t __pthread_self(void); +int __pthread_setcancelstate(int, int *); +int __pthread_setcanceltype(int, int *); +int __pthread_setconcurrency(int); +int __pthread_setschedparam(pthread_t, int, const struct sched_param *); +int __pthread_setspecific(pthread_key_t, const void *); +int __pthread_sigmask(int, const sigset_t *, sigset_t *); +void __pthread_testcancel(void); -void * -_pthread_getspecific(pthread_key_t key) -{ - return __pthread_getspecific(key); -} +static pthread_mutex_t allocmutexlock = PTHREAD_MUTEX_INITIALIZER; +enum uthread_mutextype { + UTHREAD_PTHREAD_MUTEX_ERRORCHECK = 1, /* Default POSIX mutex */ + UTHREAD_PTHREAD_MUTEX_RECURSIVE = 2, /* Recursive mutex */ + UTHREAD_PTHREAD_MUTEX_NORMAL = 3, /* No error checking */ + MUTEX_TYPE_MAX +}; -int -_pthread_key_create(pthread_key_t *key, void (*destructor) (void *)) -{ - return __pthread_key_create(key, destructor); -} +enum { + UTHREAD_PTHREAD_CREATE_JOINABLE = 0, + UTHREAD_PTHREAD_CREATE_DETACHED = 1 +}; -int -_pthread_key_delete(pthread_key_t key) -{ - return pthread_key_delete(key); -} +enum { + UTHREAD_PTHREAD_INHERIT_SCHED = 0, + UTHREAD_PTHREAD_EXPLICIT_SCHED = 1 +}; -int -_pthread_mutex_destroy(pthread_mutex_t **mutex) + +enum { + UTHREAD_PTHREAD_SCOPE_SYSTEM = 0, + UTHREAD_PTHREAD_SCOPE_PROCESS = 1 +}; + +enum { + UTHREAD_PTHREAD_PROCESS_PRIVATE = 0, + UTHREAD_PTHREAD_PROCESS_SHARED = 1 +}; + + +enum { + UTHREAD_PTHREAD_CANCEL_ENABLE = 0, + UTHREAD_PTHREAD_CANCEL_DISABLE = 1, + UTHREAD_PTHREAD_CANCEL_DEFERRED = 0, + UTHREAD_PTHREAD_CANCEL_ASYNCHRONOUS = 2 +}; + +#define UTHREAD_PTHREAD_CANCELED ((void *) 1) + +enum { + UTHREAD_PTHREAD_PRIO_NONE = 0, + UTHREAD_PTHREAD_PRIO_INHERIT = 1, + UTHREAD_PTHREAD_PRIO_PROTECT = 2 +}; + + +struct uthread_pthread_once { + int state; + pthread_mutex_t *mutex; +}; + +typedef struct uthread_pthread_once uthread_pthread_once_t; + +/* + * Flags for once initialization. + */ +#define UTHREAD_PTHREAD_NEEDS_INIT 0 +#define UTHREAD_PTHREAD_DONE_INIT 1 + + +static int allocbarrier(pthread_barrier_t **barrier); +static int alloccond(pthread_cond_t **cond); +static int allocmutex(pthread_mutex_t **mutex); +static int allocrwlock(pthread_rwlock_t **rwlock); + +static int +allocbarrier(pthread_barrier_t **barrier) { + pthread_barrier_t *b; int ret; - - ret = __pthread_mutex_destroy(*mutex); - if (ret == 0) - free(*mutex); - return ret; + + b = malloc(sizeof(pthread_barrier_t)); + if (b == NULL) + return ENOMEM; + ret = __pthread_barrier_init(b, NULL, 1); + if (ret != 0) { + free(b); + return ret; + } + __pthread_mutex_lock(&allocmutexlock); + if (*barrier != NULL) { + __pthread_mutex_unlock(&allocmutexlock); + __pthread_barrier_destroy(b); + free(b); + return 0; + } + *barrier = b; + __pthread_mutex_unlock(&allocmutexlock); + return 0; } +static int +alloccond(pthread_cond_t **cond) +{ + pthread_cond_t *c; + int ret; -static pthread_mutex_t allocmutexlock = PTHREAD_MUTEX_INITIALIZER; + c = malloc(sizeof(pthread_cond_t)); + if (c == NULL) + return ENOMEM; + ret = __pthread_cond_init(c, NULL); + if (ret != 0) { + free(c); + return ret; + } + __pthread_mutex_lock(&allocmutexlock); + if (*cond != NULL) { + __pthread_mutex_unlock(&allocmutexlock); + __pthread_cond_destroy(c); + free(c); + return 0; + } + *cond = c; + __pthread_mutex_unlock(&allocmutexlock); + return 0; +} static int allocmutex(pthread_mutex_t **mutex) @@ -97,18 +371,749 @@ allocmutex(pthread_mutex_t **mutex) return 0; } +static int +allocrwlock(pthread_rwlock_t **rwlock) +{ + pthread_rwlock_t *rw; + int ret; + + rw = malloc(sizeof(pthread_rwlock_t)); + if (rw == NULL) + return ENOMEM; + ret = __pthread_rwlock_init(rw, NULL); + if (ret != 0) { + free(rw); + return ret; + } + __pthread_mutex_lock(&allocmutexlock); + if (*rwlock != NULL) { + __pthread_mutex_unlock(&allocmutexlock); + __pthread_rwlock_destroy(rw); + free(rw); + return 0; + } + *rwlock = rw; + __pthread_mutex_unlock(&allocmutexlock); + return 0; +} + +int +_pthread_atfork(void (*prepare)(void), + void (*parent)(void), + void (*child)(void)) +{ + return __pthread_atfork(prepare, parent, child); +} + +int +_pthread_attr_destroy(pthread_attr_t **attr) +{ + int ret; + + if (attr == NULL || *attr == NULL) + return EINVAL; + ret = __pthread_attr_destroy(*attr); + if (ret == 0) { + free(*attr); + *attr = NULL; + } + return ret; +} + + +int +_pthread_attr_getdetachstate(const pthread_attr_t **attr, int *detachstate) +{ + int ret; + int lstate; + + if (attr == NULL || *attr == NULL || detachstate == NULL) + return EINVAL; + ret = __pthread_attr_getdetachstate(*attr, &lstate); + if (ret == 0) { + switch (lstate) { + case PTHREAD_CREATE_JOINABLE: + *detachstate = UTHREAD_PTHREAD_CREATE_JOINABLE; + break; + case PTHREAD_CREATE_DETACHED: + *detachstate = UTHREAD_PTHREAD_CREATE_DETACHED; + break; + default: + ret = EINVAL; + } + } + return ret; +} + +int +_pthread_attr_getguardsize(const pthread_attr_t **attr, size_t *guardsize) +{ + if (attr == NULL || *attr == NULL) + return EINVAL; + return __pthread_attr_getguardsize(*attr, guardsize); +} + +int +_pthread_attr_getinheritsched(const pthread_attr_t **attr, int *inherit) +{ + int ret; + int linherit; + + if (attr == NULL || *attr == NULL || inherit == NULL) + return EINVAL; + ret = __pthread_attr_getinheritsched(*attr, &linherit); + if (ret == 0) { + switch (linherit) { + case PTHREAD_EXPLICIT_SCHED: + *inherit = UTHREAD_PTHREAD_EXPLICIT_SCHED; + break; + case PTHREAD_INHERIT_SCHED: + *inherit = UTHREAD_PTHREAD_INHERIT_SCHED; + break; + default: + ret = EINVAL; + } + } + return ret; +} + +int +_pthread_attr_getschedparam(const pthread_attr_t **attr, + struct sched_param *sparam) +{ + if (attr == NULL || *attr == NULL || sparam == NULL) + return EINVAL; + return __pthread_attr_getschedparam(*attr, sparam); +} + +int +_pthread_attr_getschedpolicy(const pthread_attr_t **attr, + int *policy) +{ + if (attr == NULL || *attr == NULL || policy == NULL) + return EINVAL; + return __pthread_attr_getschedpolicy(*attr, policy); +} + +int +_pthread_attr_getscope(const pthread_attr_t **attr, + int *scope) +{ + int ret; + int lscope; + + if (attr == NULL || *attr == NULL || scope == NULL) + return EINVAL; + ret = __pthread_attr_getscope(*attr, &lscope); + if (ret == 0) { + switch (lscope) { + case PTHREAD_SCOPE_SYSTEM: + *scope = UTHREAD_PTHREAD_SCOPE_SYSTEM; + break; + case PTHREAD_SCOPE_PROCESS: + *scope = UTHREAD_PTHREAD_SCOPE_PROCESS; + break; + default: + ret = EINVAL; + } + } + return ret; +} + +int +_pthread_attr_getstack(const pthread_attr_t **attr, + void **stackaddr, + size_t *stacksize) +{ + if (attr == NULL || *attr == NULL || + stackaddr == NULL || stacksize == NULL) + return EINVAL; + return __pthread_attr_getstack(*attr, stackaddr, stacksize); +} + +int +_pthread_attr_getstackaddr(const pthread_attr_t **attr, + void **stackaddr) +{ + if (attr == NULL || *attr == NULL || stackaddr == NULL) + return EINVAL; + return __pthread_attr_getstackaddr(*attr, stackaddr); +} + +int +_pthread_attr_getstacksize(const pthread_attr_t **attr, + size_t *stacksize) +{ + if (attr == NULL || *attr == NULL || stacksize == NULL) + return EINVAL; + return __pthread_attr_getstacksize(*attr, stacksize); +} + +int +_pthread_attr_init(pthread_attr_t **attr) +{ + int ret; + pthread_attr_t *res; + + if (attr == NULL) + return EINVAL; + res = malloc(sizeof(pthread_attr_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_attr_init(res); + if (ret == 0) + *attr = res; + else + free(res); + return ret; +} +int +_pthread_attr_setdetachstate(pthread_attr_t **attr, int detachstate) +{ + if (attr == NULL || *attr == NULL) + return EINVAL; + switch (detachstate) { + case UTHREAD_PTHREAD_CREATE_JOINABLE: + return __pthread_attr_setdetachstate(*attr, + PTHREAD_CREATE_JOINABLE); + case UTHREAD_PTHREAD_CREATE_DETACHED: + return __pthread_attr_setdetachstate(*attr, + PTHREAD_CREATE_DETACHED); + default: + return EINVAL; + } +} + +int +_pthread_attr_setguardsize(pthread_attr_t **attr, size_t guardsize) +{ + if (attr == NULL || *attr == NULL) + return EINVAL; + return __pthread_attr_setguardsize(*attr, guardsize); +} + +int +_pthread_attr_setinheritsched(pthread_attr_t **attr, int inherit) +{ + if (attr == NULL || *attr == NULL) + return EINVAL; + switch (inherit) { + case UTHREAD_PTHREAD_EXPLICIT_SCHED: + return __pthread_attr_setinheritsched(*attr, + PTHREAD_EXPLICIT_SCHED); + case UTHREAD_PTHREAD_INHERIT_SCHED: + return __pthread_attr_setinheritsched(*attr, + PTHREAD_INHERIT_SCHED); + default: + return EINVAL; + } +} + +int +_pthread_attr_setschedparam(pthread_attr_t **attr, + struct sched_param *sparam) +{ + if (attr == NULL || *attr == NULL || sparam == NULL) + return EINVAL; + return __pthread_attr_setschedparam(*attr, sparam); +} + +int +_pthread_attr_setschedpolicy(pthread_attr_t **attr, + int policy) +{ + if (attr == NULL || *attr == NULL) + return EINVAL; + return __pthread_attr_setschedpolicy(*attr, policy); +} + +int +_pthread_attr_setscope(pthread_attr_t **attr, + int scope) +{ + if (attr == NULL || *attr == NULL) + return EINVAL; + switch (scope) { + case UTHREAD_PTHREAD_SCOPE_SYSTEM: + return __pthread_attr_setscope(*attr, PTHREAD_SCOPE_SYSTEM); + case UTHREAD_PTHREAD_SCOPE_PROCESS: + return __pthread_attr_setscope(*attr, PTHREAD_SCOPE_PROCESS); + default: + return EINVAL; + } +} + +int +_pthread_attr_setstack(pthread_attr_t **attr, + void *stackaddr, + size_t stacksize) +{ + if (attr == NULL || *attr == NULL) + return EINVAL; + return __pthread_attr_setstack(*attr, stackaddr, stacksize); +} + +int +_pthread_attr_setstackaddr(pthread_attr_t **attr, + void *stackaddr) +{ + if (attr == NULL || *attr == NULL) + return EINVAL; + return __pthread_attr_setstackaddr(*attr, stackaddr); +} + +int +_pthread_attr_setstacksize(pthread_attr_t **attr, + size_t stacksize) +{ + if (attr == NULL || *attr == NULL) + return EINVAL; + return __pthread_attr_setstacksize(*attr, stacksize); +} + +int +_pthread_barrier_destroy(pthread_barrier_t **barrier) +{ + int ret; + + if (barrier == NULL || *barrier == NULL) + return EINVAL; + ret = __pthread_barrier_destroy(*barrier); + if (ret == 0) { + free(*barrier); + *barrier = NULL; + } + return ret; +} + +int +_pthread_barrier_init(pthread_barrier_t **barrier, + pthread_barrierattr_t **battr, + unsigned int count) +{ + int ret; + pthread_barrier_t *res; + + if (barrier == NULL) + return EINVAL; + res = malloc(sizeof(pthread_barrier_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_barrier_init(res, battr != NULL ? *battr : NULL, + count); + if (ret == 0) + *barrier = res; + else + free(res); + return ret; +} + +int +_pthread_barrier_wait(pthread_barrier_t **barrier) +{ + int ret; + + if (barrier == NULL) + return EINVAL; + if (*barrier == NULL) { + ret = allocbarrier(barrier); + if (ret != 0) + return ret; + } + return __pthread_barrier_wait(*barrier); +} + +int +_pthread_barrierattr_destroy(pthread_barrierattr_t **battr) +{ + int ret; + + if (battr == NULL || *battr == NULL) + return EINVAL; + ret = __pthread_barrierattr_destroy(*battr); + if (ret == 0) { + free(*battr); + *battr = NULL; + } + return ret; +} + +int +_pthread_barrierattr_getpshared(const pthread_barrierattr_t **battr, + int *pshared) +{ + int ret; + int lshared; + + if (battr == NULL || *battr == NULL || pshared == NULL) + return EINVAL; + ret = __pthread_barrierattr_getpshared(*battr, &lshared); + if (ret == 0) { + switch (lshared) { + case PTHREAD_PROCESS_PRIVATE: + *pshared = UTHREAD_PTHREAD_PROCESS_PRIVATE; + break; + case PTHREAD_PROCESS_SHARED: + *pshared = UTHREAD_PTHREAD_PROCESS_SHARED; + break; + default: + ret = EINVAL; + } + } + return ret; +} + +int +_pthread_barrierattr_init(pthread_barrierattr_t **battr) +{ + int ret; + pthread_barrierattr_t *res; + + if (battr == NULL) + return EINVAL; + res = malloc(sizeof(pthread_barrierattr_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_barrierattr_init(res); + if (ret == 0) + *battr = res; + else + free(res); + return ret; +} + +int +_pthread_barrierattr_setpshared(pthread_barrierattr_t **battr, + int pshared) +{ + if (battr == NULL || *battr == NULL) + return EINVAL; + switch (pshared) { + case UTHREAD_PTHREAD_PROCESS_PRIVATE: + return __pthread_barrierattr_setpshared(*battr, + PTHREAD_PROCESS_PRIVATE); + case UTHREAD_PTHREAD_PROCESS_SHARED: + return __pthread_barrierattr_setpshared(*battr, + PTHREAD_PROCESS_SHARED); + default: + return EINVAL; + } +} + +int +_pthread_cancel(pthread_t tid) +{ + return __pthread_cancel(tid); +} + +int +_pthread_cond_broadcast(pthread_cond_t **cond) +{ + int ret; + + if (cond == NULL) + return EINVAL; + if (*cond == NULL) { + ret = alloccond(cond); + if (ret != 0) + return ret; + } + return __pthread_cond_broadcast(*cond); +} + +int +_pthread_cond_destroy(pthread_cond_t **cond) +{ + int ret; + + if (cond == NULL || *cond == NULL) + return EINVAL; + ret = __pthread_cond_destroy(*cond); + if (ret == 0) { + free(*cond); + *cond = NULL; + } + return ret; +} + +int +_pthread_cond_init(pthread_cond_t **cond, + pthread_condattr_t **cattr) +{ + int ret; + pthread_cond_t *res; + + if (cond == NULL) + return EINVAL; + res = malloc(sizeof(pthread_cond_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_cond_init(res, cattr != NULL ? *cattr : NULL); + if (ret == 0) + *cond = res; + else + free(res); + return ret; +} + +int +_pthread_cond_signal(pthread_cond_t **cond) +{ + int ret; + + if (cond == NULL) + return EINVAL; + if (*cond == NULL) { + ret = alloccond(cond); + if (ret != 0) + return ret; + } + return __pthread_cond_signal(*cond); +} + +int +_pthread_cond_timedwait(pthread_cond_t **cond, + pthread_mutex_t **mutex, + const struct timespec *timespec) +{ + int ret; + + if (cond == NULL || mutex == NULL) + return EINVAL; + if (*cond == NULL) { + ret = alloccond(cond); + if (ret != 0) + return ret; + } + if (*mutex == NULL) { + ret = allocmutex(mutex); + if (ret != 0) + return ret; + } + return __pthread_cond_timedwait(*cond, *mutex, timespec); +} + +int +_pthread_cond_wait(pthread_cond_t **cond, + pthread_mutex_t **mutex) +{ + int ret; + + if (cond == NULL || mutex == NULL) + return EINVAL; + if (*cond == NULL) { + ret = alloccond(cond); + if (ret != 0) + return ret; + } + if (*mutex == NULL) { + ret = allocmutex(mutex); + if (ret != 0) + return ret; + } + return __pthread_cond_wait(*cond, *mutex); +} + +int +_pthread_condattr_destroy(pthread_condattr_t **cattr) +{ + int ret; + + if (cattr == NULL || *cattr == NULL) + return EINVAL; + ret = __pthread_condattr_destroy(*cattr); + if (ret == 0) { + free(*cattr); + *cattr = NULL; + } + return ret; +} + +int +_pthread_condattr_getpshared(const pthread_condattr_t **rwattr, + int *pshared) +{ + int ret; + int lshared; + + if (rwattr == NULL || *rwattr == NULL || pshared == NULL) + return EINVAL; + ret = __pthread_condattr_getpshared(*rwattr, &lshared); + if (ret == 0) { + switch (lshared) { + case PTHREAD_PROCESS_PRIVATE: + *pshared = UTHREAD_PTHREAD_PROCESS_PRIVATE; + break; + case PTHREAD_PROCESS_SHARED: + *pshared = UTHREAD_PTHREAD_PROCESS_SHARED; + break; + default: + ret = EINVAL; + } + } + return ret; +} + int -_pthread_mutex_init(pthread_mutex_t **mutex, const pthread_mutexattr_t *mattr) +_pthread_condattr_init(pthread_condattr_t **cattr) { - (void) mattr; - *mutex = malloc(sizeof(pthread_mutex_t)); - return __pthread_mutex_init(*mutex, NULL); // XXX + pthread_condattr_t *res; + int ret; + + if (cattr == NULL) + return EINVAL; + res = malloc(sizeof(pthread_condattr_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_condattr_init(res); + if (ret == 0) + *cattr = res; + else + free(res); + return ret; +} + +int +_pthread_condattr_setpshared(pthread_condattr_t **cattr, + int pshared) +{ + if (cattr == NULL || *cattr == NULL) + return EINVAL; + switch (pshared) { + case UTHREAD_PTHREAD_PROCESS_PRIVATE: + return __pthread_condattr_setpshared(*cattr, + PTHREAD_PROCESS_PRIVATE); + case UTHREAD_PTHREAD_PROCESS_SHARED: + return __pthread_condattr_setpshared(*cattr, + PTHREAD_PROCESS_SHARED); + default: + return EINVAL; + } +} + +int +_pthread_create(pthread_t *tid, + const pthread_attr_t **attr, + void *(*startfunc)(void *), + void *arg) +{ + return __pthread_create(tid, + attr != NULL ? *attr : NULL, + startfunc, + arg); +} + +int +_pthread_detach(pthread_t tid) +{ + return __pthread_detach(tid); +} + +int +_pthread_equal(pthread_t tid1, pthread_t tid2) +{ + return __pthread_equal(tid1, tid2); +} + +void +_pthread_exit(void *retval) +{ + __pthread_exit(retval); +} + +int +_pthread_getconcurrency(void) +{ + return __pthread_getconcurrency(); +} + +int +_pthread_getcpuclockid(pthread_t tid, clockid_t *clockid) +{ + return EINVAL; +} + +int +_pthread_getschedparam(pthread_t tid, int *policy, struct sched_param *sparam) +{ + if (sparam == NULL || policy == NULL) + return EINVAL; + return __pthread_getschedparam(tid, policy, sparam); +} + +void * +_pthread_getspecific(pthread_key_t key) +{ + return __pthread_getspecific(key); +} + +int +_pthread_join(pthread_t tid, void **treturn) +{ + if (treturn == NULL) + return EINVAL; + return __pthread_join(tid, treturn); +} + +int +_pthread_key_create(pthread_key_t *key, void (*destructor) (void *)) +{ + return __pthread_key_create(key, destructor); +} + +int +_pthread_key_delete(pthread_key_t key) +{ + return __pthread_key_delete(key); +} + +int +_pthread_kill(pthread_t tid, int signo) +{ + return __pthread_kill(tid, signo); +} + +int +_pthread_mutex_destroy(pthread_mutex_t **mutex) +{ + int ret; + + if (mutex == NULL || *mutex == NULL) + return EINVAL; + ret = __pthread_mutex_destroy(*mutex); + if (ret == 0) { + free(*mutex); + *mutex = NULL; + } + return ret; +} + +int +_pthread_mutex_init(pthread_mutex_t **mutex, const pthread_mutexattr_t **mattr) +{ + int ret; + pthread_mutex_t *res; + + if (mutex == NULL) + return EINVAL; + res = malloc(sizeof(pthread_mutex_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_mutex_init(res, mattr != NULL ? *mattr : NULL); + if (ret == 0) + *mutex = res; + else + free(res); + return ret; } int _pthread_mutex_lock(pthread_mutex_t **mutex) { int ret; + + if (mutex == NULL) + return EINVAL; if (*mutex == NULL) { ret = allocmutex(mutex); if (ret != 0) @@ -118,58 +1123,166 @@ _pthread_mutex_lock(pthread_mutex_t **mutex) } int -_pthread_mutex_trylock(pthread_mutex_t **mutex) +_pthread_mutex_timedlock(pthread_mutex_t **mutex, + const struct timespec *abstime) { int ret; + + if (mutex == NULL) + return EINVAL; if (*mutex == NULL) { ret = allocmutex(mutex); if (ret != 0) return ret; } - return __pthread_mutex_trylock(*mutex); + return __pthread_mutex_timedlock(*mutex, abstime); } int -_pthread_mutex_unlock(pthread_mutex_t **mutex) +_pthread_mutex_trylock(pthread_mutex_t **mutex) { int ret; + + if (mutex == NULL) + return EINVAL; if (*mutex == NULL) { ret = allocmutex(mutex); if (ret != 0) return ret; } + return __pthread_mutex_trylock(*mutex); +} + +int +_pthread_mutex_unlock(pthread_mutex_t **mutex) +{ + if (mutex == NULL || *mutex == NULL) + return EINVAL; return __pthread_mutex_unlock(*mutex); } int -_pthread_mutexattr_init(pthread_mutexattr_t *mattr) +_pthread_mutexattr_destroy(pthread_mutexattr_t **mattr) { - return EINVAL; + int ret; + + if (mattr == NULL || *mattr == NULL) + return EINVAL; + ret = __pthread_mutexattr_destroy(*mattr); + if (ret == 0) { + free(*mattr); + *mattr = NULL; + } + return ret; } int -_pthread_mutexattr_destroy(pthread_mutexattr_t *mattr) +_pthread_mutexattr_getpshared(const pthread_mutexattr_t **mattr, int *pshared) { - return EINVAL; + int ret; + int lshared; + + if (mattr == NULL || *mattr == NULL || pshared == NULL) + return EINVAL; + ret = __pthread_mutexattr_getpshared(*mattr, &lshared); + if (ret == 0) { + switch (lshared) { + case PTHREAD_PROCESS_PRIVATE: + *pshared = UTHREAD_PTHREAD_PROCESS_PRIVATE; + break; + case PTHREAD_PROCESS_SHARED: + *pshared = UTHREAD_PTHREAD_PROCESS_SHARED; + break; + default: + ret = EINVAL; + } + } + return ret; } int -_pthread_mutexattr_settype(pthread_mutexattr_t *mattr, int type) +_pthread_mutexattr_gettype(const pthread_mutexattr_t **mattr, int *type) { - return EINVAL; + int ret; + int ltype; + + if (mattr == NULL || *mattr == NULL || type == NULL) + return EINVAL; + ret = __pthread_mutexattr_gettype(*mattr, <ype); + if (ret == 0) { + switch (ltype) { + case PTHREAD_MUTEX_ERRORCHECK: + *type = UTHREAD_PTHREAD_MUTEX_ERRORCHECK; + break; + case PTHREAD_MUTEX_RECURSIVE: + *type = UTHREAD_PTHREAD_MUTEX_RECURSIVE; + break; + case PTHREAD_MUTEX_NORMAL: + *type = UTHREAD_PTHREAD_MUTEX_NORMAL; + break; + default: + return EINVAL; + } + } + return ret; } -struct uthread_pthread_once { - int state; - pthread_mutex_t *mutex; -}; -typedef struct uthread_pthread_once uthread_pthread_once_t; +int +_pthread_mutexattr_init(pthread_mutexattr_t **mattr) +{ + pthread_mutexattr_t *res; + int ret; + + if (mattr == NULL) + return EINVAL; + res = malloc(sizeof(pthread_mutexattr_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_mutexattr_init(res); + if (ret == 0) + *mattr = res; + else + free(res); + return ret; +} -/* - * Flags for once initialization. - */ -#define UTHREAD_PTHREAD_NEEDS_INIT 0 -#define UTHREAD_PTHREAD_DONE_INIT 1 +int +_pthread_mutexattr_setpshared(pthread_mutexattr_t **mattr, + int pshared) +{ + if (mattr == NULL || *mattr == NULL) + return EINVAL; + switch (pshared) { + case UTHREAD_PTHREAD_PROCESS_PRIVATE: + return __pthread_mutexattr_setpshared(*mattr, + PTHREAD_PROCESS_PRIVATE); + case UTHREAD_PTHREAD_PROCESS_SHARED: + return __pthread_mutexattr_setpshared(*mattr, + PTHREAD_PROCESS_SHARED); + default: + return EINVAL; + } +} + +int +_pthread_mutexattr_settype(pthread_mutexattr_t **mattr, int type) +{ + if (mattr == NULL || *mattr == NULL) + return EINVAL; + switch (type) { + case UTHREAD_PTHREAD_MUTEX_ERRORCHECK: + return __pthread_mutexattr_settype(*mattr, + PTHREAD_MUTEX_ERRORCHECK); + case UTHREAD_PTHREAD_MUTEX_RECURSIVE: + return __pthread_mutexattr_settype(*mattr, + PTHREAD_MUTEX_ERRORCHECK); + case UTHREAD_PTHREAD_MUTEX_NORMAL: + return __pthread_mutexattr_settype(*mattr, + PTHREAD_MUTEX_NORMAL); + default: + return EINVAL; + } +} int _pthread_once(uthread_pthread_once_t *once_control, @@ -186,10 +1299,298 @@ _pthread_once(uthread_pthread_once_t *once_control, return (0); } +int +_pthread_rwlock_destroy(pthread_rwlock_t **rwlock) +{ + int ret; + + if (rwlock == NULL || *rwlock == NULL) + return EINVAL; + ret = __pthread_rwlock_destroy(*rwlock); + if (ret == 0) { + free(*rwlock); + *rwlock = NULL; + } + return ret; +} + +int +_pthread_rwlock_init(pthread_rwlock_t **rwlock, + const pthread_rwlockattr_t **rwlockattr) +{ + pthread_rwlock_t *res; + int ret; + + if (rwlock == NULL) + return EINVAL; + res = malloc(sizeof(pthread_rwlock_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_rwlock_init(res, + rwlockattr != NULL ? *rwlockattr : NULL); + if (ret == 0) + *rwlock = res; + else + free(res); + return ret; +} + +int +_pthread_rwlock_rdlock(pthread_rwlock_t **rwlock) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_rdlock(*rwlock); +} + +int +_pthread_rwlock_timedrdlock(pthread_rwlock_t **rwlock, + const struct timespec *abstime) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_timedrdlock(*rwlock, abstime); +} + +int +_pthread_rwlock_timedwrlock(pthread_rwlock_t **rwlock, + const struct timespec *abstime) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_timedwrlock(*rwlock, abstime); +} + +int +_pthread_rwlock_tryrdlock(pthread_rwlock_t **rwlock) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_tryrdlock(*rwlock); +} + +int +_pthread_rwlock_trywrlock(pthread_rwlock_t **rwlock) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_trywrlock(*rwlock); +} + +int +_pthread_rwlock_unlock(pthread_rwlock_t **rwlock) +{ + if (rwlock == NULL || *rwlock == NULL) + return EINVAL; + return __pthread_rwlock_unlock(*rwlock); +} + +int +_pthread_rwlock_wrlock(pthread_rwlock_t **rwlock) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_wrlock(*rwlock); +} + +int +_pthread_rwlockattr_destroy(pthread_rwlockattr_t **rwattr) +{ + int ret; + + if (rwattr == NULL || *rwattr == NULL) + return EINVAL; + ret = __pthread_rwlockattr_destroy(*rwattr); + if (ret == 0) { + free(*rwattr); + *rwattr = NULL; + } + return ret; +} + +int +_pthread_rwlockattr_getpshared(const pthread_rwlockattr_t **rwattr, + int *pshared) +{ + int ret; + int lshared; + + if (rwattr == NULL || *rwattr == NULL || pshared == NULL) + return EINVAL; + ret = __pthread_rwlockattr_getpshared(*rwattr, &lshared); + if (ret == 0) { + switch (lshared) { + case PTHREAD_PROCESS_PRIVATE: + *pshared = UTHREAD_PTHREAD_PROCESS_PRIVATE; + break; + case PTHREAD_PROCESS_SHARED: + *pshared = UTHREAD_PTHREAD_PROCESS_SHARED; + break; + default: + ret = EINVAL; + } + } + return ret; +} + +int +_pthread_rwlockattr_init(pthread_rwlockattr_t **rwattr) +{ + pthread_rwlockattr_t *res; + int ret; + + if (rwattr == NULL) + return EINVAL; + res = malloc(sizeof(pthread_rwlockattr_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_rwlockattr_init(res); + if (ret == 0) + *rwattr = res; + else + free(res); + return ret; +} + +int +_pthread_rwlockattr_setpshared(pthread_rwlockattr_t **rwattr, + int pshared) +{ + if (rwattr == NULL || *rwattr == NULL) + return EINVAL; + switch (pshared) { + case UTHREAD_PTHREAD_PROCESS_PRIVATE: + return __pthread_rwlockattr_setpshared(*rwattr, + PTHREAD_PROCESS_PRIVATE); + case UTHREAD_PTHREAD_PROCESS_SHARED: + return __pthread_rwlockattr_setpshared(*rwattr, + PTHREAD_PROCESS_SHARED); + default: + return EINVAL; + } +} + pthread_t _pthread_self(void) { - return pthread_self(); + return __pthread_self(); +} + +int +_pthread_setcancelstate(int newstate, int *oldstate) +{ + int ret; + int lold; + + switch (newstate) { + case UTHREAD_PTHREAD_CANCEL_ENABLE: + ret = __pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &lold); + break; + case UTHREAD_PTHREAD_CANCEL_DISABLE: + ret = __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &lold); + break; + default: + ret = EINVAL; + } + if (ret == 0 && oldstate != NULL) { + switch (lold) { + case PTHREAD_CANCEL_ENABLE: + *oldstate = UTHREAD_PTHREAD_CANCEL_ENABLE; + break; + case PTHREAD_CANCEL_DISABLE: + *oldstate = UTHREAD_PTHREAD_CANCEL_DISABLE; + break; + default: + ret = EINVAL; + } + } + return ret; +} + +int +_pthread_setcanceltype(int newtype, int *oldtype) +{ + int ret; + int lold; + + switch (newtype) { + case UTHREAD_PTHREAD_CANCEL_DEFERRED: + ret = __pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &lold); + break; + case UTHREAD_PTHREAD_CANCEL_ASYNCHRONOUS: + ret = __pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &lold); + break; + default: + ret = EINVAL; + } + if (ret == 0 && oldtype != NULL) { + switch (lold) { + case PTHREAD_CANCEL_DEFERRED: + *oldtype = UTHREAD_PTHREAD_CANCEL_DEFERRED; + break; + case PTHREAD_CANCEL_ASYNCHRONOUS: + *oldtype = UTHREAD_PTHREAD_CANCEL_ASYNCHRONOUS; + break; + default: + ret = EINVAL; + } + } + return ret; +} + +int +_pthread_setconcurrency(int level) +{ + return __pthread_setconcurrency(level); +} + +int +_pthread_setschedparam(pthread_t tid, int policy, + const struct sched_param *sparam) +{ + return __pthread_setschedparam(tid, policy, sparam); } int @@ -197,3 +1598,138 @@ _pthread_setspecific(pthread_key_t key, const void *value) { return __pthread_setspecific(key, value); } + +int +_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) +{ + return __pthread_sigmask(how, set, oset); +} + +void +_pthread_testcancel(void) +{ + __pthread_testcancel(); +} + +#ifdef LINUXTHREADS_WRAP_API + +#include "internals.h" + +void linuxthreads__pthread_cleanup_pop(struct _pthread_cleanup_buffer *buf, + int execute); +void linuxthreads__pthread_cleanup_push(struct _pthread_cleanup_buffer *buf, + void (*)(void *), + void *); + +void wrap_pthread_cleanup_pop(int) __asm__("_pthread_cleanup_pop"); + +void wrap_pthread_cleanup_push(void (*)(void *), void *) __asm__("_pthread_cleanup_push"); + +#undef pthread_cleanup_pop +#undef pthread_cleanup_push + +extern int pthread_cleanup_pop(int) __attribute__ ((weak, alias("_pthread_cleanup_pop"))); + +extern int pthread_cleanup_push(void (*)(void *), void *) __attribute__ ((weak, alias("_pthread_cleanup_push"))); + +struct wrap_pthread_cleanup_buffer { + struct _pthread_cleanup_buffer _buf; + void (*func)(void *); + void *arg; + void *nextfree; +}; + + +static pthread_mutex_t cleanup_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_key_t cleanup_key = (pthread_key_t) -1; +static void free_cleanup_buffers(void *arg); + +static struct wrap_pthread_cleanup_buffer * +alloc_cleanup_buffer(void) +{ + struct wrap_pthread_cleanup_buffer *buf; + + if (cleanup_key == (pthread_key_t) -1) { + __pthread_mutex_lock(&cleanup_mutex); + if (cleanup_key == (pthread_key_t) -1) { + if (__pthread_key_create(&cleanup_key, + free_cleanup_buffers) < 0) { + __pthread_mutex_unlock(&cleanup_mutex); + abort(); + } + } + __pthread_mutex_unlock(&cleanup_mutex); + } + buf = __pthread_getspecific(cleanup_key); + if (buf == NULL) { + buf = (struct wrap_pthread_cleanup_buffer *) + malloc(sizeof(struct wrap_pthread_cleanup_buffer)); + } else { + __pthread_setspecific(cleanup_key, buf->nextfree); + } + if (buf != NULL) { + buf->nextfree = NULL; + } + return buf; +} + + +static void +stash_cleanup_buffer(struct wrap_pthread_cleanup_buffer *buf) +{ + buf->nextfree = __pthread_getspecific(cleanup_key); + __pthread_setspecific(cleanup_key, buf); +} + +static void +free_cleanup_buffers(void *arg) +{ + struct wrap_pthread_cleanup_buffer *buf; + struct wrap_pthread_cleanup_buffer *nbuf; + + buf = (struct wrap_pthread_cleanup_buffer *) arg; + while (buf != NULL) { + nbuf = buf->nextfree; + free(buf); + buf = nbuf; + } +} + +static void +wrap_cleanup(void *arg) +{ + struct wrap_pthread_cleanup_buffer *buf; + + buf = (struct wrap_pthread_cleanup_buffer *) arg; + buf->func(buf->arg); + + /* Cannot free buffer yet ==> stash it on a thread specific freelist */ + stash_cleanup_buffer(buf); +} + +void +wrap_pthread_cleanup_pop(int execute) +{ + pthread_descr self; + struct _pthread_cleanup_buffer *buf; + + self = thread_self(); + buf = THREAD_GETMEM(self, p_cleanup); + + linuxthreads__pthread_cleanup_pop(buf, execute); +} + +void +wrap_pthread_cleanup_push(void (*func)(void *), + void *arg) +{ + struct wrap_pthread_cleanup_buffer *buf; + + buf = alloc_cleanup_buffer(); + buf->func = func; + buf->arg = arg; + linuxthreads__pthread_cleanup_push(&buf->_buf, + wrap_cleanup, + buf); +} +#endif |