From 49a669c97d85e988d73df72729fdbdcf54d586f5 Mon Sep 17 00:00:00 2001 From: rpj Date: Tue, 12 Apr 2005 06:27:18 +0000 Subject: '' --- ANNOUNCE | 2 +- GNUmakefile | 1109 +++++++++++----------- Makefile | 4 +- NEWS | 31 + README | 1094 +++++++++++----------- pthread.h | 2782 +++++++++++++++++++++++++++---------------------------- pthread_once.c | 26 +- tests/ChangeLog | 54 +- tests/Debug.ncb | Bin 66583 -> 0 bytes tests/Debug.opt | Bin 53776 -> 0 bytes tests/Makefile | 9 +- 11 files changed, 2612 insertions(+), 2499 deletions(-) delete mode 100644 tests/Debug.ncb delete mode 100644 tests/Debug.opt diff --git a/ANNOUNCE b/ANNOUNCE index a5c9910..1b97ad2 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,4 +1,4 @@ - PTHREADS-WIN32 RELEASE 2.2.0 (2005-04-04) + PTHREADS-WIN32 RELEASE 2.3.0 (2005-04-12) ----------------------------------------- Web Site: http://sources.redhat.com/pthreads-win32/ FTP Site: ftp://sources.redhat.com/pub/pthreads-win32 diff --git a/GNUmakefile b/GNUmakefile index 00eeb8e..94f49f1 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,537 +1,572 @@ -# -# -------------------------------------------------------------------------- -# -# Pthreads-win32 - POSIX Threads Library for Win32 -# Copyright(C) 1998 John E. Bossom -# Copyright(C) 1999,2005 Pthreads-win32 contributors -# -# Contact Email: rpj@callisto.canberra.edu.au -# -# The current list of contributors is contained -# in the file CONTRIBUTORS included with the source -# code distribution. The list can also be seen at the -# following World Wide Web location: -# http://sources.redhat.com/pthreads-win32/contributors.html -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library in the file COPYING.LIB; -# if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -# - -DLL_VER = 2 - -DEVROOT = C:\PTHREADS - -DLLDEST = $(DEVROOT)\DLL -LIBDEST = $(DEVROOT)\DLL - -# If Running MsysDTK -RM = rm -f -MV = mv -f -CP = cp -f -RC = windres - -# If not. -#RM = erase -#MV = rename -#CP = copy - -AR = ar - -#OPT = -g -O0 -#OPT = -O3 -OPT = $(CLEANUP) -O3 -finline-functions -XOPT = - -RCFLAGS = --include-dir=. -LFLAGS = -lwsock32 - -# ---------------------------------------------------------------------- -# The library can be built with some alternative behaviour to -# facilitate development of applications on Win32 that will be ported -# to other POSIX systems. Nothing definable here will make the library -# non-compliant, but applications that make assumptions that POSIX -# does not garrantee may fail or misbehave under some settings. -# -# PTW32_THREAD_ID_REUSE_INCREMENT -# Purpose: -# POSIX says that applications should assume that thread IDs can be -# recycled. However, Solaris and some other systems use a [very large] -# sequence number as the thread ID, which provides virtual uniqueness. -# -# Usage: -# Set to any value in the range: 0 <= value <= 2^wordsize -# -# Examples: -# Set to 0 to emulate non recycle-unique behaviour like Linux or *BSD. -# Set to 1 for recycle-unique thread IDs like Solaris (this is the default). -# Set to some other +ve value to emulate smaller word size types (i.e. will -# wrap sooner). This might be useful to emulate some embedded systems. -# -#PTW32_FLAGS = "-DPTW32_THREAD_ID_REUSE_INCREMENT=0" -# -# ---------------------------------------------------------------------- - -GC_CFLAGS = $(PTW32_FLAGS) -GCE_CFLAGS = $(PTW32_FLAGS) -mthreads - -## Mingw32 -MAKE = make -CFLAGS = $(OPT) $(XOPT) -I. -DHAVE_CONFIG_H -Wall - -DLL_INLINED_OBJS = \ - pthread.o \ - version.o - -# Agregate modules for inlinability -DLL_OBJS = \ - attr.o \ - barrier.o \ - cancel.o \ - cleanup.o \ - condvar.o \ - create.o \ - dll.o \ - errno.o \ - exit.o \ - fork.o \ - global.o \ - misc.o \ - mutex.o \ - nonportable.o \ - private.o \ - rwlock.o \ - sched.o \ - semaphore.o \ - signal.o \ - spin.o \ - sync.o \ - tsd.o \ - version.o - -# Separate modules for minimum size statically linked images -SMALL_STATIC_OBJS = \ - pthread_attr_init.o \ - pthread_attr_destroy.o \ - pthread_attr_getdetachstate.o \ - pthread_attr_setdetachstate.o \ - pthread_attr_getstackaddr.o \ - pthread_attr_setstackaddr.o \ - pthread_attr_getstacksize.o \ - pthread_attr_setstacksize.o \ - pthread_attr_getscope.o \ - pthread_attr_setscope.o \ - pthread_attr_setschedpolicy.o \ - pthread_attr_getschedpolicy.o \ - pthread_attr_setschedparam.o \ - pthread_attr_getschedparam.o \ - pthread_attr_setinheritsched.o \ - pthread_attr_getinheritsched.o \ - pthread_barrier_init.o \ - pthread_barrier_destroy.o \ - pthread_barrier_wait.o \ - pthread_barrierattr_init.o \ - pthread_barrierattr_destroy.o \ - pthread_barrierattr_setpshared.o \ - pthread_barrierattr_getpshared.o \ - pthread_setcancelstate.o \ - pthread_setcanceltype.o \ - pthread_testcancel.o \ - pthread_cancel.o \ - cleanup.o \ - pthread_condattr_destroy.o \ - pthread_condattr_getpshared.o \ - pthread_condattr_init.o \ - pthread_condattr_setpshared.o \ - pthread_cond_destroy.o \ - pthread_cond_init.o \ - pthread_cond_signal.o \ - pthread_cond_wait.o \ - create.o \ - dll.o \ - errno.o \ - pthread_exit.o \ - fork.o \ - global.o \ - pthread_mutex_init.o \ - pthread_mutex_destroy.o \ - pthread_mutexattr_init.o \ - pthread_mutexattr_destroy.o \ - pthread_mutexattr_getpshared.o \ - pthread_mutexattr_setpshared.o \ - pthread_mutexattr_settype.o \ - pthread_mutexattr_gettype.o \ - pthread_mutex_lock.o \ - pthread_mutex_timedlock.o \ - pthread_mutex_unlock.o \ - pthread_mutex_trylock.o \ - pthread_mutexattr_setkind_np.o \ - pthread_mutexattr_getkind_np.o \ - pthread_getw32threadhandle_np.o \ - pthread_delay_np.o \ - pthread_num_processors_np.o \ - pthread_win32_attach_detach_np.o \ - pthread_equal.o \ - pthread_getconcurrency.o \ - pthread_once.o \ - pthread_self.o \ - pthread_setconcurrency.o \ - pthread_rwlock_init.o \ - pthread_rwlock_destroy.o \ - pthread_rwlockattr_init.o \ - pthread_rwlockattr_destroy.o \ - pthread_rwlockattr_getpshared.o \ - pthread_rwlockattr_setpshared.o \ - pthread_rwlock_rdlock.o \ - pthread_rwlock_wrlock.o \ - pthread_rwlock_unlock.o \ - pthread_rwlock_tryrdlock.o \ - pthread_rwlock_trywrlock.o \ - pthread_setschedparam.o \ - pthread_getschedparam.o \ - pthread_timechange_handler_np.o \ - ptw32_is_attr.o \ - ptw32_cond_check_need_init.o \ - ptw32_mutex_check_need_init.o \ - ptw32_processInitialize.o \ - ptw32_processTerminate.o \ - ptw32_threadStart.o \ - ptw32_threadDestroy.o \ - ptw32_tkAssocCreate.o \ - ptw32_tkAssocDestroy.o \ - ptw32_callUserDestroyRoutines.o \ - ptw32_timespec.o \ - ptw32_throw.o \ - ptw32_InterlockedCompareExchange.o \ - ptw32_getprocessors.o \ - ptw32_calloc.o \ - ptw32_new.o \ - ptw32_reuse.o \ - ptw32_semwait.o \ - ptw32_rwlock_check_need_init.o \ - sched_get_priority_max.o \ - sched_get_priority_min.o \ - sched_setscheduler.o \ - sched_getscheduler.o \ - sched_yield.o \ - sem_init.o \ - sem_destroy.o \ - sem_trywait.o \ - sem_timedwait.o \ - sem_wait.o \ - sem_post.o \ - sem_post_multiple.o \ - sem_getvalue.o \ - sem_open.o \ - sem_close.o \ - sem_unlink.o \ - ptw32_increase_semaphore.o \ - ptw32_decrease_semaphore.o \ - signal.o \ - pthread_kill.o \ - ptw32_spinlock_check_need_init.o \ - pthread_spin_init.o \ - pthread_spin_destroy.o \ - pthread_spin_lock.o \ - pthread_spin_unlock.o \ - pthread_spin_trylock.o \ - pthread_detach.o \ - pthread_join.o \ - pthread_key_create.o \ - pthread_key_delete.o \ - pthread_setspecific.o \ - pthread_getspecific.o \ - w32_CancelableWait.o \ - version.o - -INCL = \ - config.h \ - implement.h \ - semaphore.h \ - pthread.h \ - need_errno.h - -ATTR_SRCS = \ - pthread_attr_init.c \ - pthread_attr_destroy.c \ - pthread_attr_getdetachstate.c \ - pthread_attr_setdetachstate.c \ - pthread_attr_getstackaddr.c \ - pthread_attr_setstackaddr.c \ - pthread_attr_getstacksize.c \ - pthread_attr_setstacksize.c \ - pthread_attr_getscope.c \ - pthread_attr_setscope.c - -BARRIER_SRCS = \ - pthread_barrier_init.c \ - pthread_barrier_destroy.c \ - pthread_barrier_wait.c \ - pthread_barrierattr_init.c \ - pthread_barrierattr_destroy.c \ - pthread_barrierattr_setpshared.c \ - pthread_barrierattr_getpshared.c - -CANCEL_SRCS = \ - pthread_setcancelstate.c \ - pthread_setcanceltype.c \ - pthread_testcancel.c \ - pthread_cancel.c - -CONDVAR_SRCS = \ - ptw32_cond_check_need_init.c \ - pthread_condattr_destroy.c \ - pthread_condattr_getpshared.c \ - pthread_condattr_init.c \ - pthread_condattr_setpshared.c \ - pthread_cond_destroy.c \ - pthread_cond_init.c \ - pthread_cond_signal.c \ - pthread_cond_wait.c - -EXIT_SRCS = \ - pthread_exit.c - -MISC_SRCS = \ - pthread_equal.c \ - pthread_getconcurrency.c \ - pthread_kill.c \ - pthread_once.c \ - pthread_self.c \ - pthread_setconcurrency.c \ - ptw32_calloc.c \ - ptw32_new.c \ - ptw32_reuse.c \ - w32_CancelableWait.c - -MUTEX_SRCS = \ - ptw32_mutex_check_need_init.c \ - pthread_mutex_init.c \ - pthread_mutex_destroy.c \ - pthread_mutexattr_init.c \ - pthread_mutexattr_destroy.c \ - pthread_mutexattr_getpshared.c \ - pthread_mutexattr_setpshared.c \ - pthread_mutexattr_settype.c \ - pthread_mutexattr_gettype.c \ - pthread_mutex_lock.c \ - pthread_mutex_timedlock.c \ - pthread_mutex_unlock.c \ - pthread_mutex_trylock.c - -NONPORTABLE_SRCS = \ - pthread_mutexattr_setkind_np.c \ - pthread_mutexattr_getkind_np.c \ - pthread_getw32threadhandle_np.c \ - pthread_delay_np.c \ - pthread_num_processors_np.c \ - pthread_win32_attach_detach_np.c \ - pthread_timechange_handler_np.c - -PRIVATE_SRCS = \ - ptw32_is_attr.c \ - ptw32_processInitialize.c \ - ptw32_processTerminate.c \ - ptw32_threadStart.c \ - ptw32_threadDestroy.c \ - ptw32_tkAssocCreate.c \ - ptw32_tkAssocDestroy.c \ - ptw32_callUserDestroyRoutines.c \ - ptw32_semwait.c \ - ptw32_timespec.c \ - ptw32_throw.c \ - ptw32_InterlockedCompareExchange.c \ - ptw32_getprocessors.c - -RWLOCK_SRCS = \ - ptw32_rwlock_check_need_init.c \ - ptw32_rwlock_cancelwrwait.c \ - pthread_rwlock_init.c \ - pthread_rwlock_destroy.c \ - pthread_rwlockattr_init.c \ - pthread_rwlockattr_destroy.c \ - pthread_rwlockattr_getpshared.c \ - pthread_rwlockattr_setpshared.c \ - pthread_rwlock_rdlock.c \ - pthread_rwlock_timedrdlock.c \ - pthread_rwlock_wrlock.c \ - pthread_rwlock_timedwrlock.c \ - pthread_rwlock_unlock.c \ - pthread_rwlock_tryrdlock.c \ - pthread_rwlock_trywrlock.c - -SCHED_SRCS = \ - pthread_attr_setschedpolicy.c \ - pthread_attr_getschedpolicy.c \ - pthread_attr_setschedparam.c \ - pthread_attr_getschedparam.c \ - pthread_attr_setinheritsched.c \ - pthread_attr_getinheritsched.c \ - pthread_setschedparam.c \ - pthread_getschedparam.c \ - sched_get_priority_max.c \ - sched_get_priority_min.c \ - sched_setscheduler.c \ - sched_getscheduler.c \ - sched_yield.c - -SEMAPHORE_SRCS = \ - sem_init.c \ - sem_destroy.c \ - sem_trywait.c \ - sem_timedwait.c \ - sem_wait.c \ - sem_post.c \ - sem_post_multiple.c \ - sem_getvalue.c \ - sem_open.c \ - sem_close.c \ - sem_unlink.c \ - ptw32_increase_semaphore.c \ - ptw32_decrease_semaphore.c - -SPIN_SRCS = \ - ptw32_spinlock_check_need_init.c \ - pthread_spin_init.c \ - pthread_spin_destroy.c \ - pthread_spin_lock.c \ - pthread_spin_unlock.c \ - pthread_spin_trylock.c - -SYNC_SRCS = \ - pthread_detach.c \ - pthread_join.c - -TSD_SRCS = \ - pthread_key_create.c \ - pthread_key_delete.c \ - pthread_setspecific.c \ - pthread_getspecific.c - - -GCE_DLL = pthreadGCE$(DLL_VER).dll -GCE_LIB = libpthreadGCE$(DLL_VER).a -GCE_INLINED_STAMP = pthreadGCE$(DLL_VER).stamp - -GC_DLL = pthreadGC$(DLL_VER).dll -GC_LIB = libpthreadGC$(DLL_VER).a -GC_INLINED_STAMP = pthreadGC$(DLL_VER).stamp -GC_STATIC_STAMP = libpthreadGC$(DLL_VER).stamp - -PTHREAD_DEF = pthread.def - -help: - @ echo "Run one of the following command lines:" - @ echo "make clean GCE (to build the GNU C dll with C++ exception handling)" - @ echo "make clean GC (to build the GNU C dll with C cleanup code)" - @ echo "make clean GCE-inlined (to build the GNU C inlined dll with C++ exception handling)" - @ echo "make clean GC-inlined (to build the GNU C inlined dll with C cleanup code)" - @ echo "make clean GC-static (to build the GNU C inlined static lib with C cleanup code)" - -all: - @ $(MAKE) clean GCE - @ $(MAKE) clean GC - -GC: - $(MAKE) CC=gcc CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_OBJS)" $(GC_DLL) - -GCE: - $(MAKE) CC=g++ CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_OBJS)" $(GCE_DLL) - -GC-inlined: - $(MAKE) CC=gcc XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_INLINED_STAMP) - -GCE-inlined: - $(MAKE) CC=g++ XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GCE_INLINED_STAMP) - -GC-static: - $(MAKE) CC=gcc XOPT="-DPTW32_BUILD_INLINED -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_STATIC_STAMP) - -tests: - @ cd tests - @ $(MAKE) auto - -%.pre: %.c - $(CC) -E -o $@ $(CFLAGS) $^ - -%.s: %.c - $(CC) -c $(CFLAGS) -Wa,-ahl $^ > $@ - -%.o: %.rc - $(RC) $(RCFLAGS) $(CLEANUP) -o $@ $< - -.SUFFIXES: .dll .rc .c .o - -.c.o:; $(CC) -c -o $@ $(CFLAGS) $(XC_FLAGS) $< - - -$(GC_DLL): $(DLL_OBJS) - $(CC) $(OPT) -shared -o $(GC_DLL) $(DLL_OBJS) $(LFLAGS) - dlltool -z pthread.def $(DLL_OBJS) - dlltool -k --dllname $@ --output-lib $(GC_LIB) --def $(PTHREAD_DEF) - -$(GCE_DLL): $(DLL_OBJS) - $(CC) $(OPT) -mthreads -shared -o $(GCE_DLL) $(DLL_OBJS) $(LFLAGS) - dlltool -z pthread.def $(DLL_OBJS) - dlltool -k --dllname $@ --output-lib $(GCE_LIB) --def $(PTHREAD_DEF) - -$(GC_INLINED_STAMP): $(DLL_INLINED_OBJS) - $(CC) $(OPT) $(XOPT) -shared -o $(GC_DLL) $(DLL_INLINED_OBJS) $(LFLAGS) - dlltool -z pthread.def $(DLL_INLINED_OBJS) - dlltool -k --dllname $(GC_DLL) --output-lib $(GC_LIB) --def $(PTHREAD_DEF) - echo touched > $(GC_INLINED_STAMP) - -$(GCE_INLINED_STAMP): $(DLL_INLINED_OBJS) - $(CC) $(OPT) $(XOPT) -mthreads -shared -o $(GCE_DLL) $(DLL_INLINED_OBJS) $(LFLAGS) - dlltool -z pthread.def $(DLL_INLINED_OBJS) - dlltool -k --dllname $(GCE_DLL) --output-lib $(GCE_LIB) --def $(PTHREAD_DEF) - echo touched > $(GCE_INLINED_STAMP) - -$(GC_STATIC_STAMP): $(DLL_INLINED_OBJS) - $(RM) $(GC_LIB) - $(AR) -rv $(GC_LIB) $(DLL_INLINED_OBJS) - echo touched > $(GC_STATIC_STAMP) - -clean: - -$(RM) *~ - -$(RM) *.i - -$(RM) *.o - -$(RM) *.obj - -$(RM) *.exe - -$(RM) $(PTHREAD_DEF) - -realclean: clean - -$(RM) $(GC_LIB) - -$(RM) $(GCE_LIB) - -$(RM) $(GC_DLL) - -$(RM) $(GCE_DLL) - -$(RM) $(GC_INLINED_STAMP) - -$(RM) $(GCE_INLINED_STAMP) - -attr.o: attr.c $(ATTR_SRCS) $(INCL) -barrier.o: barrier.c $(BARRIER_SRCS) $(INCL) -cancel.o: cancel.c $(CANCEL_SRCS) $(INCL) -condvar.o: condvar.c $(CONDVAR_SRCS) $(INCL) -exit.o: exit.c $(EXIT_SRCS) $(INCL) -misc.o: misc.c $(MISC_SRCS) $(INCL) -mutex.o: mutex.c $(MUTEX_SRCS) $(INCL) -nonportable.o: nonportable.c $(NONPORTABLE_SRCS) $(INCL) -private.o: private.c $(PRIVATE_SRCS) $(INCL) -rwlock.o: rwlock.c $(RWLOCK_SRCS) $(INCL) -sched.o: sched.c $(SCHED_SRCS) $(INCL) -semaphore.o: semaphore.c $(SEMAPHORE_SRCS) $(INCL) -spin.o: spin.c $(SPIN_SRCS) $(INCL) -sync.o: sync.c $(SYNC_SRCS) $(INCL) -tsd.o: tsd.c $(TSD_SRCS) $(INCL) -version.o: version.rc $(INCL) +# +# -------------------------------------------------------------------------- +# +# Pthreads-win32 - POSIX Threads Library for Win32 +# Copyright(C) 1998 John E. Bossom +# Copyright(C) 1999,2005 Pthreads-win32 contributors +# +# Contact Email: rpj@callisto.canberra.edu.au +# +# The current list of contributors is contained +# in the file CONTRIBUTORS included with the source +# code distribution. The list can also be seen at the +# following World Wide Web location: +# http://sources.redhat.com/pthreads-win32/contributors.html +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library in the file COPYING.LIB; +# if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +# + +DLL_VER = 2 +DLL_VERD= $(DLL_VER)d + +DEVROOT = C:\PTHREADS + +DLLDEST = $(DEVROOT)\DLL +LIBDEST = $(DEVROOT)\DLL + +# If Running MsysDTK +RM = rm -f +MV = mv -f +CP = cp -f +RC = windres + +# If not. +#RM = erase +#MV = rename +#CP = copy + +AR = ar + +OPT = $(CLEANUP) -O3 -finline-functions +DOPT = $(CLEANUP) -g -O0 +XOPT = + +RCFLAGS = --include-dir=. +LFLAGS = -lwsock32 + +# ---------------------------------------------------------------------- +# The library can be built with some alternative behaviour to +# facilitate development of applications on Win32 that will be ported +# to other POSIX systems. Nothing definable here will make the library +# non-compliant, but applications that make assumptions that POSIX +# does not garrantee may fail or misbehave under some settings. +# +# PTW32_THREAD_ID_REUSE_INCREMENT +# Purpose: +# POSIX says that applications should assume that thread IDs can be +# recycled. However, Solaris and some other systems use a [very large] +# sequence number as the thread ID, which provides virtual uniqueness. +# +# Usage: +# Set to any value in the range: 0 <= value <= 2^wordsize +# +# Examples: +# Set to 0 to emulate non recycle-unique behaviour like Linux or *BSD. +# Set to 1 for recycle-unique thread IDs like Solaris (this is the default). +# Set to some other +ve value to emulate smaller word size types (i.e. will +# wrap sooner). This might be useful to emulate some embedded systems. +# +#PTW32_FLAGS = "-DPTW32_THREAD_ID_REUSE_INCREMENT=0" +# +# ---------------------------------------------------------------------- + +GC_CFLAGS = $(PTW32_FLAGS) +GCE_CFLAGS = $(PTW32_FLAGS) -mthreads + +## Mingw32 +MAKE = make +CFLAGS = $(OPT) $(XOPT) -I. -DHAVE_CONFIG_H -Wall + +DLL_INLINED_OBJS = \ + pthread.o \ + version.o + +# Agregate modules for inlinability +DLL_OBJS = \ + attr.o \ + barrier.o \ + cancel.o \ + cleanup.o \ + condvar.o \ + create.o \ + dll.o \ + errno.o \ + exit.o \ + fork.o \ + global.o \ + misc.o \ + mutex.o \ + nonportable.o \ + private.o \ + rwlock.o \ + sched.o \ + semaphore.o \ + signal.o \ + spin.o \ + sync.o \ + tsd.o \ + version.o + +# Separate modules for minimum size statically linked images +SMALL_STATIC_OBJS = \ + pthread_attr_init.o \ + pthread_attr_destroy.o \ + pthread_attr_getdetachstate.o \ + pthread_attr_setdetachstate.o \ + pthread_attr_getstackaddr.o \ + pthread_attr_setstackaddr.o \ + pthread_attr_getstacksize.o \ + pthread_attr_setstacksize.o \ + pthread_attr_getscope.o \ + pthread_attr_setscope.o \ + pthread_attr_setschedpolicy.o \ + pthread_attr_getschedpolicy.o \ + pthread_attr_setschedparam.o \ + pthread_attr_getschedparam.o \ + pthread_attr_setinheritsched.o \ + pthread_attr_getinheritsched.o \ + pthread_barrier_init.o \ + pthread_barrier_destroy.o \ + pthread_barrier_wait.o \ + pthread_barrierattr_init.o \ + pthread_barrierattr_destroy.o \ + pthread_barrierattr_setpshared.o \ + pthread_barrierattr_getpshared.o \ + pthread_setcancelstate.o \ + pthread_setcanceltype.o \ + pthread_testcancel.o \ + pthread_cancel.o \ + cleanup.o \ + pthread_condattr_destroy.o \ + pthread_condattr_getpshared.o \ + pthread_condattr_init.o \ + pthread_condattr_setpshared.o \ + pthread_cond_destroy.o \ + pthread_cond_init.o \ + pthread_cond_signal.o \ + pthread_cond_wait.o \ + create.o \ + dll.o \ + errno.o \ + pthread_exit.o \ + fork.o \ + global.o \ + pthread_mutex_init.o \ + pthread_mutex_destroy.o \ + pthread_mutexattr_init.o \ + pthread_mutexattr_destroy.o \ + pthread_mutexattr_getpshared.o \ + pthread_mutexattr_setpshared.o \ + pthread_mutexattr_settype.o \ + pthread_mutexattr_gettype.o \ + pthread_mutex_lock.o \ + pthread_mutex_timedlock.o \ + pthread_mutex_unlock.o \ + pthread_mutex_trylock.o \ + pthread_mutexattr_setkind_np.o \ + pthread_mutexattr_getkind_np.o \ + pthread_getw32threadhandle_np.o \ + pthread_delay_np.o \ + pthread_num_processors_np.o \ + pthread_win32_attach_detach_np.o \ + pthread_equal.o \ + pthread_getconcurrency.o \ + pthread_once.o \ + pthread_self.o \ + pthread_setconcurrency.o \ + pthread_rwlock_init.o \ + pthread_rwlock_destroy.o \ + pthread_rwlockattr_init.o \ + pthread_rwlockattr_destroy.o \ + pthread_rwlockattr_getpshared.o \ + pthread_rwlockattr_setpshared.o \ + pthread_rwlock_rdlock.o \ + pthread_rwlock_wrlock.o \ + pthread_rwlock_unlock.o \ + pthread_rwlock_tryrdlock.o \ + pthread_rwlock_trywrlock.o \ + pthread_setschedparam.o \ + pthread_getschedparam.o \ + pthread_timechange_handler_np.o \ + ptw32_is_attr.o \ + ptw32_cond_check_need_init.o \ + ptw32_mutex_check_need_init.o \ + ptw32_processInitialize.o \ + ptw32_processTerminate.o \ + ptw32_threadStart.o \ + ptw32_threadDestroy.o \ + ptw32_tkAssocCreate.o \ + ptw32_tkAssocDestroy.o \ + ptw32_callUserDestroyRoutines.o \ + ptw32_timespec.o \ + ptw32_throw.o \ + ptw32_InterlockedCompareExchange.o \ + ptw32_getprocessors.o \ + ptw32_calloc.o \ + ptw32_new.o \ + ptw32_reuse.o \ + ptw32_semwait.o \ + ptw32_rwlock_check_need_init.o \ + sched_get_priority_max.o \ + sched_get_priority_min.o \ + sched_setscheduler.o \ + sched_getscheduler.o \ + sched_yield.o \ + sem_init.o \ + sem_destroy.o \ + sem_trywait.o \ + sem_timedwait.o \ + sem_wait.o \ + sem_post.o \ + sem_post_multiple.o \ + sem_getvalue.o \ + sem_open.o \ + sem_close.o \ + sem_unlink.o \ + ptw32_increase_semaphore.o \ + ptw32_decrease_semaphore.o \ + signal.o \ + pthread_kill.o \ + ptw32_spinlock_check_need_init.o \ + pthread_spin_init.o \ + pthread_spin_destroy.o \ + pthread_spin_lock.o \ + pthread_spin_unlock.o \ + pthread_spin_trylock.o \ + pthread_detach.o \ + pthread_join.o \ + pthread_key_create.o \ + pthread_key_delete.o \ + pthread_setspecific.o \ + pthread_getspecific.o \ + w32_CancelableWait.o \ + version.o + +INCL = \ + config.h \ + implement.h \ + semaphore.h \ + pthread.h \ + need_errno.h + +ATTR_SRCS = \ + pthread_attr_init.c \ + pthread_attr_destroy.c \ + pthread_attr_getdetachstate.c \ + pthread_attr_setdetachstate.c \ + pthread_attr_getstackaddr.c \ + pthread_attr_setstackaddr.c \ + pthread_attr_getstacksize.c \ + pthread_attr_setstacksize.c \ + pthread_attr_getscope.c \ + pthread_attr_setscope.c + +BARRIER_SRCS = \ + pthread_barrier_init.c \ + pthread_barrier_destroy.c \ + pthread_barrier_wait.c \ + pthread_barrierattr_init.c \ + pthread_barrierattr_destroy.c \ + pthread_barrierattr_setpshared.c \ + pthread_barrierattr_getpshared.c + +CANCEL_SRCS = \ + pthread_setcancelstate.c \ + pthread_setcanceltype.c \ + pthread_testcancel.c \ + pthread_cancel.c + +CONDVAR_SRCS = \ + ptw32_cond_check_need_init.c \ + pthread_condattr_destroy.c \ + pthread_condattr_getpshared.c \ + pthread_condattr_init.c \ + pthread_condattr_setpshared.c \ + pthread_cond_destroy.c \ + pthread_cond_init.c \ + pthread_cond_signal.c \ + pthread_cond_wait.c + +EXIT_SRCS = \ + pthread_exit.c + +MISC_SRCS = \ + pthread_equal.c \ + pthread_getconcurrency.c \ + pthread_kill.c \ + pthread_once.c \ + pthread_self.c \ + pthread_setconcurrency.c \ + ptw32_calloc.c \ + ptw32_new.c \ + ptw32_reuse.c \ + w32_CancelableWait.c + +MUTEX_SRCS = \ + ptw32_mutex_check_need_init.c \ + pthread_mutex_init.c \ + pthread_mutex_destroy.c \ + pthread_mutexattr_init.c \ + pthread_mutexattr_destroy.c \ + pthread_mutexattr_getpshared.c \ + pthread_mutexattr_setpshared.c \ + pthread_mutexattr_settype.c \ + pthread_mutexattr_gettype.c \ + pthread_mutex_lock.c \ + pthread_mutex_timedlock.c \ + pthread_mutex_unlock.c \ + pthread_mutex_trylock.c + +NONPORTABLE_SRCS = \ + pthread_mutexattr_setkind_np.c \ + pthread_mutexattr_getkind_np.c \ + pthread_getw32threadhandle_np.c \ + pthread_delay_np.c \ + pthread_num_processors_np.c \ + pthread_win32_attach_detach_np.c \ + pthread_timechange_handler_np.c + +PRIVATE_SRCS = \ + ptw32_is_attr.c \ + ptw32_processInitialize.c \ + ptw32_processTerminate.c \ + ptw32_threadStart.c \ + ptw32_threadDestroy.c \ + ptw32_tkAssocCreate.c \ + ptw32_tkAssocDestroy.c \ + ptw32_callUserDestroyRoutines.c \ + ptw32_semwait.c \ + ptw32_timespec.c \ + ptw32_throw.c \ + ptw32_InterlockedCompareExchange.c \ + ptw32_getprocessors.c + +RWLOCK_SRCS = \ + ptw32_rwlock_check_need_init.c \ + ptw32_rwlock_cancelwrwait.c \ + pthread_rwlock_init.c \ + pthread_rwlock_destroy.c \ + pthread_rwlockattr_init.c \ + pthread_rwlockattr_destroy.c \ + pthread_rwlockattr_getpshared.c \ + pthread_rwlockattr_setpshared.c \ + pthread_rwlock_rdlock.c \ + pthread_rwlock_timedrdlock.c \ + pthread_rwlock_wrlock.c \ + pthread_rwlock_timedwrlock.c \ + pthread_rwlock_unlock.c \ + pthread_rwlock_tryrdlock.c \ + pthread_rwlock_trywrlock.c + +SCHED_SRCS = \ + pthread_attr_setschedpolicy.c \ + pthread_attr_getschedpolicy.c \ + pthread_attr_setschedparam.c \ + pthread_attr_getschedparam.c \ + pthread_attr_setinheritsched.c \ + pthread_attr_getinheritsched.c \ + pthread_setschedparam.c \ + pthread_getschedparam.c \ + sched_get_priority_max.c \ + sched_get_priority_min.c \ + sched_setscheduler.c \ + sched_getscheduler.c \ + sched_yield.c + +SEMAPHORE_SRCS = \ + sem_init.c \ + sem_destroy.c \ + sem_trywait.c \ + sem_timedwait.c \ + sem_wait.c \ + sem_post.c \ + sem_post_multiple.c \ + sem_getvalue.c \ + sem_open.c \ + sem_close.c \ + sem_unlink.c \ + ptw32_increase_semaphore.c \ + ptw32_decrease_semaphore.c + +SPIN_SRCS = \ + ptw32_spinlock_check_need_init.c \ + pthread_spin_init.c \ + pthread_spin_destroy.c \ + pthread_spin_lock.c \ + pthread_spin_unlock.c \ + pthread_spin_trylock.c + +SYNC_SRCS = \ + pthread_detach.c \ + pthread_join.c + +TSD_SRCS = \ + pthread_key_create.c \ + pthread_key_delete.c \ + pthread_setspecific.c \ + pthread_getspecific.c + + +GCE_DLL = pthreadGCE$(DLL_VER).dll +GCED_DLL= pthreadGCE$(DLL_VERD).dll +GCE_LIB = libpthreadGCE$(DLL_VER).a +GCED_LIB= libpthreadGCE$(DLL_VERD).a +GCE_INLINED_STAMP = pthreadGCE$(DLL_VER).stamp +GCED_INLINED_STAMP = pthreadGCE$(DLL_VERD).stamp + +GC_DLL = pthreadGC$(DLL_VER).dll +GCD_DLL = pthreadGC$(DLL_VERD).dll +GC_LIB = libpthreadGC$(DLL_VER).a +GCD_LIB = libpthreadGC$(DLL_VERD).a +GC_INLINED_STAMP = pthreadGC$(DLL_VER).stamp +GCD_INLINED_STAMP = pthreadGC$(DLL_VERD).stamp +GC_STATIC_STAMP = libpthreadGC$(DLL_VER).stamp +GCD_STATIC_STAMP = libpthreadGC$(DLL_VERD).stamp + +PTHREAD_DEF = pthread.def + +help: + @ echo "Run one of the following command lines:" + @ echo "make clean GC (to build the GNU C dll with C cleanup code)" + @ echo "make clean GCE (to build the GNU C dll with C++ exception handling)" + @ echo "make clean GC-inlined (to build the GNU C inlined dll with C cleanup code)" + @ echo "make clean GCE-inlined (to build the GNU C inlined dll with C++ exception handling)" + @ echo "make clean GC-static (to build the GNU C inlined static lib with C cleanup code)" + @ echo "make clean GC-debug (to build the GNU C debug dll with C cleanup code)" + @ echo "make clean GCE-debug (to build the GNU C debug dll with C++ exception handling)" + @ echo "make clean GC-inlined-debug (to build the GNU C inlined debug dll with C cleanup code)" + @ echo "make clean GCE-inlined-debug (to build the GNU C inlined debug dll with C++ exception handling)" + @ echo "make clean GC-static-debug (to build the GNU C inlined static debug lib with C cleanup code)" + +all: + @ $(MAKE) clean GCE + @ $(MAKE) clean GC + +GC: + $(MAKE) CC=gcc CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_OBJS)" $(GC_DLL) + +GC-debug: + $(MAKE) CC=gcc CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCD_DLL) + +GCE: + $(MAKE) CC=g++ CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_OBJS)" $(GCE_DLL) + +GCE-debug: + $(MAKE) CC=g++ CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCED_DLL) + +GC-inlined: + $(MAKE) CC=gcc XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_INLINED_STAMP) + +GC-inlined-debug: + $(MAKE) CC=gcc XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCD_INLINED_STAMP) + +GCE-inlined: + $(MAKE) CC=g++ XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GCE_INLINED_STAMP) + +GCE-inlined-debug: + $(MAKE) CC=g++ XOPT="-DPTW32_BUILD_INLINED" CLEANUP=-D__CLEANUP_CXX XC_FLAGS="$(GCE_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCED_INLINED_STAMP) + +GC-static: + $(MAKE) CC=gcc XOPT="-DPTW32_BUILD_INLINED -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_STATIC_STAMP) + +GC-static-debug: + $(MAKE) CC=gcc XOPT="-DPTW32_BUILD_INLINED -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCD_STATIC_STAMP) + +tests: + @ cd tests + @ $(MAKE) auto + +%.pre: %.c + $(CC) -E -o $@ $(CFLAGS) $^ + +%.s: %.c + $(CC) -c $(CFLAGS) -Wa,-ahl $^ > $@ + +%.o: %.rc + $(RC) $(RCFLAGS) $(CLEANUP) -o $@ $< + +.SUFFIXES: .dll .rc .c .o + +.c.o:; $(CC) -c -o $@ $(CFLAGS) $(XC_FLAGS) $< + + +$(GC_DLL) $(GCD_DLL): $(DLL_OBJS) + $(CC) $(OPT) -shared -o $(GC_DLL) $(DLL_OBJS) $(LFLAGS) + dlltool -z pthread.def $(DLL_OBJS) + dlltool -k --dllname $@ --output-lib $(GC_LIB) --def $(PTHREAD_DEF) + +$(GCE_DLL): $(DLL_OBJS) + $(CC) $(OPT) -mthreads -shared -o $(GCE_DLL) $(DLL_OBJS) $(LFLAGS) + dlltool -z pthread.def $(DLL_OBJS) + dlltool -k --dllname $@ --output-lib $(GCE_LIB) --def $(PTHREAD_DEF) + +$(GC_INLINED_STAMP) $(GCD_INLINED_STAMP): $(DLL_INLINED_OBJS) + $(CC) $(OPT) $(XOPT) -shared -o $(GC_DLL) $(DLL_INLINED_OBJS) $(LFLAGS) + dlltool -z pthread.def $(DLL_INLINED_OBJS) + dlltool -k --dllname $(GC_DLL) --output-lib $(GC_LIB) --def $(PTHREAD_DEF) + echo touched > $(GC_INLINED_STAMP) + +$(GCE_INLINED_STAMP) $(GCED_INLINED_STAMP): $(DLL_INLINED_OBJS) + $(CC) $(OPT) $(XOPT) -mthreads -shared -o $(GCE_DLL) $(DLL_INLINED_OBJS) $(LFLAGS) + dlltool -z pthread.def $(DLL_INLINED_OBJS) + dlltool -k --dllname $(GCE_DLL) --output-lib $(GCE_LIB) --def $(PTHREAD_DEF) + echo touched > $(GCE_INLINED_STAMP) + +$(GC_STATIC_STAMP) $(GCD_STATIC_STAMP): $(DLL_INLINED_OBJS) + $(RM) $(GC_LIB) + $(AR) -rv $(GC_LIB) $(DLL_INLINED_OBJS) + echo touched > $(GC_STATIC_STAMP) + +clean: + -$(RM) *~ + -$(RM) *.i + -$(RM) *.o + -$(RM) *.obj + -$(RM) *.exe + -$(RM) $(PTHREAD_DEF) + +realclean: clean + -$(RM) $(GC_LIB) + -$(RM) $(GCE_LIB) + -$(RM) $(GC_DLL) + -$(RM) $(GCE_DLL) + -$(RM) $(GC_INLINED_STAMP) + -$(RM) $(GCE_INLINED_STAMP) + -$(RM) $(GC_STATIC_STAMP) + -$(RM) $(GCD_LIB) + -$(RM) $(GCED_LIB) + -$(RM) $(GCD_DLL) + -$(RM) $(GCED_DLL) + -$(RM) $(GCD_INLINED_STAMP) + -$(RM) $(GCED_INLINED_STAMP) + -$(RM) $(GCD_STATIC_STAMP) + +attr.o: attr.c $(ATTR_SRCS) $(INCL) +barrier.o: barrier.c $(BARRIER_SRCS) $(INCL) +cancel.o: cancel.c $(CANCEL_SRCS) $(INCL) +condvar.o: condvar.c $(CONDVAR_SRCS) $(INCL) +exit.o: exit.c $(EXIT_SRCS) $(INCL) +misc.o: misc.c $(MISC_SRCS) $(INCL) +mutex.o: mutex.c $(MUTEX_SRCS) $(INCL) +nonportable.o: nonportable.c $(NONPORTABLE_SRCS) $(INCL) +private.o: private.c $(PRIVATE_SRCS) $(INCL) +rwlock.o: rwlock.c $(RWLOCK_SRCS) $(INCL) +sched.o: sched.c $(SCHED_SRCS) $(INCL) +semaphore.o: semaphore.c $(SEMAPHORE_SRCS) $(INCL) +spin.o: spin.c $(SPIN_SRCS) $(INCL) +sync.o: sync.c $(SYNC_SRCS) $(INCL) +tsd.o: tsd.c $(TSD_SRCS) $(INCL) +version.o: version.rc $(INCL) diff --git a/Makefile b/Makefile index 7745080..b267b5b 100644 --- a/Makefile +++ b/Makefile @@ -441,8 +441,8 @@ VC-static-debug: @ nmake /nologo EHFLAGS="$(OPTIMD) $(VCFLAGSD) /DPTW32_BUILD_INLINED /DPTW32_STATIC_LIB" CLEANUP=__CLEANUP_C pthreadVC$(DLL_VERD).static realclean: clean - if exist *.dll del *.dll - if exist *.lib del *.lib + if exist pthread*.dll del pthread*.dll + if exist pthread*.lib del pthread*.lib if exist *.stamp del *.stamp clean: diff --git a/NEWS b/NEWS index a7a31e2..a6ad59e 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,34 @@ +RELEASE 2.3.0^M +-------------^M +(2005-04-12)^M +^M +General +------- + +Release 1.7.0 is a backport of features and bug fixes new in +this release. See earlier notes under Release 2.0.0/General. + +Bugs fixed +---------- + +* Fixed pthread_once potential for post once_routine cancellation +hanging due to starvation. See comments in pthread_once.c. +Momentary priority boosting is used to ensure that, after a +once_routine is cancelled, the thread that will run the +once_routine is not starved by higher priority waiting threads at +critical times. Priority boosting occurs only AFTER a once_routine +cancellation, and is applied only to that once_control. The +once_routine is run at the thread's normal base priority. + +New tests +--------- + +* once4.c: Aggressively tests pthread_once() under realtime +conditions using threads with varying priorities. Windows' +random priority boosting does not occur for threads with realtime +priority levels. + + RELEASE 2.2.0 ------------- (2005-04-04) diff --git a/README b/README index c6e8718..a1f896d 100644 --- a/README +++ b/README @@ -1,526 +1,568 @@ -PTHREADS-WIN32 -============== - -Pthreads-win32 is free software, distributed under the GNU Lesser -General Public License (LGPL). See the file 'COPYING.LIB' for terms -and conditions. Also see the file 'COPYING' for information -specific to pthreads-win32, copyrights and the LGPL. - - -What is it? ------------ - -Pthreads-win32 is an Open Source Software implementation of the -Threads component of the POSIX 1003.1c 1995 Standard (or later) -for Microsoft's Win32 environment. Some functions from POSIX -1003.1b are also supported including semaphores. Other related -functions include the set of read-write lock functions. The -library also supports some of the functionality of the Open -Group's Single Unix specification, version 2, namely mutex types, -plus some common and pthreads-win32 specific non-portable -routines (see README.NONPORTABLE). - -See the file "ANNOUNCE" for more information including standards -conformance details and the list of supported and unsupported -routines. - - -Prerequisites -------------- -MSVC or GNU C (MinGW32 MSys development kit) - To build from source. - -QueueUserAPCEx by Panagiotis E. Hadjidoukas - For true async cancelation of threads (including blocked threads). - This is a DLL and Windows driver that provides pre-emptive APC - by forcing threads into an alertable state when the APC is queued. - Both the DLL and driver are provided with the pthreads-win32.exe - self-unpacking ZIP, and on the pthreads-win32 FTP site (in source - and pre-built forms). Currently this is a separate LGPL package to - pthreads-win32. See the README in the QueueUserAPCEx folder for - installation instructions. - - Pthreads-win32 will automatically detect if the QueueUserAPCEx DLL - QuserEx.DLL is available and whether the driver AlertDrv.sys is - loaded. If it is not available, pthreads-win32 will simulate async - cancelation, which means that it cannot pre-empt blocked threads. - - -Library naming --------------- - -Because the library is being built using various exception -handling schemes and compilers - and because the library -may not work reliably if these are mixed in an application, -each different version of the library has it's own name. - -Note 1: the incompatibility is really between EH implementations -of the different compilers. It should be possible to use the -standard C version from either compiler with C++ applications -built with a different compiler. If you use an EH version of -the library, then you must use the same compiler for the -application. This is another complication and dependency that -can be avoided by using only the standard C library version. - -Note 2: if you use a standard C pthread*.dll with a C++ -application, then any functions that you define that are -intended to be called via pthread_cleanup_push() must be -__cdecl. - -Note 3: the intention was to also name either the VC or GC -version (it should be arbitrary) as pthread.dll, including -pthread.lib and libpthread.a as appropriate. This is no longer -likely to happen. - -Note 4: the compatibility number was added so that applications -can differentiate between binary incompatible versions of the -libs and dlls. - -In general: - pthread[VG]{SE,CE,C}c.dll - pthread[VG]{SE,CE,C}c.lib - -where: - [VG] indicates the compiler - V - MS VC, or - G - GNU C - - {SE,CE,C} indicates the exception handling scheme - SE - Structured EH, or - CE - C++ EH, or - C - no exceptions - uses setjmp/longjmp - - c - DLL compatibility number indicating ABI and API - compatibility with applications built against - any snapshot with the same compatibility number. - See 'Version numbering' below. - -For example: - pthreadVSE.dll (MSVC/SEH) - pthreadGCE.dll (GNUC/C++ EH) - pthreadGC.dll (GNUC/not dependent on exceptions) - pthreadVC1.dll (MSVC/not dependent on exceptions - not binary - compatible with pthreadVC.dll) - -The GNU library archive file names have correspondingly changed to: - - libpthreadGCEc.a - libpthreadGCc.a - - -Versioning numbering --------------------- - -Version numbering is separate from the snapshot dating system, and -is the canonical version identification system embedded within the -DLL using the Microsoft version resource system. The versioning -system chosen follows the GNU Libtool system. See -http://www.gnu.org/software/libtool/manual.html section 6.2. - -See the resource file 'version.rc'. - -Microsoft version numbers use 4 integers: - - 0.0.0.0 - -Pthreads-win32 uses the first 3 following the Libtool convention. -The fourth is commonly used for the build number, but will be reserved -for future use. - - current.revision.age.0 - -The numbers are changed as follows: - -1. If the library source code has changed at all since the last update, - then increment revision (`c:r:a' becomes `c:r+1:a'). -2. If any interfaces have been added, removed, or changed since the last - update, increment current, and set revision to 0. -3. If any interfaces have been added since the last public release, then - increment age. -4. If any interfaces have been removed or changed since the last public - release, then set age to 0. - - -DLL compatibility numbering is an attempt to ensure that applications -always load a compatible pthreads-win32 DLL by using a DLL naming system -that is consistent with the version numbering system. It also allows -older and newer DLLs to coexist in the same filesystem so that older -applications can continue to be used. For pre .NET Windows systems, -this inevitably requires incompatible versions of the same DLLs to have -different names. - -Pthreads-win32 has adopted the Cygwin convention of appending a single -integer number to the DLL name. The number used is based on the library -version number and is computed as 'current' - 'age'. - -(See http://home.att.net/~perlspinr/libversioning.html for a nicely -detailed explanation.) - -Using this method, DLL name/s will only change when the DLL's -backwards compatibility changes. Note that the addition of new -'interfaces' will not of itself change the DLL's compatibility for older -applications. - - -Which of the several dll versions to use? ------------------------------------------ -or, ---- -What are all these pthread*.dll and pthread*.lib files? -------------------------------------------------------- - -Simple, use either pthreadGCv.* if you use GCC, or pthreadVCv.* if you -use MSVC - where 'v' is the DLL versioning (compatibility) number. - -Otherwise, you need to choose carefully and know WHY. - -The most important choice you need to make is whether to use a -version that uses exceptions internally, or not. There are versions -of the library that use exceptions as part of the thread -cancelation and exit implementation. The default version uses -setjmp/longjmp. - -There is some contension amongst POSIX threads experts as -to how POSIX threads cancelation and exit should work -with languages that use exceptions, e.g. C++ and even C -(Microsoft's Structured Exceptions). - -The issue is: should cancelation of a thread in, say, -a C++ application cause object destructors and C++ exception -handlers to be invoked as the stack unwinds during thread -exit, or not? - -There seems to be more opinion in favour of using the -standard C version of the library (no EH) with C++ applications -for the reason that this appears to be the assumption commercial -pthreads implementations make. Therefore, if you use an EH version -of pthreads-win32 then you may be under the illusion that -your application will be portable, when in fact it is likely to -behave differently when linked with other pthreads libraries. - -Now you may be asking: then why have you kept the EH versions of -the library? - -There are a couple of reasons: -- there is division amongst the experts and so the code may - be needed in the future. Yes, it's in the repository and we - can get it out anytime in the future, but it would be difficult - to find. -- pthreads-win32 is one of the few implementations, and possibly - the only freely available one, that has EH versions. It may be - useful to people who want to play with or study application - behaviour under these conditions. - -Notes: - -[If you use either pthreadVCE or pthreadGCE] - -1. [See also the discussion in the FAQ file - Q2, Q4, and Q5] - -If your application contains catch(...) blocks in your POSIX -threads then you will need to replace the "catch(...)" with the macro -"PtW32Catch", eg. - - #ifdef PtW32Catch - PtW32Catch { - ... - } - #else - catch(...) { - ... - } - #endif - -Otherwise neither pthreads cancelation nor pthread_exit() will work -reliably when using versions of the library that use C++ exceptions -for cancelation and thread exit. - -This is due to what is believed to be a C++ compliance error in VC++ -whereby you may not have multiple handlers for the same exception in -the same try/catch block. GNU G++ doesn't have this restriction. - - -Other name changes ------------------- - -All snapshots prior to and including snapshot 2000-08-13 -used "_pthread_" as the prefix to library internal -functions, and "_PTHREAD_" to many library internal -macros. These have now been changed to "ptw32_" and "PTW32_" -respectively so as to not conflict with the ANSI standard's -reservation of identifiers beginning with "_" and "__" for -use by compiler implementations only. - -If you have written any applications and you are linking -statically with the pthreads-win32 library then you may have -included a call to _pthread_processInitialize. You will -now have to change that to ptw32_processInitialize. - - -Cleanup code default style --------------------------- - -Previously, if not defined, the cleanup style was determined automatically -from the compiler used, and one of the following was defined accordingly: - - __CLEANUP_SEH MSVC only - __CLEANUP_CXX C++, including MSVC++, GNU G++ - __CLEANUP_C C, including GNU GCC, not MSVC - -These defines determine the style of cleanup (see pthread.h) and, -most importantly, the way that cancelation and thread exit (via -pthread_exit) is performed (see the routine ptw32_throw()). - -In short, the exceptions versions of the library throw an exception -when a thread is canceled, or exits via pthread_exit(). This exception is -caught by a handler in the thread startup routine, so that the -the correct stack unwinding occurs regardless of where the thread -is when it's canceled or exits via pthread_exit(). - -In this snapshot, unless the build explicitly defines (e.g. via a -compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then -the build NOW always defaults to __CLEANUP_C style cleanup. This style -uses setjmp/longjmp in the cancelation and pthread_exit implementations, -and therefore won't do stack unwinding even when linked to applications -that have it (e.g. C++ apps). This is for consistency with most/all -commercial Unix POSIX threads implementations. - -Although it was not clearly documented before, it is still necessary to -build your application using the same __CLEANUP_* define as was -used for the version of the library that you link with, so that the -correct parts of pthread.h are included. That is, the possible -defines require the following library versions: - - __CLEANUP_SEH pthreadVSE.dll - __CLEANUP_CXX pthreadVCE.dll or pthreadGCE.dll - __CLEANUP_C pthreadVC.dll or pthreadGC.dll - -It is recommended that you let pthread.h use it's default __CLEANUP_C -for both library and application builds. That is, don't define any of -the above, and then link with pthreadVC.lib (MSVC or MSVC++) and -libpthreadGC.a (MinGW GCC or G++). The reason is explained below, but -another reason is that the prebuilt pthreadVCE.dll is currently broken. -Versions built with MSVC++ later than version 6 may not be broken, but I -can't verify this yet. - -WHY ARE WE MAKING THE DEFAULT STYLE LESS EXCEPTION-FRIENDLY? -Because no commercial Unix POSIX threads implementation allows you to -choose to have stack unwinding. Therefore, providing it in pthread-win32 -as a default is dangerous. We still provide the choice but unless -you consciously choose to do otherwise, your pthreads applications will -now run or crash in similar ways irrespective of the pthreads platform -you use. Or at least this is the hope. - - -Building under VC++ using C++ EH, Structured EH, or just C ----------------------------------------------------------- - -From the source directory run one of the following: - -nmake clean VC-inlined (builds the VC setjmp/longjmp version of -pthreadVC.dll) - -or: - -nmake clean VCE-inlined (builds the VC++ C++ EH version pthreadVCE.dll) - -or: - -nmake clean VSE-inlined (builds the VC++ structured EH version -pthreadVSE.dll) - -You can run the testsuite by changing to the "tests" directory and -running the target corresponding to the DLL version you built: - -nmake clean VC - -or: - -nmake clean VCE - -or: - -nmake clean VSE - -or: - -nmake clean VCX (tests the VC version of the library with C++ (EH) - applications) - - -Building under Mingw32 ----------------------- - -The dll can be built easily with recent versions of Mingw32. -(The distributed versions are built using Mingw32 and MsysDTK -from www.mingw32.org.) - -From the source directory, run - -make clean GC-inlined - -or: - -make clean GCE-inlined - -You can run the testsuite by changing to the "tests" directory and -running - -make clean GC - -or: - -make clean GCE - -or: - -make clean GCX (tests the GC version of the library with C++ (EH) - applications) - - -Building the library as a statically linkable library ------------------------------------------------------ - -General: PTW32_STATIC_LIB must be defined for both the library build and the -application build. The following 'make' command lines define this for the -library build. - -MSVC (creates pthreadVCn.lib as a static link lib): -nmake clean VC-static - -MinGW32 (creates libpthreadGCn.a as a static link lib): -make clean GC-static - -Define PTW32_STATIC_LIB when building your application. - - -Building the library under Cygwin ---------------------------------- - -Cygwin is implementing it's own POSIX threads routines and these -will be the ones to use if you develop using Cygwin. - - -Ready to run binaries ---------------------- - -For convenience, the following ready-to-run files can be downloaded -from the FTP site (see under "Availability" below): - - pthread.h - semaphore.h - sched.h - pthreadVC.dll - built with MSVC compiler using C setjmp/longjmp - pthreadVC.lib - pthreadVCE.dll - built with MSVC++ compiler using C++ EH - pthreadVCE.lib - pthreadVSE.dll - built with MSVC compiler using SEH - pthreadVSE.lib - pthreadGC.dll - built with Mingw32 GCC - libpthreadGC.a - derived from pthreadGC.dll - pthreadGCE.dll - built with Mingw32 G++ - libpthreadGCE.a - derived from pthreadGCE.dll - -As of August 2003 pthreads-win32 pthreadG* versions are built and tested -using the MinGW + MsysDTK environment current as of that date or later. -The following file MAY be needed for older MinGW environments. - - gcc.dll - needed to build and run applications that use - pthreadGCE.dll. - - -Building applications with GNU compilers ----------------------------------------- - -If you're using pthreadGC.dll: - -With the three header files, pthreadGC.dll and libpthreadGC.a in the -same directory as your application myapp.c, you could compile, link -and run myapp.c under Mingw32 as follows: - - gcc -o myapp.exe myapp.c -I. -L. -lpthreadGC - myapp - -Or put pthreadGC.dll in an appropriate directory in your PATH, -put libpthreadGC.a in your system lib directory, and -put the three header files in your system include directory, -then use: - - gcc -o myapp.exe myapp.c -lpthreadGC - myapp - - -If you're using pthreadGCE.dll: - -With the three header files, pthreadGCE.dll, gcc.dll and libpthreadGCE.a -in the same directory as your application myapp.c, you could compile, -link and run myapp.c under Mingw32 as follows: - - gcc -x c++ -o myapp.exe myapp.c -I. -L. -lpthreadGCE - myapp - -Or put pthreadGCE.dll and gcc.dll in an appropriate directory in -your PATH, put libpthreadGCE.a in your system lib directory, and -put the three header files in your system include directory, -then use: - - gcc -x c++ -o myapp.exe myapp.c -lpthreadGCE - myapp - - -Availability ------------- - -The complete source code in either unbundled, self-extracting -Zip file, or tar/gzipped format can be found at: - - ftp://sources.redhat.com/pub/pthreads-win32 - -The pre-built DLL, export libraries and matching pthread.h can -be found at: - - ftp://sources.redhat.com/pub/pthreads-win32/dll-latest - -Home page: - - http://sources.redhat.com/pthreads-win32/ - - -Mailing list ------------- - -There is a mailing list for discussing pthreads on Win32. -To join, send email to: - - pthreads-win32-subscribe@sources.redhat.com - -Unsubscribe by sending mail to: - - pthreads-win32-unsubscribe@sources.redhat.com - - -Acknowledgements ----------------- - -See the ANNOUNCE file for acknowledgements. -See the 'CONTRIBUTORS' file for the list of contributors. - -As much as possible, the ChangeLog file attributes -contributions and patches that have been incorporated -in the library to the individuals responsible. - -Finally, thanks to all those who work on and contribute to the -POSIX and Single Unix Specification standards. The maturity of an -industry can be measured by it's open standards. - ----- -Ross Johnson - - - - - - - - - +PTHREADS-WIN32 +============== + +Pthreads-win32 is free software, distributed under the GNU Lesser +General Public License (LGPL). See the file 'COPYING.LIB' for terms +and conditions. Also see the file 'COPYING' for information +specific to pthreads-win32, copyrights and the LGPL. + + +What is it? +----------- + +Pthreads-win32 is an Open Source Software implementation of the +Threads component of the POSIX 1003.1c 1995 Standard (or later) +for Microsoft's Win32 environment. Some functions from POSIX +1003.1b are also supported including semaphores. Other related +functions include the set of read-write lock functions. The +library also supports some of the functionality of the Open +Group's Single Unix specification, version 2, namely mutex types, +plus some common and pthreads-win32 specific non-portable +routines (see README.NONPORTABLE). + +See the file "ANNOUNCE" for more information including standards +conformance details and the list of supported and unsupported +routines. + + +Prerequisites +------------- +MSVC or GNU C (MinGW32 MSys development kit) + To build from source. + +QueueUserAPCEx by Panagiotis E. Hadjidoukas + For true async cancelation of threads (including blocked threads). + This is a DLL and Windows driver that provides pre-emptive APC + by forcing threads into an alertable state when the APC is queued. + Both the DLL and driver are provided with the pthreads-win32.exe + self-unpacking ZIP, and on the pthreads-win32 FTP site (in source + and pre-built forms). Currently this is a separate LGPL package to + pthreads-win32. See the README in the QueueUserAPCEx folder for + installation instructions. + + Pthreads-win32 will automatically detect if the QueueUserAPCEx DLL + QuserEx.DLL is available and whether the driver AlertDrv.sys is + loaded. If it is not available, pthreads-win32 will simulate async + cancelation, which means that it can async cancel only threads that + are runnable. The simulated async cancellation cannot cancel blocked + threads. + + +Library naming +-------------- + +Because the library is being built using various exception +handling schemes and compilers - and because the library +may not work reliably if these are mixed in an application, +each different version of the library has it's own name. + +Note 1: the incompatibility is really between EH implementations +of the different compilers. It should be possible to use the +standard C version from either compiler with C++ applications +built with a different compiler. If you use an EH version of +the library, then you must use the same compiler for the +application. This is another complication and dependency that +can be avoided by using only the standard C library version. + +Note 2: if you use a standard C pthread*.dll with a C++ +application, then any functions that you define that are +intended to be called via pthread_cleanup_push() must be +__cdecl. + +Note 3: the intention was to also name either the VC or GC +version (it should be arbitrary) as pthread.dll, including +pthread.lib and libpthread.a as appropriate. This is no longer +likely to happen. + +Note 4: the compatibility number was added so that applications +can differentiate between binary incompatible versions of the +libs and dlls. + +In general: + pthread[VG]{SE,CE,C}c.dll + pthread[VG]{SE,CE,C}c.lib + +where: + [VG] indicates the compiler + V - MS VC, or + G - GNU C + + {SE,CE,C} indicates the exception handling scheme + SE - Structured EH, or + CE - C++ EH, or + C - no exceptions - uses setjmp/longjmp + + c - DLL compatibility number indicating ABI and API + compatibility with applications built against + any snapshot with the same compatibility number. + See 'Version numbering' below. + +The name may also be suffixed by a 'd' to indicate a debugging version +of the library. E.g. pthreadVC2d.lib. Debugging versions contain +additional information for debugging (symbols etc) and are often not +optimised in any way (compiled with optimisation turned off). + +For example: + pthreadVSE.dll (MSVC/SEH) + pthreadGCE.dll (GNUC/C++ EH) + pthreadGC.dll (GNUC/not dependent on exceptions) + pthreadVC1.dll (MSVC/not dependent on exceptions - not binary + compatible with pthreadVC.dll) + pthreadVC2.dll (MSVC/not dependent on exceptions - not binary + compatible with pthreadVC1.dll or pthreadVC.dll) + +The GNU library archive file names have correspondingly changed to: + + libpthreadGCEc.a + libpthreadGCc.a + + +Versioning numbering +-------------------- + +Version numbering is separate from the snapshot dating system, and +is the canonical version identification system embedded within the +DLL using the Microsoft version resource system. The versioning +system chosen follows the GNU Libtool system. See +http://www.gnu.org/software/libtool/manual.html section 6.2. + +See the resource file 'version.rc'. + +Microsoft version numbers use 4 integers: + + 0.0.0.0 + +Pthreads-win32 uses the first 3 following the Libtool convention. +The fourth is commonly used for the build number, but will be reserved +for future use. + + current.revision.age.0 + +The numbers are changed as follows: + +1. If the library source code has changed at all since the last update, + then increment revision (`c:r:a' becomes `c:r+1:a'). +2. If any interfaces have been added, removed, or changed since the last + update, increment current, and set revision to 0. +3. If any interfaces have been added since the last public release, then + increment age. +4. If any interfaces have been removed or changed since the last public + release, then set age to 0. + + +DLL compatibility numbering is an attempt to ensure that applications +always load a compatible pthreads-win32 DLL by using a DLL naming system +that is consistent with the version numbering system. It also allows +older and newer DLLs to coexist in the same filesystem so that older +applications can continue to be used. For pre .NET Windows systems, +this inevitably requires incompatible versions of the same DLLs to have +different names. + +Pthreads-win32 has adopted the Cygwin convention of appending a single +integer number to the DLL name. The number used is based on the library +version number and is computed as 'current' - 'age'. + +(See http://home.att.net/~perlspinr/libversioning.html for a nicely +detailed explanation.) + +Using this method, DLL name/s will only change when the DLL's +backwards compatibility changes. Note that the addition of new +'interfaces' will not of itself change the DLL's compatibility for older +applications. + + +Which of the several dll versions to use? +----------------------------------------- +or, +--- +What are all these pthread*.dll and pthread*.lib files? +------------------------------------------------------- + +Simple, use either pthreadGCv.* if you use GCC, or pthreadVCv.* if you +use MSVC - where 'v' is the DLL versioning (compatibility) number. + +Otherwise, you need to choose carefully and know WHY. + +The most important choice you need to make is whether to use a +version that uses exceptions internally, or not. There are versions +of the library that use exceptions as part of the thread +cancelation and exit implementation. The default version uses +setjmp/longjmp. + +There is some contension amongst POSIX threads experts as +to how POSIX threads cancelation and exit should work +with languages that use exceptions, e.g. C++ and even C +(Microsoft's Structured Exceptions). + +The issue is: should cancelation of a thread in, say, +a C++ application cause object destructors and C++ exception +handlers to be invoked as the stack unwinds during thread +exit, or not? + +There seems to be more opinion in favour of using the +standard C version of the library (no EH) with C++ applications +for the reason that this appears to be the assumption commercial +pthreads implementations make. Therefore, if you use an EH version +of pthreads-win32 then you may be under the illusion that +your application will be portable, when in fact it is likely to +behave differently when linked with other pthreads libraries. + +Now you may be asking: then why have you kept the EH versions of +the library? + +There are a couple of reasons: +- there is division amongst the experts and so the code may + be needed in the future. Yes, it's in the repository and we + can get it out anytime in the future, but it would be difficult + to find. +- pthreads-win32 is one of the few implementations, and possibly + the only freely available one, that has EH versions. It may be + useful to people who want to play with or study application + behaviour under these conditions. + +Notes: + +[If you use either pthreadVCE or pthreadGCE] + +1. [See also the discussion in the FAQ file - Q2, Q4, and Q5] + +If your application contains catch(...) blocks in your POSIX +threads then you will need to replace the "catch(...)" with the macro +"PtW32Catch", eg. + + #ifdef PtW32Catch + PtW32Catch { + ... + } + #else + catch(...) { + ... + } + #endif + +Otherwise neither pthreads cancelation nor pthread_exit() will work +reliably when using versions of the library that use C++ exceptions +for cancelation and thread exit. + +This is due to what is believed to be a C++ compliance error in VC++ +whereby you may not have multiple handlers for the same exception in +the same try/catch block. GNU G++ doesn't have this restriction. + + +Other name changes +------------------ + +All snapshots prior to and including snapshot 2000-08-13 +used "_pthread_" as the prefix to library internal +functions, and "_PTHREAD_" to many library internal +macros. These have now been changed to "ptw32_" and "PTW32_" +respectively so as to not conflict with the ANSI standard's +reservation of identifiers beginning with "_" and "__" for +use by compiler implementations only. + +If you have written any applications and you are linking +statically with the pthreads-win32 library then you may have +included a call to _pthread_processInitialize. You will +now have to change that to ptw32_processInitialize. + + +Cleanup code default style +-------------------------- + +Previously, if not defined, the cleanup style was determined automatically +from the compiler used, and one of the following was defined accordingly: + + __CLEANUP_SEH MSVC only + __CLEANUP_CXX C++, including MSVC++, GNU G++ + __CLEANUP_C C, including GNU GCC, not MSVC + +These defines determine the style of cleanup (see pthread.h) and, +most importantly, the way that cancelation and thread exit (via +pthread_exit) is performed (see the routine ptw32_throw()). + +In short, the exceptions versions of the library throw an exception +when a thread is canceled, or exits via pthread_exit(). This exception is +caught by a handler in the thread startup routine, so that the +the correct stack unwinding occurs regardless of where the thread +is when it's canceled or exits via pthread_exit(). + +In this snapshot, unless the build explicitly defines (e.g. via a +compiler option) __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then +the build NOW always defaults to __CLEANUP_C style cleanup. This style +uses setjmp/longjmp in the cancelation and pthread_exit implementations, +and therefore won't do stack unwinding even when linked to applications +that have it (e.g. C++ apps). This is for consistency with most/all +commercial Unix POSIX threads implementations. + +Although it was not clearly documented before, it is still necessary to +build your application using the same __CLEANUP_* define as was +used for the version of the library that you link with, so that the +correct parts of pthread.h are included. That is, the possible +defines require the following library versions: + + __CLEANUP_SEH pthreadVSE.dll + __CLEANUP_CXX pthreadVCE.dll or pthreadGCE.dll + __CLEANUP_C pthreadVC.dll or pthreadGC.dll + +It is recommended that you let pthread.h use it's default __CLEANUP_C +for both library and application builds. That is, don't define any of +the above, and then link with pthreadVC.lib (MSVC or MSVC++) and +libpthreadGC.a (MinGW GCC or G++). The reason is explained below, but +another reason is that the prebuilt pthreadVCE.dll is currently broken. +Versions built with MSVC++ later than version 6 may not be broken, but I +can't verify this yet. + +WHY ARE WE MAKING THE DEFAULT STYLE LESS EXCEPTION-FRIENDLY? +Because no commercial Unix POSIX threads implementation allows you to +choose to have stack unwinding. Therefore, providing it in pthread-win32 +as a default is dangerous. We still provide the choice but unless +you consciously choose to do otherwise, your pthreads applications will +now run or crash in similar ways irrespective of the pthreads platform +you use. Or at least this is the hope. + + +Building under VC++ using C++ EH, Structured EH, or just C +---------------------------------------------------------- + +From the source directory run nmake without any arguments to list +help information. E.g. + +$ nmake + +Microsoft (R) Program Maintenance Utility Version 6.00.8168.0 +Copyright (C) Microsoft Corp 1988-1998. All rights reserved. + +Run one of the following command lines: +nmake clean VCE (to build the MSVC dll with C++ exception handling) +nmake clean VSE (to build the MSVC dll with structured exception handling) +nmake clean VC (to build the MSVC dll with C cleanup code) +nmake clean VCE-inlined (to build the MSVC inlined dll with C++ exception handling) +nmake clean VSE-inlined (to build the MSVC inlined dll with structured exception handling) +nmake clean VC-inlined (to build the MSVC inlined dll with C cleanup code) +nmake clean VC-static (to build the MSVC static lib with C cleanup code) +nmake clean VCE-debug (to build the debug MSVC dll with C++ exception handling) +nmake clean VSE-debug (to build the debug MSVC dll with structured exception handling) +nmake clean VC-debug (to build the debug MSVC dll with C cleanup code) +nmake clean VCE-inlined-debug (to build the debug MSVC inlined dll with C++ exception handling) +nmake clean VSE-inlined-debug (to build the debug MSVC inlined dll with structured exception handling) +nmake clean VC-inlined-debug (to build the debug MSVC inlined dll with C cleanup code) +nmake clean VC-static-debug (to build the debug MSVC static lib with C cleanup code) + + +The pre-built dlls are normally built using the *-inlined targets. + +You can run the testsuite by changing to the "tests" directory and +running nmake. E.g.: + +$ cd tests +$ nmake + +Microsoft (R) Program Maintenance Utility Version 6.00.8168.0 +Copyright (C) Microsoft Corp 1988-1998. All rights reserved. + +Run one of the following command lines: +nmake clean VC (to test using VC dll with VC (no EH) applications) +nmake clean VCX (to test using VC dll with VC++ (EH) applications) +nmake clean VCE (to test using the VCE dll with VC++ EH applications) +nmake clean VSE (to test using VSE dll with VC (SEH) applications) +nmake clean VC-bench (to benchtest using VC dll with C bench app) +nmake clean VCX-bench (to benchtest using VC dll with C++ bench app) +nmake clean VCE-bench (to benchtest using VCE dll with C++ bench app) +nmake clean VSE-bench (to benchtest using VSE dll with SEH bench app) +nmake clean VC-static (to test using VC static lib with VC (no EH) applications) + + +Building under Mingw32 +---------------------- + +The dll can be built easily with recent versions of Mingw32. +(The distributed versions are built using Mingw32 and MsysDTK +from www.mingw32.org.) + +From the source directory, run make for help information. E.g.: + +$ make +Run one of the following command lines: +make clean GC (to build the GNU C dll with C cleanup code) +make clean GCE (to build the GNU C dll with C++ exception handling) +make clean GC-inlined (to build the GNU C inlined dll with C cleanup code) +make clean GCE-inlined (to build the GNU C inlined dll with C++ exception handling) +make clean GC-static (to build the GNU C inlined static lib with C cleanup code) +make clean GC-debug (to build the GNU C debug dll with C cleanup code) +make clean GCE-debug (to build the GNU C debug dll with C++ exception handling) +make clean GC-inlined-debug (to build the GNU C inlined debug dll with C cleanup code) +make clean GCE-inlined-debug (to build the GNU C inlined debug dll with C++ exception handling) +make clean GC-static-debug (to build the GNU C inlined static debug lib with C cleanup code) + + +The pre-built dlls are normally built using the *-inlined targets. + +You can run the testsuite by changing to the "tests" directory and +running make for help information. E.g.: + +$ cd tests +$ make +Run one of the following command lines: +make clean GC (to test using GC dll with C (no EH) applications) +make clean GCX (to test using GC dll with C++ (EH) applications) +make clean GCE (to test using GCE dll with C++ (EH) applications) +make clean GC-bench (to benchtest using GNU C dll with C cleanup code) +make clean GCE-bench (to benchtest using GNU C dll with C++ exception handling) +make clean GC-static (to test using GC static lib with C (no EH) applications) + + +Building the library as a statically linkable library +----------------------------------------------------- + +General: PTW32_STATIC_LIB must be defined for both the library build and the +application build. The following 'make' command lines will define this for the +static library builds. + +MSVC (creates pthreadVCnd.lib as a static link lib): + +nmake clean VC-static + + +MinGW32 (creates libpthreadGCn.a as a static link lib): + +make clean GC-static + + +Define PTW32_STATIC_LIB when building your application. + +The tests makefiles have the same targets but only check that the +static library is statically linkable. They don't run the full +testsuite. To run the full testsuite, build the dlls and run the +dll test targets. + + +Building the library under Cygwin +--------------------------------- + +Cygwin is implementing it's own POSIX threads routines and these +will be the ones to use if you develop using Cygwin. + + +Ready to run binaries +--------------------- + +For convenience, the following ready-to-run files can be downloaded +from the FTP site (see under "Availability" below): + + pthread.h + semaphore.h + sched.h + pthreadVC.dll - built with MSVC compiler using C setjmp/longjmp + pthreadVC.lib + pthreadVCE.dll - built with MSVC++ compiler using C++ EH + pthreadVCE.lib + pthreadVSE.dll - built with MSVC compiler using SEH + pthreadVSE.lib + pthreadGC.dll - built with Mingw32 GCC + libpthreadGC.a - derived from pthreadGC.dll + pthreadGCE.dll - built with Mingw32 G++ + libpthreadGCE.a - derived from pthreadGCE.dll + +As of August 2003 pthreads-win32 pthreadG* versions are built and tested +using the MinGW + MsysDTK environment current as of that date or later. +The following file MAY be needed for older MinGW environments. + + gcc.dll - needed to build and run applications that use + pthreadGCE.dll. + + +Building applications with GNU compilers +---------------------------------------- + +If you're using pthreadGC.dll: + +With the three header files, pthreadGC.dll and libpthreadGC.a in the +same directory as your application myapp.c, you could compile, link +and run myapp.c under Mingw32 as follows: + + gcc -o myapp.exe myapp.c -I. -L. -lpthreadGC + myapp + +Or put pthreadGC.dll in an appropriate directory in your PATH, +put libpthreadGC.a in your system lib directory, and +put the three header files in your system include directory, +then use: + + gcc -o myapp.exe myapp.c -lpthreadGC + myapp + + +If you're using pthreadGCE.dll: + +With the three header files, pthreadGCE.dll, gcc.dll and libpthreadGCE.a +in the same directory as your application myapp.c, you could compile, +link and run myapp.c under Mingw32 as follows: + + gcc -x c++ -o myapp.exe myapp.c -I. -L. -lpthreadGCE + myapp + +Or put pthreadGCE.dll and gcc.dll in an appropriate directory in +your PATH, put libpthreadGCE.a in your system lib directory, and +put the three header files in your system include directory, +then use: + + gcc -x c++ -o myapp.exe myapp.c -lpthreadGCE + myapp + + +Availability +------------ + +The complete source code in either unbundled, self-extracting +Zip file, or tar/gzipped format can be found at: + + ftp://sources.redhat.com/pub/pthreads-win32 + +The pre-built DLL, export libraries and matching pthread.h can +be found at: + + ftp://sources.redhat.com/pub/pthreads-win32/dll-latest + +Home page: + + http://sources.redhat.com/pthreads-win32/ + + +Mailing list +------------ + +There is a mailing list for discussing pthreads on Win32. +To join, send email to: + + pthreads-win32-subscribe@sources.redhat.com + +Unsubscribe by sending mail to: + + pthreads-win32-unsubscribe@sources.redhat.com + + +Acknowledgements +---------------- + +See the ANNOUNCE file for acknowledgements. +See the 'CONTRIBUTORS' file for the list of contributors. + +As much as possible, the ChangeLog file attributes +contributions and patches that have been incorporated +in the library to the individuals responsible. + +Finally, thanks to all those who work on and contribute to the +POSIX and Single Unix Specification standards. The maturity of an +industry can be measured by it's open standards. + +---- +Ross Johnson + + + + + + + + + diff --git a/pthread.h b/pthread.h index 9e7b2ef..f50a6a1 100644 --- a/pthread.h +++ b/pthread.h @@ -1,1391 +1,1391 @@ -/* This is an implementation of the threads API of POSIX 1003.1-2001. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if !defined( PTHREAD_H ) -#define PTHREAD_H - -/* - * See the README file for an explanation of the pthreads-win32 version - * numbering scheme and how the DLL is named etc. - */ -#define PTW32_VERSION 2,2,0,0 -#define PTW32_VERSION_STRING "2, 2, 0, 0\0" - -/* There are three implementations of cancel cleanup. - * Note that pthread.h is included in both application - * compilation units and also internally for the library. - * The code here and within the library aims to work - * for all reasonable combinations of environments. - * - * The three implementations are: - * - * WIN32 SEH - * C - * C++ - * - * Please note that exiting a push/pop block via - * "return", "exit", "break", or "continue" will - * lead to different behaviour amongst applications - * depending upon whether the library was built - * using SEH, C++, or C. For example, a library built - * with SEH will call the cleanup routine, while both - * C++ and C built versions will not. - */ - -/* - * Define defaults for cleanup code. - * Note: Unless the build explicitly defines one of the following, then - * we default to standard C style cleanup. This style uses setjmp/longjmp - * in the cancelation and thread exit implementations and therefore won't - * do stack unwinding if linked to applications that have it (e.g. - * C++ apps). This is currently consistent with most/all commercial Unix - * POSIX threads implementations. - */ -#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) -# define __CLEANUP_C -#endif - -#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) -#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. -#endif - -/* - * Stop here if we are being included by the resource compiler. - */ -#ifndef RC_INVOKED - -#undef PTW32_LEVEL - -#if defined(_POSIX_SOURCE) -#define PTW32_LEVEL 0 -/* Early POSIX */ -#endif - -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 -#undef PTW32_LEVEL -#define PTW32_LEVEL 1 -/* Include 1b, 1c and 1d */ -#endif - -#if defined(INCLUDE_NP) -#undef PTW32_LEVEL -#define PTW32_LEVEL 2 -/* Include Non-Portable extensions */ -#endif - -#define PTW32_LEVEL_MAX 3 - -#if !defined(PTW32_LEVEL) -#define PTW32_LEVEL PTW32_LEVEL_MAX -/* Include everything */ -#endif - -#ifdef _UWIN -# define HAVE_STRUCT_TIMESPEC 1 -# define HAVE_SIGNAL_H 1 -# undef HAVE_CONFIG_H -# pragma comment(lib, "pthread") -#endif - -/* - * ------------------------------------------------------------- - * - * - * Module: pthread.h - * - * Purpose: - * Provides an implementation of PThreads based upon the - * standard: - * - * POSIX 1003.1-2001 - * and - * The Single Unix Specification version 3 - * - * (these two are equivalent) - * - * in order to enhance code portability between Windows, - * various commercial Unix implementations, and Linux. - * - * See the ANNOUNCE file for a full list of conforming - * routines and defined constants, and a list of missing - * routines and constants not defined in this implementation. - * - * Authors: - * There have been many contributors to this library. - * The initial implementation was contributed by - * John Bossom, and several others have provided major - * sections or revisions of parts of the implementation. - * Often significant effort has been contributed to - * find and fix important bugs and other problems to - * improve the reliability of the library, which sometimes - * is not reflected in the amount of code which changed as - * result. - * As much as possible, the contributors are acknowledged - * in the ChangeLog file in the source code distribution - * where their changes are noted in detail. - * - * Contributors are listed in the CONTRIBUTORS file. - * - * As usual, all bouquets go to the contributors, and all - * brickbats go to the project maintainer. - * - * Maintainer: - * The code base for this project is coordinated and - * eventually pre-tested, packaged, and made available by - * - * Ross Johnson - * - * QA Testers: - * Ultimately, the library is tested in the real world by - * a host of competent and demanding scientists and - * engineers who report bugs and/or provide solutions - * which are then fixed or incorporated into subsequent - * versions of the library. Each time a bug is fixed, a - * test case is written to prove the fix and ensure - * that later changes to the code don't reintroduce the - * same error. The number of test cases is slowly growing - * and therefore so is the code reliability. - * - * Compliance: - * See the file ANNOUNCE for the list of implemented - * and not-implemented routines and defined options. - * Of course, these are all defined is this file as well. - * - * Web site: - * The source code and other information about this library - * are available from - * - * http://sources.redhat.com/pthreads-win32/ - * - * ------------------------------------------------------------- - */ - -/* Try to avoid including windows.h */ -#if defined(__MINGW32__) && defined(__cplusplus) -/* - * FIXME: The pthreadGCE.dll build gets linker unresolved errors - * on pthread_key_create() unless windows.h is included here. - * It appears to have something to do with an argument type mismatch. - * Looking at tsd.o with 'nm' shows this line: - * 00000000 T _pthread_key_create__FPP14pthread_key_t_PFPv_v - * instead of - * 00000000 T _pthread_key_create - */ -#define PTW32_INCLUDE_WINDOWS_H -#endif - -#ifdef PTW32_INCLUDE_WINDOWS_H -#include -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) -/* - * VC++6.0 or early compiler's header has no DWORD_PTR type. - */ -typedef unsigned long DWORD_PTR; -#endif -/* - * ----------------- - * autoconf switches - * ----------------- - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif /* HAVE_CONFIG_H */ - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - -/* Try to avoid including windows.h */ -#if defined(__MINGW32__) && defined(__cplusplus) -/* - * FIXME: The pthreadGCE.dll build gets linker unresolved errors - * on pthread_key_create() unless windows.h is included here. - * It appears to have something to do with an argument type mismatch. - * Looking at tsd.o with 'nm' shows this line: - * 00000000 T _pthread_key_create__FPP14pthread_key_t_PFPv_v - * instead of - * 00000000 T _pthread_key_create - */ -#define PTW32_INCLUDE_WINDOWS_H -#endif - -#ifdef PTW32_INCLUDE_WINDOWS_H -#include -#endif - -#ifndef NEED_FTIME -#include -#else /* NEED_FTIME */ -/* use native WIN32 time API */ -#endif /* NEED_FTIME */ - -#if HAVE_SIGNAL_H -#include -#endif /* HAVE_SIGNAL_H */ - -#include -#include - -/* - * Boolean values to make us independent of system includes. - */ -enum { - PTW32_FALSE = 0, - PTW32_TRUE = (! PTW32_FALSE) -}; - -/* - * This is a duplicate of what is in the autoconf config.h, - * which is only used when building the pthread-win32 libraries. - */ - -#ifndef PTW32_CONFIG_H -# if defined(WINCE) -# define NEED_ERRNO -# define NEED_SEM -# endif -# if defined(_UWIN) || defined(__MINGW32__) -# define HAVE_MODE_T -# endif -#endif - -/* - * - */ - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX -#ifdef NEED_ERRNO -#include "need_errno.h" -#else -#include -#endif -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Several systems don't define some error numbers. - */ -#ifndef ENOTSUP -# define ENOTSUP 48 /* This is the value in Solaris. */ -#endif - -#ifndef ETIMEDOUT -# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ -#endif - -#ifndef ENOSYS -# define ENOSYS 140 /* Semi-arbitrary value */ -#endif - -#ifndef EDEADLK -# ifdef EDEADLOCK -# define EDEADLK EDEADLOCK -# else -# define EDEADLK 36 /* This is the value in MSVC. */ -# endif -#endif - -#include - -/* - * To avoid including windows.h we define only those things that we - * actually need from it. I don't like the potential incompatibility that - * this creates with future versions of windows. - */ -#ifndef PTW32_INCLUDE_WINDOWS_H -#ifndef HANDLE -# define PTW32__HANDLE_DEF -# define HANDLE void * -#endif -#ifndef DWORD -# define PTW32__DWORD_DEF -# define DWORD unsigned long -#endif -#endif - -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -#ifndef HAVE_STRUCT_TIMESPEC -#define HAVE_STRUCT_TIMESPEC 1 -struct timespec { - long tv_sec; - long tv_nsec; -}; -#endif /* HAVE_STRUCT_TIMESPEC */ - -#ifndef SIG_BLOCK -#define SIG_BLOCK 0 -#endif /* SIG_BLOCK */ - -#ifndef SIG_UNBLOCK -#define SIG_UNBLOCK 1 -#endif /* SIG_UNBLOCK */ - -#ifndef SIG_SETMASK -#define SIG_SETMASK 2 -#endif /* SIG_SETMASK */ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -/* - * ------------------------------------------------------------- - * - * POSIX 1003.1-2001 Options - * ========================= - * - * Options are normally set in , which is not provided - * with pthreads-win32. - * - * For conformance with the Single Unix Specification (version 3), all of the - * options below are defined, and have a value of either -1 (not supported) - * or 200112L (supported). - * - * These options can neither be left undefined nor have a value of 0, because - * either indicates that sysconf(), which is not implemented, may be used at - * runtime to check the status of the option. - * - * _POSIX_THREADS (== 200112L) - * If == 200112L, you can use threads - * - * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) - * If == 200112L, you can control the size of a thread's - * stack - * pthread_attr_getstacksize - * pthread_attr_setstacksize - * - * _POSIX_THREAD_ATTR_STACKADDR (== -1) - * If == 200112L, you can allocate and control a thread's - * stack. If not supported, the following functions - * will return ENOSYS, indicating they are not - * supported: - * pthread_attr_getstackaddr - * pthread_attr_setstackaddr - * - * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) - * If == 200112L, you can use realtime scheduling. - * This option indicates that the behaviour of some - * implemented functions conforms to the additional TPS - * requirements in the standard. E.g. rwlocks favour - * writers over readers when threads have equal priority. - * - * _POSIX_THREAD_PRIO_INHERIT (== -1) - * If == 200112L, you can create priority inheritance - * mutexes. - * pthread_mutexattr_getprotocol + - * pthread_mutexattr_setprotocol + - * - * _POSIX_THREAD_PRIO_PROTECT (== -1) - * If == 200112L, you can create priority ceiling mutexes - * Indicates the availability of: - * pthread_mutex_getprioceiling - * pthread_mutex_setprioceiling - * pthread_mutexattr_getprioceiling - * pthread_mutexattr_getprotocol + - * pthread_mutexattr_setprioceiling - * pthread_mutexattr_setprotocol + - * - * _POSIX_THREAD_PROCESS_SHARED (== -1) - * If set, you can create mutexes and condition - * variables that can be shared with another - * process.If set, indicates the availability - * of: - * pthread_mutexattr_getpshared - * pthread_mutexattr_setpshared - * pthread_condattr_getpshared - * pthread_condattr_setpshared - * - * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) - * If == 200112L you can use the special *_r library - * functions that provide thread-safe behaviour - * - * _POSIX_READER_WRITER_LOCKS (== 200112L) - * If == 200112L, you can use read/write locks - * - * _POSIX_SPIN_LOCKS (== 200112L) - * If == 200112L, you can use spin locks - * - * _POSIX_BARRIERS (== 200112L) - * If == 200112L, you can use barriers - * - * + These functions provide both 'inherit' and/or - * 'protect' protocol, based upon these macro - * settings. - * - * ------------------------------------------------------------- - */ - -/* - * POSIX Options - */ -#undef _POSIX_THREADS -#define _POSIX_THREADS 200112L - -#undef _POSIX_READER_WRITER_LOCKS -#define _POSIX_READER_WRITER_LOCKS 200112L - -#undef _POSIX_SPIN_LOCKS -#define _POSIX_SPIN_LOCKS 200112L - -#undef _POSIX_BARRIERS -#define _POSIX_BARRIERS 200112L - -#undef _POSIX_THREAD_SAFE_FUNCTIONS -#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L - -#undef _POSIX_THREAD_ATTR_STACKSIZE -#define _POSIX_THREAD_ATTR_STACKSIZE 200112L - -/* - * The following options are not supported - */ -#undef _POSIX_THREAD_ATTR_STACKADDR -#define _POSIX_THREAD_ATTR_STACKADDR -1 - -#undef _POSIX_THREAD_PRIO_INHERIT -#define _POSIX_THREAD_PRIO_INHERIT -1 - -#undef _POSIX_THREAD_PRIO_PROTECT -#define _POSIX_THREAD_PRIO_PROTECT -1 - -/* TPS is not fully supported. */ -#undef _POSIX_THREAD_PRIORITY_SCHEDULING -#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 - -#undef _POSIX_THREAD_PROCESS_SHARED -#define _POSIX_THREAD_PROCESS_SHARED -1 - - -/* - * POSIX 1003.1-2001 Limits - * =========================== - * - * These limits are normally set in , which is not provided with - * pthreads-win32. - * - * PTHREAD_DESTRUCTOR_ITERATIONS - * Maximum number of attempts to destroy - * a thread's thread-specific data on - * termination (must be at least 4) - * - * PTHREAD_KEYS_MAX - * Maximum number of thread-specific data keys - * available per process (must be at least 128) - * - * PTHREAD_STACK_MIN - * Minimum supported stack size for a thread - * - * PTHREAD_THREADS_MAX - * Maximum number of threads supported per - * process (must be at least 64). - * - * _POSIX_SEM_NSEMS_MAX - * The maximum number of semaphores a process can have. - * (only defined if not already defined) - * - * _POSIX_SEM_VALUE_MAX - * The maximum value a semaphore can have. - * (only defined if not already defined) - * - */ -#undef PTHREAD_DESTRUCTOR_ITERATIONS -#define PTHREAD_DESTRUCTOR_ITERATIONS 4 - -#undef PTHREAD_KEYS_MAX -#define PTHREAD_KEYS_MAX 64 - -#undef PTHREAD_STACK_MIN -#define PTHREAD_STACK_MIN 0 - -#if PTW32_LEVEL < 2 - /* Arbitrary value */ -# undef PTHREAD_THREADS_MAX -# define PTHREAD_THREADS_MAX 2019 -#endif - - /* Arbitrary value */ -#undef _POSIX_THREAD_THREADS_MAX -#define _POSIX_THREAD_THREADS_MAX 2019 - - /* Arbitrary value */ -#undef _POSIX_SEM_NSEMS_MAX -#define _POSIX_SEM_NSEMS_MAX 1024 - -#undef _POSIX_SEM_VALUE_MAX -#define _POSIX_SEM_VALUE_MAX (INT_MAX/2) - - -#if __GNUC__ && ! defined (__declspec) -# error Please upgrade your GNU compiler to one that supports __declspec. -#endif - -/* - * When building the DLL code, you should define PTW32_BUILD so that - * the variables/functions are exported correctly. When using the DLL, - * do NOT define PTW32_BUILD, and then the variables/functions will - * be imported correctly. - */ -#ifndef PTW32_STATIC_LIB -# ifdef PTW32_BUILD -# define PTW32_DLLPORT __declspec (dllexport) -# else -# define PTW32_DLLPORT __declspec (dllimport) -# endif -#else -# define PTW32_DLLPORT -#endif - -/* - * The Open Watcom C/C++ compiler uses a non-standard calling convention - * that passes function args in registers unless __cdecl is explicitly specified - * in exposed function prototypes. - * - * We force all calls to cdecl even though this could slow Watcom code down - * slightly. If you know that the Watcom compiler will be used to build both - * the DLL and application, then you can probably define this as a null string. - * Remember that pthread.h (this file) is used for both the DLL and application builds. - */ -#define PTW32_CDECL __cdecl - -#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX -# include -#else -/* - * Generic handle type - intended to extend uniqueness beyond - * that available with a simple pointer. It should scale for either - * IA-32 or IA-64. - */ -typedef struct { - void * p; /* Pointer to actual object */ - unsigned int x; /* Extra information - reuse count etc */ -} ptw32_handle_t; - -typedef ptw32_handle_t pthread_t; -typedef struct pthread_attr_t_ * pthread_attr_t; -typedef struct pthread_once_t_ pthread_once_t; -typedef struct pthread_key_t_ * pthread_key_t; -typedef struct pthread_mutex_t_ * pthread_mutex_t; -typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; -typedef struct pthread_cond_t_ * pthread_cond_t; -typedef struct pthread_condattr_t_ * pthread_condattr_t; -#endif -typedef struct pthread_rwlock_t_ * pthread_rwlock_t; -typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; -typedef struct pthread_spinlock_t_ * pthread_spinlock_t; -typedef struct pthread_barrier_t_ * pthread_barrier_t; -typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; - -/* - * ==================== - * ==================== - * POSIX Threads - * ==================== - * ==================== - */ - -enum { -/* - * pthread_attr_{get,set}detachstate - */ - PTHREAD_CREATE_JOINABLE = 0, /* Default */ - PTHREAD_CREATE_DETACHED = 1, - -/* - * pthread_attr_{get,set}inheritsched - */ - PTHREAD_INHERIT_SCHED = 0, - PTHREAD_EXPLICIT_SCHED = 1, /* Default */ - -/* - * pthread_{get,set}scope - */ - PTHREAD_SCOPE_PROCESS = 0, - PTHREAD_SCOPE_SYSTEM = 1, /* Default */ - -/* - * pthread_setcancelstate paramters - */ - PTHREAD_CANCEL_ENABLE = 0, /* Default */ - PTHREAD_CANCEL_DISABLE = 1, - -/* - * pthread_setcanceltype parameters - */ - PTHREAD_CANCEL_ASYNCHRONOUS = 0, - PTHREAD_CANCEL_DEFERRED = 1, /* Default */ - -/* - * pthread_mutexattr_{get,set}pshared - * pthread_condattr_{get,set}pshared - */ - PTHREAD_PROCESS_PRIVATE = 0, - PTHREAD_PROCESS_SHARED = 1, - -/* - * pthread_barrier_wait - */ - PTHREAD_BARRIER_SERIAL_THREAD = -1 -}; - -/* - * ==================== - * ==================== - * Cancelation - * ==================== - * ==================== - */ -#define PTHREAD_CANCELED ((void *) -1) - - -/* - * ==================== - * ==================== - * Once Key - * ==================== - * ==================== - */ -#define PTHREAD_ONCE_INIT { 0, PTW32_FALSE, 0, 0} - -struct pthread_once_t_ -{ - int state; /* indicates if user function has been executed, or cancelled */ - int started; - int eventUsers; - HANDLE event; -}; - - -/* - * ==================== - * ==================== - * Object initialisers - * ==================== - * ==================== - */ -#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) -#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2) -#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3) - -/* - * Compatibility with LinuxThreads - */ -#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER -#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER - -#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) - -#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) - -#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) - - -/* - * Mutex types. - */ -enum -{ - /* Compatibility with LinuxThreads */ - PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_RECURSIVE_NP, - PTHREAD_MUTEX_ERRORCHECK_NP, - PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, - /* For compatibility with POSIX */ - PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, - PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, - PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL -}; - - -typedef struct ptw32_cleanup_t ptw32_cleanup_t; - -#if defined(_MSC_VER) -/* Disable MSVC 'anachronism used' warning */ -#pragma warning( disable : 4229 ) -#endif - -typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); - -#if defined(_MSC_VER) -#pragma warning( default : 4229 ) -#endif - -struct ptw32_cleanup_t -{ - ptw32_cleanup_callback_t routine; - void *arg; - struct ptw32_cleanup_t *prev; -}; - -#ifdef __CLEANUP_SEH - /* - * WIN32 SEH version of cancel cleanup. - */ - -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - ptw32_cleanup_t _cleanup; \ - \ - _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ - _cleanup.arg = (_arg); \ - __try \ - { \ - -#define pthread_cleanup_pop( _execute ) \ - } \ - __finally \ - { \ - if( _execute || AbnormalTermination()) \ - { \ - (*(_cleanup.routine))( _cleanup.arg ); \ - } \ - } \ - } - -#else /* __CLEANUP_SEH */ - -#ifdef __CLEANUP_C - - /* - * C implementation of PThreads cancel cleanup - */ - -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - ptw32_cleanup_t _cleanup; \ - \ - ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ - -#define pthread_cleanup_pop( _execute ) \ - (void) ptw32_pop_cleanup( _execute ); \ - } - -#else /* __CLEANUP_C */ - -#ifdef __CLEANUP_CXX - - /* - * C++ version of cancel cleanup. - * - John E. Bossom. - */ - - class PThreadCleanup { - /* - * PThreadCleanup - * - * Purpose - * This class is a C++ helper class that is - * used to implement pthread_cleanup_push/ - * pthread_cleanup_pop. - * The destructor of this class automatically - * pops the pushed cleanup routine regardless - * of how the code exits the scope - * (i.e. such as by an exception) - */ - ptw32_cleanup_callback_t cleanUpRout; - void * obj; - int executeIt; - - public: - PThreadCleanup() : - cleanUpRout( 0 ), - obj( 0 ), - executeIt( 0 ) - /* - * No cleanup performed - */ - { - } - - PThreadCleanup( - ptw32_cleanup_callback_t routine, - void * arg ) : - cleanUpRout( routine ), - obj( arg ), - executeIt( 1 ) - /* - * Registers a cleanup routine for 'arg' - */ - { - } - - ~PThreadCleanup() - { - if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) - { - (void) (*cleanUpRout)( obj ); - } - } - - void execute( int exec ) - { - executeIt = exec; - } - }; - - /* - * C++ implementation of PThreads cancel cleanup; - * This implementation takes advantage of a helper - * class who's destructor automatically calls the - * cleanup routine if we exit our scope weirdly - */ -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ - (void *) (_arg) ); - -#define pthread_cleanup_pop( _execute ) \ - cleanup.execute( _execute ); \ - } - -#else - -#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. - -#endif /* __CLEANUP_CXX */ - -#endif /* __CLEANUP_C */ - -#endif /* __CLEANUP_SEH */ - -/* - * =============== - * =============== - * Methods - * =============== - * =============== - */ - -/* - * PThread Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, - int *detachstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, - void **stackaddr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, - size_t * stacksize); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, - int detachstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, - void *stackaddr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, - size_t stacksize); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, - struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, - const struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, - int); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, - int *); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, - int inheritsched); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, - int * inheritsched); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, - int); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, - int *); - -/* - * PThread Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, - const pthread_attr_t * attr, - void *(*start) (void *), - void *arg); - -PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); - -PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, - pthread_t t2); - -PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); - -PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, - void **value_ptr); - -PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); - -PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); - -PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, - int *oldstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, - int *oldtype); - -PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); - -PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, - void (*init_routine) (void)); - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX -PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); - -PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, - void (*routine) (void *), - void *arg); -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Thread Specific Data Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, - void (*destructor) (void *)); - -PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); - -PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, - const void *value); - -PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); - - -/* - * Mutex Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t - * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, - int pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); - -/* - * Barrier Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t - * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, - int pshared); - -/* - * Mutex Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, - const pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); - -/* - * Spinlock Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); - -/* - * Barrier Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, - const pthread_barrierattr_t * attr, - unsigned int count); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); - -/* - * Condition Variable Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, - int pshared); - -/* - * Condition Variable Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, - const pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, - pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, - pthread_mutex_t * mutex, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); - -/* - * Scheduling - */ -PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, - int policy, - const struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, - int *policy, - struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); - -PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); - -/* - * Read-Write Lock Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, - const pthread_rwlockattr_t *attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, - int pshared); - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 - -/* - * Signal Functions. Should be defined in but MSVC and MinGW32 - * already have signal.h that don't define these. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); - -/* - * Non-portable functions - */ - -/* - * Compatibility with Linux. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, - int kind); -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, - int *kind); - -/* - * Possibly supported by other POSIX threads implementations - */ -PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); -PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); - -/* - * Useful if an application wants to statically link - * the lib rather than load the DLL at run-time. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); - -/* - * Features that are auto-detected at load/run time. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); -enum ptw32_features { - PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ - PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ -}; - -/* - * Register a system time change with the library. - * Causes the library to perform various functions - * in response to the change. Should be called whenever - * the application's top level window receives a - * WM_TIMECHANGE message. It can be passed directly to - * pthread_create() as a new thread if desired. - */ -PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); - -#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - -/* - * Returns the Win32 HANDLE for the POSIX thread. - */ -PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); - - -/* - * Protected Methods - * - * This function blocks until the given WIN32 handle - * is signaled or pthread_cancel had been called. - * This function allows the caller to hook into the - * PThreads cancel mechanism. It is implemented using - * - * WaitForMultipleObjects - * - * on 'waitHandle' and a manually reset WIN32 Event - * used to implement pthread_cancel. The 'timeout' - * argument to TimedWait is simply passed to - * WaitForMultipleObjects. - */ -PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); -PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, - DWORD timeout); - -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Thread-Safe C Runtime Library Mappings. - */ -#ifndef _UWIN -# if defined(NEED_ERRNO) - PTW32_DLLPORT int * PTW32_CDECL _errno( void ); -# else -# ifndef errno -# if (defined(_MT) || defined(_DLL)) - __declspec(dllimport) extern int * __cdecl _errno(void); -# define errno (*_errno()) -# endif -# endif -# endif -#endif - -/* - * WIN32 C runtime library had been made thread-safe - * without affecting the user interface. Provide - * mappings from the UNIX thread-safe versions to - * the standard C runtime library calls. - * Only provide function mappings for functions that - * actually exist on WIN32. - */ - -#if !defined(__MINGW32__) -#define strtok_r( _s, _sep, _lasts ) \ - ( *(_lasts) = strtok( (_s), (_sep) ) ) -#endif /* !__MINGW32__ */ - -#define asctime_r( _tm, _buf ) \ - ( strcpy( (_buf), asctime( (_tm) ) ), \ - (_buf) ) - -#define ctime_r( _clock, _buf ) \ - ( strcpy( (_buf), ctime( (_clock) ) ), \ - (_buf) ) - -#define gmtime_r( _clock, _result ) \ - ( *(_result) = *gmtime( (_clock) ), \ - (_result) ) - -#define localtime_r( _clock, _result ) \ - ( *(_result) = *localtime( (_clock) ), \ - (_result) ) - -#define rand_r( _seed ) \ - ( _seed == _seed? rand() : rand() ) - - -/* - * Some compiler environments don't define some things. - */ -#if defined(__BORLANDC__) -# define _ftime ftime -# define _timeb timeb -#endif - -#ifdef __cplusplus - -/* - * Internal exceptions - */ -class ptw32_exception {}; -class ptw32_exception_cancel : public ptw32_exception {}; -class ptw32_exception_exit : public ptw32_exception {}; - -#endif - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - -/* FIXME: This is only required if the library was built using SEH */ -/* - * Get internal SEH tag - */ -PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); - -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -#ifndef PTW32_BUILD - -#ifdef __CLEANUP_SEH - -/* - * Redefine the SEH __except keyword to ensure that applications - * propagate our internal exceptions up to the library's internal handlers. - */ -#define __except( E ) \ - __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ - ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) - -#endif /* __CLEANUP_SEH */ - -#ifdef __CLEANUP_CXX - -/* - * Redefine the C++ catch keyword to ensure that applications - * propagate our internal exceptions up to the library's internal handlers. - */ -#ifdef _MSC_VER - /* - * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' - * if you want Pthread-Win32 cancelation and pthread_exit to work. - */ - -#ifndef PtW32NoCatchWarn - -#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") -#pragma message("------------------------------------------------------------------") -#pragma message("When compiling applications with MSVC++ and C++ exception handling:") -#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") -#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") -#pragma message(" cancelation and pthread_exit to work. For example:") -#pragma message("") -#pragma message(" #ifdef PtW32CatchAll") -#pragma message(" PtW32CatchAll") -#pragma message(" #else") -#pragma message(" catch(...)") -#pragma message(" #endif") -#pragma message(" {") -#pragma message(" /* Catchall block processing */") -#pragma message(" }") -#pragma message("------------------------------------------------------------------") - -#endif - -#define PtW32CatchAll \ - catch( ptw32_exception & ) { throw; } \ - catch( ... ) - -#else /* _MSC_VER */ - -#define catch( E ) \ - catch( ptw32_exception & ) { throw; } \ - catch( E ) - -#endif /* _MSC_VER */ - -#endif /* __CLEANUP_CXX */ - -#endif /* ! PTW32_BUILD */ - -#ifdef __cplusplus -} /* End of extern "C" */ -#endif /* __cplusplus */ - -#ifdef PTW32__HANDLE_DEF -# undef HANDLE -#endif -#ifdef PTW32__DWORD_DEF -# undef DWORD -#endif - -#undef PTW32_LEVEL -#undef PTW32_LEVEL_MAX - -#endif /* ! RC_INVOKED */ - -#endif /* PTHREAD_H */ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +/* + * See the README file for an explanation of the pthreads-win32 version + * numbering scheme and how the DLL is named etc. + */ +#define PTW32_VERSION 2,3,0,0 +#define PTW32_VERSION_STRING "2, 3, 0, 0\0" + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) +# define __CLEANUP_C +#endif + +#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) +#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. +#endif + +/* + * Stop here if we are being included by the resource compiler. + */ +#ifndef RC_INVOKED + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#ifdef _UWIN +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1-2001 + * and + * The Single Unix Specification version 3 + * + * (these two are equivalent) + * + * in order to enhance code portability between Windows, + * various commercial Unix implementations, and Linux. + * + * See the ANNOUNCE file for a full list of conforming + * routines and defined constants, and a list of missing + * routines and constants not defined in this implementation. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the CONTRIBUTORS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* Try to avoid including windows.h */ +#if defined(__MINGW32__) && defined(__cplusplus) +/* + * FIXME: The pthreadGCE.dll build gets linker unresolved errors + * on pthread_key_create() unless windows.h is included here. + * It appears to have something to do with an argument type mismatch. + * Looking at tsd.o with 'nm' shows this line: + * 00000000 T _pthread_key_create__FPP14pthread_key_t_PFPv_v + * instead of + * 00000000 T _pthread_key_create + */ +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#ifdef PTW32_INCLUDE_WINDOWS_H +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) +/* + * VC++6.0 or early compiler's header has no DWORD_PTR type. + */ +typedef unsigned long DWORD_PTR; +#endif +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* Try to avoid including windows.h */ +#if defined(__MINGW32__) && defined(__cplusplus) +/* + * FIXME: The pthreadGCE.dll build gets linker unresolved errors + * on pthread_key_create() unless windows.h is included here. + * It appears to have something to do with an argument type mismatch. + * Looking at tsd.o with 'nm' shows this line: + * 00000000 T _pthread_key_create__FPP14pthread_key_t_PFPv_v + * instead of + * 00000000 T _pthread_key_create + */ +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#ifdef PTW32_INCLUDE_WINDOWS_H +#include +#endif + +#ifndef NEED_FTIME +#include +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ + +#include +#include + +/* + * Boolean values to make us independent of system includes. + */ +enum { + PTW32_FALSE = 0, + PTW32_TRUE = (! PTW32_FALSE) +}; + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Several systems don't define some error numbers. + */ +#ifndef ENOTSUP +# define ENOTSUP 48 /* This is the value in Solaris. */ +#endif + +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#ifndef ENOSYS +# define ENOSYS 140 /* Semi-arbitrary value */ +#endif + +#ifndef EDEADLK +# ifdef EDEADLOCK +# define EDEADLK EDEADLOCK +# else +# define EDEADLK 36 /* This is the value in MSVC. */ +# endif +#endif + +#include + +/* + * To avoid including windows.h we define only those things that we + * actually need from it. I don't like the potential incompatibility that + * this creates with future versions of windows. + */ +#ifndef PTW32_INCLUDE_WINDOWS_H +#ifndef HANDLE +# define PTW32__HANDLE_DEF +# define HANDLE void * +#endif +#ifndef DWORD +# define PTW32__DWORD_DEF +# define DWORD unsigned long +#endif +#endif + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1-2001 Options + * ========================= + * + * Options are normally set in , which is not provided + * with pthreads-win32. + * + * For conformance with the Single Unix Specification (version 3), all of the + * options below are defined, and have a value of either -1 (not supported) + * or 200112L (supported). + * + * These options can neither be left undefined nor have a value of 0, because + * either indicates that sysconf(), which is not implemented, may be used at + * runtime to check the status of the option. + * + * _POSIX_THREADS (== 200112L) + * If == 200112L, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) + * If == 200112L, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (== -1) + * If == 200112L, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) + * If == 200112L, you can use realtime scheduling. + * This option indicates that the behaviour of some + * implemented functions conforms to the additional TPS + * requirements in the standard. E.g. rwlocks favour + * writers over readers when threads have equal priority. + * + * _POSIX_THREAD_PRIO_INHERIT (== -1) + * If == 200112L, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (== -1) + * If == 200112L, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (== -1) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) + * If == 200112L you can use the special *_r library + * functions that provide thread-safe behaviour + * + * _POSIX_READER_WRITER_LOCKS (== 200112L) + * If == 200112L, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (== 200112L) + * If == 200112L, you can use spin locks + * + * _POSIX_BARRIERS (== 200112L) + * If == 200112L, you can use barriers + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#undef _POSIX_THREADS +#define _POSIX_THREADS 200112L + +#undef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS 200112L + +#undef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS 200112L + +#undef _POSIX_BARRIERS +#define _POSIX_BARRIERS 200112L + +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +#undef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* + * The following options are not supported + */ +#undef _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR -1 + +#undef _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT -1 + +#undef _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT -1 + +/* TPS is not fully supported. */ +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 + +#undef _POSIX_THREAD_PROCESS_SHARED +#define _POSIX_THREAD_PROCESS_SHARED -1 + + +/* + * POSIX 1003.1-2001 Limits + * =========================== + * + * These limits are normally set in , which is not provided with + * pthreads-win32. + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * _POSIX_SEM_NSEMS_MAX + * The maximum number of semaphores a process can have. + * (only defined if not already defined) + * + * _POSIX_SEM_VALUE_MAX + * The maximum value a semaphore can have. + * (only defined if not already defined) + * + */ +#undef PTHREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_DESTRUCTOR_ITERATIONS 4 + +#undef PTHREAD_KEYS_MAX +#define PTHREAD_KEYS_MAX 64 + +#undef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 + +#if PTW32_LEVEL < 2 + /* Arbitrary value */ +# undef PTHREAD_THREADS_MAX +# define PTHREAD_THREADS_MAX 2019 +#endif + + /* Arbitrary value */ +#undef _POSIX_THREAD_THREADS_MAX +#define _POSIX_THREAD_THREADS_MAX 2019 + + /* Arbitrary value */ +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 1024 + +#undef _POSIX_SEM_VALUE_MAX +#define _POSIX_SEM_VALUE_MAX (INT_MAX/2) + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * The Open Watcom C/C++ compiler uses a non-standard calling convention + * that passes function args in registers unless __cdecl is explicitly specified + * in exposed function prototypes. + * + * We force all calls to cdecl even though this could slow Watcom code down + * slightly. If you know that the Watcom compiler will be used to build both + * the DLL and application, then you can probably define this as a null string. + * Remember that pthread.h (this file) is used for both the DLL and application builds. + */ +#define PTW32_CDECL __cdecl + +#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX +# include +#else +/* + * Generic handle type - intended to extend uniqueness beyond + * that available with a simple pointer. It should scale for either + * IA-32 or IA-64. + */ +typedef struct { + void * p; /* Pointer to actual object */ + unsigned int x; /* Extra information - reuse count etc */ +} ptw32_handle_t; + +typedef ptw32_handle_t pthread_t; +typedef struct pthread_attr_t_ * pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ * pthread_key_t; +typedef struct pthread_mutex_t_ * pthread_mutex_t; +typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; +typedef struct pthread_cond_t_ * pthread_cond_t; +typedef struct pthread_condattr_t_ * pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ * pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ * pthread_spinlock_t; +typedef struct pthread_barrier_t_ * pthread_barrier_t; +typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { 0, PTW32_FALSE, 0, 0} + +struct pthread_once_t_ +{ + int state; /* indicates if user function has been executed, or cancelled */ + int started; + int eventUsers; + HANDLE event; +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3) + +/* + * Compatibility with LinuxThreads + */ +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) + + +/* + * Mutex types. + */ +enum +{ + /* Compatibility with LinuxThreads */ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, + /* For compatibility with POSIX */ + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; + +#if defined(_MSC_VER) +/* Disable MSVC 'anachronism used' warning */ +#pragma warning( disable : 4229 ) +#endif + +typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); + +#if defined(_MSC_VER) +#pragma warning( default : 4229 ) +#endif + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#ifdef __CLEANUP_SEH + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( 0 ), + obj( 0 ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, + int *); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), + void *arg); + +PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); + +PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, + pthread_t t2); + +PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); + +PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, + void **value_ptr); + +PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, + int *oldstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, + int *oldtype); + +PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, + void (*init_routine) (void)); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); + +PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + void (*routine) (void *), + void *arg); +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread Specific Data Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, + void (*destructor) (void *)); + +PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); + +PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, + const void *value); + +PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); + +/* + * Barrier Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); + +PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 + +/* + * Signal Functions. Should be defined in but MSVC and MinGW32 + * already have signal.h that don't define these. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, + int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, + int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); +PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); + +/* + * Features that are auto-detected at load/run time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); +enum ptw32_features { + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ + PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ +}; + +/* + * Register a system time change with the library. + * Causes the library to perform various functions + * in response to the change. Should be called whenever + * the application's top level window receives a + * WM_TIMECHANGE message. It can be passed directly to + * pthread_create() as a new thread if desired. + */ +PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); + +#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, + DWORD timeout); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#ifndef _UWIN +# if defined(NEED_ERRNO) + PTW32_DLLPORT int * PTW32_CDECL _errno( void ); +# else +# ifndef errno +# if (defined(_MT) || defined(_DLL)) + __declspec(dllimport) extern int * __cdecl _errno(void); +# define errno (*_errno()) +# endif +# endif +# endif +#endif + +/* + * WIN32 C runtime library had been made thread-safe + * without affecting the user interface. Provide + * mappings from the UNIX thread-safe versions to + * the standard C runtime library calls. + * Only provide function mappings for functions that + * actually exist on WIN32. + */ + +#if !defined(__MINGW32__) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif /* !__MINGW32__ */ + +#define asctime_r( _tm, _buf ) \ + ( strcpy( (_buf), asctime( (_tm) ) ), \ + (_buf) ) + +#define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + +#define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) + +#define rand_r( _seed ) \ + ( _seed == _seed? rand() : rand() ) + + +/* + * Some compiler environments don't define some things. + */ +#if defined(__BORLANDC__) +# define _ftime ftime +# define _timeb timeb +#endif + +#ifdef __cplusplus + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#ifndef PTW32_BUILD + +#ifdef __CLEANUP_SEH + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_CXX + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#ifdef _MSC_VER + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#ifndef PtW32NoCatchWarn + +#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") +#pragma message("------------------------------------------------------------------") +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") +#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") +#pragma message(" cancelation and pthread_exit to work. For example:") +#pragma message("") +#pragma message(" #ifdef PtW32CatchAll") +#pragma message(" PtW32CatchAll") +#pragma message(" #else") +#pragma message(" catch(...)") +#pragma message(" #endif") +#pragma message(" {") +#pragma message(" /* Catchall block processing */") +#pragma message(" }") +#pragma message("------------------------------------------------------------------") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __CLEANUP_CXX */ + +#endif /* ! PTW32_BUILD */ + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#ifdef PTW32__HANDLE_DEF +# undef HANDLE +#endif +#ifdef PTW32__DWORD_DEF +# undef DWORD +#endif + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* ! RC_INVOKED */ + +#endif /* PTHREAD_H */ diff --git a/pthread_once.c b/pthread_once.c index 0a8c45e..8da10d8 100644 --- a/pthread_once.c +++ b/pthread_once.c @@ -194,7 +194,7 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) if (!w32Thread) { self = pthread_self(); - w32Thread = pthread_getw32threadhandle_np(self); + w32Thread = ((ptw32_thread_t *)self.p)->threadH; } /* * Prevent pthread_setschedparam() from changing our priority while we're boosted. @@ -205,10 +205,6 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) if (!PTW32_INTERLOCKED_EXCHANGE((LPLONG)&once_control->started, (LONG)PTW32_TRUE)) { - /* - * Clear residual state from a cancelled init_routine - * (and DONE still hasn't been set of course). - */ if (cancelled) { /* @@ -241,10 +237,18 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) pthread_mutex_unlock(&((ptw32_thread_t *)self.p)->threadLock); } +#ifdef _MSC_VER +#pragma inline_depth(0) +#endif + pthread_cleanup_push(ptw32_once_init_routine_cleanup, (void *) once_control); (*init_routine)(); pthread_cleanup_pop(0); +#ifdef _MSC_VER +#pragma inline_depth() +#endif + (void) PTW32_INTERLOCKED_EXCHANGE((LPLONG)&once_control->state, (LONG)PTW32_ONCE_DONE); /* @@ -273,8 +277,7 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) * while waiting, create an event to wait on */ - EnterCriticalSection(&ptw32_once_event_lock); - once_control->eventUsers++; + InterlockedIncrement((LPLONG) &once_control->eventUsers); /* * RE CANCELLATION: @@ -296,6 +299,7 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) * forever. */ + EnterCriticalSection(&ptw32_once_event_lock); if (!once_control->event) { once_control->event = CreateEvent(NULL, PTW32_TRUE, PTW32_FALSE, NULL); @@ -309,21 +313,21 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) * then the event handle is guaranteed to be seen and triggered). */ - if (!InterlockedExchangeAdd((LPLONG)&once_control->state, 0L)) /* Atomic Read */ + if (!InterlockedExchangeAdd((LPLONG)&once_control->state, 0L)) { /* Neither DONE nor CANCELLED */ (void) WaitForSingleObject(once_control->event, INFINITE); } /* last one out shut off the lights */ - EnterCriticalSection(&ptw32_once_event_lock); - if (0 == --once_control->eventUsers) + if (0 == InterlockedDecrement((LPLONG)&once_control->eventUsers)) { /* we were last */ + EnterCriticalSection(&ptw32_once_event_lock); CloseHandle(once_control->event); once_control->event = 0; + LeaveCriticalSection(&ptw32_once_event_lock); } - LeaveCriticalSection(&ptw32_once_event_lock); } } diff --git a/tests/ChangeLog b/tests/ChangeLog index 43ba41b..da6b15c 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,34 +1,34 @@ -2005-04-11 Ross Johnson - - * once4.c: New test; tries to test priority adjustments; - set priority class to realtime so that any failures can be - seen. - -2005-04-06 Ross Johnson - - * cleanup0.c: Fix unguarded global variable accesses. - * cleanup1.c: Likewise. - * cleanup2.c: Likewise. - * cleanup3.c: Likewise. - * once2.c: Likewise. - * once3.c: Likewise. - -2005-04-01 Ross Johnson - - * GNUmakefile: Add target to test linking static link library. - * Makefile: Likewise. - * self1.c: Run process attach/detach routines when static linked. - +2005-04-11 Ross Johnson + + * once4.c: New test; tries to test priority adjustments + in pthread_once(); set priority class to realtime so that + any failures can be seen. + +2005-04-06 Ross Johnson + + * cleanup0.c: Fix unguarded global variable accesses. + * cleanup1.c: Likewise. + * cleanup2.c: Likewise. + * cleanup3.c: Likewise. + * once2.c: Likewise. + * once3.c: Likewise. + +2005-04-01 Ross Johnson + + * GNUmakefile: Add target to test linking static link library. + * Makefile: Likewise. + * self1.c: Run process attach/detach routines when static linked. + 2005-03-16 Ross Johnson - - * mutex5.c: Prevent optimiser from removing asserts. - + + * mutex5.c: Prevent optimiser from removing asserts. + 2005-03-12 Ross Johnson - + * once3.c: New test. - + 2005-03-08 Ross Johnson - + * once2.c: New test. 2004-11-19 Ross Johnson diff --git a/tests/Debug.ncb b/tests/Debug.ncb deleted file mode 100644 index 44a6223..0000000 Binary files a/tests/Debug.ncb and /dev/null differ diff --git a/tests/Debug.opt b/tests/Debug.opt deleted file mode 100644 index 9a9d866..0000000 Binary files a/tests/Debug.opt and /dev/null differ diff --git a/tests/Makefile b/tests/Makefile index 6e6ecf3..786d85e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -95,7 +95,7 @@ PASSES= sizes.pass loadfree.pass \ mutex6s.pass mutex6es.pass mutex6rs.pass \ mutex7.pass mutex7n.pass mutex7e.pass mutex7r.pass \ mutex8.pass mutex8n.pass mutex8e.pass mutex8r.pass \ - count1.pass once1.pass once2.pass once3.pass tsd1.pass \ + count1.pass once1.pass once2.pass once3.pass once4.pass tsd1.pass \ self2.pass \ cancel1.pass cancel2.pass \ semaphore4.pass semaphore4t.pass \ @@ -120,9 +120,9 @@ PASSES= sizes.pass loadfree.pass \ BENCHRESULTS = \ benchtest1.bench benchtest2.bench benchtest3.bench benchtest4.bench benchtest5.bench -STATICRESULTS = \ - self1.pass - +STATICRESULTS = \ + self1.pass + help: @ $(ECHO) Run one of the following command lines: @ $(ECHO) nmake clean VC (to test using VC dll with VC (no EH) applications) @@ -332,6 +332,7 @@ mutex8r.pass: mutex7r.pass once1.pass: create1.pass once2.pass: once1.pass once3.pass: once2.pass +once4.pass: once3.pass priority1.pass: join1.pass priority2.pass: priority1.pass barrier3.pass reuse1.pass: create2.pass -- cgit v1.2.3