summaryrefslogtreecommitdiff
path: root/devel/linuxthreads/files
diff options
context:
space:
mode:
authorTor Egge <tegge@FreeBSD.org>2003-06-09 03:48:31 +0000
committerTor Egge <tegge@FreeBSD.org>2003-06-09 03:48:31 +0000
commitf390ff8ee2cd9f3d83e4bd7a724a54fa90b0b83a (patch)
tree04653183d749220ab7d9c65b9ca3ba277f313bdc /devel/linuxthreads/files
parentMark 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.
Notes
Notes: svn path=/head/; revision=82560
Diffstat (limited to 'devel/linuxthreads/files')
-rw-r--r--devel/linuxthreads/files/README.FreeBSD20
-rw-r--r--devel/linuxthreads/files/ldwrap117
-rw-r--r--devel/linuxthreads/files/patch-aa29
-rw-r--r--devel/linuxthreads/files/wraputhread.c1634
4 files changed, 1748 insertions, 52 deletions
diff --git a/devel/linuxthreads/files/README.FreeBSD b/devel/linuxthreads/files/README.FreeBSD
index 31b59b43b2b4..4a85faf0b40b 100644
--- a/devel/linuxthreads/files/README.FreeBSD
+++ b/devel/linuxthreads/files/README.FreeBSD
@@ -91,7 +91,25 @@ set at 20 + 16 * MAXUSERS.
library causes the liblgcc_r.a version of those functions to be used.
Use liblstdc++ and liblsupc++.
-4) Exit handling is broken.
+ Experimental wrapper support:
+
+ If the linuxthreads library has been compiled with
+ LINUXTHREADS_WRAP_API defined in the ports makefile then
+ the API functions are internally prefixed with linuxthreads_
+ to avoid conflict with native threads. Weak symbols without
+ that prefix points to the wrapper functions (internally
+ prefixed by _) that makes the linuxthreads functions available
+ with the native threads API. Applications including the
+ linuxthreads version of pthread.h will try to call the
+ prefixed methods (e.g. linuxthreads_pthread_create) while
+ applications including the native pthread.h will use the
+ wrapper functions. This allows for some level of coexistence
+ of libraries compiled with linuxthreads header file and
+ libraries compiled with native threads header files as long
+ as none of the pthread data types leaks out as function arguments
+ or structure members.
+
+5) Exit handling is broken.
If the linuxthreads library has been compiled with
LINUXTHREADS_DETECT_UNSAFE_EXIT defined in the ports makefile then
diff --git a/devel/linuxthreads/files/ldwrap b/devel/linuxthreads/files/ldwrap
new file mode 100644
index 000000000000..9415c7dac375
--- /dev/null
+++ b/devel/linuxthreads/files/ldwrap
@@ -0,0 +1,117 @@
+#!/bin/sh -e
+#
+# Gross hack. Wrapper for ld that renames various functions to avoid
+# conflicts between linuxthreads and native threads
+#
+echo "[ldwrap $@]"
+if test "$1" = "-o" -a "$2" != "wraputhread.o.tmp" -a "$2" != "wraputhread.Po.tmp" -a "$2" != "wraputhread.So.tmp"
+then
+ target=$2
+ shift
+ shift
+ ld -o $target.tmp "$@"
+objcopy \
+--redefine-sym _pthread_cleanup_pop=linuxthreads__pthread_cleanup_pop \
+--redefine-sym _pthread_cleanup_pop_restore=linuxthreads__pthread_cleanup_pop_restore \
+--redefine-sym _pthread_cleanup_push=linuxthreads__pthread_cleanup_push \
+--redefine-sym _pthread_cleanup_push_defer=linuxthreads__pthread_cleanup_push_defer \
+--redefine-sym pthread_atfork=linuxthreads_pthread_atfork \
+--redefine-sym pthread_attr_destroy=linuxthreads_pthread_attr_destroy \
+--redefine-sym pthread_attr_getdetachstate=linuxthreads_pthread_attr_getdetachstate \
+--redefine-sym pthread_attr_getguardsize=linuxthreads_pthread_attr_getguardsize \
+--redefine-sym pthread_attr_getinheritsched=linuxthreads_pthread_attr_getinheritsched \
+--redefine-sym pthread_attr_getschedparam=linuxthreads_pthread_attr_getschedparam \
+--redefine-sym pthread_attr_getschedpolicy=linuxthreads_pthread_attr_getschedpolicy \
+--redefine-sym pthread_attr_getscope=linuxthreads_pthread_attr_getscope \
+--redefine-sym pthread_attr_getstack=linuxthreads_pthread_attr_getstack \
+--redefine-sym pthread_attr_getstackaddr=linuxthreads_pthread_attr_getstackaddr \
+--redefine-sym pthread_attr_getstacksize=linuxthreads_pthread_attr_getstacksize \
+--redefine-sym pthread_attr_init=linuxthreads_pthread_attr_init \
+--redefine-sym pthread_attr_setdetachstate=linuxthreads_pthread_attr_setdetachstate \
+--redefine-sym pthread_attr_setguardsize=linuxthreads_pthread_attr_setguardsize \
+--redefine-sym pthread_attr_setinheritsched=linuxthreads_pthread_attr_setinheritsched \
+--redefine-sym pthread_attr_setschedparam=linuxthreads_pthread_attr_setschedparam \
+--redefine-sym pthread_attr_setschedpolicy=linuxthreads_pthread_attr_setschedpolicy \
+--redefine-sym pthread_attr_setscope=linuxthreads_pthread_attr_setscope \
+--redefine-sym pthread_attr_setstack=linuxthreads_pthread_attr_setstack \
+--redefine-sym pthread_attr_setstackaddr=linuxthreads_pthread_attr_setstackaddr \
+--redefine-sym pthread_attr_setstacksize=linuxthreads_pthread_attr_setstacksize \
+--redefine-sym pthread_barrier_destroy=linuxthreads_pthread_barrier_destroy \
+--redefine-sym pthread_barrier_init=linuxthreads_pthread_barrier_init \
+--redefine-sym pthread_barrier_wait=linuxthreads_pthread_barrier_wait \
+--redefine-sym pthread_barrierattr_destroy=linuxthreads_pthread_barrierattr_destroy \
+--redefine-sym pthread_barrierattr_getpshared=linuxthreads_pthread_barrierattr_getpshared \
+--redefine-sym pthread_barrierattr_init=linuxthreads_pthread_barrierattr_init \
+--redefine-sym pthread_barrierattr_setpshared=linuxthreads_pthread_barrierattr_setpshared \
+--redefine-sym pthread_cancel=linuxthreads_pthread_cancel \
+--redefine-sym pthread_cond_broadcast=linuxthreads_pthread_cond_broadcast \
+--redefine-sym pthread_cond_destroy=linuxthreads_pthread_cond_destroy \
+--redefine-sym pthread_cond_init=linuxthreads_pthread_cond_init \
+--redefine-sym pthread_cond_signal=linuxthreads_pthread_cond_signal \
+--redefine-sym pthread_cond_timedwait=linuxthreads_pthread_cond_timedwait \
+--redefine-sym pthread_cond_wait=linuxthreads_pthread_cond_wait \
+--redefine-sym pthread_condattr_destroy=linuxthreads_pthread_condattr_destroy \
+--redefine-sym pthread_condattr_getpshared=linuxthreads_pthread_condattr_getpshared \
+--redefine-sym pthread_condattr_init=linuxthreads_pthread_condattr_init \
+--redefine-sym pthread_condattr_setpshared=linuxthreads_pthread_condattr_setpshared \
+--redefine-sym pthread_create=linuxthreads_pthread_create \
+--redefine-sym pthread_detach=linuxthreads_pthread_detach \
+--redefine-sym pthread_equal=linuxthreads_pthread_equal \
+--redefine-sym pthread_exit=linuxthreads_pthread_exit \
+--redefine-sym pthread_getattr_np=linuxthreads_pthread_getattr_np \
+--redefine-sym pthread_getconcurrency=linuxthreads_pthread_getconcurrency \
+--redefine-sym pthread_getcpuclockid=linuxthreads_pthread_getcpuclockid \
+--redefine-sym pthread_getschedparam=linuxthreads_pthread_getschedparam \
+--redefine-sym pthread_getspecific=linuxthreads_pthread_getspecific \
+--redefine-sym pthread_join=linuxthreads_pthread_join \
+--redefine-sym pthread_key_create=linuxthreads_pthread_key_create \
+--redefine-sym pthread_key_delete=linuxthreads_pthread_key_delete \
+--redefine-sym pthread_kill=linuxthreads_pthread_kill \
+--redefine-sym pthread_kill_other_threads_np=linuxthreads_pthread_kill_other_threads_np \
+--redefine-sym pthread_mutex_destroy=linuxthreads_pthread_mutex_destroy \
+--redefine-sym pthread_mutex_init=linuxthreads_pthread_mutex_init \
+--redefine-sym pthread_mutex_lock=linuxthreads_pthread_mutex_lock \
+--redefine-sym pthread_mutex_timedlock=linuxthreads_pthread_mutex_timedlock \
+--redefine-sym pthread_mutex_trylock=linuxthreads_pthread_mutex_trylock \
+--redefine-sym pthread_mutex_unlock=linuxthreads_pthread_mutex_unlock \
+--redefine-sym pthread_mutexattr_destroy=linuxthreads_pthread_mutexattr_destroy \
+--redefine-sym pthread_mutexattr_getpshared=linuxthreads_pthread_mutexattr_getpshared \
+--redefine-sym pthread_mutexattr_gettype=linuxthreads_pthread_mutexattr_gettype \
+--redefine-sym pthread_mutexattr_init=linuxthreads_pthread_mutexattr_init \
+--redefine-sym pthread_mutexattr_setpshared=linuxthreads_pthread_mutexattr_setpshared \
+--redefine-sym pthread_mutexattr_settype=linuxthreads_pthread_mutexattr_settype \
+--redefine-sym pthread_once=linuxthreads_pthread_once \
+--redefine-sym pthread_rwlock_destroy=linuxthreads_pthread_rwlock_destroy \
+--redefine-sym pthread_rwlock_init=linuxthreads_pthread_rwlock_init \
+--redefine-sym pthread_rwlock_rdlock=linuxthreads_pthread_rwlock_rdlock \
+--redefine-sym pthread_rwlock_timedrdlock=linuxthreads_pthread_rwlock_timedrdlock \
+--redefine-sym pthread_rwlock_timedwrlock=linuxthreads_pthread_rwlock_timedwrlock \
+--redefine-sym pthread_rwlock_tryrdlock=linuxthreads_pthread_rwlock_tryrdlock \
+--redefine-sym pthread_rwlock_trywrlock=linuxthreads_pthread_rwlock_trywrlock \
+--redefine-sym pthread_rwlock_unlock=linuxthreads_pthread_rwlock_unlock \
+--redefine-sym pthread_rwlock_wrlock=linuxthreads_pthread_rwlock_wrlock \
+--redefine-sym pthread_rwlockattr_destroy=linuxthreads_pthread_rwlockattr_destroy \
+--redefine-sym pthread_rwlockattr_getkind_np=linuxthreads_pthread_rwlockattr_getkind_np \
+--redefine-sym pthread_rwlockattr_getpshared=linuxthreads_pthread_rwlockattr_getpshared \
+--redefine-sym pthread_rwlockattr_init=linuxthreads_pthread_rwlockattr_init \
+--redefine-sym pthread_rwlockattr_setkind_np=linuxthreads_pthread_rwlockattr_setkind_np \
+--redefine-sym pthread_rwlockattr_setpshared=linuxthreads_pthread_rwlockattr_setpshared \
+--redefine-sym pthread_self=linuxthreads_pthread_self \
+--redefine-sym pthread_setcancelstate=linuxthreads_pthread_setcancelstate \
+--redefine-sym pthread_setcanceltype=linuxthreads_pthread_setcanceltype \
+--redefine-sym pthread_setconcurrency=linuxthreads_pthread_setconcurrency \
+--redefine-sym pthread_setschedparam=linuxthreads_pthread_setschedparam \
+--redefine-sym pthread_setspecific=linuxthreads_pthread_setspecific \
+--redefine-sym pthread_sigmask=linuxthreads_pthread_sigmask \
+--redefine-sym pthread_spin_destroy=linuxthreads_pthread_spin_destroy \
+--redefine-sym pthread_spin_init=linuxthreads_pthread_spin_init \
+--redefine-sym pthread_spin_lock=linuxthreads_pthread_spin_lock \
+--redefine-sym pthread_spin_trylock=linuxthreads_pthread_spin_trylock \
+--redefine-sym pthread_spin_unlock=linuxthreads_pthread_spin_unlock \
+--redefine-sym pthread_testcancel=linuxthreads_pthread_testcancel \
+--redefine-sym pthread_yield=linuxthreads_pthread_yield \
+$target.tmp $target
+ rm -f $target.tmp
+else
+ exec ld "$@"
+fi
diff --git a/devel/linuxthreads/files/patch-aa b/devel/linuxthreads/files/patch-aa
index e0a30bfaa397..b411dc08d7cd 100644
--- a/devel/linuxthreads/files/patch-aa
+++ b/devel/linuxthreads/files/patch-aa
@@ -13,15 +13,23 @@ diff -ru ../../work/linuxthreads-2.2.3/Examples/Makefile ./Examples/Makefile
diff -ru ../../work/linuxthreads-2.2.3/Makefile ./Makefile
--- ../../work/linuxthreads-2.2.3/Makefile Wed Apr 25 21:50:59 2001
+++ ./Makefile Thu Jun 7 23:13:52 2001
-@@ -1,128 +1,91 @@
+@@ -1,128 +1,104 @@
-# Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
-# This file is part of the GNU C Library.
+LIB=lthread
++.if defined(LINUXTHREADS_WRAP_API)
++.if defined(USING_GCC3)
++SHLIB_MAJOR= 5
++.else
++SHLIB_MAJOR= 4
++.endif
++.else
+.if defined(USING_GCC3)
+SHLIB_MAJOR= 3
+.else
+SHLIB_MAJOR= 2
+.endif
++.endif
+SHLIB_MINOR= 2
+
+.if defined(INSTALL_LIBLTHREAD_PIC_ARCHIVE)
@@ -61,6 +69,11 @@ diff -ru ../../work/linuxthreads-2.2.3/Makefile ./Makefile
+CFLAGS += -DLINUXTHREADS_DETECT_UNSAFE_EXIT
+.endif
+
++.if defined(LINUXTHREADS_WRAP_API)
++CFLAGS += -DLINUXTHREADS_WRAP_API
++LD=${LINUXTHREADS_WRAP_LD}
++.endif
++
+AINC = -I${LIBSRC_BASE}/libc/${MACHINE_ARCH} -I${.CURDIR}/sysdeps/${MACHINE_ARCH}
+
+# Contents of the library.
@@ -262,14 +275,26 @@ diff -ru ../../work/linuxthreads-2.2.3/attr.c ./attr.c
diff -ru ../../work/linuxthreads-2.2.3/cancel.c ./cancel.c
--- ../../work/linuxthreads-2.2.3/cancel.c Thu Apr 12 23:10:53 2001
+++ ./cancel.c Thu Jun 7 22:59:29 2001
-@@ -20,7 +20,6 @@
+@@ -20,8 +20,10 @@
#include "internals.h"
#include "spinlock.h"
#include "restart.h"
-#include <stackinfo.h>
++#if 1
++#define FRAME_LEFT(frame, other) 0
++#else
#ifdef _STACK_GROWS_DOWN
# define FRAME_LEFT(frame, other) ((char *) frame >= (char *) other)
+ #elif _STACK_GROWS_UP
+@@ -29,6 +31,7 @@
+ #else
+ # error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+ #endif
++#endif
+
+
+ int pthread_setcancelstate(int state, int * oldstate)
@@ -202,9 +201,11 @@
break;
}
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, &ltype);
+ 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