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 | Mark memgrep as i386 only. (diff) |
Add new experimental option, LINUXTHREADS_WRAP_API, that adds wrapper
functions providing most of the native threads API while avoiding name
clashes by transparently prefixing all function names that directly
provide the linuxthreads API.
Diffstat (limited to 'devel/linuxthreads')
-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 |