thread attributes for the main thread. Add emulation of native threads (libc_r) method of getting the current thread attributes (pthread_attr_get_np()) and adjust emulation of native threads pthread_attr_getstackaddr() to return bottom of stack instead of top of stack. Correct emulation of native threads pthread_mutexattr_settype() when selecting recursive mutexes. Previously, the argument conversion before calling the linuxthreads version of pthread_mutexattr_setattr() ended up selecting errorcheck mutexes instead of recursive mutexes.
1751 lines
42 KiB
C
1751 lines
42 KiB
C
/*
|
|
* Copyright (c) 2005 Yahoo! Technologies Norway AS
|
|
* Copyright (c) 2003 Overture Services Norway AS
|
|
* Copyright (c) 2001 Daniel Eischen <deischen@FreeBSD.org>.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS''
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* 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.5 2007-03-21 21:40:24 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_getattr_np linuxthreads_pthread_getattr_np
|
|
#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_getattr_np pthread_getattr_np
|
|
#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_getattr_np(pthread_t, pthread_attr_t *);
|
|
int __pthread_getconcurrency(void);
|
|
int __pthread_getschedparam(pthread_t, int *, struct sched_param *);
|
|
void *__pthread_getspecific(pthread_key_t);
|
|
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);
|
|
|
|
extern int pthread_attr_get_np(pthread_t, pthread_attr_t *)
|
|
__attribute__ ((weak, alias("_pthread_attr_get_np")));
|
|
|
|
|
|
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
|
|
};
|
|
|
|
enum {
|
|
UTHREAD_PTHREAD_CREATE_JOINABLE = 0,
|
|
UTHREAD_PTHREAD_CREATE_DETACHED = 1
|
|
};
|
|
|
|
enum {
|
|
UTHREAD_PTHREAD_INHERIT_SCHED = 4,
|
|
UTHREAD_PTHREAD_EXPLICIT_SCHED = 0
|
|
};
|
|
|
|
|
|
enum {
|
|
UTHREAD_PTHREAD_SCOPE_SYSTEM = 2,
|
|
UTHREAD_PTHREAD_SCOPE_PROCESS = 0
|
|
};
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
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)
|
|
{
|
|
pthread_mutex_t *m;
|
|
int ret;
|
|
|
|
m = malloc(sizeof(pthread_mutex_t));
|
|
if (m == NULL)
|
|
return ENOMEM;
|
|
ret = __pthread_mutex_init(m, NULL);
|
|
if (ret != 0) {
|
|
free(m);
|
|
return ret;
|
|
}
|
|
__pthread_mutex_lock(&allocmutexlock);
|
|
if (*mutex != NULL) {
|
|
__pthread_mutex_unlock(&allocmutexlock);
|
|
__pthread_mutex_destroy(m);
|
|
free(m);
|
|
return 0;
|
|
}
|
|
*mutex = m;
|
|
__pthread_mutex_unlock(&allocmutexlock);
|
|
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)
|
|
{
|
|
size_t stacksize;
|
|
if (attr == NULL || *attr == NULL || stackaddr == NULL)
|
|
return EINVAL;
|
|
return __pthread_attr_getstack(*attr, stackaddr, &stacksize);
|
|
}
|
|
|
|
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_get_np(pthread_t tid, pthread_attr_t **dst)
|
|
{
|
|
if (dst == NULL || *dst == NULL)
|
|
return EINVAL;
|
|
return __pthread_getattr_np(tid, *dst);
|
|
}
|
|
|
|
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_condattr_init(pthread_condattr_t **cattr)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
return ret;
|
|
}
|
|
return __pthread_mutex_lock(*mutex);
|
|
}
|
|
|
|
int
|
|
_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_timedlock(*mutex, abstime);
|
|
}
|
|
|
|
int
|
|
_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_destroy(pthread_mutexattr_t **mattr)
|
|
{
|
|
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_getpshared(const pthread_mutexattr_t **mattr, int *pshared)
|
|
{
|
|
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_gettype(const pthread_mutexattr_t **mattr, int *type)
|
|
{
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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_RECURSIVE);
|
|
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,
|
|
void (*init_routine) (void))
|
|
{
|
|
if (once_control->state == UTHREAD_PTHREAD_NEEDS_INIT) {
|
|
_pthread_mutex_lock(&(once_control->mutex));
|
|
if (once_control->state == UTHREAD_PTHREAD_NEEDS_INIT) {
|
|
init_routine();
|
|
once_control->state = UTHREAD_PTHREAD_DONE_INIT;
|
|
}
|
|
_pthread_mutex_unlock(&(once_control->mutex));
|
|
}
|
|
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();
|
|
}
|
|
|
|
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
|
|
_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
|