diff options
author | Tor Egge <tegge@FreeBSD.org> | 2003-06-09 03:48:31 +0000 |
---|---|---|
committer | Tor Egge <tegge@FreeBSD.org> | 2003-06-09 03:48:31 +0000 |
commit | f390ff8ee2cd9f3d83e4bd7a724a54fa90b0b83a (patch) | |
tree | 04653183d749220ab7d9c65b9ca3ba277f313bdc /devel/linuxthreads | |
parent | 78604ed669aaa28dc26e4db0fc7ff002da79e03a (diff) | |
download | ports-f390ff8ee2cd9f3d83e4bd7a724a54fa90b0b83a.tar.gz ports-f390ff8ee2cd9f3d83e4bd7a724a54fa90b0b83a.zip |
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')
-rw-r--r-- | devel/linuxthreads/Makefile | 32 | ||||
-rw-r--r-- | devel/linuxthreads/files/README.FreeBSD | 20 | ||||
-rw-r--r-- | devel/linuxthreads/files/ldwrap | 117 | ||||
-rw-r--r-- | devel/linuxthreads/files/patch-aa | 29 | ||||
-rw-r--r-- | devel/linuxthreads/files/wraputhread.c | 1634 |
5 files changed, 1778 insertions, 54 deletions
diff --git a/devel/linuxthreads/Makefile b/devel/linuxthreads/Makefile index ff55a6e57b3e..c3696a5fa46c 100644 --- a/devel/linuxthreads/Makefile +++ b/devel/linuxthreads/Makefile @@ -7,7 +7,7 @@ PORTNAME= linuxthreads PORTVERSION= 2.2.3 -PORTREVISION= 11 +PORTREVISION= 12 CATEGORIES= devel MASTER_SITES= ${MASTER_SITE_GNU} MASTER_SITE_SUBDIR= glibc @@ -16,6 +16,10 @@ DISTNAME= glibc-linuxthreads-${PORTVERSION} MAINTAINER= tegge@freebsd.org COMMENT= POSIX pthreads implementation using rfork to generate kernel threads +.if defined(LINUXTHREADS_WRAP_API) +USE_PERL5_BUILD=true +.endif + .include <bsd.port.pre.mk> # This port only works on i386 right now. @@ -34,6 +38,10 @@ MAKE_ENV+= INSTALL_LIBLTHREAD_PIC_ARCHIVE=yes .if defined(LINUXTHREADS_DETECT_UNSAFE_EXIT) MAKE_ENV+= LINUXTHREADS_DETECT_UNSAFE_EXIT=yes .endif +.if defined(LINUXTHREADS_WRAP_API) +MAKE_ENV+= LINUXTHREADS_WRAP_API=yes +MAKE_ENV+= LINUXTHREADS_WRAP_LD="sh ${FILESDIR}/ldwrap" +.endif threads_files := README.FreeBSD clone.S clone.h freebsd-compat.h getgr_r.c \ gethostby_r.c getnetby_r.c getprotoby_r.c getpw_r.c getservby_r.c \ @@ -59,6 +67,13 @@ pre-fetch: @${ECHO} "for more info." @${ECHO} .endif +.if !defined(LINUXTHREADS_WRAP_API) + @${ECHO} + @${ECHO} "Some conflicts with native threads can be avoided by defining" + @${ECHO} "LINUXTHREADS_WRAP_API, see files/README.FreeBSD" + @${ECHO} "for more info." + @${ECHO} +.endif @if ${TEST} -f /usr/src/gnu/lib/libgcc/Makefile; then \ : ; \ else \ @@ -122,8 +137,9 @@ post-extract: ${WRKSRC}/libsupc++/Makefile.inc .endif -.if defined(WITH_CONDWAIT_PATCH) +.if defined(WITH_CONDWAIT_PATCH) || defined(LINUXTHREADS_WRAP_API) post-patch: +.if defined(WITH_CONDWAIT_PATCH) @${ECHO_MSG} "===> Applying experimental patch condwait-patch" @if ${PATCH} ${PATCH_ARGS} < ${PATCHDIR}/condwait-patch; then \ ${ECHO_MSG} "===> Patch condwait-patch applied successfully"; \ @@ -132,6 +148,10 @@ post-patch: ${FALSE}; \ fi .endif +.if defined(LINUXTHREADS_WRAP_API) + perl -pi -e '$$func=$$1 if m/^extern\s+\S+\s+\*?(\S+)\s+\(/; $$alias="#ifdef COMPILING_WRAPUTHREAD\n\t__attribute__((weak, alias(\"_$$func\")))\n#endif\n"; $$wrap="#ifndef COMPILING_LINUXTHREADS\n\t__asm__(\"linuxthreads_$$func\")\n#endif\n"; $$alias="" if ( $$func =~ m/^(pthread_spin|_pthread_cleanup|pthread_rwlockattr_[gs]etkind_np|pthread_kill_other_threads_np)/ ); s=__THROW=\n$$wrap$$alias\t__THROW= unless m/^#/;' ${WRKSRC}/sysdeps/pthread/pthread.h ${WRKSRC}/sysdeps/unix/sysv/linux/bits/sigthread.h +.endif +.endif pre-build: @cd ${WRKSRC}/libgcc_r ; \ @@ -182,10 +202,18 @@ PLIST_SUB+= LIBLTHREADPICARCHIVE:="@comment " .endif .if defined(USING_GCC3) PLIST_SUB+= GCC3ONLY:="" +.if defined(LINUXTHREADS_WRAP_API) +PLIST_SUB+= LTHREADSHMAJOR:="5" +.else PLIST_SUB+= LTHREADSHMAJOR:="3" +.endif .else PLIST_SUB+= GCC3ONLY:="@comment " +.if defined(LINUXTHREADS_WRAP_API) +PLIST_SUB+= LTHREADSHMAJOR:="4" +.else PLIST_SUB+= LTHREADSHMAJOR:="2" .endif +.endif .include <bsd.port.post.mk> 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, <ype); + if (ret == 0) { + switch (ltype) { + case PTHREAD_MUTEX_ERRORCHECK: + *type = UTHREAD_PTHREAD_MUTEX_ERRORCHECK; + break; + case PTHREAD_MUTEX_RECURSIVE: + *type = UTHREAD_PTHREAD_MUTEX_RECURSIVE; + break; + case PTHREAD_MUTEX_NORMAL: + *type = UTHREAD_PTHREAD_MUTEX_NORMAL; + break; + default: + return EINVAL; + } + } + return ret; } -struct uthread_pthread_once { - int state; - pthread_mutex_t *mutex; -}; -typedef struct uthread_pthread_once uthread_pthread_once_t; +int +_pthread_mutexattr_init(pthread_mutexattr_t **mattr) +{ + pthread_mutexattr_t *res; + int ret; + + if (mattr == NULL) + return EINVAL; + res = malloc(sizeof(pthread_mutexattr_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_mutexattr_init(res); + if (ret == 0) + *mattr = res; + else + free(res); + return ret; +} -/* - * Flags for once initialization. - */ -#define UTHREAD_PTHREAD_NEEDS_INIT 0 -#define UTHREAD_PTHREAD_DONE_INIT 1 +int +_pthread_mutexattr_setpshared(pthread_mutexattr_t **mattr, + int pshared) +{ + if (mattr == NULL || *mattr == NULL) + return EINVAL; + switch (pshared) { + case UTHREAD_PTHREAD_PROCESS_PRIVATE: + return __pthread_mutexattr_setpshared(*mattr, + PTHREAD_PROCESS_PRIVATE); + case UTHREAD_PTHREAD_PROCESS_SHARED: + return __pthread_mutexattr_setpshared(*mattr, + PTHREAD_PROCESS_SHARED); + default: + return EINVAL; + } +} + +int +_pthread_mutexattr_settype(pthread_mutexattr_t **mattr, int type) +{ + if (mattr == NULL || *mattr == NULL) + return EINVAL; + switch (type) { + case UTHREAD_PTHREAD_MUTEX_ERRORCHECK: + return __pthread_mutexattr_settype(*mattr, + PTHREAD_MUTEX_ERRORCHECK); + case UTHREAD_PTHREAD_MUTEX_RECURSIVE: + return __pthread_mutexattr_settype(*mattr, + PTHREAD_MUTEX_ERRORCHECK); + case UTHREAD_PTHREAD_MUTEX_NORMAL: + return __pthread_mutexattr_settype(*mattr, + PTHREAD_MUTEX_NORMAL); + default: + return EINVAL; + } +} int _pthread_once(uthread_pthread_once_t *once_control, @@ -186,10 +1299,298 @@ _pthread_once(uthread_pthread_once_t *once_control, return (0); } +int +_pthread_rwlock_destroy(pthread_rwlock_t **rwlock) +{ + int ret; + + if (rwlock == NULL || *rwlock == NULL) + return EINVAL; + ret = __pthread_rwlock_destroy(*rwlock); + if (ret == 0) { + free(*rwlock); + *rwlock = NULL; + } + return ret; +} + +int +_pthread_rwlock_init(pthread_rwlock_t **rwlock, + const pthread_rwlockattr_t **rwlockattr) +{ + pthread_rwlock_t *res; + int ret; + + if (rwlock == NULL) + return EINVAL; + res = malloc(sizeof(pthread_rwlock_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_rwlock_init(res, + rwlockattr != NULL ? *rwlockattr : NULL); + if (ret == 0) + *rwlock = res; + else + free(res); + return ret; +} + +int +_pthread_rwlock_rdlock(pthread_rwlock_t **rwlock) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_rdlock(*rwlock); +} + +int +_pthread_rwlock_timedrdlock(pthread_rwlock_t **rwlock, + const struct timespec *abstime) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_timedrdlock(*rwlock, abstime); +} + +int +_pthread_rwlock_timedwrlock(pthread_rwlock_t **rwlock, + const struct timespec *abstime) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_timedwrlock(*rwlock, abstime); +} + +int +_pthread_rwlock_tryrdlock(pthread_rwlock_t **rwlock) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_tryrdlock(*rwlock); +} + +int +_pthread_rwlock_trywrlock(pthread_rwlock_t **rwlock) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_trywrlock(*rwlock); +} + +int +_pthread_rwlock_unlock(pthread_rwlock_t **rwlock) +{ + if (rwlock == NULL || *rwlock == NULL) + return EINVAL; + return __pthread_rwlock_unlock(*rwlock); +} + +int +_pthread_rwlock_wrlock(pthread_rwlock_t **rwlock) +{ + int ret; + + if (rwlock == NULL) + return EINVAL; + if (*rwlock == NULL) { + ret = allocrwlock(rwlock); + if (ret != 0) + return ret; + } + return __pthread_rwlock_wrlock(*rwlock); +} + +int +_pthread_rwlockattr_destroy(pthread_rwlockattr_t **rwattr) +{ + int ret; + + if (rwattr == NULL || *rwattr == NULL) + return EINVAL; + ret = __pthread_rwlockattr_destroy(*rwattr); + if (ret == 0) { + free(*rwattr); + *rwattr = NULL; + } + return ret; +} + +int +_pthread_rwlockattr_getpshared(const pthread_rwlockattr_t **rwattr, + int *pshared) +{ + int ret; + int lshared; + + if (rwattr == NULL || *rwattr == NULL || pshared == NULL) + return EINVAL; + ret = __pthread_rwlockattr_getpshared(*rwattr, &lshared); + if (ret == 0) { + switch (lshared) { + case PTHREAD_PROCESS_PRIVATE: + *pshared = UTHREAD_PTHREAD_PROCESS_PRIVATE; + break; + case PTHREAD_PROCESS_SHARED: + *pshared = UTHREAD_PTHREAD_PROCESS_SHARED; + break; + default: + ret = EINVAL; + } + } + return ret; +} + +int +_pthread_rwlockattr_init(pthread_rwlockattr_t **rwattr) +{ + pthread_rwlockattr_t *res; + int ret; + + if (rwattr == NULL) + return EINVAL; + res = malloc(sizeof(pthread_rwlockattr_t)); + if (res == NULL) + return ENOMEM; + ret = __pthread_rwlockattr_init(res); + if (ret == 0) + *rwattr = res; + else + free(res); + return ret; +} + +int +_pthread_rwlockattr_setpshared(pthread_rwlockattr_t **rwattr, + int pshared) +{ + if (rwattr == NULL || *rwattr == NULL) + return EINVAL; + switch (pshared) { + case UTHREAD_PTHREAD_PROCESS_PRIVATE: + return __pthread_rwlockattr_setpshared(*rwattr, + PTHREAD_PROCESS_PRIVATE); + case UTHREAD_PTHREAD_PROCESS_SHARED: + return __pthread_rwlockattr_setpshared(*rwattr, + PTHREAD_PROCESS_SHARED); + default: + return EINVAL; + } +} + pthread_t _pthread_self(void) { - return pthread_self(); + return __pthread_self(); +} + +int +_pthread_setcancelstate(int newstate, int *oldstate) +{ + int ret; + int lold; + + switch (newstate) { + case UTHREAD_PTHREAD_CANCEL_ENABLE: + ret = __pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &lold); + break; + case UTHREAD_PTHREAD_CANCEL_DISABLE: + ret = __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &lold); + break; + default: + ret = EINVAL; + } + if (ret == 0 && oldstate != NULL) { + switch (lold) { + case PTHREAD_CANCEL_ENABLE: + *oldstate = UTHREAD_PTHREAD_CANCEL_ENABLE; + break; + case PTHREAD_CANCEL_DISABLE: + *oldstate = UTHREAD_PTHREAD_CANCEL_DISABLE; + break; + default: + ret = EINVAL; + } + } + return ret; +} + +int +_pthread_setcanceltype(int newtype, int *oldtype) +{ + int ret; + int lold; + + switch (newtype) { + case UTHREAD_PTHREAD_CANCEL_DEFERRED: + ret = __pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &lold); + break; + case UTHREAD_PTHREAD_CANCEL_ASYNCHRONOUS: + ret = __pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &lold); + break; + default: + ret = EINVAL; + } + if (ret == 0 && oldtype != NULL) { + switch (lold) { + case PTHREAD_CANCEL_DEFERRED: + *oldtype = UTHREAD_PTHREAD_CANCEL_DEFERRED; + break; + case PTHREAD_CANCEL_ASYNCHRONOUS: + *oldtype = UTHREAD_PTHREAD_CANCEL_ASYNCHRONOUS; + break; + default: + ret = EINVAL; + } + } + return ret; +} + +int +_pthread_setconcurrency(int level) +{ + return __pthread_setconcurrency(level); +} + +int +_pthread_setschedparam(pthread_t tid, int policy, + const struct sched_param *sparam) +{ + return __pthread_setschedparam(tid, policy, sparam); } int @@ -197,3 +1598,138 @@ _pthread_setspecific(pthread_key_t key, const void *value) { return __pthread_setspecific(key, value); } + +int +_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) +{ + return __pthread_sigmask(how, set, oset); +} + +void +_pthread_testcancel(void) +{ + __pthread_testcancel(); +} + +#ifdef LINUXTHREADS_WRAP_API + +#include "internals.h" + +void linuxthreads__pthread_cleanup_pop(struct _pthread_cleanup_buffer *buf, + int execute); +void linuxthreads__pthread_cleanup_push(struct _pthread_cleanup_buffer *buf, + void (*)(void *), + void *); + +void wrap_pthread_cleanup_pop(int) __asm__("_pthread_cleanup_pop"); + +void wrap_pthread_cleanup_push(void (*)(void *), void *) __asm__("_pthread_cleanup_push"); + +#undef pthread_cleanup_pop +#undef pthread_cleanup_push + +extern int pthread_cleanup_pop(int) __attribute__ ((weak, alias("_pthread_cleanup_pop"))); + +extern int pthread_cleanup_push(void (*)(void *), void *) __attribute__ ((weak, alias("_pthread_cleanup_push"))); + +struct wrap_pthread_cleanup_buffer { + struct _pthread_cleanup_buffer _buf; + void (*func)(void *); + void *arg; + void *nextfree; +}; + + +static pthread_mutex_t cleanup_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_key_t cleanup_key = (pthread_key_t) -1; +static void free_cleanup_buffers(void *arg); + +static struct wrap_pthread_cleanup_buffer * +alloc_cleanup_buffer(void) +{ + struct wrap_pthread_cleanup_buffer *buf; + + if (cleanup_key == (pthread_key_t) -1) { + __pthread_mutex_lock(&cleanup_mutex); + if (cleanup_key == (pthread_key_t) -1) { + if (__pthread_key_create(&cleanup_key, + free_cleanup_buffers) < 0) { + __pthread_mutex_unlock(&cleanup_mutex); + abort(); + } + } + __pthread_mutex_unlock(&cleanup_mutex); + } + buf = __pthread_getspecific(cleanup_key); + if (buf == NULL) { + buf = (struct wrap_pthread_cleanup_buffer *) + malloc(sizeof(struct wrap_pthread_cleanup_buffer)); + } else { + __pthread_setspecific(cleanup_key, buf->nextfree); + } + if (buf != NULL) { + buf->nextfree = NULL; + } + return buf; +} + + +static void +stash_cleanup_buffer(struct wrap_pthread_cleanup_buffer *buf) +{ + buf->nextfree = __pthread_getspecific(cleanup_key); + __pthread_setspecific(cleanup_key, buf); +} + +static void +free_cleanup_buffers(void *arg) +{ + struct wrap_pthread_cleanup_buffer *buf; + struct wrap_pthread_cleanup_buffer *nbuf; + + buf = (struct wrap_pthread_cleanup_buffer *) arg; + while (buf != NULL) { + nbuf = buf->nextfree; + free(buf); + buf = nbuf; + } +} + +static void +wrap_cleanup(void *arg) +{ + struct wrap_pthread_cleanup_buffer *buf; + + buf = (struct wrap_pthread_cleanup_buffer *) arg; + buf->func(buf->arg); + + /* Cannot free buffer yet ==> stash it on a thread specific freelist */ + stash_cleanup_buffer(buf); +} + +void +wrap_pthread_cleanup_pop(int execute) +{ + pthread_descr self; + struct _pthread_cleanup_buffer *buf; + + self = thread_self(); + buf = THREAD_GETMEM(self, p_cleanup); + + linuxthreads__pthread_cleanup_pop(buf, execute); +} + +void +wrap_pthread_cleanup_push(void (*func)(void *), + void *arg) +{ + struct wrap_pthread_cleanup_buffer *buf; + + buf = alloc_cleanup_buffer(); + buf->func = func; + buf->arg = arg; + linuxthreads__pthread_cleanup_push(&buf->_buf, + wrap_cleanup, + buf); +} +#endif |