summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrpj <rpj>2002-02-18 03:16:52 +0000
committerrpj <rpj>2002-02-18 03:16:52 +0000
commita416ab17ecf9f2cb0f1e3f7bd645a8d1ce690ca2 (patch)
tree72f776cd64e48824a5578ff7a523bc69097143b4
parente6f1797e9e9925ae7f9dda54806ef8f52ae3ed07 (diff)
Major reorganisation of source code; new routine and tests added.
-rw-r--r--ChangeLog213
-rw-r--r--GNUmakefile353
-rw-r--r--Makefile644
-rw-r--r--Nmakefile.tests396
-rw-r--r--attr.c21
-rw-r--r--barrier.c14
-rw-r--r--cancel.c8
-rw-r--r--condvar.c20
-rw-r--r--global.c9
-rw-r--r--implement.h259
-rw-r--r--misc.c2
-rw-r--r--mutex.c1080
-rw-r--r--nonportable.c14
-rw-r--r--private.c980
-rw-r--r--pthread.c7
-rw-r--r--pthread.def325
-rw-r--r--pthread.h61
-rw-r--r--pthread_attr_destroy.c (renamed from attr_destroy.c)4
-rw-r--r--pthread_attr_getdetachstate.c (renamed from attr_getdetachstate.c)4
-rw-r--r--pthread_attr_getinheritsched.c52
-rw-r--r--pthread_attr_getschedparam.c52
-rw-r--r--pthread_attr_getschedpolicy.c62
-rw-r--r--pthread_attr_getscope.c (renamed from attr_getscope.c)2
-rw-r--r--pthread_attr_getstackaddr.c (renamed from attr_getstackaddr.c)4
-rw-r--r--pthread_attr_getstacksize.c (renamed from attr_getstacksize.c)4
-rw-r--r--pthread_attr_init.c (renamed from attr_init.c)2
-rw-r--r--pthread_attr_setdetachstate.c (renamed from attr_setdetachstate.c)4
-rw-r--r--pthread_attr_setinheritsched.c58
-rw-r--r--pthread_attr_setschedparam.c63
-rw-r--r--pthread_attr_setschedpolicy.c56
-rw-r--r--pthread_attr_setscope.c (renamed from attr_setscope.c)2
-rw-r--r--pthread_attr_setstackaddr.c (renamed from attr_setstackaddr.c)4
-rw-r--r--pthread_attr_setstacksize.c (renamed from attr_setstacksize.c)4
-rw-r--r--pthread_barrier_destroy.c (renamed from barrier_destroy.c)2
-rw-r--r--pthread_barrier_init.c (renamed from barrier_init.c)2
-rw-r--r--pthread_barrier_wait.c (renamed from barrier_wait.c)2
-rw-r--r--pthread_barrierattr_destroy.c (renamed from barrier_attr_destroy.c)2
-rw-r--r--pthread_barrierattr_getpshared.c (renamed from barrier_attr_getpshared.c)2
-rw-r--r--pthread_barrierattr_init.c (renamed from barrier_attr_init.c)2
-rw-r--r--pthread_barrierattr_setpshared.c (renamed from barrier_attr_setpshared.c)2
-rw-r--r--pthread_cancel.c (renamed from cancel_cancel.c)2
-rw-r--r--pthread_cond_destroy.c (renamed from condvar_destroy.c)32
-rw-r--r--pthread_cond_init.c (renamed from condvar_init.c)23
-rw-r--r--pthread_cond_signal.c (renamed from condvar_signal.c)2
-rw-r--r--pthread_cond_wait.c (renamed from condvar_wait.c)2
-rw-r--r--pthread_condattr_destroy.c (renamed from condvar_attr_destroy.c)0
-rw-r--r--pthread_condattr_getpshared.c (renamed from condvar_attr_getpshared.c)2
-rw-r--r--pthread_condattr_init.c (renamed from condvar_attr_init.c)2
-rw-r--r--pthread_condattr_setpshared.c (renamed from condvar_attr_setpshared.c)2
-rw-r--r--pthread_delay_np.c (renamed from np_delay.c)2
-rw-r--r--pthread_detach.c88
-rw-r--r--pthread_getschedparam.c74
-rw-r--r--pthread_getspecific.c75
-rw-r--r--pthread_getw32threadhandle_np.c (renamed from np_getw32threadhandle.c)2
-rw-r--r--pthread_join.c152
-rw-r--r--pthread_key_create.c108
-rw-r--r--pthread_key_delete.c127
-rw-r--r--pthread_mutex_destroy.c134
-rw-r--r--pthread_mutex_init.c107
-rw-r--r--pthread_mutex_lock.c105
-rw-r--r--pthread_mutex_timedlock.c356
-rw-r--r--pthread_mutex_trylock.c99
-rw-r--r--pthread_mutex_unlock.c93
-rw-r--r--pthread_mutexattr_destroy.c83
-rw-r--r--pthread_mutexattr_getkind_np.c (renamed from np_mutexattr_setkind.c)15
-rw-r--r--pthread_mutexattr_getpshared.c97
-rw-r--r--pthread_mutexattr_gettype.c57
-rw-r--r--pthread_mutexattr_init.c86
-rw-r--r--pthread_mutexattr_setkind_np.c45
-rw-r--r--pthread_mutexattr_setpshared.c120
-rw-r--r--pthread_mutexattr_settype.c144
-rw-r--r--pthread_num_processors_np.c (renamed from np_num_processors.c)2
-rw-r--r--pthread_rwlock_destroy.c140
-rw-r--r--pthread_rwlock_init.c109
-rw-r--r--pthread_rwlock_rdlock.c101
-rw-r--r--pthread_rwlock_tryrdlock.c101
-rw-r--r--pthread_rwlock_trywrlock.c120
-rw-r--r--pthread_rwlock_unlock.c93
-rw-r--r--pthread_rwlock_wrlock.c146
-rw-r--r--pthread_rwlockattr_destroy.c85
-rw-r--r--pthread_rwlockattr_getpshared.c99
-rw-r--r--pthread_rwlockattr_init.c84
-rw-r--r--pthread_rwlockattr_setpshared.c122
-rw-r--r--pthread_setcancelstate.c (renamed from cancel_setcancelstate.c)2
-rw-r--r--pthread_setcanceltype.c (renamed from cancel_setcanceltype.c)2
-rw-r--r--pthread_setschedparam.c78
-rw-r--r--pthread_setspecific.c151
-rw-r--r--pthread_spin_destroy.c102
-rw-r--r--pthread_spin_init.c123
-rw-r--r--pthread_spin_lock.c77
-rw-r--r--pthread_spin_trylock.c69
-rw-r--r--pthread_spin_unlock.c64
-rw-r--r--pthread_testcancel.c (renamed from cancel_testcancel.c)2
-rw-r--r--pthread_timechange_handler_np.c108
-rw-r--r--pthread_win32_attach_detach_np.c (renamed from np_win32_attach.c)2
-rw-r--r--ptw32_InterlockedCompareExchange.c108
-rw-r--r--ptw32_callUserDestroyRoutines.c155
-rw-r--r--ptw32_cond_check_need_init.c (renamed from condvar_check_need_init.c)4
-rw-r--r--ptw32_decrease_semaphore.c (renamed from semaphore_decrease.c)2
-rw-r--r--ptw32_getprocessors.c84
-rw-r--r--ptw32_increase_semaphore.c (renamed from semaphore_increase.c)2
-rw-r--r--ptw32_is_attr.c (renamed from attr_is_attr.c)8
-rw-r--r--ptw32_mutex_check_need_init.c94
-rw-r--r--ptw32_processInitialize.c100
-rw-r--r--ptw32_processTerminate.c100
-rw-r--r--ptw32_rwlock_check_need_init.c93
-rw-r--r--ptw32_spinlock_check_need_init.c81
-rw-r--r--ptw32_threadDestroy.c66
-rw-r--r--ptw32_threadStart.c373
-rw-r--r--ptw32_throw.c130
-rw-r--r--ptw32_timespec.c81
-rw-r--r--ptw32_tkAssocCreate.c142
-rw-r--r--ptw32_tkAssocDestroy.c68
-rw-r--r--rwlock.c826
-rw-r--r--sched.c361
-rw-r--r--sched_get_priority_max.c69
-rw-r--r--sched_get_priority_min.c69
-rw-r--r--sched_getscheduler.c66
-rw-r--r--sched_setscheduler.c78
-rw-r--r--sched_yield.c71
-rw-r--r--sem_close.c (renamed from semaphore_close.c)2
-rw-r--r--sem_destroy.c (renamed from semaphore_destroy.c)2
-rw-r--r--sem_getvalue.c (renamed from semaphore_getvalue.c)2
-rw-r--r--sem_init.c (renamed from semaphore_init.c)2
-rw-r--r--sem_open.c (renamed from semaphore_open.c)2
-rw-r--r--sem_post.c (renamed from semaphore_post.c)2
-rw-r--r--sem_post_multiple.c (renamed from semaphore_postmultiple.c)2
-rw-r--r--sem_timedwait.c (renamed from semaphore_timedwait.c)11
-rw-r--r--sem_trywait.c (renamed from semaphore_trywait.c)2
-rw-r--r--sem_unlink.c (renamed from semaphore_unlink.c)2
-rw-r--r--sem_wait.c (renamed from semaphore_wait.c)2
-rw-r--r--semaphore.c26
-rw-r--r--spin.c281
-rw-r--r--sync.c160
-rw-r--r--tests/ChangeLog5
-rw-r--r--tests/GNUmakefile7
-rw-r--r--tests/Makefile4
-rw-r--r--tests/condvar1_1.c117
-rw-r--r--tests/condvar1_2.c122
-rw-r--r--tests/condvar3_1.c2
-rw-r--r--tests/exit4.c13
-rw-r--r--tsd.c308
142 files changed, 8341 insertions, 4981 deletions
diff --git a/ChangeLog b/ChangeLog
index 3b68aad..f01e060 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,124 @@
+2002-02-17 Ross Johnson <rpj@setup1.ise.canberra.edu.au
+
+ * Testsuite passed.
+
+ * pthread_timechange_handler_np.c: New; following
+ a suggestion from Alexander Terekhov that CVs should
+ be broadcast so that they all re-evaluate their
+ condition variables and reset a new timeout if
+ required, whenever an application receives a
+ WM_TIMECHANGE message. This message indicates that
+ the system time has been changed. Therefore, CVs
+ waiting for a timeout set as an abs_time will possibly
+ not wake up at the expected time. Some applications
+ may not be tolerant of this.
+ * pthread_cond_init.c: Add CV to linked list.
+ * pthread_cond_destroy.c: Remove CV from linked list.
+ * global.c (ptw32_cond_list_head): New variable.
+ (ptw32_cond_list_tail): New variable.
+ (ptw32_cond_list_cs): New critical section.
+ * ptw32_processInitialize (ptw32_cond_list_cs): Initialize.
+ * ptw32_processTerminate (ptw32_cond_list_cs): Delete.
+
+
+ * Reduce executable size.
+ -----------------------
+ When linking with the static library, only those
+ routines actually called, either directly or indirectly
+ should be included.
+
+ [Gcc has the -ffunction-segments option to do this but MSVC
+ doesn't have this feature as far as I can determine. Other
+ compilers are undetermined as well. - rpj]
+
+ * spin.c: Split file into function segments.
+ * ptw32_spinlock_check_need_init.c: Separated routine from spin.c.
+ * pthread_spin_init.c: Likewise.
+ * pthread_spin_destroy.c: Likewise.
+ * pthread_spin_lock.c: Likewise.
+ * pthread_spin_unlock.c: Likewise.
+ * pthread_spin_trylock.c: Likewise.
+
+ * sync.c: Split file into function segments.
+ * pthread_detach.c: Separated routine from sync.c.
+ * pthread_join.c: Likewise.
+
+ * tsd.c: Split file into function segments.
+ * pthread_key_create.c: Separated routine from tsd.c.
+ * pthread_key_delete.c: Likewise.
+ * pthread_setspecific.c: Likewise.
+ * pthread_getspecific.c: Likewise.
+
+ * sched.c: Split file into function segments.
+ * pthread_attr_setschedpolicy.c: Separated routine from sched.c.
+ * pthread_attr_getschedpolicy.c: Likewise.
+ * pthread_attr_setschedparam.c: Likewise.
+ * pthread_attr_getschedparam.c: Likewise.
+ * pthread_attr_setinheritsched.c: Likewise.
+ * pthread_attr_getinheritsched.c: Likewise.
+ * pthread_setschedparam.c: Likewise.
+ * pthread_getschedparam.c: Likewise.
+ * sched_get_priority_max.c: Likewise.
+ * sched_get_priority_min.c: Likewise.
+ * sched_setscheduler.c: Likewise.
+ * sched_getscheduler.c: Likewise.
+ * sched_yield.c: Likewise.
+
+
+2002-02-16 Ross Johnson <rpj@setup1.ise.canberra.edu.au
+
+ Reduce executable size.
+ -----------------------
+ When linking with the static library, only those
+ routines actually called, either directly or indirectly
+ should be included.
+
+ [Gcc has the -ffunction-segments option to do this but MSVC
+ doesn't have this feature as far as I can determine. Other
+ compilers are undetermined as well. - rpj]
+
+ * mutex.c: Split file into function segments.
+ * pthread_mutexattr_destroy.c: Separated routine from mutex.c
+ * pthread_mutexattr_getpshared.c: Likewise.
+ * pthread_mutexattr_gettype.c: Likewise.
+ * pthread_mutexattr_init.c: Likewise.
+ * pthread_mutexattr_setpshared.c: Likewise.
+ * pthread_mutexattr_settype.c: Likewise.
+ * ptw32_mutex_check_need_init.c: Likewise.
+ * pthread_mutex_destroy.c: Likewise.
+ * pthread_mutex_init.c: Likewise.
+ * pthread_mutex_lock.c: Likewise.
+ * pthread_mutex_timedlock.c: Likewise.
+ * pthread_mutex_trylock.c: Likewise.
+ * pthread_mutex_unlock.c: Likewise.
+
+ * private.c: Split file into function segments.
+ * ptw32_InterlockedCompareExchange.c: Separated routine from private.c
+ * ptw32_callUserDestroyRoutines.c: Likewise.
+ * ptw32_getprocessors.c: Likewise.
+ * ptw32_processInitialize.c: Likewise.
+ * ptw32_processTerminate.c: Likewise.
+ * ptw32_threadDestroy.c: Likewise.
+ * ptw32_threadStart.c: Likewise.
+ * ptw32_throw.c: Likewise.
+ * ptw32_timespec.c: Likewise.
+ * ptw32_tkAssocCreate.c: Likewise.
+ * ptw32_tkAssocDestroy.c: Likewise.
+
+ * rwlock.c: Split file into function segments.
+ * pthread_rwlockattr_destroy.c: Separated routine from rwlock.c
+ * pthread_rwlockattr_getpshared.c: Likewise.
+ * pthread_rwlockattr_init.c: Likewise.
+ * pthread_rwlockattr_setpshared.c: Likewise.
+ * ptw32_rwlock_check_need_init.c: Likewise.
+ * pthread_rwlock_destroy.c: Likewise.
+ * pthread_rwlock_init.c: Likewise.
+ * pthread_rwlock_rdlock.c: Likewise.
+ * pthread_rwlock_tryrdlock.c: Likewise.
+ * pthread_rwlock_trywrlock.c: Likewise.
+ * pthread_rwlock_unlock.c: Likewise.
+ * pthread_rwlock_wrlock.c: Likewise.
+
2002-02-10 Ross Johnson <rpj@setup1.ise.canberra.edu.au
Reduce executable size.
@@ -14,8 +135,10 @@
* np_delay.c: Separated routine from nonportable.c
* np_getw32threadhandle.c: Likewise.
* np_mutexattr_setkind.c: Likewise.
+ * np_mutexattr_getkind.c: Likewise.
* np_num_processors.c: Likewise.
- * np_win32_attach.c: Likewise.
+ * np_win32_attach_detach.c: Likewise.
+
* misc.c: Split file into function segments.
* pthread_equal.c: Separated routine from nonportable.c.
* pthread_getconcurrency.c: Likewise.
@@ -39,15 +162,15 @@
compilers are undetermined as well. - rpj]
* condvar.c: Split file into function segments.
- * condvar_attr_destroy.c: Separated routine from condvar.c.
- * condvar_attr_getpshared.c: Likewise.
- * condvar_attr_init.c: Likewise.
- * condvar_attr_setpshared.c: Likewise.
- * condvar_check_need_init.c: Likewise.
- * condvar_destroy.c: Likewise.
- * condvar_init.c: Likewise.
- * condvar_signal.c: Likewise.
- * condvar_wait.c: Likewise.
+ * pthread_condattr_destroy.c: Separated routine from condvar.c.
+ * pthread_condattr_getpshared.c: Likewise.
+ * pthread_condattr_init.c: Likewise.
+ * pthread_condattr_setpshared.c: Likewise.
+ * ptw32_cond_check_need_init.c: Likewise.
+ * pthread_cond_destroy.c: Likewise.
+ * pthread_cond_init.c: Likewise.
+ * pthread_cond_signal.c: Likewise.
+ * pthread_cond_wait.c: Likewise.
2002-02-07 Alexander Terekhov<TEREKHOV@de.ibm.com>
@@ -78,17 +201,17 @@
This file is used to congregate the separate modules for
potential inline optimisation and backward build compatibility.
* cancel.c: Likewise.
- * barrier_attr_destroy.c: Separated routine from cancel.c.
- * barrier_attr_getpshared.c: Likewise.
- * barrier_attr_init.c: Likewise.
- * barrier_attr_setpshared.c: Likewise.
- * barrier_destroy.c: Likewise.
- * barrier_init.c: Likewise.
- * barrier_wait.c: Likewise.
- * cancel_cancel.c: Likewise.
- * cancel_setcancelstate.c: Likewise.
- * cancel_setcanceltype.c: Likewise.
- * cancel_testcancel.c: Likewise.
+ * pthread_barrierattr_destroy.c: Separated routine from cancel.c.
+ * pthread_barrierattr_getpshared.c: Likewise.
+ * pthread_barrierattr_init.c: Likewise.
+ * pthread_barrierattr_setpshared.c: Likewise.
+ * pthread_barrier_destroy.c: Likewise.
+ * pthread_barrier_init.c: Likewise.
+ * pthread_barrier_wait.c: Likewise.
+ * pthread_cancel.c: Likewise.
+ * pthread_setcancelstate.c: Likewise.
+ * pthread_setcanceltype.c: Likewise.
+ * pthread_testcancel.c: Likewise.
2002-02-04 Max Woodbury <mtew@cds.duke.edu>
@@ -123,19 +246,19 @@
* semaphore.c: All routines are now in separate compilation units;
This file is used to congregate the separate modules for
potential inline optimisation and backward build compatibility.
- * semaphore_close.c: Separated routine from semaphore.c.
- * semaphore_decrease.c: Likewise.
- * semaphore_destroy.c: Likewise.
- * semaphore_getvalue.c: Likewise.
- * semaphore_increase.c: Likewise.
- * semaphore_init.c: Likewise.
- * semaphore_open.c: Likewise.
- * semaphore_post.c: Likewise.
- * semaphore_postmultiple.c: Likewise.
- * semaphore_timedwait.c: Likewise.
- * semaphore_trywait.c: Likewise.
- * semaphore_unlink.c: Likewise.
- * semaphore_wait.c: Likewise.
+ * sem_close.c: Separated routine from semaphore.c.
+ * ptw32_decrease_semaphore.c: Likewise.
+ * sem_destroy.c: Likewise.
+ * sem_getvalue.c: Likewise.
+ * ptw32_increase_semaphore.c: Likewise.
+ * sem_init.c: Likewise.
+ * sem_open.c: Likewise.
+ * sem_post.c: Likewise.
+ * sem_post_multiple.c: Likewise.
+ * sem_timedwait.c: Likewise.
+ * sem_trywait.c: Likewise.
+ * sem_unlink.c: Likewise.
+ * sem_wait.c: Likewise.
2002-02-04 Ross Johnson <rpj@setup1.ise.canberra.edu.au>
@@ -144,17 +267,17 @@
* attr.c: All routines are now in separate compilation units;
This file is used to congregate the separate modules for
potential inline optimisation and backward build compatibility.
- * attr_destroy.c: Separated routine from attr.c.
- * attr_getdetachstate.c: Likewise.
- * attr_getscope.c: Likewise.
- * attr_getstackaddr.c: Likewise.
- * attr_getstacksize.c: Likewise.
- * attr_init.c: Likewise.
- * attr_is_attr.c: Likewise.
- * attr_setdetachstate.c: Likewise.
- * attr_setscope.c: Likewise.
- * attr_setstackaddr.c: Likewise.
- * attr_setstacksize.c: Likewise.
+ * pthread_attr_destroy.c: Separated routine from attr.c.
+ * pthread_attr_getdetachstate.c: Likewise.
+ * pthread_attr_getscope.c: Likewise.
+ * pthread_attr_getstackaddr.c: Likewise.
+ * pthread_attr_getstacksize.c: Likewise.
+ * pthread_attr_init.c: Likewise.
+ * pthread_attr_is_attr.c: Likewise.
+ * pthread_attr_setdetachstate.c: Likewise.
+ * pthread_attr_setscope.c: Likewise.
+ * pthread_attr_setstackaddr.c: Likewise.
+ * pthread_attr_setstacksize.c: Likewise.
* pthread.c: Agregation of agregate modules for super-inlineability.
diff --git a/GNUmakefile b/GNUmakefile
index ddaa96c..ad995ff 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -90,78 +90,133 @@ DLL_OBJS = \
# Separate modules for minimum size statically linked images
SMALL_STATIC_OBJS = \
- attr_is_attr.o \
- attr_init.o \
- attr_destroy.o \
- attr_getdetachstate.o \
- attr_setdetachstate.o \
- attr_getstackaddr.o \
- attr_setstackaddr.o \
- attr_getstacksize.o \
- attr_setstacksize.o \
- attr_getscope.o \
- attr_setscope.o \
- barrier_init.o \
- barrier_destroy.o \
- barrier_wait.o \
- barrier_attr_init.o \
- barrier_attr_destroy.o \
- barrier_attr_setpshared.o \
- barrier_attr_getpshared.o \
- cancel_setcancelstate.o \
- cancel_setcanceltype.o \
- cancel_testcancel.o \
- cancel_cancel.o \
+ 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 \
- condvar_attr_destroy.o \
- condvar_attr_getpshared.o \
- condvar_attr_init.o \
- condvar_attr_setpshared.o \
- condvar_check_need_init.o \
- condvar_destroy.o \
- condvar_init.o \
- condvar_signal.o \
- condvar_wait.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 \
exit.o \
fork.o \
global.o \
- mutex.o \
- np_mutexattr_setkind.o \
- np_mutexattr_getkind.o \
- np_getw32threadhandle.o \
- np_delay.o \
- np_num_processors.o \
- np_win32_attach.o \
- private.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 \
- rwlock.o \
- sched.o \
- semaphore_init.o \
- semaphore_destroy.o \
- semaphore_trywait.o \
- semaphore_timedwait.o \
- semaphore_wait.o \
- semaphore_post.o \
- semaphore_postmultiple.o \
- semaphore_getvalue.o \
- semaphore_increase.o \
- semaphore_decrease.o \
- semaphore_open.o \
- semaphore_close.o \
- semaphore_unlink.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 \
- spin.o \
- sync.o \
- tsd.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
INCL = \
@@ -172,43 +227,42 @@ INCL = \
need_errno.h
ATTR_SRCS = \
- attr_is_attr.c \
- attr_init.c \
- attr_destroy.c \
- attr_getdetachstate.c \
- attr_setdetachstate.c \
- attr_getstackaddr.c \
- attr_setstackaddr.c \
- attr_getstacksize.c \
- attr_setstacksize.c \
- attr_getscope.c \
- attr_setscope.c
+ 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 = \
- barrier_init.c \
- barrier_destroy.c \
- barrier_wait.c \
- barrier_attr_init.c \
- barrier_attr_destroy.c \
- barrier_attr_setpshared.c \
- barrier_attr_getpshared.c
+ 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 = \
- cancel_setcancelstate.c \
- cancel_setcanceltype.c \
- cancel_testcancel.c \
- cancel_cancel.c
+ pthread_setcancelstate.c \
+ pthread_setcanceltype.c \
+ pthread_testcancel.c \
+ pthread_cancel.c
CONDVAR_SRCS = \
- condvar_attr_destroy.c \
- condvar_attr_getpshared.c \
- condvar_attr_init.c \
- condvar_attr_setpshared.c \
- condvar_check_need_init.c \
- condvar_destroy.c \
- condvar_init.c \
- condvar_signal.c \
- condvar_wait.c
+ 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
MISC_SRCS = \
pthread_equal.c \
@@ -220,28 +274,106 @@ MISC_SRCS = \
ptw32_new.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 = \
- np_mutexattr_setkind.c \
- np_mutexattr_getkind.c \
- np_getw32threadhandle.c \
- np_delay.c \
- np_num_processors.c \
- np_win32_attach.c
+ 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_timespec.c \
+ ptw32_throw.c \
+ ptw32_InterlockedCompareExchange.c \
+ ptw32_getprocessors.c
+
+RWLOCK_SRCS = \
+ ptw32_rwlock_check_need_init.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_wrlock.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 = \
- semaphore_init.c \
- semaphore_destroy.c \
- semaphore_trywait.c \
- semaphore_timedwait.c \
- semaphore_wait.c \
- semaphore_post.c \
- semaphore_postmultiple.c \
- semaphore_getvalue.c \
- semaphore_increase.c \
- semaphore_decrease.c \
- semaphore_open.c \
- semaphore_close.c \
- semaphore_unlink.c
+ 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
+
GC_DLL = pthreadGC.dll
GCE_DLL = pthreadGCE.dll
@@ -305,5 +437,12 @@ barrier.o: barrier.c $(BARRIER_SRCS) $(INCL)
cancel.o: cancel.c $(CANCEL_SRCS) $(INCL)
condvar.o: condvar.c $(CONDVAR_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)
diff --git a/Makefile b/Makefile
index 4bb23c7..1a19e97 100644
--- a/Makefile
+++ b/Makefile
@@ -1,253 +1,391 @@
-# This makefile is compatible with MS nmake and can be used as a
-# replacement for buildlib.bat. I've changed the target from an ordinary dll
-# (/LD) to a debugging dll (/LDd).
-#
-# The variables $DLLDEST and $LIBDEST hold the destination directories for the
-# dll and the lib, respectively. Probably all that needs to change is $DEVROOT.
-
-DEVROOT=c:\pthreads
-
-DLLDEST=$(DEVROOT)\DLL
-LIBDEST=$(DEVROOT)\DLL
-
-DLLS = pthreadVCE.dll pthreadVSE.dll pthreadVC.dll
-
-OPTIM = /O2
-
-# C++ Exceptions
-VCEFLAGS = /GX /TP /D__CLEANUP_CXX
-#Structured Exceptions
-VSEFLAGS = /D__CLEANUP_SEH
-#C cleanup code
-VCFLAGS = /D__CLEANUP_C
-
-#CFLAGS = $(OPTIM) /W3 /MT /nologo /Yd /Zi /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H /DTEST_ICE
-CFLAGS = $(OPTIM) /W3 /MT /nologo /Yd /Zi /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H
-
-# Agregate modules for inlinability
-DLL_OBJS = \
- attr.obj \
- barrier.obj \
- cancel.obj \
- cleanup.obj \
- condvar.obj \
- create.obj \
- dll.obj \
- errno.obj \
- exit.obj \
- fork.obj \
- global.obj \
- misc.obj \
- mutex.obj \
- nonportable.obj \
- private.obj \
- rwlock.obj \
- sched.obj \
- semaphore.obj \
- signal.obj \
- spin.obj \
- sync.obj \
- tsd.obj
-
-# Separate modules for minimising the size of statically linked images
-SMALL_STATIC_OBJS = \
- attr_is_attr.obj \
- attr_init.obj \
- attr_destroy.obj \
- attr_getdetachstate.obj \
- attr_setdetachstate.obj \
- attr_getstackaddr.obj \
- attr_setstackaddr.obj \
- attr_getstacksize.obj \
- attr_setstacksize.obj \
- attr_getscope.obj \
- attr_setscope.obj \
- barrier_init.obj \
- barrier_destroy.obj \
- barrier_wait.obj \
- barrier_attr_init.obj \
- barrier_attr_destroy.obj \
- barrier_attr_setpshared.obj \
- barrier_attr_getpshared.obj \
- cancel_setcancelstate.obj \
- cancel_setcanceltype.obj \
- cancel_testcancel.obj \
- cancel_cancel.obj \
- cleanup.obj \
- condvar_attr_destroy.obj \
- condvar_attr_getpshared.obj \
- condvar_attr_init.obj \
- condvar_attr_setpshared.obj \
- condvar_check_need_init.obj \
- condvar_destroy.obj \
- condvar_init.obj \
- condvar_signal.obj \
- condvar_wait.obj \
- create.obj \
- dll.obj \
- errno.obj \
- exit.obj \
- fork.obj \
- global.obj \
- mutex.obj \
- np_mutexattr_setkind.obj \
- np_mutexattr_getkind.obj \
- np_getw32threadhandle.obj \
- np_delay.obj \
- np_num_processors.obj \
- np_win32_attach.obj \
- private.obj \
- pthread_equal.obj \
- pthread_getconcurrency.obj \
- pthread_once.obj \
- pthread_self.obj \
- pthread_setconcurrency.obj \
- ptw32_calloc.obj \
- ptw32_new.obj \
- rwlock.obj \
- sched.obj \
- semaphore_init.obj \
- semaphore_destroy.obj \
- semaphore_trywait.obj \
- semaphore_timedwait.obj \
- semaphore_wait.obj \
- semaphore_post.obj \
- semaphore_postmultiple.obj \
- semaphore_getvalue.obj \
- semaphore_increase.obj \
- semaphore_decrease.obj \
- semaphore_open.obj \
- semaphore_close.obj \
- semaphore_unlink.obj \
- signal.obj \
- spin.obj \
- sync.obj \
- tsd.obj \
- w32_CancelableWait.obj
-
-INCL = config.h implement.h semaphore.h pthread.h need_errno.h
-
-ATTR_SRCS = \
- attr_is_attr.c \
- attr_init.c \
- attr_destroy.c \
- attr_getdetachstate.c \
- attr_setdetachstate.c \
- attr_getstackaddr.c \
- attr_setstackaddr.c \
- attr_getstacksize.c \
- attr_setstacksize.c \
- attr_getscope.c \
- attr_setscope.c
-
-BARRIER_SRCS = \
- barrier_init.c \
- barrier_destroy.c \
- barrier_wait.c \
- barrier_attr_init.c \
- barrier_attr_destroy.c \
- barrier_attr_setpshared.c \
- barrier_attr_getpshared.c
-
-CANCEL_SRCS = \
- cancel_setcancelstate.c \
- cancel_setcanceltype.c \
- cancel_testcancel.c \
- cancel_cancel.c
-
-CONDVAR_SRCS = \
- condvar_attr_destroy.c \
- condvar_attr_getpshared.c \
- condvar_attr_init.c \
- condvar_attr_setpshared.c \
- condvar_check_need_init.c \
- condvar_destroy.c \
- condvar_init.c \
- condvar_signal.c \
- condvar_wait.c
-
-MISC_SRCS = \
- pthread_equal.c \
- pthread_getconcurrency.c \
- pthread_once.c \
- pthread_self.c \
- pthread_setconcurrency.c \
- ptw32_calloc.c \
- ptw32_new.c \
- w32_CancelableWait.c
-
-NONPORTABLE_SRCS = \
- np_mutexattr_setkind.c \
- np_mutexattr_getkind.c \
- np_getw32threadhandle.c \
- np_delay.c \
- np_num_processors.c \
- np_win32_attach.c
-
-SEMAPHORE_SRCS = \
- semaphore_init.c \
- semaphore_destroy.c \
- semaphore_trywait.c \
- semaphore_timedwait.c \
- semaphore_wait.c \
- semaphore_post.c \
- semaphore_postmultiple.c \
- semaphore_getvalue.c \
- semaphore_increase.c \
- semaphore_decrease.c \
- semaphore_open.c \
- semaphore_close.c \
- semaphore_unlink.c
-
-all:
- @ echo Run one of the following command lines:
- @ echo nmake clean VCE (to build the MSVC dll with C++ exception handling)
- @ echo nmake clean VSE (to build the MSVC dll with structured exception handling)
- @ echo nmake clean VC (to build the MSVC dll with C cleanup code)
-
-auto:
- @ nmake clean VCE
- @ nmake clean VSE
- @ nmake clean VC
-
-VCE:
- @ nmake /nologo EHFLAGS="$(VCEFLAGS)" pthreadVCE.dll
-
-VSE:
- @ nmake /nologo EHFLAGS="$(VSEFLAGS)" pthreadVSE.dll
-
-VC:
- @ nmake /nologo EHFLAGS="$(VCFLAGS)" pthreadVC.dll
-
-realclean: clean
- if exist *.dll del *.dll
- if exist *.lib del *.lib
-
-clean:
- if exist *.obj del *.obj
- if exist *.ilk del *.ilk
- if exist *.pdb del *.pdb
- if exist *.exp del *.exp
- if exist *.o del *.o
-
-
-install: $(DLLS)
- copy pthread*.dll $(DLLDEST)
- copy pthread*.lib $(LIBDEST)
-
-$(DLLS): $(DLL_OBJS) pthread.def
- cl /LD /Zi /nologo $(DLL_OBJS) \
- /link /nodefaultlib:libcmt /implib:$*.lib \
- msvcrt.lib wsock32.lib /def:pthread.def /out:$@
-
-.c.obj:
- cl $(EHFLAGS) $(CFLAGS) -c $<
-
-attr.obj: attr.c $(ATTR_SRCS) $(INCL)
-barrier.obj: barrier.c $(BARRIER_SRCS) $(INCL)
-cancel.obj: cancel.c $(CANCEL_SRCS) $(INCL)
-condvar.obj: condvar.c $(CONDVAR_SRCS) $(INCL)
-misc.obj: misc.c $(MISC_SRCS) $(INCL)
-nonportable.obj: nonportable.c $(NONPORTABLE_SRCS) $(INCL)
-semaphore.obj: semaphore.c $(SEMAPHORE_SRCS) $(INCL)
-
+# This makefile is compatible with MS nmake and can be used as a
+# replacement for buildlib.bat. I've changed the target from an ordinary dll
+# (/LD) to a debugging dll (/LDd).
+#
+# The variables $DLLDEST and $LIBDEST hold the destination directories for the
+# dll and the lib, respectively. Probably all that needs to change is $DEVROOT.
+
+DEVROOT=c:\pthreads
+
+DLLDEST=$(DEVROOT)\DLL
+LIBDEST=$(DEVROOT)\DLL
+
+DLLS = pthreadVCE.dll pthreadVSE.dll pthreadVC.dll
+
+OPTIM = /O2
+
+# C++ Exceptions
+VCEFLAGS = /GX /TP /D__CLEANUP_CXX
+#Structured Exceptions
+VSEFLAGS = /D__CLEANUP_SEH
+#C cleanup code
+VCFLAGS = /D__CLEANUP_C
+
+#CFLAGS = $(OPTIM) /W3 /MT /nologo /Yd /Zi /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H /DTEST_ICE
+CFLAGS = $(OPTIM) /W3 /MT /nologo /Yd /Zi /I. /D_WIN32_WINNT=0x400 /DHAVE_CONFIG_H
+
+# Agregate modules for inlinability
+DLL_OBJS = \
+ attr.obj \
+ barrier.obj \
+ cancel.obj \
+ cleanup.obj \
+ condvar.obj \
+ create.obj \
+ dll.obj \
+ errno.obj \
+ exit.obj \
+ fork.obj \
+ global.obj \
+ misc.obj \
+ mutex.obj \
+ nonportable.obj \
+ private.obj \
+ rwlock.obj \
+ sched.obj \
+ semaphore.obj \
+ signal.obj \
+ spin.obj \
+ sync.obj \
+ tsd.obj
+
+# Separate modules for minimising the size of statically linked images
+SMALL_STATIC_OBJS = \
+ pthread_attr_init.obj \
+ pthread_attr_destroy.obj \
+ pthread_attr_getdetachstate.obj \
+ pthread_attr_setdetachstate.obj \
+ pthread_attr_getstackaddr.obj \
+ pthread_attr_setstackaddr.obj \
+ pthread_attr_getstacksize.obj \
+ pthread_attr_setstacksize.obj \
+ pthread_attr_getscope.obj \
+ pthread_attr_setscope.obj \
+ pthread_attr_setschedpolicy.obj \
+ pthread_attr_getschedpolicy.obj \
+ pthread_attr_setschedparam.obj \
+ pthread_attr_getschedparam.obj \
+ pthread_attr_setinheritsched.obj \
+ pthread_attr_getinheritsched.obj \
+ pthread_barrier_init.obj \
+ pthread_barrier_destroy.obj \
+ pthread_barrier_wait.obj \
+ pthread_barrierattr_init.obj \
+ pthread_barrierattr_destroy.obj \
+ pthread_barrierattr_setpshared.obj \
+ pthread_barrierattr_getpshared.obj \
+ pthread_setcancelstate.obj \
+ pthread_setcanceltype.obj \
+ pthread_testcancel.obj \
+ pthread_cancel.obj \
+ cleanup.obj \
+ pthread_condattr_destroy.obj \
+ pthread_condattr_getpshared.obj \
+ pthread_condattr_init.obj \
+ pthread_condattr_setpshared.obj \
+ pthread_cond_destroy.obj \
+ pthread_cond_init.obj \
+ pthread_cond_signal.obj \
+ pthread_cond_wait.obj \
+ create.obj \
+ dll.obj \
+ errno.obj \
+ exit.obj \
+ fork.obj \
+ global.obj \
+ pthread_mutex_init.obj \
+ pthread_mutex_destroy.obj \
+ pthread_mutexattr_init.obj \
+ pthread_mutexattr_destroy.obj \
+ pthread_mutexattr_getpshared.obj \
+ pthread_mutexattr_setpshared.obj \
+ pthread_mutexattr_settype.obj \
+ pthread_mutexattr_gettype.obj \
+ pthread_mutex_lock.obj \
+ pthread_mutex_timedlock.obj \
+ pthread_mutex_unlock.obj \
+ pthread_mutex_trylock.obj \
+ pthread_mutexattr_setkind_np.obj \
+ pthread_mutexattr_getkind_np.obj \
+ pthread_getw32threadhandle_np.obj \
+ pthread_delay_np.obj \
+ pthread_num_processors_np.obj \
+ pthread_win32_attach_detach_np.obj \
+ pthread_equal.obj \
+ pthread_getconcurrency.obj \
+ pthread_once.obj \
+ pthread_self.obj \
+ pthread_setconcurrency.obj \
+ pthread_rwlock_init.obj \
+ pthread_rwlock_destroy.obj \
+ pthread_rwlockattr_init.obj \
+ pthread_rwlockattr_destroy.obj \
+ pthread_rwlockattr_getpshared.obj \
+ pthread_rwlockattr_setpshared.obj \
+ pthread_rwlock_rdlock.obj \
+ pthread_rwlock_wrlock.obj \
+ pthread_rwlock_unlock.obj \
+ pthread_rwlock_tryrdlock.obj \
+ pthread_rwlock_trywrlock.obj \
+ pthread_setschedparam.obj \
+ pthread_getschedparam.obj \
+ pthread_timechange_handler_np.obj \
+ ptw32_is_attr.obj \
+ ptw32_processInitialize.obj \
+ ptw32_processTerminate.obj \
+ ptw32_threadStart.obj \
+ ptw32_threadDestroy.obj \
+ ptw32_tkAssocCreate.obj \
+ ptw32_tkAssocDestroy.obj \
+ ptw32_callUserDestroyRoutines.obj \
+ ptw32_timespec.obj \
+ ptw32_throw.obj \
+ ptw32_InterlockedCompareExchange.obj \
+ ptw32_getprocessors.obj \
+ ptw32_calloc.obj \
+ ptw32_new.obj \
+ ptw32_rwlock_check_need_init.obj \
+ ptw32_cond_check_need_init.obj \
+ ptw32_mutex_check_need_init.obj \
+ sched_get_priority_max.obj \
+ sched_get_priority_min.obj \
+ sched_setscheduler.obj \
+ sched_getscheduler.obj \
+ sched_yield.obj \
+ sem_init.obj \
+ sem_destroy.obj \
+ sem_trywait.obj \
+ sem_timedwait.obj \
+ sem_wait.obj \
+ sem_post.obj \
+ sem_post_multiple.obj \
+ sem_getvalue.obj \
+ sem_open.obj \
+ sem_close.obj \
+ sem_unlink.obj \
+ ptw32_increase_semaphore.obj \
+ ptw32_decrease_semaphore.obj \
+ signal.obj \
+ ptw32_spinlock_check_need_init.obj \
+ pthread_spin_init.obj \
+ pthread_spin_destroy.obj \
+ pthread_spin_lock.obj \
+ pthread_spin_unlock.obj \
+ pthread_spin_trylock.obj \
+ pthread_detach.obj \
+ pthread_join.obj \
+ pthread_key_create.obj \
+ pthread_key_delete.obj \
+ pthread_setspecific.obj \
+ pthread_getspecific.obj \
+ w32_CancelableWait.obj
+
+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
+
+MISC_SRCS = \
+ pthread_equal.c \
+ pthread_getconcurrency.c \
+ pthread_once.c \
+ pthread_self.c \
+ pthread_setconcurrency.c \
+ ptw32_calloc.c \
+ ptw32_new.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_timespec.c \
+ ptw32_throw.c \
+ ptw32_InterlockedCompareExchange.c \
+ ptw32_getprocessors.c
+
+RWLOCK_SRCS = \
+ ptw32_rwlock_check_need_init.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_wrlock.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
+
+
+all:
+ @ echo Run one of the following command lines:
+ @ echo nmake clean VCE (to build the MSVC dll with C++ exception handling)
+ @ echo nmake clean VSE (to build the MSVC dll with structured exception handling)
+ @ echo nmake clean VC (to build the MSVC dll with C cleanup code)
+
+auto:
+ @ nmake clean VCE
+ @ nmake clean VSE
+ @ nmake clean VC
+
+VCE:
+ @ nmake /nologo EHFLAGS="$(VCEFLAGS)" pthreadVCE.dll
+
+VSE:
+ @ nmake /nologo EHFLAGS="$(VSEFLAGS)" pthreadVSE.dll
+
+VC:
+ @ nmake /nologo EHFLAGS="$(VCFLAGS)" pthreadVC.dll
+
+realclean: clean
+ if exist *.dll del *.dll
+ if exist *.lib del *.lib
+
+clean:
+ if exist *.obj del *.obj
+ if exist *.ilk del *.ilk
+ if exist *.pdb del *.pdb
+ if exist *.exp del *.exp
+ if exist *.o del *.o
+
+
+install: $(DLLS)
+ copy pthread*.dll $(DLLDEST)
+ copy pthread*.lib $(LIBDEST)
+
+$(DLLS): $(DLL_OBJS) pthread.def
+ cl /LD /Zi /nologo $(DLL_OBJS) \
+ /link /nodefaultlib:libcmt /implib:$*.lib \
+ msvcrt.lib wsock32.lib /def:pthread.def /out:$@
+
+.c.obj:
+ cl $(EHFLAGS) $(CFLAGS) -c $<
+
+attr.obj: attr.c $(ATTR_SRCS) $(INCL)
+barrier.obj: barrier.c $(BARRIER_SRCS) $(INCL)
+cancel.obj: cancel.c $(CANCEL_SRCS) $(INCL)
+condvar.obj: condvar.c $(CONDVAR_SRCS) $(INCL)
+misc.obj: misc.c $(MISC_SRCS) $(INCL)
+mutex.obj: mutex.c $(MUTEX_SRCS) $(INCL)
+nonportable.obj: nonportable.c $(NONPORTABLE_SRCS) $(INCL)
+private.obj: private.c $(PRIVATE_SRCS) $(INCL)
+rwlock.obj: rwlock.c $(RWLOCK_SRCS) $(INCL)
+sched.obj: sched.c $(SCHED_SRCS) $(INCL)
+semaphore.obj: semaphore.c $(SEMAPHORE_SRCS) $(INCL)
+spin.obj: spin.c $(SPIN_SRCS) $(INCL)
+sync.obj: sync.c $(SYNC_SRCS) $(INCL)
+tsd.obj: tsd.c $(TSD_SRCS) $(INCL)
diff --git a/Nmakefile.tests b/Nmakefile.tests
index b604551..6ca0b5c 100644
--- a/Nmakefile.tests
+++ b/Nmakefile.tests
@@ -1,196 +1,200 @@
-/* for running tests */
-CCFLAGS = -g
-_MT == 1
-_timeb == timeb
-_ftime == ftime
-
-.SOURCE: tests
-/*
-:PACKAGE: pthread
-*/
-
-set keepgoing
-
-":test:" : .MAKE .OPERATOR
- local I
- $(<:D:B:S=.pass) : .IMPLICIT $(>:D:B:S=.pass)
- for I $(<) $(>)
- $(I:D:B:S=.pass) : .VIRTUAL .FORCE $(I)
- $(>)
- end
-loadfree:: loadfree.c
-mutex1:: mutex1.c
-mutex1e:: mutex1e.c
-mutex1n:: mutex1n.c
-mutex1r:: mutex1r.c
-mutex2:: mutex1.2
-exit1:: exit1.c
-condvar1:: condvar1.c
-self1:: self1.c
-condvar2:: condvar2.c
-condvar2_1:: condvar2_1.c
-condvar3_1:: condvar3_1.c
-condvar3_2:: condvar3_2.c
-condvar3_3:: condvar3_3.c
-create1.:: create1.c
-cancel1:: cancel1.c
-cancel2:: cancel2.c
-mutex3:: mutex3.c
-mutex4:: mutex4.c
-mutex5:: mutex5.c
-mutex6:: mutex6.c
-mutex6e:: mutex6e.c
-mutex6n:: mutex6n.c
-mutex6r:: mutex6r.c
-mutex7:: mutex7.c
-mutex7e:: mutex7e.c
-mutex7n:: mutex7n.c
-mutex7r:: mutex7r.c
-mutex8:: mutex8.c
-mutex8e:: mutex8e.c
-mutex8n:: mutex8n.c
-mutex8r:: mutex8r.c
-equal1:: equal1.c
-exit2:: exit2.c
-exit3:: exit3.c
-exit4:: exit4.c
-join0:: join0.c
-join1:: join1.c
-join2:: join2.c
-count1:: count1.c
-once1:: once1.c
-tsd1:: tsd1.c
-self2:: self2.c
-eyal1:: eyal1.c
-condvar3:: condvar3.c
-condvar4:: condvar4.c
-condvar5:: condvar5.c
-condvar6:: condvar6.c
-condvar7:: condvar7.c
-condvar8:: condvar8.c
-condvar9:: condvar9.c
-errno1:: errno1.c
-rwlock1:: rwlock1.c
-rwlock2:: rwlock2.c
-rwlock3:: rwlock3.c
-rwlock4:: rwlock4.c
-rwlock5:: rwlock5.c
-rwlock6:: rwlock6.c
-rwlock7:: rwlock7.c
-context1:: context1.c
-cancel3:: cancel3.c
-cancel4:: cancel4.c
-cancel5:: cancel5.c
-cancel6a:: cancel6a.c
-cancel6d:: cancel6d.c
-cleanup0:: cleanup0.c
-cleanup1:: cleanup1.c
-cleanup2:: cleanup2.c
-cleanup3:: cleanup3.c
-priority1:: priority1.c
-priority2:: priority2.c
-inherit1:: inherit1.c
-spin1:: spin1.c
-spin2:: spin2.c
-spin3:: spin3.c
-spin4:: spin4.c
-barrier1:: barrier1.c
-barrier2:: barrier2.c
-barrier3:: barrier3.c
-barrier4:: barrier4.c
-barrier5:: barrier5.c
-exception1:: exception1.c
-exception2:: exception2.c
-exception3:: exception3.c
-benchtest1:: benchtest1.c
-benchtest2:: benchtest2.c
-benchtest3:: benchtest3.c
-benchtest4:: benchtest4.c
-benchtest5:: benchtest5.c
-
-loadfree: :test:
-mutex5 :test: loadfree
-mutex1 :test: loadfree
-mutex2 :test: loadfree
-exit1 :test: loadfree
-condvar1 :test: loadfree
-self1 :test: loadfree
-condvar2 :test: condvar1
-condvar2_1 :test: condvar2
-create1 :test: mutex2
-cancel1 :test: create1
-cancel2 :test: cancel1
-mutex3 :test: create1
-mutex4 :test: mutex3
-mutex6 :test: mutex4
-mutex6n :test: mutex4
-mutex6e :test: mutex4
-mutex6r :test: mutex4
-mutex7 :test: mutex6
-mutex7n :test: mutex6n
-mutex7e :test: mutex6e
-mutex7r :test: mutex6r
-mutex8 :test: mutex7
-mutex8n :test: mutex7n
-mutex8e :test: mutex7e
-mutex8r :test: mutex7r
-equal1 :test: create1
-exit2 :test: create1
-exit3 :test: create1
-join0 :test: create1
-join1 :test: create1
-join2 :test: create1
-count1 :test: join1
-once1 :test: create1
-tsd1 :test: join1
-self2 :test: create1
-eyal1 :test: tsd1
-condvar3 :test: create1
-condvar3_1 :test: condvar3
-condvar3_2 :test: condvar3_1
-condvar3_3 :test: condvar3_2
-condvar4 :test: create1
-condvar5 :test: condvar4
-condvar6 :test: condvar5
-condvar7 :test: condvar6 cleanup1
-condvar8 :test: condvar7
-condvar9 :test: condvar8
-errno1 :test: mutex3
-rwlock1 :test: condvar6
-rwlock2 :test: rwlock1
-rwlock3 :test: rwlock2
-rwlock4 :test: rwlock3
-rwlock5 :test: rwlock4
-rwlock6 :test: rwlock5
-context1 :test: cancel2
-cancel3 :test: context1
-cancel4 :test: cancel3
-cancel5 :test: cancel3
-cancel6a :test: cancel3
-cancel6d :test: cancel3
-cleanup0 :test: cancel5
-cleanup1 :test: cleanup0
-cleanup2 :test: cleanup1
-cleanup3 :test: cleanup2
-priority1 :test: join1
-priority2 :test: priority1
-inherit1 :test: join1
-spin1 :test:
-spin2 :test: spin1.c
-spin3 :test: spin2.c
-spin4 :test: spin3.c
-barrier1 :test:
-barrier2 :test: barrier1.c
-barrier3 :test: barrier2.c
-barrier4 :test: barrier3.c
-barrier5 :test: barrier4.c
-benchtest1 :test: mutex3
-benchtest2 :test: benchtest1
-benchtest3 :test: benchtest2
-benchtest4 :test: benchtest3
-benchtest5 :test: benchtest4
-exception1 :test: cancel4
-exception2 :test: exception1
-exception3 :test: exception2
-exit4 :test: exit3
-
+/* for running tests */
+CCFLAGS = -g
+_MT == 1
+_timeb == timeb
+_ftime == ftime
+
+.SOURCE: tests
+/*
+:PACKAGE: pthread
+*/
+
+set keepgoing
+
+":test:" : .MAKE .OPERATOR
+ local I
+ $(<:D:B:S=.pass) : .IMPLICIT $(>:D:B:S=.pass)
+ for I $(<) $(>)
+ $(I:D:B:S=.pass) : .VIRTUAL .FORCE $(I)
+ $(>)
+ end
+loadfree:: loadfree.c
+mutex1:: mutex1.c
+mutex1e:: mutex1e.c
+mutex1n:: mutex1n.c
+mutex1r:: mutex1r.c
+mutex2:: mutex1.2
+exit1:: exit1.c
+condvar1:: condvar1.c
+condvar1_1:: condvar1_1.c
+condvar1_2:: condvar1_2.c
+self1:: self1.c
+condvar2:: condvar2.c
+condvar2_1:: condvar2_1.c
+condvar3_1:: condvar3_1.c
+condvar3_2:: condvar3_2.c
+condvar3_3:: condvar3_3.c
+create1.:: create1.c
+cancel1:: cancel1.c
+cancel2:: cancel2.c
+mutex3:: mutex3.c
+mutex4:: mutex4.c
+mutex5:: mutex5.c
+mutex6:: mutex6.c
+mutex6e:: mutex6e.c
+mutex6n:: mutex6n.c
+mutex6r:: mutex6r.c
+mutex7:: mutex7.c
+mutex7e:: mutex7e.c
+mutex7n:: mutex7n.c
+mutex7r:: mutex7r.c
+mutex8:: mutex8.c
+mutex8e:: mutex8e.c
+mutex8n:: mutex8n.c
+mutex8r:: mutex8r.c
+equal1:: equal1.c
+exit2:: exit2.c
+exit3:: exit3.c
+exit4:: exit4.c
+join0:: join0.c
+join1:: join1.c
+join2:: join2.c
+count1:: count1.c
+once1:: once1.c
+tsd1:: tsd1.c
+self2:: self2.c
+eyal1:: eyal1.c
+condvar3:: condvar3.c
+condvar4:: condvar4.c
+condvar5:: condvar5.c
+condvar6:: condvar6.c
+condvar7:: condvar7.c
+condvar8:: condvar8.c
+condvar9:: condvar9.c
+errno1:: errno1.c
+rwlock1:: rwlock1.c
+rwlock2:: rwlock2.c
+rwlock3:: rwlock3.c
+rwlock4:: rwlock4.c
+rwlock5:: rwlock5.c
+rwlock6:: rwlock6.c
+rwlock7:: rwlock7.c
+context1:: context1.c
+cancel3:: cancel3.c
+cancel4:: cancel4.c
+cancel5:: cancel5.c
+cancel6a:: cancel6a.c
+cancel6d:: cancel6d.c
+cleanup0:: cleanup0.c
+cleanup1:: cleanup1.c
+cleanup2:: cleanup2.c
+cleanup3:: cleanup3.c
+priority1:: priority1.c
+priority2:: priority2.c
+inherit1:: inherit1.c
+spin1:: spin1.c
+spin2:: spin2.c
+spin3:: spin3.c
+spin4:: spin4.c
+barrier1:: barrier1.c
+barrier2:: barrier2.c
+barrier3:: barrier3.c
+barrier4:: barrier4.c
+barrier5:: barrier5.c
+exception1:: exception1.c
+exception2:: exception2.c
+exception3:: exception3.c
+benchtest1:: benchtest1.c
+benchtest2:: benchtest2.c
+benchtest3:: benchtest3.c
+benchtest4:: benchtest4.c
+benchtest5:: benchtest5.c
+
+loadfree: :test:
+mutex5 :test: loadfree
+mutex1 :test: loadfree
+mutex2 :test: loadfree
+exit1 :test: loadfree
+condvar1 :test: loadfree
+condvar1_1 :test: condvar1
+condvar1_2 :test: join2
+self1 :test: loadfree
+condvar2 :test: condvar1
+condvar2_1 :test: condvar2
+create1 :test: mutex2
+cancel1 :test: create1
+cancel2 :test: cancel1
+mutex3 :test: create1
+mutex4 :test: mutex3
+mutex6 :test: mutex4
+mutex6n :test: mutex4
+mutex6e :test: mutex4
+mutex6r :test: mutex4
+mutex7 :test: mutex6
+mutex7n :test: mutex6n
+mutex7e :test: mutex6e
+mutex7r :test: mutex6r
+mutex8 :test: mutex7
+mutex8n :test: mutex7n
+mutex8e :test: mutex7e
+mutex8r :test: mutex7r
+equal1 :test: create1
+exit2 :test: create1
+exit3 :test: create1
+join0 :test: create1
+join1 :test: create1
+join2 :test: create1
+count1 :test: join1
+once1 :test: create1
+tsd1 :test: join1
+self2 :test: create1
+eyal1 :test: tsd1
+condvar3 :test: create1
+condvar3_1 :test: condvar3
+condvar3_2 :test: condvar3_1
+condvar3_3 :test: condvar3_2
+condvar4 :test: create1
+condvar5 :test: condvar4
+condvar6 :test: condvar5
+condvar7 :test: condvar6 cleanup1
+condvar8 :test: condvar7
+condvar9 :test: condvar8
+errno1 :test: mutex3
+rwlock1 :test: condvar6
+rwlock2 :test: rwlock1
+rwlock3 :test: rwlock2
+rwlock4 :test: rwlock3
+rwlock5 :test: rwlock4
+rwlock6 :test: rwlock5
+context1 :test: cancel2
+cancel3 :test: context1
+cancel4 :test: cancel3
+cancel5 :test: cancel3
+cancel6a :test: cancel3
+cancel6d :test: cancel3
+cleanup0 :test: cancel5
+cleanup1 :test: cleanup0
+cleanup2 :test: cleanup1
+cleanup3 :test: cleanup2
+priority1 :test: join1
+priority2 :test: priority1
+inherit1 :test: join1
+spin1 :test:
+spin2 :test: spin1.c
+spin3 :test: spin2.c
+spin4 :test: spin3.c
+barrier1 :test:
+barrier2 :test: barrier1.c
+barrier3 :test: barrier2.c
+barrier4 :test: barrier3.c
+barrier5 :test: barrier4.c
+benchtest1 :test: mutex3
+benchtest2 :test: benchtest1
+benchtest3 :test: benchtest2
+benchtest4 :test: benchtest3
+benchtest5 :test: benchtest4
+exception1 :test: cancel4
+exception2 :test: exception1
+exception3 :test: exception2
+exit4 :test: exit3
+
diff --git a/attr.c b/attr.c
index e74f4dc..dfae24d 100644
--- a/attr.c
+++ b/attr.c
@@ -41,15 +41,14 @@
#include "pthread.h"
#include "implement.h"
-#include "attr_is_attr.c"
-#include "attr_init.c"
-#include "attr_destroy.c"
-#include "attr_getdetachstate.c"
-#include "attr_setdetachstate.c"
-#include "attr_getstackaddr.c"
-#include "attr_setstackaddr.c"
-#include "attr_getstacksize.c"
-#include "attr_setstacksize.c"
-#include "attr_getscope.c"
-#include "attr_setscope.c"
+#include "pthread_attr_init.c"
+#include "pthread_attr_destroy.c"
+#include "pthread_attr_getdetachstate.c"
+#include "pthread_attr_setdetachstate.c"
+#include "pthread_attr_getstackaddr.c"
+#include "pthread_attr_setstackaddr.c"
+#include "pthread_attr_getstacksize.c"
+#include "pthread_attr_setstacksize.c"
+#include "pthread_attr_getscope.c"
+#include "pthread_attr_setscope.c"
diff --git a/barrier.c b/barrier.c
index 762d742..e948306 100644
--- a/barrier.c
+++ b/barrier.c
@@ -38,11 +38,11 @@
#include "implement.h"
-#include "barrier_init.c"
-#include "barrier_destroy.c"
-#include "barrier_wait.c"
-#include "barrier_attr_init.c"
-#include "barrier_attr_destroy.c"
-#include "barrier_attr_getpshared.c"
-#include "barrier_attr_setpshared.c"
+#include "pthread_barrier_init.c"
+#include "pthread_barrier_destroy.c"
+#include "pthread_barrier_wait.c"
+#include "pthread_barrierattr_init.c"
+#include "pthread_barrierattr_destroy.c"
+#include "pthread_barrierattr_getpshared.c"
+#include "pthread_barrierattr_setpshared.c"
diff --git a/cancel.c b/cancel.c
index 92a18d7..1e50446 100644
--- a/cancel.c
+++ b/cancel.c
@@ -38,8 +38,8 @@
#include "implement.h"
-#include "cancel_setcancelstate.c"
-#include "cancel_setcanceltype.c"
-#include "cancel_testcancel.c"
-#include "cancel_cancel.c"
+#include "pthread_setcancelstate.c"
+#include "pthread_setcanceltype.c"
+#include "pthread_testcancel.c"
+#include "pthread_cancel.c"
diff --git a/condvar.c b/condvar.c
index 59878b2..560ed01 100644
--- a/condvar.c
+++ b/condvar.c
@@ -39,14 +39,12 @@
#include "pthread.h"
#include "implement.h"
-#include "condvar_check_need_init.c"
-#include "condvar_attr_init.c"
-#include "condvar_attr_destroy.c"
-#include "condvar_attr_getpshared.c"
-#include "condvar_attr_setpshared.c"
-#include "condvar_init.c"
-#include "condvar_destroy.c"
-#include "condvar_wait.c"
-#include "condvar_timedwait.c"
-#include "condvar_signal.c"
-#include "condvar_broadcast.c"
+#include "ptw32_cond_check_need_init.c"
+#include "pthread_condattr_init.c"
+#include "pthread_condattr_destroy.c"
+#include "pthread_condattr_getpshared.c"
+#include "pthread_condattr_setpshared.c"
+#include "pthread_cond_init.c"
+#include "pthread_cond_destroy.c"
+#include "pthread_cond_wait.c"
+#include "pthread_cond_signal.c"
diff --git a/global.c b/global.c
index 33a29fe..d541aa4 100644
--- a/global.c
+++ b/global.c
@@ -42,6 +42,8 @@
int ptw32_processInitialized = FALSE;
pthread_key_t ptw32_selfThreadKey = NULL;
pthread_key_t ptw32_cleanupKey = NULL;
+pthread_cond_t ptw32_cond_list_head = NULL;
+pthread_cond_t ptw32_cond_list_tail = NULL;
int ptw32_concurrency = 0;
@@ -77,6 +79,13 @@ CRITICAL_SECTION ptw32_rwlock_test_init_lock;
*/
CRITICAL_SECTION ptw32_spinlock_test_init_lock;
+/*
+ * Global lock for condition variable linked list. The list exists
+ * to wake up CVs when a WM_TIMECHANGE message arrives. See
+ * w32_TimeChangeHandler.c.
+ */
+CRITICAL_SECTION ptw32_cond_list_lock;
+
#ifdef _UWIN
/*
* Keep a count of the number of threads.
diff --git a/implement.h b/implement.h
index c6cef70..a564105 100644
--- a/implement.h
+++ b/implement.h
@@ -7,32 +7,32 @@
*
* --------------------------------------------------------------------------
*
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
*
- * Contact Email: rpj@ise.canberra.edu.au
+ * Contact Email: rpj@ise.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
+ * 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 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.
+ * 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
+ * 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
*/
#ifndef _IMPLEMENT_H
@@ -83,14 +83,14 @@ typedef enum {
* The thread is still "alive" if the numeric value of the
* state is greater or equal "PThreadStateRunning".
*/
- PThreadStateInitial = 0, /* Thread not running */
- PThreadStateRunning, /* Thread alive & kicking */
- PThreadStateSuspended, /* Thread alive but suspended */
- PThreadStateCanceling, /* Thread alive but and is */
- /* in the process of terminating */
- /* due to a cancellation request */
- PThreadStateException, /* Thread alive but exiting */
- /* due to an exception */
+ PThreadStateInitial = 0, /* Thread not running */
+ PThreadStateRunning, /* Thread alive & kicking */
+ PThreadStateSuspended, /* Thread alive but suspended */
+ PThreadStateCanceling, /* Thread alive but and is */
+ /* in the process of terminating */
+ /* due to a cancellation request */
+ PThreadStateException, /* Thread alive but exiting */
+ /* due to an exception */
PThreadStateLast
}
PThreadState;
@@ -101,11 +101,11 @@ typedef enum {
* This enumeration represents the reason why a thread has
* terminated/is terminating.
*/
- PThreadDemisePeaceful = 0, /* Death due natural causes */
- PThreadDemiseCancelled, /* Death due to user cancel */
- PThreadDemiseException, /* Death due to unhandled */
- /* exception */
- PThreadDemiseNotDead /* I'm not dead! */
+ PThreadDemisePeaceful = 0, /* Death due natural causes */
+ PThreadDemiseCancelled, /* Death due to user cancel */
+ PThreadDemiseException, /* Death due to unhandled */
+ /* exception */
+ PThreadDemiseNotDead /* I'm not dead! */
}
PThreadDemise;
@@ -177,19 +177,19 @@ struct sem_t_ {
#define PTW32_OBJECT_INVALID NULL
struct pthread_mutex_t_ {
- LONG lock_idx; /* Provides exclusive access to mutex state
- via the Interlocked* mechanism, as well
- as a count of the number of threads
- waiting on the mutex. */
- int recursive_count; /* Number of unlocks a thread needs to perform
- before the lock is released (recursive
- mutexes only). */
- int kind; /* Mutex type. */
+ LONG lock_idx; /* Provides exclusive access to mutex state
+ via the Interlocked* mechanism, as well
+ as a count of the number of threads
+ waiting on the mutex. */
+ int recursive_count; /* Number of unlocks a thread needs to perform
+ before the lock is released (recursive
+ mutexes only). */
+ int kind; /* Mutex type. */
pthread_t ownerThread;
- sem_t wait_sema; /* Mutex release notification to waiting
- threads. */
+ sem_t wait_sema; /* Mutex release notification to waiting
+ threads. */
CRITICAL_SECTION wait_cs; /* Serialise lock_idx decrement after mutex
- timeout. */
+ timeout. */
};
struct pthread_mutexattr_t_ {
@@ -219,10 +219,10 @@ struct pthread_mutexattr_t_ {
#define PTW32_SPIN_USE_MUTEX (3)
struct pthread_spinlock_t_ {
- long interlock; /* Locking element for multi-cpus. */
+ long interlock; /* Locking element for multi-cpus. */
union {
- int cpus; /* No. of cpus if multi cpus, or */
- pthread_mutex_t mutex; /* mutex if single cpu. */
+ int cpus; /* No. of cpus if multi cpus, or */
+ pthread_mutex_t mutex; /* mutex if single cpu. */
} u;
};
@@ -257,17 +257,19 @@ struct ThreadParms {
struct pthread_cond_t_ {
- long nWaitersBlocked; /* Number of threads blocked */
- long nWaitersGone; /* Number of threads timed out */
- long nWaitersToUnblock; /* Number of threads to unblock */
- sem_t semBlockQueue; /* Queue up threads waiting for the */
- /* condition to become signalled */
- sem_t semBlockLock; /* Semaphore that guards access to */
- /* | waiters blocked count/block queue */
- /* +-> Mandatory Sync.LEVEL-1 */
- pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */
- /* | waiters (to)unblock(ed) counts */
- /* +-> Optional* Sync.LEVEL-2 */
+ long nWaitersBlocked; /* Number of threads blocked */
+ long nWaitersGone; /* Number of threads timed out */
+ long nWaitersToUnblock; /* Number of threads to unblock */
+ sem_t semBlockQueue; /* Queue up threads waiting for the */
+ /* condition to become signalled */
+ sem_t semBlockLock; /* Semaphore that guards access to */
+ /* | waiters blocked count/block queue */
+ /* +-> Mandatory Sync.LEVEL-1 */
+ pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */
+ /* | waiters (to)unblock(ed) counts */
+ /* +-> Optional* Sync.LEVEL-2 */
+ pthread_cond_t next; /* Doubly linked list */
+ pthread_cond_t prev;
};
@@ -281,65 +283,65 @@ struct pthread_rwlock_t_ {
pthread_mutex_t mtxExclusiveAccess;
pthread_mutex_t mtxSharedAccessCompleted;
pthread_cond_t cndSharedAccessCompleted;
- int nSharedAccessCount;
- int nExclusiveAccessCount;
- int nCompletedSharedAccessCount;
- int nMagic;
+ int nSharedAccessCount;
+ int nExclusiveAccessCount;
+ int nCompletedSharedAccessCount;
+ int nMagic;
};
struct pthread_rwlockattr_t_ {
- int pshared;
+ int pshared;
};
struct ThreadKeyAssoc {
/*
* Purpose:
- * This structure creates an association between a
- * thread and a key.
- * It is used to implement the implicit invocation
- * of a user defined destroy routine for thread
- * specific data registered by a user upon exiting a
- * thread.
+ * This structure creates an association between a
+ * thread and a key.
+ * It is used to implement the implicit invocation
+ * of a user defined destroy routine for thread
+ * specific data registered by a user upon exiting a
+ * thread.
*
* Attributes:
- * lock
- * protects access to the rest of the structure
+ * lock
+ * protects access to the rest of the structure
*
- * thread
- * reference to the thread that owns the association.
- * As long as this is not NULL, the association remains
- * referenced by the pthread_t.
+ * thread
+ * reference to the thread that owns the association.
+ * As long as this is not NULL, the association remains
+ * referenced by the pthread_t.
*
- * key
- * reference to the key that owns the association.
- * As long as this is not NULL, the association remains
- * referenced by the pthread_key_t.
+ * key
+ * reference to the key that owns the association.
+ * As long as this is not NULL, the association remains
+ * referenced by the pthread_key_t.
*
- * nextKey
- * The pthread_t->keys attribute is the head of a
- * chain of associations that runs through the nextKey
- * link. This chain provides the 1 to many relationship
- * between a pthread_t and all pthread_key_t on which
- * it called pthread_setspecific.
+ * nextKey
+ * The pthread_t->keys attribute is the head of a
+ * chain of associations that runs through the nextKey
+ * link. This chain provides the 1 to many relationship
+ * between a pthread_t and all pthread_key_t on which
+ * it called pthread_setspecific.
*
- * nextThread
- * The pthread_key_t->threads attribute is the head of
- * a chain of assoctiations that runs through the
- * nextThreads link. This chain provides the 1 to many
- * relationship between a pthread_key_t and all the
- * PThreads that have called pthread_setspecific for
- * this pthread_key_t.
+ * nextThread
+ * The pthread_key_t->threads attribute is the head of
+ * a chain of assoctiations that runs through the
+ * nextThreads link. This chain provides the 1 to many
+ * relationship between a pthread_key_t and all the
+ * PThreads that have called pthread_setspecific for
+ * this pthread_key_t.
*
*
* Notes:
- * 1) As long as one of the attributes, thread or key, is
- * not NULL, the association is being referenced; once
- * both are NULL, the association must be released.
+ * 1) As long as one of the attributes, thread or key, is
+ * not NULL, the association is being referenced; once
+ * both are NULL, the association must be released.
*
- * 2) Under WIN32, an association is only created by
- * pthread_setspecific if the user provided a
- * destroyRoutine when they created the key.
+ * 2) Under WIN32, an association is only created by
+ * pthread_setspecific if the user provided a
+ * destroyRoutine when they created the key.
*
*
*/
@@ -355,27 +357,27 @@ struct ThreadKeyAssoc {
/*
* --------------------------------------------------------------
* MAKE_SOFTWARE_EXCEPTION
- * This macro constructs a software exception code following
- * the same format as the standard Win32 error codes as defined
- * in WINERROR.H
+ * This macro constructs a software exception code following
+ * the same format as the standard Win32 error codes as defined
+ * in WINERROR.H
* Values are 32 bit values layed out as follows:
*
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* +---+-+-+-----------------------+-------------------------------+
- * |Sev|C|R| Facility | Code |
+ * |Sev|C|R| Facility | Code |
* +---+-+-+-----------------------+-------------------------------+
*
* Severity Values:
*/
-#define SE_SUCCESS 0x00
-#define SE_INFORMATION 0x01
-#define SE_WARNING 0x02
-#define SE_ERROR 0x03
+#define SE_SUCCESS 0x00
+#define SE_INFORMATION 0x01
+#define SE_WARNING 0x02
+#define SE_ERROR 0x03
#define MAKE_SOFTWARE_EXCEPTION( _severity, _facility, _exception ) \
( (DWORD) ( ( (_severity) << 30 ) | /* Severity code */ \
- ( 1 << 29 ) | /* MS=0, User=1 */ \
- ( 0 << 28 ) | /* Reserved */ \
+ ( 1 << 29 ) | /* MS=0, User=1 */ \
+ ( 0 << 28 ) | /* Reserved */ \
( (_facility) << 16 ) | /* Facility Code */ \
( (_exception) << 0 ) /* Exception Code */ \
) )
@@ -391,8 +393,8 @@ struct ThreadKeyAssoc {
PTW32_SERVICES_FACILITY, \
PTW32_SERVICES_ERROR )
-#define PTW32_SERVICES_FACILITY 0xBAD
-#define PTW32_SERVICES_ERROR 0xDEED
+#define PTW32_SERVICES_FACILITY 0xBAD
+#define PTW32_SERVICES_ERROR 0xDEED
#endif /* __CLEANUP_SEH */
@@ -402,8 +404,8 @@ struct ThreadKeyAssoc {
* generic exception selectors.
*/
-#define PTW32_EPS_EXIT (1)
-#define PTW32_EPS_CANCEL (2)
+#define PTW32_EPS_EXIT (1)
+#define PTW32_EPS_CANCEL (2)
/* Mutex constants */
enum {
@@ -413,24 +415,27 @@ enum {
/* Useful macros */
-#define PTW32_MAX(a,b) ((a)<(b)?(b):(a))
-#define PTW32_MIN(a,b) ((a)>(b)?(b):(a))
+#define PTW32_MAX(a,b) ((a)<(b)?(b):(a))
+#define PTW32_MIN(a,b) ((a)>(b)?(b):(a))
/* Declared in global.c */
extern PTW32_INTERLOCKED_LONG (WINAPI *ptw32_interlocked_compare_exchange)(PTW32_INTERLOCKED_LPLONG,
- PTW32_INTERLOCKED_LONG,
- PTW32_INTERLOCKED_LONG);
+ PTW32_INTERLOCKED_LONG,
+ PTW32_INTERLOCKED_LONG);
extern int ptw32_processInitialized;
extern pthread_key_t ptw32_selfThreadKey;
extern pthread_key_t ptw32_cleanupKey;
+extern pthread_cond_t ptw32_cond_list_head;
+extern pthread_cond_t ptw32_cond_list_tail;
extern int ptw32_mutex_default_kind;
extern int ptw32_concurrency;
extern CRITICAL_SECTION ptw32_mutex_test_init_lock;
+extern CRITICAL_SECTION ptw32_cond_list_lock;
extern CRITICAL_SECTION ptw32_cond_test_init_lock;
extern CRITICAL_SECTION ptw32_rwlock_test_init_lock;
extern CRITICAL_SECTION ptw32_spinlock_test_init_lock;
@@ -459,10 +464,17 @@ extern "C" {
* =====================
* =====================
*/
+
+int ptw32_is_attr (const pthread_attr_t *attr);
+
+int ptw32_cond_check_need_init(pthread_cond_t *cond);
+int ptw32_mutex_check_need_init(pthread_mutex_t *mutex);
+int ptw32_rwlock_check_need_init(pthread_rwlock_t *rwlock);
+
PTW32_INTERLOCKED_LONG WINAPI
ptw32_InterlockedCompareExchange(PTW32_INTERLOCKED_LPLONG location,
- PTW32_INTERLOCKED_LONG value,
- PTW32_INTERLOCKED_LONG comparand);
+ PTW32_INTERLOCKED_LONG value,
+ PTW32_INTERLOCKED_LONG comparand);
int ptw32_processInitialize (void);
@@ -495,9 +507,14 @@ void ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc);
#ifdef NEED_SEM
void ptw32_decrease_semaphore(sem_t * sem);
BOOL ptw32_increase_semaphore(sem_t * sem,
- unsigned int n);
+ unsigned int n);
#endif /* NEED_SEM */
+#ifdef NEED_FTIME
+void ptw32_timespec_to_filetime(const struct timespec *ts, FILETIME *ft);
+void ptw32_filetime_to_timespec(const FILETIME *ft, struct timespec *ts);
+#endif
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
@@ -542,7 +559,7 @@ BOOL ptw32_increase_semaphore(sem_t * sem,
arg, \
flags, \
pid) \
- CreateThread(security, \
+ CreateThread(security, \
stack_size, \
(LPTHREAD_START_ROUTINE) start_proc, \
arg, \
diff --git a/misc.c b/misc.c
index 4e3b286..8aa7f96 100644
--- a/misc.c
+++ b/misc.c
@@ -43,7 +43,7 @@
#include "pthread_equal.c"
#include "pthread_setconcurrency.c"
#include "pthread_getconcurrency.c"
-#include "w32_CancelableWait.c"
#include "ptw32_new.c"
#include "ptw32_calloc.c"
+#include "w32_CancelableWait.c"
diff --git a/mutex.c b/mutex.c
index fa48760..6bf6acd 100644
--- a/mutex.c
+++ b/mutex.c
@@ -44,1073 +44,19 @@
#include "implement.h"
-static INLINE int
-ptw32_mutex_check_need_init(pthread_mutex_t *mutex)
-{
- int result = 0;
+#include "ptw32_mutex_check_need_init.c"
+#include "pthread_mutex_init.c"
+#include "pthread_mutex_destroy.c"
+#include "pthread_mutexattr_init.c"
+#include "pthread_mutexattr_destroy.c"
+#include "pthread_mutexattr_getpshared.c"
+#include "pthread_mutexattr_setpshared.c"
+#include "pthread_mutexattr_settype.c"
+#include "pthread_mutexattr_gettype.c"
+#include "pthread_mutex_lock.c"
+#include "pthread_mutex_timedlock.c"
+#include "pthread_mutex_unlock.c"
+#include "pthread_mutex_trylock.c"
- /*
- * The following guarded test is specifically for statically
- * initialised mutexes (via PTHREAD_MUTEX_INITIALIZER).
- *
- * Note that by not providing this synchronisation we risk
- * introducing race conditions into applications which are
- * correctly written.
- *
- * Approach
- * --------
- * We know that static mutexes will not be PROCESS_SHARED
- * so we can serialise access to internal state using
- * Win32 Critical Sections rather than Win32 Mutexes.
- *
- * If using a single global lock slows applications down too much,
- * multiple global locks could be created and hashed on some random
- * value associated with each mutex, the pointer perhaps. At a guess,
- * a good value for the optimal number of global locks might be
- * the number of processors + 1.
- *
- */
- EnterCriticalSection(&ptw32_mutex_test_init_lock);
-
- /*
- * We got here possibly under race
- * conditions. Check again inside the critical section
- * and only initialise if the mutex is valid (not been destroyed).
- * If a static mutex has been destroyed, the application can
- * re-initialise it only by calling pthread_mutex_init()
- * explicitly.
- */
- if (*mutex == PTHREAD_MUTEX_INITIALIZER)
- {
- result = pthread_mutex_init(mutex, NULL);
- }
- else if (*mutex == NULL)
- {
- /*
- * The mutex has been destroyed while we were waiting to
- * initialise it, so the operation that caused the
- * auto-initialisation should fail.
- */
- result = EINVAL;
- }
-
- LeaveCriticalSection(&ptw32_mutex_test_init_lock);
-
- return(result);
-}
-
-int
-pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
-{
- int result = 0;
- pthread_mutex_t mx;
-
- if (mutex == NULL)
- {
- return EINVAL;
- }
-
- if (attr != NULL
- && *attr != NULL
- && (*attr)->pshared == PTHREAD_PROCESS_SHARED
- )
- {
- /*
- * Creating mutex that can be shared between
- * processes.
- */
-#if _POSIX_THREAD_PROCESS_SHARED
-
- /*
- * Not implemented yet.
- */
-
-#error ERROR [__FILE__, line __LINE__]: Process shared mutexes are not supported yet.
-
-#else
-
- return ENOSYS;
-
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
-
- }
-
- mx = (pthread_mutex_t) calloc(1, sizeof(*mx));
-
- if (mx == NULL)
- {
- result = ENOMEM;
- }
- else
- {
- mx->lock_idx = PTW32_MUTEX_LOCK_IDX_INIT;
- mx->recursive_count = 0;
- mx->kind = (attr == NULL || *attr == NULL
- ? PTHREAD_MUTEX_DEFAULT
- : (*attr)->kind);
- mx->ownerThread = NULL;
-
- if ( 0 != sem_init( &mx->wait_sema, 0, 0 ))
- {
- result = EAGAIN;
- free(mx);
- mx = NULL;
- }
- else
- {
- InitializeCriticalSection( &mx->wait_cs );
- }
- }
-
- *mutex = mx;
-
- return(result);
-}
-
-int
-pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
- int result = 0;
- pthread_mutex_t mx;
-
- if (mutex == NULL
- || *mutex == NULL)
- {
- return EINVAL;
- }
-
- /*
- * Check to see if we have something to delete.
- */
- if (*mutex != PTHREAD_MUTEX_INITIALIZER)
- {
- mx = *mutex;
-
- result = pthread_mutex_trylock(&mx);
-
- /*
- * The mutex type may not be RECURSIVE therefore trylock may return EBUSY if
- * we already own the mutex. Here we are assuming that it's OK to destroy
- * a mutex that we own and have locked recursively. Is this correct?
- *
- * For FAST mutexes we record the owner as ANONYMOUS for speed. In this
- * case we assume that the thread calling pthread_mutex_destroy() is the
- * owner, if the mutex is owned at all.
- */
- if (result == 0
- || mx->ownerThread == (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS
- || pthread_equal( mx->ownerThread, pthread_self() ) )
- {
- /*
- * FIXME!!!
- * The mutex isn't held by another thread but we could still
- * be too late invalidating the mutex below since another thread
- * may already have entered mutex_lock and the check for a valid
- * *mutex != NULL.
- */
- *mutex = NULL;
-
- result = pthread_mutex_unlock(&mx);
-
- if (result == 0)
- {
- (void) sem_destroy( &mx->wait_sema );
- DeleteCriticalSection( &mx->wait_cs );
- free(mx);
- }
- else
- {
- /*
- * Restore the mutex before we return the error.
- */
- *mutex = mx;
- }
- }
- }
- else
- {
- /*
- * See notes in ptw32_mutex_check_need_init() above also.
- */
- EnterCriticalSection(&ptw32_mutex_test_init_lock);
-
- /*
- * Check again.
- */
- if (*mutex == PTHREAD_MUTEX_INITIALIZER)
- {
- /*
- * This is all we need to do to destroy a statically
- * initialised mutex that has not yet been used (initialised).
- * If we get to here, another thread
- * waiting to initialise this mutex will get an EINVAL.
- */
- *mutex = NULL;
- }
- else
- {
- /*
- * The mutex has been initialised while we were waiting
- * so assume it's in use.
- */
- result = EBUSY;
- }
-
- LeaveCriticalSection(&ptw32_mutex_test_init_lock);
- }
-
- return(result);
-}
-
-int
-pthread_mutexattr_init (pthread_mutexattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Initializes a mutex attributes object with default
- * attributes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- *
- * DESCRIPTION
- * Initializes a mutex attributes object with default
- * attributes.
- *
- * NOTES:
- * 1) Used to define mutex types
- *
- * RESULTS
- * 0 successfully initialized attr,
- * ENOMEM insufficient memory for attr.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- pthread_mutexattr_t ma;
-
- ma = (pthread_mutexattr_t) calloc (1, sizeof (*ma));
-
- if (ma == NULL)
- {
- result = ENOMEM;
- }
- else
- {
- ma->pshared = PTHREAD_PROCESS_PRIVATE;
- ma->kind = PTHREAD_MUTEX_DEFAULT;
- }
-
- *attr = ma;
-
- return(result);
-} /* pthread_mutexattr_init */
-
-
-int
-pthread_mutexattr_destroy (pthread_mutexattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Destroys a mutex attributes object. The object can
- * no longer be used.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- *
- * DESCRIPTION
- * Destroys a mutex attributes object. The object can
- * no longer be used.
- *
- * NOTES:
- * 1) Does not affect mutexes created using 'attr'
- *
- * RESULTS
- * 0 successfully released attr,
- * EINVAL 'attr' is invalid.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
-
- if (attr == NULL || *attr == NULL)
- {
- result = EINVAL;
- }
- else
- {
- pthread_mutexattr_t ma = *attr;
-
- *attr = NULL;
- free (ma);
- }
-
- return(result);
-} /* pthread_mutexattr_destroy */
-
-
-int
-pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr,
- int *pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Determine whether mutexes created with 'attr' can be
- * shared between processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- * pshared
- * will be set to one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- *
- * DESCRIPTION
- * Mutexes creatd with 'attr' can be shared between
- * processes if pthread_mutex_t variable is allocated
- * in memory shared by these processes.
- * NOTES:
- * 1) pshared mutexes MUST be allocated in shared
- * memory.
- * 2) The following macro is defined if shared mutexes
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully retrieved attribute,
- * EINVAL 'attr' is invalid,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL) &&
- (pshared != NULL))
- {
- *pshared = (*attr)->pshared;
- result = 0;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-
-} /* pthread_mutexattr_getpshared */
-
-
-int
-pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
- int pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Mutexes created with 'attr' can be shared between
- * processes if pthread_mutex_t variable is allocated
- * in memory shared by these processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- * pshared
- * must be one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- * DESCRIPTION
- * Mutexes creatd with 'attr' can be shared between
- * processes if pthread_mutex_t variable is allocated
- * in memory shared by these processes.
- *
- * NOTES:
- * 1) pshared mutexes MUST be allocated in shared
- * memory.
- *
- * 2) The following macro is defined if shared mutexes
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully set attribute,
- * EINVAL 'attr' or pshared is invalid,
- * ENOSYS PTHREAD_PROCESS_SHARED not supported,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL) &&
- ((pshared == PTHREAD_PROCESS_SHARED) ||
- (pshared == PTHREAD_PROCESS_PRIVATE)))
- {
- if (pshared == PTHREAD_PROCESS_SHARED)
- {
-
-#if !defined( _POSIX_THREAD_PROCESS_SHARED )
-
- result = ENOSYS;
- pshared = PTHREAD_PROCESS_PRIVATE;
-
-#else
-
- result = 0;
-
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
-
- }
- else
- {
- result = 0;
- }
-
- (*attr)->pshared = pshared;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-
-} /* pthread_mutexattr_setpshared */
-
-
-int
-pthread_mutexattr_settype (pthread_mutexattr_t * attr,
- int kind)
- /*
- * ------------------------------------------------------
- *
- * DOCPUBLIC
- * The pthread_mutexattr_settype() and
- * pthread_mutexattr_gettype() functions respectively set and
- * get the mutex type attribute. This attribute is set in the
- * type parameter to these functions.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_mutexattr_t
- *
- * type
- * must be one of:
- *
- * PTHREAD_MUTEX_DEFAULT
- *
- * PTHREAD_MUTEX_NORMAL
- *
- * PTHREAD_MUTEX_ERRORCHECK
- *
- * PTHREAD_MUTEX_RECURSIVE
- *
- * DESCRIPTION
- * The pthread_mutexattr_settype() and
- * pthread_mutexattr_gettype() functions respectively set and
- * get the mutex type attribute. This attribute is set in the
- * type parameter to these functions. The default value of the
- * type attribute is PTHREAD_MUTEX_DEFAULT.
- *
- * The type of mutex is contained in the type attribute of the
- * mutex attributes. Valid mutex types include:
- *
- * PTHREAD_MUTEX_NORMAL
- * This type of mutex does not detect deadlock. A
- * thread attempting to relock this mutex without
- * first unlocking it will deadlock. Attempting to
- * unlock a mutex locked by a different thread
- * results in undefined behavior. Attempting to
- * unlock an unlocked mutex results in undefined
- * behavior.
- *
- * PTHREAD_MUTEX_ERRORCHECK
- * This type of mutex provides error checking. A
- * thread attempting to relock this mutex without
- * first unlocking it will return with an error. A
- * thread attempting to unlock a mutex which another
- * thread has locked will return with an error. A
- * thread attempting to unlock an unlocked mutex will
- * return with an error.
- *
- * PTHREAD_MUTEX_DEFAULT
- * Same as PTHREAD_MUTEX_NORMAL.
- *
- * PTHREAD_MUTEX_RECURSIVE
- * A thread attempting to relock this mutex without
- * first unlocking it will succeed in locking the
- * mutex. The relocking deadlock which can occur with
- * mutexes of type PTHREAD_MUTEX_NORMAL cannot occur
- * with this type of mutex. Multiple locks of this
- * mutex require the same number of unlocks to
- * release the mutex before another thread can
- * acquire the mutex. A thread attempting to unlock a
- * mutex which another thread has locked will return
- * with an error. A thread attempting to unlock an
- * unlocked mutex will return with an error. This
- * type of mutex is only supported for mutexes whose
- * process shared attribute is
- * PTHREAD_PROCESS_PRIVATE.
- *
- * RESULTS
- * 0 successfully set attribute,
- * EINVAL 'attr' or 'type' is invalid,
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
-
- if ((attr != NULL && *attr != NULL))
- {
- switch (kind)
- {
- case PTHREAD_MUTEX_FAST_NP:
- case PTHREAD_MUTEX_RECURSIVE_NP:
- case PTHREAD_MUTEX_ERRORCHECK_NP:
- (*attr)->kind = kind;
- break;
- default:
- result = EINVAL;
- break;
- }
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-} /* pthread_mutexattr_settype */
-
-
-int
-pthread_mutexattr_gettype (pthread_mutexattr_t * attr,
- int *kind)
-{
- int result = 0;
-
- if (attr != NULL && *attr != NULL && kind != NULL)
- {
- *kind = (*attr)->kind;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-}
-
-
-static INLINE int
-ptw32_timed_semwait (sem_t * sem, const struct timespec * abstime)
- /*
- * ------------------------------------------------------
- * DESCRIPTION
- * This function waits on a POSIX semaphore. If the
- * semaphore value is greater than zero, it decreases
- * its value by one. If the semaphore value is zero, then
- * the calling thread (or process) is blocked until it can
- * successfully decrease the value or until abstime.
- * If abstime has passed when this routine is called then
- * it returns a result to indicate this.
- *
- * If 'abstime' is a NULL pointer then this function will
- * block until it can successfully decrease the value or
- * until interrupted by a signal.
- *
- * RESULTS
- * 2 abstime has passed already
- * 1 abstime timed out while waiting
- * 0 successfully decreased semaphore,
- * -1 failed, error in errno.
- * ERRNO
- * EINVAL 'sem' is not a valid semaphore,
- * ENOSYS semaphores are not supported,
- * EINTR the function was interrupted by a signal,
- * EDEADLK a deadlock condition was detected.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
-
-#ifdef NEED_FTIME
-
- struct timespec currSysTime;
-
-#else /* NEED_FTIME */
-
- struct _timeb currSysTime;
-
-#endif /* NEED_FTIME */
-
- const DWORD NANOSEC_PER_MILLISEC = 1000000;
- const DWORD MILLISEC_PER_SEC = 1000;
- DWORD milliseconds;
- DWORD status;
-
- if (sem == NULL)
- {
- result = EINVAL;
- }
- else
- {
- if (abstime == NULL)
- {
- milliseconds = INFINITE;
- }
- else
- {
- /*
- * Calculate timeout as milliseconds from current system time.
- */
-
- /* get current system time */
-
-#ifdef NEED_FTIME
-
- {
- FILETIME ft;
- SYSTEMTIME st;
-
- GetSystemTime(&st);
- SystemTimeToFileTime(&st, &ft);
- /*
- * GetSystemTimeAsFileTime(&ft); would be faster,
- * but it does not exist on WinCE
- */
-
- filetime_to_timespec(&ft, &currSysTime);
- }
-
- /*
- * subtract current system time from abstime
- */
- milliseconds = (abstime->tv_sec - currSysTime.tv_sec) * MILLISEC_PER_SEC;
- milliseconds += ((abstime->tv_nsec - currSysTime.tv_nsec) + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;
-
-#else /* NEED_FTIME */
- _ftime(&currSysTime);
-
- /*
- * subtract current system time from abstime
- */
- milliseconds = (abstime->tv_sec - currSysTime.time) * MILLISEC_PER_SEC;
- milliseconds += ((abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC) -
- currSysTime.millitm;
-
-#endif /* NEED_FTIME */
-
-
- if (((int) milliseconds) < 0)
- {
- return 2;
- }
- }
-
-#ifdef NEED_SEM
-
- status = WaitForSingleObject( (*sem)->event, milliseconds );
-
-#else /* NEED_SEM */
-
- status = WaitForSingleObject( (*sem)->sem, milliseconds );
-
-#endif
-
- if (status == WAIT_OBJECT_0)
- {
-
-#ifdef NEED_SEM
-
- ptw32_decrease_semaphore(sem);
-
-#endif /* NEED_SEM */
-
- return 0;
- }
- else if (status == WAIT_TIMEOUT)
- {
- return 1;
- }
- else
- {
- result = EINVAL;
- }
- }
-
- if (result != 0)
- {
- errno = result;
- return -1;
- }
-
- return 0;
-
-} /* ptw32_timed_semwait */
-
-
-int
-pthread_mutex_lock(pthread_mutex_t *mutex)
-{
- int result = 0;
- pthread_mutex_t mx;
-
-
- if (mutex == NULL || *mutex == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static mutex. We check
- * again inside the guarded section of ptw32_mutex_check_need_init()
- * to avoid race conditions.
- */
- if (*mutex == PTHREAD_MUTEX_INITIALIZER)
- {
- if ((result = ptw32_mutex_check_need_init(mutex)) != 0)
- {
- return(result);
- }
- }
-
- mx = *mutex;
-
- if( 0 == InterlockedIncrement( &mx->lock_idx ) )
- {
- mx->recursive_count = 1;
- mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
- ? pthread_self()
- : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
- }
- else
- {
- if( mx->kind != PTHREAD_MUTEX_FAST_NP &&
- pthread_equal( mx->ownerThread, pthread_self() ) )
- {
- (void) InterlockedDecrement( &mx->lock_idx );
-
- if( mx->kind == PTHREAD_MUTEX_RECURSIVE_NP )
- {
- mx->recursive_count++;
- }
- else
- {
- result = EDEADLK;
- }
- }
- else
- {
- if ((result = sem_wait( &mx->wait_sema )) == 0)
- {
- mx->recursive_count = 1;
- mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
- ? pthread_self()
- : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
- }
- }
- }
-
- return(result);
-}
-
-
-int
-pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime)
-{
- int result = 0;
- pthread_mutex_t mx;
-
-#ifdef NEED_SEM
- errno = ENOTSUP;
- return -1;
-#endif
-
- if (mutex == NULL || *mutex == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static mutex. We check
- * again inside the guarded section of ptw32_mutex_check_need_init()
- * to avoid race conditions.
- */
- if (*mutex == PTHREAD_MUTEX_INITIALIZER)
- {
- if ((result = ptw32_mutex_check_need_init(mutex)) != 0)
- {
- return(result);
- }
- }
-
- mx = *mutex;
-
- if( 0 == InterlockedIncrement( &mx->lock_idx ) )
- {
- mx->recursive_count = 1;
- mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
- ? pthread_self()
- : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
- }
- else
- {
- if( mx->kind != PTHREAD_MUTEX_FAST_NP &&
- pthread_equal( mx->ownerThread, pthread_self() ) )
- {
- (void) InterlockedDecrement( &mx->lock_idx );
-
- if( mx->kind == PTHREAD_MUTEX_RECURSIVE_NP )
- {
- mx->recursive_count++;
- }
- else
- {
- result = EDEADLK;
- }
- }
- else
- {
- if (abstime == NULL)
- {
- result = EINVAL;
- }
- else
- {
- switch (ptw32_timed_semwait( &mx->wait_sema, abstime ))
- {
- case 0: /* We got the mutex. */
- {
- mx->recursive_count = 1;
- mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
- ? pthread_self()
- : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
- break;
- }
- case 1: /* Timedout, try a second grab. */
- {
- EnterCriticalSection(&mx->wait_cs);
-
- /*
- * If we timeout, it is up to us to adjust lock_idx to say
- * we're no longer waiting. If the mutex was also unlocked
- * while we were timing out, and we simply return ETIMEDOUT,
- * then wait_sema would be left in a state that is not consistent
- * with the state of lock_idx.
- *
- * We must check to see if wait_sema has just been posted
- * but we can't just call sem_getvalue - we must compete for
- * the semaphore using sem_trywait(), otherwise we would need
- * additional critical sections elsewhere, which would make the
- * logic too inefficient.
- *
- * If sem_trywait returns EAGAIN then either wait_sema
- * was given directly to another waiting thread or
- * another thread has called sem_*wait() before us and
- * taken the lock. Then we MUST decrement lock_idx and return
- * ETIMEDOUT.
- *
- * Otherwise we MUST return success (because we have effectively
- * acquired the lock that would have been ours had we not
- * timed out), and NOT decrement lock_idx.
- *
- * We can almost guarrantee that EAGAIN is the only
- * possible error, so no need to test errno.
- */
-
- if ( -1 == sem_trywait( &mx->wait_sema ) )
- {
- (void) InterlockedDecrement( &mx->lock_idx );
- result = ETIMEDOUT;
- }
-
- LeaveCriticalSection(&mx->wait_cs);
- break;
- }
- case 2: /* abstime passed before we started to wait. */
- {
- /*
- * If we timeout, it is up to us to adjust lock_idx to say
- * we're no longer waiting.
- *
- * The owner thread may still have posted wait_sema thinking
- * we were waiting. I believe we must check but then NOT do any
- * programmed work if we have acquired the mutex because
- * we don't how long ago abstime was. We MUST just release it
- * immediately.
- */
- EnterCriticalSection(&mx->wait_cs);
-
- result = ETIMEDOUT;
-
- if ( -1 == sem_trywait( &mx->wait_sema ) )
- {
- (void) InterlockedDecrement( &mx->lock_idx );
- }
- else
- {
- if ( InterlockedDecrement( &mx->lock_idx ) >= 0 )
- {
- /* Someone else is waiting on that mutex */
- if ( sem_post( &mx->wait_sema ) != 0 )
- {
- result = errno;
- }
- }
- }
-
- LeaveCriticalSection(&mx->wait_cs);
- break;
- }
- default:
- {
- result = errno;
- break;
- }
- }
- }
- }
- }
-
- return(result);
-}
-
-
-int
-pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
- int result = 0;
- pthread_mutex_t mx;
-
- if (mutex == NULL || *mutex == NULL)
- {
- return EINVAL;
- }
-
- mx = *mutex;
-
- /*
- * If the thread calling us holds the mutex then there is no
- * race condition. If another thread holds the
- * lock then we shouldn't be in here.
- */
- if (mx != PTHREAD_MUTEX_INITIALIZER)
- {
- if (mx->ownerThread == (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS
- || pthread_equal(mx->ownerThread, pthread_self()))
- {
- if( mx->kind != PTHREAD_MUTEX_RECURSIVE_NP
- || 0 == --mx->recursive_count )
- {
- mx->ownerThread = NULL;
- EnterCriticalSection( &mx->wait_cs );
-
- if( InterlockedDecrement( &mx->lock_idx ) >= 0 )
- {
- /* Someone is waiting on that mutex */
- if (sem_post( &mx->wait_sema ) != 0)
- {
- result = errno;
- }
- }
-
- LeaveCriticalSection( &mx->wait_cs );
- }
- }
- else
- {
- result = EPERM;
- }
- }
- else
- {
- result = EINVAL;
- }
-
- return(result);
-}
-
-int
-pthread_mutex_trylock(pthread_mutex_t *mutex)
-{
- int result = 0;
- pthread_mutex_t mx;
-
- if (mutex == NULL || *mutex == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static mutex. We check
- * again inside the guarded section of ptw32_mutex_check_need_init()
- * to avoid race conditions.
- */
- if (*mutex == PTHREAD_MUTEX_INITIALIZER)
- {
- result = ptw32_mutex_check_need_init(mutex);
- }
-
- mx = *mutex;
-
- if (result == 0)
- {
- if ( (PTW32_INTERLOCKED_LONG) PTW32_MUTEX_LOCK_IDX_INIT ==
- ptw32_interlocked_compare_exchange((PTW32_INTERLOCKED_LPLONG) &mx->lock_idx,
- (PTW32_INTERLOCKED_LONG) 0,
- (PTW32_INTERLOCKED_LONG) PTW32_MUTEX_LOCK_IDX_INIT))
- {
- mx->recursive_count = 1;
- mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
- ? pthread_self()
- : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
- }
- else
- {
- if( mx->kind != PTHREAD_MUTEX_FAST_NP &&
- pthread_equal( mx->ownerThread, pthread_self() ) )
- {
- if( mx->kind == PTHREAD_MUTEX_RECURSIVE_NP )
- {
- mx->recursive_count++;
- }
- else
- {
- result = EDEADLK;
- }
- }
- else
- {
- result = EBUSY;
- }
- }
- }
-
- return(result);
-}
diff --git a/nonportable.c b/nonportable.c
index 4c8b449..8e0e507 100644
--- a/nonportable.c
+++ b/nonportable.c
@@ -37,9 +37,11 @@
#include "pthread.h"
#include "implement.h"
-#include "np_mutexattr_setkind.c"
-#include "np_mutexattr_getkind.c"
-#include "np_getw32threadhandle.c"
-#include "np_delay.c"
-#include "np_num_processors.c"
-#include "np_win32_attach.c"
+#include "pthread_mutexattr_setkind_np.c"
+#include "pthread_mutexattr_getkind_np.c"
+#include "pthread_getw32threadhandle_np.c"
+#include "pthread_delay_np.c"
+#include "pthread_num_processors_np.c"
+#include "pthread_win32_attach_detach_np.c"
+#include "pthread_timechange_handler_np.c"
+
diff --git a/private.c b/private.c
index e0ca43a..19a7aeb 100644
--- a/private.c
+++ b/private.c
@@ -36,974 +36,18 @@
*/
#include "pthread.h"
-#include "semaphore.h"
#include "implement.h"
-int
-ptw32_processInitialize (void)
- /*
- * ------------------------------------------------------
- * DOCPRIVATE
- * This function performs process wide initialization for
- * the pthread library.
- *
- * PARAMETERS
- * N/A
- *
- * DESCRIPTION
- * This function performs process wide initialization for
- * the pthread library.
- * If successful, this routine sets the global variable
- * ptw32_processInitialized to TRUE.
- *
- * RESULTS
- * TRUE if successful,
- * FALSE otherwise
- *
- * ------------------------------------------------------
- */
-{
- if (ptw32_processInitialized) {
- /*
- * ignore if already initialized. this is useful for
- * programs that uses a non-dll pthread
- * library. such programs must call ptw32_processInitialize() explicitely,
- * since this initialization routine is automatically called only when
- * the dll is loaded.
- */
- return TRUE;
- }
-
- ptw32_processInitialized = TRUE;
-
- /*
- * Initialize Keys
- */
- if ((pthread_key_create (&ptw32_selfThreadKey, NULL) != 0) ||
- (pthread_key_create (&ptw32_cleanupKey, NULL) != 0))
- {
-
- ptw32_processTerminate ();
- }
-
- /*
- * Set up the global test and init check locks.
- */
- InitializeCriticalSection(&ptw32_mutex_test_init_lock);
- InitializeCriticalSection(&ptw32_cond_test_init_lock);
- InitializeCriticalSection(&ptw32_rwlock_test_init_lock);
- InitializeCriticalSection(&ptw32_spinlock_test_init_lock);
-
- return (ptw32_processInitialized);
-
-} /* processInitialize */
-
-void
-ptw32_processTerminate (void)
- /*
- * ------------------------------------------------------
- * DOCPRIVATE
- * This function performs process wide termination for
- * the pthread library.
- *
- * PARAMETERS
- * N/A
- *
- * DESCRIPTION
- * This function performs process wide termination for
- * the pthread library.
- * This routine sets the global variable
- * ptw32_processInitialized to FALSE
- *
- * RESULTS
- * N/A
- *
- * ------------------------------------------------------
- */
-{
- if (ptw32_processInitialized)
- {
-
- if (ptw32_selfThreadKey != NULL)
- {
- /*
- * Release ptw32_selfThreadKey
- */
- pthread_key_delete (ptw32_selfThreadKey);
-
- ptw32_selfThreadKey = NULL;
- }
-
- if (ptw32_cleanupKey != NULL)
- {
- /*
- * Release ptw32_cleanupKey
- */
- pthread_key_delete (ptw32_cleanupKey);
-
- ptw32_cleanupKey = NULL;
- }
-
- /*
- * Destroy the global test and init check locks.
- */
- DeleteCriticalSection(&ptw32_spinlock_test_init_lock);
- DeleteCriticalSection(&ptw32_rwlock_test_init_lock);
- DeleteCriticalSection(&ptw32_cond_test_init_lock);
- DeleteCriticalSection(&ptw32_mutex_test_init_lock);
-
- ptw32_processInitialized = FALSE;
- }
-
-} /* processTerminate */
-
-#ifdef __CLEANUP_SEH
-
-static DWORD
-ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
-{
- switch (ep->ExceptionRecord->ExceptionCode)
- {
- case EXCEPTION_PTW32_SERVICES:
- {
- DWORD param;
- DWORD numParams = ep->ExceptionRecord->NumberParameters;
-
- numParams = (numParams > 3) ? 3 : numParams;
-
- for (param = 0; param < numParams; param++)
- {
- ei[param] = ep->ExceptionRecord->ExceptionInformation[param];
- }
-
- return EXCEPTION_EXECUTE_HANDLER;
- break;
- }
- default:
- {
- /*
- * A system unexpected exception has occurred running the user's
- * routine. We need to cleanup before letting the exception
- * out of thread scope.
- */
- pthread_t self = pthread_self();
-
- (void) pthread_mutex_destroy(&self->cancelLock);
- ptw32_callUserDestroyRoutines(self);
-
- return EXCEPTION_CONTINUE_SEARCH;
- break;
- }
- }
-}
-
-#elif defined(__CLEANUP_CXX)
-
-#if defined(_MSC_VER)
-#include <eh.h>
-static terminate_function ptw32_oldTerminate;
-#else
-#include <new.h>
-static terminate_handler ptw32_oldTerminate;
-#endif
-
-#if 0
-#include <stdio.h>
-static pthread_mutex_t termLock = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-void
-ptw32_terminate ()
-{
- pthread_t self = pthread_self();
-#if 0
- FILE * fp;
- pthread_mutex_lock(&termLock);
- fp = fopen("pthread.log", "a");
- fprintf(fp, "Terminate\n");
- fclose(fp);
- pthread_mutex_unlock(&termLock);
-#endif
- set_terminate(ptw32_oldTerminate);
- (void) pthread_mutex_destroy(&self->cancelLock);
- ptw32_callUserDestroyRoutines(self);
- terminate();
-}
-
-#endif /* _MSC_VER */
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
-unsigned __stdcall
-#else
-void
-#endif
-ptw32_threadStart (void * vthreadParms)
-{
- ThreadParms *threadParms = (ThreadParms *) vthreadParms;
- pthread_t self;
- void *(*start) (void *);
- void *arg;
-
-#ifdef __CLEANUP_SEH
- DWORD ei[] = {0,0,0};
-#endif
-
-#ifdef __CLEANUP_C
- int setjmp_rc;
-#endif
-
- void * status = (void *) 0;
-
- self = threadParms->tid;
- start = threadParms->start;
- arg = threadParms->arg;
-
- free (threadParms);
-
-#if defined (__MINGW32__) && ! defined (__MSVCRT__)
- /*
- * beginthread does not return the thread id and is running
- * before it returns us the thread handle, and so we do it here.
- */
- self->thread = GetCurrentThreadId ();
- /*
- * Here we're using cancelLock as a general-purpose lock
- * to make the new thread wait until the creating thread
- * has the new handle.
- */
- if (pthread_mutex_lock(&self->cancelLock) == 0)
- {
- (void) pthread_mutex_unlock(&self->cancelLock);
- }
-#endif
-
- pthread_setspecific (ptw32_selfThreadKey, self);
-
- self->state = PThreadStateRunning;
-
-#ifdef __CLEANUP_SEH
-
- __try
- {
- /*
- * Run the caller's routine;
- */
- status = self->exitStatus = (*start) (arg);
-
-#ifdef _UWIN
- if (--pthread_count <= 0)
- exit(0);
-#endif
-
- }
- __except (ExceptionFilter(GetExceptionInformation(), ei))
- {
- switch (ei[0])
- {
- case PTW32_EPS_CANCEL:
- status = PTHREAD_CANCELED;
-#ifdef _UWIN
- if (--pthread_count <= 0)
- exit(0);
-#endif
- break;
- case PTW32_EPS_EXIT:
- status = self->exitStatus;
- break;
- default:
- status = PTHREAD_CANCELED;
- break;
- }
- }
-
-#else /* __CLEANUP_SEH */
-
-#ifdef __CLEANUP_C
-
- setjmp_rc = setjmp( self->start_mark );
-
- if( 0 == setjmp_rc ) {
-
- /*
- * Run the caller's routine;
- */
- status = self->exitStatus = (*start) (arg);
- }
-
- else {
-
- switch (setjmp_rc)
- {
- case PTW32_EPS_CANCEL:
- status = PTHREAD_CANCELED;
- break;
- case PTW32_EPS_EXIT:
- status = self->exitStatus;
- break;
- default:
- status = PTHREAD_CANCELED;
- break;
- }
- }
-
-#else /* __CLEANUP_C */
-
-#ifdef __CLEANUP_CXX
-
- ptw32_oldTerminate = set_terminate(&ptw32_terminate);
-
- try
- {
- /*
- * Run the caller's routine in a nested try block so that we
- * can run the user's terminate function, which may call
- * pthread_exit() or be canceled.
- */
- try
- {
- status = self->exitStatus = (*start) (arg);
- }
- catch (ptw32_exception &)
- {
- /*
- * Pass these through to the outer block.
- */
- throw;
- }
- catch(...)
- {
- /*
- * We want to run the user's terminate function if supplied.
- * That function may call pthread_exit() or be canceled, which will
- * be handled by the outer try block.
- *
- * ptw32_terminate() will be called if there is no user
- * supplied function.
- */
-
-#if defined(_MSC_VER)
- terminate_function term_func = set_terminate(0);
-#else
- terminate_handler term_func = set_terminate(0);
-#endif
-
- set_terminate(term_func);
-
- if (term_func != 0) {
- term_func();
- }
-
- throw;
- }
- }
- catch (ptw32_exception_cancel &)
- {
- /*
- * Thread was canceled.
- */
- status = self->exitStatus = PTHREAD_CANCELED;
- }
- catch (ptw32_exception_exit &)
- {
- /*
- * Thread was exited via pthread_exit().
- */
- status = self->exitStatus;
- }
- catch (...)
- {
- /*
- * A system unexpected exception has occurred running the user's
- * terminate routine. We get control back within this block - cleanup
- * and release the exception out of thread scope.
- */
- status = self->exitStatus = PTHREAD_CANCELED;
- (void) pthread_mutex_lock(&self->cancelLock);
- self->state = PThreadStateException;
- (void) pthread_mutex_unlock(&self->cancelLock);
- (void) pthread_mutex_destroy(&self->cancelLock);
- (void) set_terminate(ptw32_oldTerminate);
- ptw32_callUserDestroyRoutines(self);
- throw;
-
- /*
- * Never reached.
- */
- }
-
- (void) set_terminate(ptw32_oldTerminate);
-
-#else
-
-#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
-
-#endif /* __CLEANUP_CXX */
-#endif /* __CLEANUP_C */
-#endif /* __CLEANUP_SEH */
-
- (void) pthread_mutex_lock(&self->cancelLock);
- self->state = PThreadStateLast;
- (void) pthread_mutex_unlock(&self->cancelLock);
-
-
- (void) pthread_mutex_destroy(&self->cancelLock);
-
-#if 1
- if (self->detachState == PTHREAD_CREATE_DETACHED)
- {
- /*
- * We need to cleanup the pthread now in case we have
- * been statically linked, in which case the cleanup
- * in dllMain won't get done. Joinable threads will
- * be cleaned up by pthread_join().
- *
- * Note that implicitly created pthreads (those created
- * for Win32 threads which have called pthreads routines)
- * must be cleaned up explicitly by the application
- * (by calling pthread_win32_thread_detach_np()) if
- * this library has been statically linked. For the dll,
- * dllMain will do the cleanup automatically.
- */
- (void) pthread_win32_thread_detach_np ();
- }
- else
- {
- ptw32_callUserDestroyRoutines (self);
- }
-#else
- ptw32_callUserDestroyRoutines (self);
-#endif
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
- _endthreadex ((unsigned) status);
-#else
- _endthread ();
-#endif
-
- /*
- * Never reached.
- */
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
- return (unsigned) status;
-#endif
-
-} /* ptw32_threadStart */
-
-void
-ptw32_threadDestroy (pthread_t thread)
-{
- if (thread != NULL)
- {
- ptw32_callUserDestroyRoutines (thread);
-
- if (thread->cancelEvent != NULL)
- {
- CloseHandle (thread->cancelEvent);
- }
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
- /* See documentation for endthread vs endthreadex. */
- if( thread->threadH != 0 )
- {
- CloseHandle( thread->threadH );
- }
-#endif
-
- free (thread);
- }
-
-} /* ptw32_threadDestroy */
-
-int
-ptw32_tkAssocCreate (ThreadKeyAssoc ** assocP,
- pthread_t thread,
- pthread_key_t key)
- /*
- * -------------------------------------------------------------------
- * This routine creates an association that
- * is unique for the given (thread,key) combination.The association
- * is referenced by both the thread and the key.
- * This association allows us to determine what keys the
- * current thread references and what threads a given key
- * references.
- * See the detailed description
- * at the beginning of this file for further details.
- *
- * Notes:
- * 1) New associations are pushed to the beginning of the
- * chain so that the internal ptw32_selfThreadKey association
- * is always last, thus allowing selfThreadExit to
- * be implicitly called by pthread_exit last.
- *
- * Parameters:
- * assocP
- * address into which the association is returned.
- * thread
- * current running thread. If NULL, then association
- * is only added to the key. A NULL thread indicates
- * that the user called pthread_setspecific prior
- * to starting a thread. That's ok.
- * key
- * key on which to create an association.
- * Returns:
- * 0 - if successful,
- * ENOMEM - not enough memory to create assoc or other object
- * EINVAL - an internal error occurred
- * ENOSYS - an internal error occurred
- * -------------------------------------------------------------------
- */
-{
- int result;
- ThreadKeyAssoc *assoc;
-
- /*
- * Have to create an association and add it
- * to both the key and the thread.
- */
- assoc = (ThreadKeyAssoc *) calloc (1, sizeof (*assoc));
-
- if (assoc == NULL)
- {
- result = ENOMEM;
- goto FAIL0;
- }
-
- /*
- * Initialise only when used for the first time.
- */
- assoc->lock = PTHREAD_MUTEX_INITIALIZER;
- assoc->thread = thread;
- assoc->key = key;
-
- /*
- * Register assoc with key
- */
- if ((result = pthread_mutex_lock (&(key->threadsLock))) != 0)
- {
- goto FAIL2;
- }
-
- assoc->nextThread = (ThreadKeyAssoc *) key->threads;
- key->threads = (void *) assoc;
-
- pthread_mutex_unlock (&(key->threadsLock));
-
- if (thread != NULL)
- {
- /*
- * Register assoc with thread
- */
- assoc->nextKey = (ThreadKeyAssoc *) thread->keys;
- thread->keys = (void *) assoc;
- }
-
- *assocP = assoc;
-
- return (result);
-
- /*
- * -------------
- * Failure Code
- * -------------
- */
-FAIL2:
- pthread_mutex_destroy (&(assoc->lock));
- free (assoc);
-
-FAIL0:
-
- return (result);
-
-} /* ptw32_tkAssocCreate */
-
-
-void
-ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc)
- /*
- * -------------------------------------------------------------------
- * This routine releases all resources for the given ThreadKeyAssoc
- * once it is no longer being referenced
- * ie) both the key and thread have stopped referencing it.
- *
- * Parameters:
- * assoc
- * an instance of ThreadKeyAssoc.
- * Returns:
- * N/A
- * -------------------------------------------------------------------
- */
-{
-
- if ((assoc != NULL) &&
- (assoc->key == NULL && assoc->thread == NULL))
- {
-
- pthread_mutex_destroy (&(assoc->lock));
-
- free (assoc);
- }
-
-} /* ptw32_tkAssocDestroy */
-
-
-void
-ptw32_callUserDestroyRoutines (pthread_t thread)
- /*
- * -------------------------------------------------------------------
- * DOCPRIVATE
- *
- * This the routine runs through all thread keys and calls
- * the destroy routines on the user's data for the current thread.
- * It simulates the behaviour of POSIX Threads.
- *
- * PARAMETERS
- * thread
- * an instance of pthread_t
- *
- * RETURNS
- * N/A
- * -------------------------------------------------------------------
- */
-{
- ThreadKeyAssoc **nextP;
- ThreadKeyAssoc *assoc;
-
- if (thread != NULL)
- {
- /*
- * Run through all Thread<-->Key associations
- * for the current thread.
- * If the pthread_key_t still exits (ie the assoc->key
- * is not NULL) then call the user's TSD destroy routine.
- * Notes:
- * If assoc->key is NULL, then the user previously called
- * PThreadKeyDestroy. The association is now only referenced
- * by the current thread and must be released; otherwise
- * the assoc will be destroyed when the key is destroyed.
- */
- nextP = (ThreadKeyAssoc **) & (thread->keys);
- assoc = *nextP;
-
- while (assoc != NULL)
- {
-
- if (pthread_mutex_lock (&(assoc->lock)) == 0)
- {
- pthread_key_t k;
- if ((k = assoc->key) != NULL)
- {
- /*
- * Key still active; pthread_key_delete
- * will block on this same mutex before
- * it can release actual key; therefore,
- * key is valid and we can call the destroy
- * routine;
- */
- void *value = NULL;
-
- value = pthread_getspecific (k);
- if (value != NULL && k->destructor != NULL)
- {
-
-#ifdef __cplusplus
-
- try
- {
- /*
- * Run the caller's cleanup routine.
- */
- (*(k->destructor)) (value);
- }
- catch (...)
- {
- /*
- * A system unexpected exception has occurred
- * running the user's destructor.
- * We get control back within this block in case
- * the application has set up it's own terminate
- * handler. Since we are leaving the thread we
- * should not get any internal pthreads
- * exceptions.
- */
- terminate();
- }
-
-#else /* __cplusplus */
-
- /*
- * Run the caller's cleanup routine.
- */
- (*(k->destructor)) (value);
-
-#endif /* __cplusplus */
- }
- }
-
- /*
- * mark assoc->thread as NULL to indicate the
- * thread no longer references this association
- */
- assoc->thread = NULL;
-
- /*
- * Remove association from the pthread_t chain
- */
- *nextP = assoc->nextKey;
-
- pthread_mutex_unlock (&(assoc->lock));
-
- ptw32_tkAssocDestroy (assoc);
-
- assoc = *nextP;
- }
- }
- }
-
-} /* ptw32_callUserDestroyRoutines */
-
-
-
-#ifdef NEED_FTIME
-
-/*
- * time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds
- */
-#define TIMESPEC_TO_FILETIME_OFFSET \
- ( ((LONGLONG) 27111902 << 32) + (LONGLONG) 3577643008 )
-
-static INLINE void
-timespec_to_filetime(const struct timespec *ts, FILETIME *ft)
- /*
- * -------------------------------------------------------------------
- * converts struct timespec
- * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
- * into FILETIME (as set by GetSystemTimeAsFileTime), where the time is
- * expressed in 100 nanoseconds from Jan 1, 1601,
- * -------------------------------------------------------------------
- */
-{
- *(LONGLONG *)ft = ts->tv_sec * 10000000 + (ts->tv_nsec + 50) / 100 + TIMESPEC_TO_FILETIME_OFFSET;
-}
-
-static INLINE void
-filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
- /*
- * -------------------------------------------------------------------
- * converts FILETIME (as set by GetSystemTimeAsFileTime), where the time is
- * expressed in 100 nanoseconds from Jan 1, 1601,
- * into struct timespec
- * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
- * -------------------------------------------------------------------
- */
-{
- ts->tv_sec = (int)((*(LONGLONG *)ft - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
- ts->tv_nsec = (int)((*(LONGLONG *)ft - TIMESPEC_TO_FILETIME_OFFSET - ((LONGLONG)ts->tv_sec * (LONGLONG)10000000)) * 100);
-}
-
-#endif /* NEED_FTIME */
-
-
-DWORD
-ptw32_get_exception_services_code(void)
-{
-#ifdef __CLEANUP_SEH
-
- return EXCEPTION_PTW32_SERVICES;
-
-#else
-
- return (DWORD) NULL;
-
-#endif
-}
-
-
-void
-ptw32_throw(DWORD exception)
-{
-#ifdef __CLEANUP_C
- pthread_t self = pthread_self();
-#endif
-
-
-#ifdef __CLEANUP_SEH
- DWORD exceptionInformation[3];
-#endif
-
- if (exception != PTW32_EPS_CANCEL &&
- exception != PTW32_EPS_EXIT)
- {
- /* Should never enter here */
- exit(1);
- }
-
-#ifdef __CLEANUP_SEH
-
-
- exceptionInformation[0] = (DWORD) (exception);
- exceptionInformation[1] = (DWORD) (0);
- exceptionInformation[2] = (DWORD) (0);
-
- RaiseException (
- EXCEPTION_PTW32_SERVICES,
- 0,
- 3,
- exceptionInformation);
-
-#else /* __CLEANUP_SEH */
-
-#ifdef __CLEANUP_C
-
- ptw32_pop_cleanup_all( 1 );
-
- longjmp( self->start_mark, exception );
-
-#else /* __CLEANUP_C */
-
-#ifdef __CLEANUP_CXX
-
- switch (exception)
- {
- case PTW32_EPS_CANCEL:
- throw ptw32_exception_cancel();
- break;
- case PTW32_EPS_EXIT:
- throw ptw32_exception_exit();
- break;
- }
-
-#else
-
-#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
-
-#endif /* __CLEANUP_CXX */
-
-#endif /* __CLEANUP_C */
-
-#endif /* __CLEANUP_SEH */
-
- /* Never reached */
-}
-
-void
-ptw32_pop_cleanup_all(int execute)
-{
- while( NULL != ptw32_pop_cleanup(execute) ) {
- }
-}
-
-
-/*
- * ptw32_InterlockedCompareExchange --
- *
- * Needed because W95 doesn't support InterlockedCompareExchange.
- * It is only used when running the dll on W95. Other versions of
- * Windows use the Win32 supported version, which may be running on
- * different processor types.
- *
- * This can't be inlined because we need to know it's address so that
- * we can call it through a pointer.
- */
-PTW32_INTERLOCKED_LONG WINAPI
-ptw32_InterlockedCompareExchange(PTW32_INTERLOCKED_LPLONG location,
- PTW32_INTERLOCKED_LONG value,
- PTW32_INTERLOCKED_LONG comparand)
-{
- PTW32_INTERLOCKED_LONG result;
-
-#if defined(_M_IX86) || defined(_X86_)
-
-#if defined(_MSC_VER)
-
- _asm {
- PUSH ecx
- PUSH edx
- MOV ecx,dword ptr [location]
- MOV edx,dword ptr [value]
- MOV eax,dword ptr [comparand]
- LOCK CMPXCHG dword ptr [ecx],edx ; if (EAX == [ECX]),
- ; [ECX] = EDX
- ; else
- ; EAX = [ECX]
- MOV dword ptr [result], eax
- POP edx
- POP ecx
- }
-
-#elif defined(__GNUC__)
-
- __asm__
- (
- "lock\n\t"
- "cmpxchgl %3,(%0)" /* if (EAX == [location]), */
- /* [location] = value */
- /* else */
- /* EAX = [location] */
- :"=r" (location), "=a" (result)
- :"0" (location), "q" (value), "a" (comparand)
- : "memory" );
-
-#endif
-
-#else
-
- /*
- * If execution gets to here then we should be running on a Win95 system
- * but either running on something other than an X86 processor, or a
- * compiler other than MSVC or GCC. Pthreads-win32 doesn't support that
- * platform (yet).
- */
-
- result = 0;
-
-#endif
-
- return result;
-}
-
-
-/*
- * ptw32_getprocessors()
- *
- * Get the number of CPUs available to the process.
- *
- * If the available number of CPUs is 1 then pthread_spin_lock()
- * will block rather than spin if the lock is already owned.
- *
- * pthread_spin_init() calls this routine when initialising
- * a spinlock. If the number of available processors changes
- * (after a call to SetProcessAffinityMask()) then only
- * newly initialised spinlocks will notice.
- */
-int
-ptw32_getprocessors(int * count)
-{
- DWORD vProcessCPUs;
- DWORD vSystemCPUs;
- int result = 0;
-
- if (GetProcessAffinityMask(GetCurrentProcess(),
- &vProcessCPUs,
- &vSystemCPUs))
- {
- DWORD bit;
- int CPUs = 0;
-
- for (bit = 1; bit != 0; bit <<= 1)
- {
- if (vProcessCPUs & bit)
- {
- CPUs++;
- }
- }
- *count = CPUs;
- }
- else
- {
- result = EAGAIN;
- }
-
- return(result);
-}
+#include "ptw32_is_attr.c"
+#include "ptw32_processInitialize.c"
+#include "ptw32_processTerminate.c"
+#include "ptw32_threadStart.c"
+#include "ptw32_threadDestroy.c"
+#include "ptw32_tkAssocCreate.c"
+#include "ptw32_tkAssocDestroy.c"
+#include "ptw32_callUserDestroyRoutines.c"
+#include "ptw32_timespec.c"
+#include "ptw32_throw.c"
+#include "ptw32_InterlockedCompareExchange.c"
+#include "ptw32_getprocessors.c"
diff --git a/pthread.c b/pthread.c
index be70f38..8fb39d7 100644
--- a/pthread.c
+++ b/pthread.c
@@ -2,7 +2,7 @@
* pthread.c
*
* Description:
- * This translation unit agregates operations on threads.
+ * This translation unit agregates pthreads-win32 translation units.
* It is used for inline optimisation of the library,
* maximising for speed at the expense of size.
*
@@ -42,4 +42,9 @@
#include "attr.c"
#include "barrier.c"
#include "cancel.c"
+#include "condvar.c"
+#include "misc.c"
+#include "mutex.c"
+#include "private.c"
+#include "rwlock.c"
#include "semaphore.c"
diff --git a/pthread.def b/pthread.def
index 1609045..621ee09 100644
--- a/pthread.def
+++ b/pthread.def
@@ -1,162 +1,163 @@
-; pthread.def
-; Last updated: $Date: 2002/02/11 01:53:22 $
-
-; Currently unimplemented functions are commented out.
-
-;LIBRARY pthread
-
-EXPORTS
-;pthread_atfork
-pthread_attr_destroy
-pthread_attr_getdetachstate
-pthread_attr_getinheritsched
-pthread_attr_getschedparam
-pthread_attr_getschedpolicy
-pthread_attr_getscope
-pthread_attr_getstackaddr
-pthread_attr_getstacksize
-pthread_attr_init
-pthread_attr_setdetachstate
-pthread_attr_setinheritsched
-pthread_attr_setschedparam
-pthread_attr_setschedpolicy
-pthread_attr_setscope
-pthread_attr_setstackaddr
-pthread_attr_setstacksize
-pthread_cancel
-;
-; These two are implemented as macros in pthread.h
-;
-;pthread_cleanup_pop
-;pthread_cleanup_push
-;
-pthread_condattr_destroy
-pthread_condattr_getpshared
-pthread_condattr_init
-pthread_condattr_setpshared
-pthread_cond_broadcast
-pthread_cond_destroy
-pthread_cond_init
-pthread_cond_signal
-pthread_cond_timedwait
-pthread_cond_wait
-pthread_create
-pthread_detach
-pthread_equal
-pthread_exit
-pthread_getconcurrency
-pthread_getschedparam
-pthread_getspecific
-pthread_join
-pthread_key_create
-pthread_key_delete
-;pthread_kill
-pthread_mutexattr_destroy
-;pthread_mutexattr_getprioceiling
-;pthread_mutexattr_getprotocol
-pthread_mutexattr_getpshared
-pthread_mutexattr_gettype
-pthread_mutexattr_init
-;pthread_mutexattr_setprioceiling
-;pthread_mutexattr_setprotocol
-pthread_mutexattr_setpshared
-pthread_mutexattr_settype
-pthread_mutexattr_destroy
-pthread_mutex_init
-pthread_mutex_destroy
-pthread_mutex_lock
-pthread_mutex_trylock
-pthread_mutex_timedlock
-pthread_mutex_unlock
-pthread_once
-pthread_self
-pthread_setcancelstate
-pthread_setcanceltype
-pthread_setconcurrency
-pthread_setschedparam
-pthread_setspecific
-;pthread_sigmask
-pthread_testcancel
-;
-; Scheduling
-;
-sched_get_priority_min
-sched_get_priority_max
-sched_getscheduler
-sched_setscheduler
-sched_yield
-;
-; Semaphores
-;
-sem_init
-sem_destroy
-sem_trywait
-sem_wait
-sem_timedwait
-sem_post
-sem_open
-sem_close
-sem_unlink
-sem_getvalue
-;
-; This next one is a macro
-;sched_rr_get_interval
-;
-;
-; Read/Write Locks
-;
-pthread_rwlock_init
-pthread_rwlock_destroy
-pthread_rwlock_tryrdlock
-pthread_rwlock_trywrlock
-pthread_rwlock_rdlock
-pthread_rwlock_wrlock
-pthread_rwlock_unlock
-;
-; Spin locks
-;
-pthread_spin_init
-pthread_spin_destroy
-pthread_spin_lock
-pthread_spin_unlock
-pthread_spin_trylock
-;
-; Barriers
-;
-pthread_barrier_init
-pthread_barrier_destroy
-pthread_barrier_wait
-pthread_barrierattr_init
-pthread_barrierattr_destroy
-pthread_barrierattr_getpshared
-pthread_barrierattr_setpshared
-;
-; Non-portable/compatibility with other implementations
-;
-pthread_delay_np
-pthread_mutexattr_getkind_np
-pthread_mutexattr_setkind_np
-;
-; Non-portable local implementation only
-;
-pthread_getw32threadhandle_np
-pthread_num_processors_np
-pthreadCancelableWait
-pthreadCancelableTimedWait
-;
-; For use when linking statically
-;
-pthread_win32_process_attach_np
-pthread_win32_process_detach_np
-pthread_win32_thread_attach_np
-pthread_win32_thread_detach_np
-;
-; Needed if !defined(_MSC_VER) && !defined(__cplusplus)
-;
-ptw32_push_cleanup
-ptw32_pop_cleanup
-;
-; Not for use directly. Needed by macros in pthread.h
-; to return internal SEH code.
-;
-ptw32_get_exception_services_code
+; pthread.def
+; Last updated: $Date: 2002/02/18 03:16:55 $
+
+; Currently unimplemented functions are commented out.
+
+;LIBRARY pthread
+
+EXPORTS
+;pthread_atfork
+pthread_attr_destroy
+pthread_attr_getdetachstate
+pthread_attr_getinheritsched
+pthread_attr_getschedparam
+pthread_attr_getschedpolicy
+pthread_attr_getscope
+pthread_attr_getstackaddr
+pthread_attr_getstacksize
+pthread_attr_init
+pthread_attr_setdetachstate
+pthread_attr_setinheritsched
+pthread_attr_setschedparam
+pthread_attr_setschedpolicy
+pthread_attr_setscope
+pthread_attr_setstackaddr
+pthread_attr_setstacksize
+pthread_cancel
+;
+; These two are implemented as macros in pthread.h
+;
+;pthread_cleanup_pop
+;pthread_cleanup_push
+;
+pthread_condattr_destroy
+pthread_condattr_getpshared
+pthread_condattr_init
+pthread_condattr_setpshared
+pthread_cond_broadcast
+pthread_cond_destroy
+pthread_cond_init
+pthread_cond_signal
+pthread_cond_timedwait
+pthread_cond_wait
+pthread_create
+pthread_detach
+pthread_equal
+pthread_exit
+pthread_getconcurrency
+pthread_getschedparam
+pthread_getspecific
+pthread_join
+pthread_key_create
+pthread_key_delete
+;pthread_kill
+pthread_mutexattr_destroy
+;pthread_mutexattr_getprioceiling
+;pthread_mutexattr_getprotocol
+pthread_mutexattr_getpshared
+pthread_mutexattr_gettype
+pthread_mutexattr_init
+;pthread_mutexattr_setprioceiling
+;pthread_mutexattr_setprotocol
+pthread_mutexattr_setpshared
+pthread_mutexattr_settype
+pthread_mutexattr_destroy
+pthread_mutex_init
+pthread_mutex_destroy
+pthread_mutex_lock
+pthread_mutex_trylock
+pthread_mutex_timedlock
+pthread_mutex_unlock
+pthread_once
+pthread_self
+pthread_setcancelstate
+pthread_setcanceltype
+pthread_setconcurrency
+pthread_setschedparam
+pthread_setspecific
+;pthread_sigmask
+pthread_testcancel
+;
+; Scheduling
+;
+sched_get_priority_min
+sched_get_priority_max
+sched_getscheduler
+sched_setscheduler
+sched_yield
+;
+; Semaphores
+;
+sem_init
+sem_destroy
+sem_trywait
+sem_wait
+sem_timedwait
+sem_post
+sem_open
+sem_close
+sem_unlink
+sem_getvalue
+;
+; This next one is a macro
+;sched_rr_get_interval
+;
+;
+; Read/Write Locks
+;
+pthread_rwlock_init
+pthread_rwlock_destroy
+pthread_rwlock_tryrdlock
+pthread_rwlock_trywrlock
+pthread_rwlock_rdlock
+pthread_rwlock_wrlock
+pthread_rwlock_unlock
+;
+; Spin locks
+;
+pthread_spin_init
+pthread_spin_destroy
+pthread_spin_lock
+pthread_spin_unlock
+pthread_spin_trylock
+;
+; Barriers
+;
+pthread_barrier_init
+pthread_barrier_destroy
+pthread_barrier_wait
+pthread_barrierattr_init
+pthread_barrierattr_destroy
+pthread_barrierattr_getpshared
+pthread_barrierattr_setpshared
+;
+; Non-portable/compatibility with other implementations
+;
+pthread_delay_np
+pthread_mutexattr_getkind_np
+pthread_mutexattr_setkind_np
+pthread_num_processors_np
+;
+; Non-portable local implementation only
+;
+pthread_getw32threadhandle_np
+pthread_timechange_handler_np
+pthreadCancelableWait
+pthreadCancelableTimedWait
+;
+; For use when linking statically
+;
+pthread_win32_process_attach_np
+pthread_win32_process_detach_np
+pthread_win32_thread_attach_np
+pthread_win32_thread_detach_np
+;
+; Needed if !defined(_MSC_VER) && !defined(__cplusplus)
+;
+ptw32_push_cleanup
+ptw32_pop_cleanup
+;
+; Not for use directly. Needed by macros in pthread.h
+; to return internal SEH code.
+;
+ptw32_get_exception_services_code
diff --git a/pthread.h b/pthread.h
index d19063b..29fef95 100644
--- a/pthread.h
+++ b/pthread.h
@@ -2,32 +2,32 @@
*
* --------------------------------------------------------------------------
*
- * Pthreads-win32 - POSIX Threads Library for Win32
- * Copyright(C) 1998 John E. Bossom
- * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
*
- * Contact Email: rpj@ise.canberra.edu.au
+ * Contact Email: rpj@ise.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
+ * 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 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.
+ * 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
+ * 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 )
@@ -549,6 +549,10 @@ struct pthread_once_t_
#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1)
+
+/*
+ * Mutex types.
+ */
enum
{
/* Compatibility with LinuxThreads */
@@ -1019,11 +1023,6 @@ int pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, int *kind);
* Possibly supported by other POSIX threads implementations
*/
int pthread_delay_np (struct timespec * interval);
-
-/*
- * Returns the number of CPUs available to the process.
- */
-int pthread_getprocessors_np(int * count);
int pthread_num_processors_np(void);
/*
@@ -1035,6 +1034,16 @@ int pthread_win32_process_detach_np(void);
int pthread_win32_thread_attach_np(void);
int pthread_win32_thread_detach_np(void);
+/*
+ * 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.
+ */
+void * pthread_timechange_handler_np(void *);
+
#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
diff --git a/attr_destroy.c b/pthread_attr_destroy.c
index e4c29d6..7560fb2 100644
--- a/attr_destroy.c
+++ b/pthread_attr_destroy.c
@@ -1,5 +1,5 @@
/*
- * attr_destroy.c
+ * pthread_attr_destroy.c
*
* Description:
* This translation unit implements operations on thread attribute objects.
@@ -63,7 +63,7 @@ pthread_attr_destroy(pthread_attr_t *attr)
* ------------------------------------------------------
*/
{
- if (is_attr(attr) != 0)
+ if (ptw32_is_attr(attr) != 0)
{
return EINVAL;
}
diff --git a/attr_getdetachstate.c b/pthread_attr_getdetachstate.c
index 1e29613..d8467b1 100644
--- a/attr_getdetachstate.c
+++ b/pthread_attr_getdetachstate.c
@@ -1,5 +1,5 @@
/*
- * attr_getdetachstate.c
+ * pthread_attr_getdetachstate.c
*
* Description:
* This translation unit implements operations on thread attribute objects.
@@ -77,7 +77,7 @@ pthread_attr_getdetachstate(const pthread_attr_t *attr,
* ------------------------------------------------------
*/
{
- if (is_attr(attr) != 0 || detachstate == NULL)
+ if (ptw32_is_attr(attr) != 0 || detachstate == NULL)
{
*detachstate = PTHREAD_CREATE_DETACHED;
return EINVAL;
diff --git a/pthread_attr_getinheritsched.c b/pthread_attr_getinheritsched.c
new file mode 100644
index 0000000..6d01cf3
--- /dev/null
+++ b/pthread_attr_getinheritsched.c
@@ -0,0 +1,52 @@
+/*
+ * pthread_attr_getinheritsched.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_getinheritsched(pthread_attr_t * attr,
+ int * inheritsched)
+{
+ if (ptw32_is_attr(attr) != 0 || inheritsched == NULL)
+ {
+ return EINVAL;
+ }
+
+ *inheritsched = (*attr)->inheritsched;
+ return 0;
+}
diff --git a/pthread_attr_getschedparam.c b/pthread_attr_getschedparam.c
new file mode 100644
index 0000000..19451fc
--- /dev/null
+++ b/pthread_attr_getschedparam.c
@@ -0,0 +1,52 @@
+/*
+ * pthread_attr_getschedparam.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_getschedparam(const pthread_attr_t *attr,
+ struct sched_param *param)
+{
+ if (ptw32_is_attr(attr) != 0 || param == NULL)
+ {
+ return EINVAL;
+ }
+
+ memcpy(param, &(*attr)->param, sizeof(*param));
+ return 0;
+}
diff --git a/pthread_attr_getschedpolicy.c b/pthread_attr_getschedpolicy.c
new file mode 100644
index 0000000..f76618c
--- /dev/null
+++ b/pthread_attr_getschedpolicy.c
@@ -0,0 +1,62 @@
+/*
+ * pthread_attr_getschedpolicy.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_getschedpolicy(pthread_attr_t *attr,
+ int * policy)
+{
+ if (ptw32_is_attr(attr) != 0 || policy == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * Validate the policy arg.
+ * Check that a policy constant wasn't passed rather than &policy.
+ */
+ if (policy <= (int *) SCHED_MAX)
+ {
+ return EINVAL;
+ }
+
+ *policy = SCHED_OTHER;
+
+ return 0;
+}
diff --git a/attr_getscope.c b/pthread_attr_getscope.c
index 52216da..06bb901 100644
--- a/attr_getscope.c
+++ b/pthread_attr_getscope.c
@@ -1,5 +1,5 @@
/*
- * attr_getscope.c
+ * pthread_attr_getscope.c
*
* Description:
* This translation unit implements operations on thread attribute objects.
diff --git a/attr_getstackaddr.c b/pthread_attr_getstackaddr.c
index 79f4c30..410cc62 100644
--- a/attr_getstackaddr.c
+++ b/pthread_attr_getstackaddr.c
@@ -1,5 +1,5 @@
/*
- * attr_getstackaddr.c
+ * pthread_attr_getstackaddr.c
*
* Description:
* This translation unit implements operations on thread attribute objects.
@@ -82,7 +82,7 @@ pthread_attr_getstackaddr(const pthread_attr_t *attr,
{
#if defined( _POSIX_THREAD_ATTR_STACKADDR )
- if (is_attr(attr) != 0)
+ if (ptw32_is_attr(attr) != 0)
{
return EINVAL;
}
diff --git a/attr_getstacksize.c b/pthread_attr_getstacksize.c
index b9e9b97..f9a584b 100644
--- a/attr_getstacksize.c
+++ b/pthread_attr_getstacksize.c
@@ -1,5 +1,5 @@
/*
- * attr_getstacksize.c
+ * pthread_attr_getstacksize.c
*
* Description:
* This translation unit implements operations on thread attribute objects.
@@ -83,7 +83,7 @@ pthread_attr_getstacksize(const pthread_attr_t *attr,
{
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
- if (is_attr(attr) != 0)
+ if (ptw32_is_attr(attr) != 0)
{
return EINVAL;
}
diff --git a/attr_init.c b/pthread_attr_init.c
index 6ea9234..efc3683 100644
--- a/attr_init.c
+++ b/pthread_attr_init.c
@@ -1,5 +1,5 @@
/*
- * attr_init.c
+ * pthread_attr_init.c
*
* Description:
* This translation unit implements operations on thread attribute objects.
diff --git a/attr_setdetachstate.c b/pthread_attr_setdetachstate.c
index 8fcfe39..19de87b 100644
--- a/attr_setdetachstate.c
+++ b/pthread_attr_setdetachstate.c
@@ -1,5 +1,5 @@
/*
- * attr_setdetachstate.c
+ * pthread_attr_setdetachstate.c
*
* Description:
* This translation unit implements operations on thread attribute objects.
@@ -76,7 +76,7 @@ pthread_attr_setdetachstate(pthread_attr_t *attr,
* ------------------------------------------------------
*/
{
- if (is_attr(attr) != 0)
+ if (ptw32_is_attr(attr) != 0)
{
return EINVAL;
}
diff --git a/pthread_attr_setinheritsched.c b/pthread_attr_setinheritsched.c
new file mode 100644
index 0000000..1653351
--- /dev/null
+++ b/pthread_attr_setinheritsched.c
@@ -0,0 +1,58 @@
+/*
+ * pthread_attr_setinheritsched.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_setinheritsched(pthread_attr_t * attr,
+ int inheritsched)
+{
+ if (ptw32_is_attr(attr) != 0)
+ {
+ return EINVAL;
+ }
+
+ if (PTHREAD_INHERIT_SCHED != inheritsched
+ && PTHREAD_EXPLICIT_SCHED != inheritsched)
+ {
+ return EINVAL;
+ }
+
+ (*attr)->inheritsched = inheritsched;
+ return 0;
+}
diff --git a/pthread_attr_setschedparam.c b/pthread_attr_setschedparam.c
new file mode 100644
index 0000000..8ad787a
--- /dev/null
+++ b/pthread_attr_setschedparam.c
@@ -0,0 +1,63 @@
+/*
+ * pthread_attr_setschedparam.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_setschedparam(pthread_attr_t *attr,
+ const struct sched_param *param)
+{
+ int priority;
+
+ if (ptw32_is_attr(attr) != 0 || param == NULL)
+ {
+ return EINVAL;
+ }
+
+ priority = param->sched_priority;
+
+ /* Validate priority level. */
+ if (priority < sched_get_priority_min(SCHED_OTHER) ||
+ priority > sched_get_priority_max(SCHED_OTHER))
+ {
+ return EINVAL;
+ }
+
+ memcpy(&(*attr)->param, param, sizeof(*param));
+ return 0;
+}
diff --git a/pthread_attr_setschedpolicy.c b/pthread_attr_setschedpolicy.c
new file mode 100644
index 0000000..1614f00
--- /dev/null
+++ b/pthread_attr_setschedpolicy.c
@@ -0,0 +1,56 @@
+/*
+ * pthread_attr_setschedpolicy.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_attr_setschedpolicy (pthread_attr_t *attr,
+ int policy)
+{
+ if (ptw32_is_attr(attr) != 0)
+ {
+ return EINVAL;
+ }
+
+ if (policy != SCHED_OTHER)
+ {
+ return ENOTSUP;
+ }
+
+ return 0;
+}
diff --git a/attr_setscope.c b/pthread_attr_setscope.c
index 7543201..8d8f2e5 100644
--- a/attr_setscope.c
+++ b/pthread_attr_setscope.c
@@ -1,5 +1,5 @@
/*
- * attr_setscope.c
+ * pthread_attr_setscope.c
*
* Description:
* This translation unit implements operations on thread attribute objects.
diff --git a/attr_setstackaddr.c b/pthread_attr_setstackaddr.c
index f5fc8af..4318e32 100644
--- a/attr_setstackaddr.c
+++ b/pthread_attr_setstackaddr.c
@@ -1,5 +1,5 @@
/*
- * attr_setstackaddr.c
+ * pthread_attr_setstackaddr.c
*
* Description:
* This translation unit implements operations on thread attribute objects.
@@ -82,7 +82,7 @@ pthread_attr_setstackaddr(pthread_attr_t *attr,
{
#if defined( _POSIX_THREAD_ATTR_STACKADDR )
- if (is_attr(attr) != 0)
+ if (ptw32_is_attr(attr) != 0)
{
return EINVAL;
}
diff --git a/attr_setstacksize.c b/pthread_attr_setstacksize.c
index 549d6be..61faa66 100644
--- a/attr_setstacksize.c
+++ b/pthread_attr_setstacksize.c
@@ -1,5 +1,5 @@
/*
- * attr_setstacksize.c
+ * pthread_attr_setstacksize.c
*
* Description:
* This translation unit implements operations on thread attribute objects.
@@ -93,7 +93,7 @@ pthread_attr_setstacksize(pthread_attr_t *attr,
#endif
- if (is_attr(attr) != 0)
+ if (ptw32_is_attr(attr) != 0)
{
return EINVAL;
}
diff --git a/barrier_destroy.c b/pthread_barrier_destroy.c
index c8c2142..bae8c20 100644
--- a/barrier_destroy.c
+++ b/pthread_barrier_destroy.c
@@ -1,5 +1,5 @@
/*
- * barrier_destroy.c
+ * pthread_barrier_destroy.c
*
* Description:
* This translation unit implements barrier primitives.
diff --git a/barrier_init.c b/pthread_barrier_init.c
index 865a82a..44b96fc 100644
--- a/barrier_init.c
+++ b/pthread_barrier_init.c
@@ -1,5 +1,5 @@
/*
- * barrier_init.c
+ * pthread_barrier_init.c
*
* Description:
* This translation unit implements barrier primitives.
diff --git a/barrier_wait.c b/pthread_barrier_wait.c
index 07ea32f..e06e87d 100644
--- a/barrier_wait.c
+++ b/pthread_barrier_wait.c
@@ -1,5 +1,5 @@
/*
- * barrier_wait.c
+ * pthread_barrier_wait.c
*
* Description:
* This translation unit implements barrier primitives.
diff --git a/barrier_attr_destroy.c b/pthread_barrierattr_destroy.c
index 7395ca3..1d0c717 100644
--- a/barrier_attr_destroy.c
+++ b/pthread_barrierattr_destroy.c
@@ -1,5 +1,5 @@
/*
- * barrier_attr_destroy.c
+ * pthread_barrier_attr_destroy.c
*
* Description:
* This translation unit implements barrier primitives.
diff --git a/barrier_attr_getpshared.c b/pthread_barrierattr_getpshared.c
index 4f7cc64..13e7373 100644
--- a/barrier_attr_getpshared.c
+++ b/pthread_barrierattr_getpshared.c
@@ -1,5 +1,5 @@
/*
- * barrier_attr_getpshared.c
+ * pthread_barrier_attr_getpshared.c
*
* Description:
* This translation unit implements barrier primitives.
diff --git a/barrier_attr_init.c b/pthread_barrierattr_init.c
index ac204fa..0dbe113 100644
--- a/barrier_attr_init.c
+++ b/pthread_barrierattr_init.c
@@ -1,5 +1,5 @@
/*
- * barrier_attr_init.c
+ * pthread_barrier_attr_init.c
*
* Description:
* This translation unit implements barrier primitives.
diff --git a/barrier_attr_setpshared.c b/pthread_barrierattr_setpshared.c
index 4ad5c52..e963cb7 100644
--- a/barrier_attr_setpshared.c
+++ b/pthread_barrierattr_setpshared.c
@@ -1,5 +1,5 @@
/*
- * barrier_attr_setpshared.c
+ * pthread_barrier_attr_setpshared.c
*
* Description:
* This translation unit implements barrier primitives.
diff --git a/cancel_cancel.c b/pthread_cancel.c
index c0ab552..7a94d8d 100644
--- a/cancel_cancel.c
+++ b/pthread_cancel.c
@@ -1,5 +1,5 @@
/*
- * cancel_cancel.c
+ * pthread_cancel.c
*
* Description:
* POSIX thread functions related to thread cancellation.
diff --git a/condvar_destroy.c b/pthread_cond_destroy.c
index d0af374..f5102ac 100644
--- a/condvar_destroy.c
+++ b/pthread_cond_destroy.c
@@ -1,5 +1,5 @@
/*
- * condvar_destroy.c
+ * pthread_cond_destroy.c
*
* Description:
* This translation unit implements condition variables and their primitives.
@@ -142,7 +142,7 @@ pthread_cond_destroy (pthread_cond_t * cond)
/*
* !TRY! lock mtxUnblockLock; try will detect busy condition
- * and will not course a deadlock with respect to concurrent
+ * and will not cause a deadlock with respect to concurrent
* signal/broadcast.
*/
if ((result = pthread_mutex_trylock(&(cv->mtxUnblockLock))) != 0)
@@ -169,6 +169,7 @@ pthread_cond_destroy (pthread_cond_t * cond)
* Now it is safe to destroy
*/
*cond = NULL;
+
if (sem_destroy(&(cv->semBlockLock)) != 0)
{
result = errno;
@@ -182,6 +183,30 @@ pthread_cond_destroy (pthread_cond_t * cond)
result2 = pthread_mutex_destroy(&(cv->mtxUnblockLock));
}
+ /* Unlink the CV from the list */
+
+ EnterCriticalSection(&ptw32_cond_list_lock);
+
+ if (ptw32_cond_list_head == cv)
+ {
+ ptw32_cond_list_head = cv->next;
+ }
+ else
+ {
+ cv->prev->next = cv->next;
+ }
+
+ if (ptw32_cond_list_tail == cv)
+ {
+ ptw32_cond_list_tail = cv->prev;
+ }
+ else
+ {
+ cv->next->prev = cv->prev;
+ }
+
+ LeaveCriticalSection(&ptw32_cond_list_lock);
+
(void) free(cv);
}
}
@@ -217,6 +242,5 @@ pthread_cond_destroy (pthread_cond_t * cond)
LeaveCriticalSection(&ptw32_cond_test_init_lock);
}
- return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
-
+ return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
}
diff --git a/condvar_init.c b/pthread_cond_init.c
index ecd4297..446fcc1 100644
--- a/condvar_init.c
+++ b/pthread_cond_init.c
@@ -1,5 +1,5 @@
/*
- * condvar_init.c
+ * pthread_cond_init.c
*
* Description:
* This translation unit implements condition variables and their primitives.
@@ -136,6 +136,27 @@ FAIL0:
cv = NULL;
DONE:
+ if (0 == result)
+ {
+ EnterCriticalSection(&ptw32_cond_list_lock);
+
+ cv->next = NULL;
+ cv->prev = ptw32_cond_list_tail;
+
+ if (ptw32_cond_list_tail != NULL)
+ {
+ ptw32_cond_list_tail->next = cv;
+ }
+
+ ptw32_cond_list_tail = cv;
+
+ if (ptw32_cond_list_head == NULL)
+ {
+ ptw32_cond_list_head = cv;
+ }
+
+ LeaveCriticalSection(&ptw32_cond_list_lock);
+ }
*cond = cv;
return result;
diff --git a/condvar_signal.c b/pthread_cond_signal.c
index 604ef4d..10bea7e 100644
--- a/condvar_signal.c
+++ b/pthread_cond_signal.c
@@ -1,5 +1,5 @@
/*
- * condvar_signal.c
+ * pthread_cond_signal.c
*
* Description:
* This translation unit implements condition variables and their primitives.
diff --git a/condvar_wait.c b/pthread_cond_wait.c
index 550b6c0..d1f5155 100644
--- a/condvar_wait.c
+++ b/pthread_cond_wait.c
@@ -1,5 +1,5 @@
/*
- * condvar_wait.c
+ * pthread_cond_wait.c
*
* Description:
* This translation unit implements condition variables and their primitives.
diff --git a/condvar_attr_destroy.c b/pthread_condattr_destroy.c
index 1be0daf..1be0daf 100644
--- a/condvar_attr_destroy.c
+++ b/pthread_condattr_destroy.c
diff --git a/condvar_attr_getpshared.c b/pthread_condattr_getpshared.c
index 6a9890e..6401a09 100644
--- a/condvar_attr_getpshared.c
+++ b/pthread_condattr_getpshared.c
@@ -1,5 +1,5 @@
/*
- * condvar_attr_getpshared.c
+ * pthread_condattr_getpshared.c
*
* Description:
* This translation unit implements condition variables and their primitives.
diff --git a/condvar_attr_init.c b/pthread_condattr_init.c
index b04c757..4162cfc 100644
--- a/condvar_attr_init.c
+++ b/pthread_condattr_init.c
@@ -1,5 +1,5 @@
/*
- * condvar_attr_init.c
+ * pthread_condattr_init.c
*
* Description:
* This translation unit implements condition variables and their primitives.
diff --git a/condvar_attr_setpshared.c b/pthread_condattr_setpshared.c
index 4e396c2..86b745c 100644
--- a/condvar_attr_setpshared.c
+++ b/pthread_condattr_setpshared.c
@@ -1,5 +1,5 @@
/*
- * condvar_attr_setpshared.c
+ * pthread_condattr_setpshared.c
*
* Description:
* This translation unit implements condition variables and their primitives.
diff --git a/np_delay.c b/pthread_delay_np.c
index d2a893e..1ee7498 100644
--- a/np_delay.c
+++ b/pthread_delay_np.c
@@ -1,5 +1,5 @@
/*
- * np_delay.c
+ * pthreads_delay_np.c
*
* Description:
* This translation unit implements non-portable thread functions.
diff --git a/pthread_detach.c b/pthread_detach.c
new file mode 100644
index 0000000..423997d
--- /dev/null
+++ b/pthread_detach.c
@@ -0,0 +1,88 @@
+/*
+ * pthread_detach.c
+ *
+ * Description:
+ * This translation unit implements functions related to thread
+ * synchronisation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_detach (pthread_t tid)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function detaches the given thread.
+ *
+ * PARAMETERS
+ * thread
+ * an instance of a pthread_t
+ *
+ *
+ * DESCRIPTION
+ * This function detaches the given thread. You may
+ * detach the main thread or to detach a joinable thread
+ * (You should have used pthread_attr_t to create the
+ * thread as detached!)
+ * NOTE: detached threads cannot be joined nor canceled;
+ * storage is freed immediately on termination.
+ *
+ * RESULTS
+ * 0 successfully detached the thread,
+ * EINVAL thread is not a joinable thread,
+ * ENOSPC a required resource has been exhausted,
+ * ESRCH no thread could be found for 'thread',
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if (tid == NULL ||
+ tid->detachState == PTHREAD_CREATE_DETACHED)
+ {
+
+ result = EINVAL;
+
+ }
+ else
+ {
+ result = 0;
+ tid->detachState = PTHREAD_CREATE_DETACHED;
+ }
+
+ return (result);
+
+} /* pthread_detach */
diff --git a/pthread_getschedparam.c b/pthread_getschedparam.c
new file mode 100644
index 0000000..e796a88
--- /dev/null
+++ b/pthread_getschedparam.c
@@ -0,0 +1,74 @@
+/*
+ * sched_getschedparam.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_getschedparam(pthread_t thread, int *policy,
+ struct sched_param *param)
+{
+ int prio;
+
+ /* Validate the thread id. */
+ if (thread == NULL || thread->threadH == 0)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * Validate the policy and param args.
+ * Check that a policy constant wasn't passed rather than &policy.
+ */
+ if (policy <= (int *) SCHED_MAX || param == NULL)
+ {
+ return EINVAL;
+ }
+
+ /* Fill out the policy. */
+ *policy = SCHED_OTHER;
+
+ /* Fill out the sched_param structure. */
+ prio = GetThreadPriority(thread->threadH);
+ if (prio == THREAD_PRIORITY_ERROR_RETURN)
+ {
+ return EINVAL;
+ }
+
+ param->sched_priority = prio;
+ return 0;
+}
diff --git a/pthread_getspecific.c b/pthread_getspecific.c
new file mode 100644
index 0000000..a8da291
--- /dev/null
+++ b/pthread_getspecific.c
@@ -0,0 +1,75 @@
+/*
+ * pthread_getspecific.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void *
+pthread_getspecific (pthread_key_t key)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function returns the current value of key in the
+ * calling thread. If no value has been set for 'key' in
+ * the thread, NULL is returned.
+ *
+ * PARAMETERS
+ * key
+ * an instance of pthread_key_t
+ *
+ *
+ * DESCRIPTION
+ * This function returns the current value of key in the
+ * calling thread. If no value has been set for 'key' in
+ * the thread, NULL is returned.
+ *
+ * RESULTS
+ * key value or NULL on failure
+ *
+ * ------------------------------------------------------
+ */
+{
+ int lasterror = GetLastError();
+ int lastWSAerror = WSAGetLastError();
+
+ void *ptr = TlsGetValue (key->key);
+
+ SetLastError( lasterror );
+ WSASetLastError( lastWSAerror );
+
+ return ptr;
+}
diff --git a/np_getw32threadhandle.c b/pthread_getw32threadhandle_np.c
index 98f610e..ebd9453 100644
--- a/np_getw32threadhandle.c
+++ b/pthread_getw32threadhandle_np.c
@@ -1,5 +1,5 @@
/*
- * np_getw32threadhandle.c
+ * pthread_getw32threadhandle_np.c
*
* Description:
* This translation unit implements non-portable thread functions.
diff --git a/pthread_join.c b/pthread_join.c
new file mode 100644
index 0000000..3c076e0
--- /dev/null
+++ b/pthread_join.c
@@ -0,0 +1,152 @@
+/*
+ * pthread_join.c
+ *
+ * Description:
+ * This translation unit implements functions related to thread
+ * synchronisation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_join (pthread_t thread, void **value_ptr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function waits for 'thread' to terminate and
+ * returns the thread's exit value if 'value_ptr' is not
+ * NULL. This also detaches the thread on successful
+ * completion.
+ *
+ * PARAMETERS
+ * thread
+ * an instance of pthread_t
+ *
+ * value_ptr
+ * pointer to an instance of pointer to void
+ *
+ *
+ * DESCRIPTION
+ * This function waits for 'thread' to terminate and
+ * returns the thread's exit value if 'value_ptr' is not
+ * NULL. This also detaches the thread on successful
+ * completion.
+ * NOTE: detached threads cannot be joined or canceled
+ *
+ * RESULTS
+ * 0 'thread' has completed
+ * EINVAL thread is not a joinable thread,
+ * ESRCH no thread could be found with ID 'thread',
+ * ENOENT thread couldn't find it's own valid handle,
+ * EDEADLK attempt to join thread with self
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ pthread_t self;
+
+ self = pthread_self ();
+ if (self == NULL)
+ {
+ return ENOENT;
+ }
+
+ if (pthread_equal (self, thread) != 0)
+ {
+ result = EDEADLK;
+ }
+ else if (thread->detachState == PTHREAD_CREATE_DETACHED)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ /*
+ * Pthread_join is a cancelation point.
+ * If we are canceled then our target thread must not be
+ * detached (destroyed). This is guarranteed because
+ * pthreadCancelableWait will not return if we
+ * are canceled.
+ */
+ result = pthreadCancelableWait(thread->threadH);
+
+ if (result == 0)
+ {
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+
+ if (value_ptr != NULL
+ && !GetExitCodeThread (thread->threadH, (LPDWORD) value_ptr))
+ {
+ result = ESRCH;
+ }
+ else
+ {
+ /*
+ * The result of making multiple simultaneous calls to
+ * pthread_join() specifying the same target is undefined.
+ */
+ ptw32_threadDestroy (thread);
+ }
+
+#else /* __MINGW32__ && ! __MSVCRT__ */
+
+ /*
+ * If using CRTDLL, the thread may have exited, and endthread
+ * will have closed the handle.
+ */
+ if (value_ptr != NULL)
+ {
+ *value_ptr = thread->exitStatus;
+ }
+
+ /*
+ * The result of making multiple simultaneous calls to
+ * pthread_join() specifying the same target is undefined.
+ */
+ ptw32_threadDestroy (thread);
+
+#endif /* __MINGW32__ && ! __MSVCRT__ */
+
+ }
+ else
+ {
+ result = ESRCH;
+ }
+ }
+
+ return (result);
+
+} /* pthread_join */
diff --git a/pthread_key_create.c b/pthread_key_create.c
new file mode 100644
index 0000000..8ec46d7
--- /dev/null
+++ b/pthread_key_create.c
@@ -0,0 +1,108 @@
+/*
+ * pthread_key_create.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/* TLS_OUT_OF_INDEXES not defined on WinCE */
+#ifndef TLS_OUT_OF_INDEXES
+#define TLS_OUT_OF_INDEXES 0xffffffff
+#endif
+
+int
+pthread_key_create (pthread_key_t * key, void (*destructor) (void *))
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function creates a thread-specific data key visible
+ * to all threads. All existing and new threads have a value
+ * NULL for key until set using pthread_setspecific. When any
+ * thread with a non-NULL value for key terminates, 'destructor'
+ * is called with key's current value for that thread.
+ *
+ * PARAMETERS
+ * key
+ * pointer to an instance of pthread_key_t
+ *
+ *
+ * DESCRIPTION
+ * This function creates a thread-specific data key visible
+ * to all threads. All existing and new threads have a value
+ * NULL for key until set using pthread_setspecific. When any
+ * thread with a non-NULL value for key terminates, 'destructor'
+ * is called with key's current value for that thread.
+ *
+ * RESULTS
+ * 0 successfully created semaphore,
+ * EAGAIN insufficient resources or PTHREAD_KEYS_MAX
+ * exceeded,
+ * ENOMEM insufficient memory to create the key,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ pthread_key_t newkey;
+
+ if ((newkey = (pthread_key_t) calloc (1, sizeof (*newkey))) == NULL)
+ {
+ result = ENOMEM;
+ }
+ else if ((newkey->key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ {
+ result = EAGAIN;
+
+ free (newkey);
+ newkey = NULL;
+ }
+ else if (destructor != NULL)
+ {
+ /*
+ * Have to manage associations between thread and key;
+ * Therefore, need a lock that allows multiple threads
+ * to gain exclusive access to the key->threads list.
+ *
+ * The mutex will only be created when it is first locked.
+ */
+ newkey->threadsLock = PTHREAD_MUTEX_INITIALIZER;
+ newkey->destructor = destructor;
+ }
+
+ *key = newkey;
+
+ return (result);
+}
diff --git a/pthread_key_delete.c b/pthread_key_delete.c
new file mode 100644
index 0000000..0fb3fbb
--- /dev/null
+++ b/pthread_key_delete.c
@@ -0,0 +1,127 @@
+/*
+ * pthread_key_delete.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_key_delete (pthread_key_t key)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function deletes a thread-specific data key. This
+ * does not change the value of the thread spcific data key
+ * for any thread and does not run the key's destructor
+ * in any thread so it should be used with caution.
+ *
+ * PARAMETERS
+ * key
+ * pointer to an instance of pthread_key_t
+ *
+ *
+ * DESCRIPTION
+ * This function deletes a thread-specific data key. This
+ * does not change the value of the thread spcific data key
+ * for any thread and does not run the key's destructor
+ * in any thread so it should be used with caution.
+ *
+ * RESULTS
+ * 0 successfully deleted the key,
+ * EINVAL key is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+ if (key != NULL)
+ {
+ if (key->threads != NULL &&
+ key->destructor != NULL &&
+ pthread_mutex_lock (&(key->threadsLock)) == 0)
+ {
+ /*
+ * Run through all Thread<-->Key associations
+ * for this key.
+ * If the pthread_t still exits (ie the assoc->thread
+ * is not NULL) then leave the assoc for the thread to
+ * destroy.
+ * Notes:
+ * If assoc->thread is NULL, then the associated thread
+ * is no longer referencing this assoc.
+ * The association is only referenced
+ * by this key and must be released; otherwise
+ * the assoc will be destroyed when the thread is destroyed.
+ */
+ ThreadKeyAssoc *assoc;
+
+ assoc = (ThreadKeyAssoc *) key->threads;
+
+ while (assoc != NULL)
+ {
+ if (pthread_mutex_lock (&(assoc->lock)) == 0)
+ {
+ ThreadKeyAssoc *next;
+
+ assoc->key = NULL;
+ next = assoc->nextThread;
+ assoc->nextThread = NULL;
+
+ pthread_mutex_unlock (&(assoc->lock));
+
+ ptw32_tkAssocDestroy (assoc);
+
+ assoc = next;
+ }
+ }
+ pthread_mutex_unlock (&(key->threadsLock));
+ }
+
+ TlsFree (key->key);
+ if (key->destructor != NULL)
+ {
+ pthread_mutex_destroy (&(key->threadsLock));
+ }
+
+#if defined( _DEBUG )
+ memset ((char *) key, 0, sizeof (*key));
+#endif
+ free (key);
+ }
+
+ return (result);
+}
diff --git a/pthread_mutex_destroy.c b/pthread_mutex_destroy.c
new file mode 100644
index 0000000..c9c1426
--- /dev/null
+++ b/pthread_mutex_destroy.c
@@ -0,0 +1,134 @@
+/*
+ * pthread_mutex_destroy.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_destroy(pthread_mutex_t *mutex)
+{
+ int result = 0;
+ pthread_mutex_t mx;
+
+ if (mutex == NULL
+ || *mutex == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * Check to see if we have something to delete.
+ */
+ if (*mutex != PTHREAD_MUTEX_INITIALIZER)
+ {
+ mx = *mutex;
+
+ result = pthread_mutex_trylock(&mx);
+
+ /*
+ * The mutex type may not be RECURSIVE therefore trylock may return EBUSY if
+ * we already own the mutex. Here we are assuming that it's OK to destroy
+ * a mutex that we own and have locked recursively. Is this correct?
+ *
+ * For FAST mutexes we record the owner as ANONYMOUS for speed. In this
+ * case we assume that the thread calling pthread_mutex_destroy() is the
+ * owner, if the mutex is owned at all.
+ */
+ if (result == 0
+ || mx->ownerThread == (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS
+ || pthread_equal( mx->ownerThread, pthread_self() ) )
+ {
+ /*
+ * FIXME!!!
+ * The mutex isn't held by another thread but we could still
+ * be too late invalidating the mutex below since another thread
+ * may already have entered mutex_lock and the check for a valid
+ * *mutex != NULL.
+ */
+ *mutex = NULL;
+
+ result = pthread_mutex_unlock(&mx);
+
+ if (result == 0)
+ {
+ (void) sem_destroy( &mx->wait_sema );
+ DeleteCriticalSection( &mx->wait_cs );
+ free(mx);
+ }
+ else
+ {
+ /*
+ * Restore the mutex before we return the error.
+ */
+ *mutex = mx;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * See notes in ptw32_mutex_check_need_init() above also.
+ */
+ EnterCriticalSection(&ptw32_mutex_test_init_lock);
+
+ /*
+ * Check again.
+ */
+ if (*mutex == PTHREAD_MUTEX_INITIALIZER)
+ {
+ /*
+ * This is all we need to do to destroy a statically
+ * initialised mutex that has not yet been used (initialised).
+ * If we get to here, another thread
+ * waiting to initialise this mutex will get an EINVAL.
+ */
+ *mutex = NULL;
+ }
+ else
+ {
+ /*
+ * The mutex has been initialised while we were waiting
+ * so assume it's in use.
+ */
+ result = EBUSY;
+ }
+
+ LeaveCriticalSection(&ptw32_mutex_test_init_lock);
+ }
+
+ return(result);
+}
diff --git a/pthread_mutex_init.c b/pthread_mutex_init.c
new file mode 100644
index 0000000..7076c22
--- /dev/null
+++ b/pthread_mutex_init.c
@@ -0,0 +1,107 @@
+/*
+ * pthread_mutex_init.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
+{
+ int result = 0;
+ pthread_mutex_t mx;
+
+ if (mutex == NULL)
+ {
+ return EINVAL;
+ }
+
+ if (attr != NULL
+ && *attr != NULL
+ && (*attr)->pshared == PTHREAD_PROCESS_SHARED
+ )
+ {
+ /*
+ * Creating mutex that can be shared between
+ * processes.
+ */
+#if _POSIX_THREAD_PROCESS_SHARED
+
+ /*
+ * Not implemented yet.
+ */
+
+#error ERROR [__FILE__, line __LINE__]: Process shared mutexes are not supported yet.
+
+#else
+
+ return ENOSYS;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ }
+
+ mx = (pthread_mutex_t) calloc(1, sizeof(*mx));
+
+ if (mx == NULL)
+ {
+ result = ENOMEM;
+ }
+ else
+ {
+ mx->lock_idx = PTW32_MUTEX_LOCK_IDX_INIT;
+ mx->recursive_count = 0;
+ mx->kind = (attr == NULL || *attr == NULL
+ ? PTHREAD_MUTEX_DEFAULT
+ : (*attr)->kind);
+ mx->ownerThread = NULL;
+
+ if ( 0 != sem_init( &mx->wait_sema, 0, 0 ))
+ {
+ result = EAGAIN;
+ free(mx);
+ mx = NULL;
+ }
+ else
+ {
+ InitializeCriticalSection( &mx->wait_cs );
+ }
+ }
+
+ *mutex = mx;
+
+ return(result);
+}
diff --git a/pthread_mutex_lock.c b/pthread_mutex_lock.c
new file mode 100644
index 0000000..5ba97dc
--- /dev/null
+++ b/pthread_mutex_lock.c
@@ -0,0 +1,105 @@
+/*
+ * pthread_mutex_lock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+ int result = 0;
+ pthread_mutex_t mx;
+
+
+ if (mutex == NULL || *mutex == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static mutex. We check
+ * again inside the guarded section of ptw32_mutex_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*mutex == PTHREAD_MUTEX_INITIALIZER)
+ {
+ if ((result = ptw32_mutex_check_need_init(mutex)) != 0)
+ {
+ return(result);
+ }
+ }
+
+ mx = *mutex;
+
+ if( 0 == InterlockedIncrement( &mx->lock_idx ) )
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
+ ? pthread_self()
+ : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
+ }
+ else
+ {
+ if( mx->kind != PTHREAD_MUTEX_FAST_NP &&
+ pthread_equal( mx->ownerThread, pthread_self() ) )
+ {
+ (void) InterlockedDecrement( &mx->lock_idx );
+
+ if( mx->kind == PTHREAD_MUTEX_RECURSIVE_NP )
+ {
+ mx->recursive_count++;
+ }
+ else
+ {
+ result = EDEADLK;
+ }
+ }
+ else
+ {
+ if ((result = sem_wait( &mx->wait_sema )) == 0)
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
+ ? pthread_self()
+ : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
+ }
+ }
+ }
+
+ return(result);
+}
diff --git a/pthread_mutex_timedlock.c b/pthread_mutex_timedlock.c
new file mode 100644
index 0000000..ec1caa9
--- /dev/null
+++ b/pthread_mutex_timedlock.c
@@ -0,0 +1,356 @@
+/*
+ * pthread_mutex_timedlock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#ifndef _UWIN
+# include <process.h>
+#endif
+#ifndef NEED_FTIME
+#include <sys/timeb.h>
+#endif
+#include "pthread.h"
+#include "implement.h"
+
+
+static INLINE int
+ptw32_timed_semwait (sem_t * sem, const struct timespec * abstime)
+ /*
+ * ------------------------------------------------------
+ * DESCRIPTION
+ * This function waits on a POSIX semaphore. If the
+ * semaphore value is greater than zero, it decreases
+ * its value by one. If the semaphore value is zero, then
+ * the calling thread (or process) is blocked until it can
+ * successfully decrease the value or until abstime.
+ * If abstime has passed when this routine is called then
+ * it returns a result to indicate this.
+ *
+ * If 'abstime' is a NULL pointer then this function will
+ * block until it can successfully decrease the value or
+ * until interrupted by a signal.
+ *
+ * RESULTS
+ * 2 abstime has passed already
+ * 1 abstime timed out while waiting
+ * 0 successfully decreased semaphore,
+ * -1 failed, error in errno.
+ * ERRNO
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS semaphores are not supported,
+ * EINTR the function was interrupted by a signal,
+ * EDEADLK a deadlock condition was detected.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+#ifdef NEED_FTIME
+
+ struct timespec currSysTime;
+
+#else /* NEED_FTIME */
+
+ struct _timeb currSysTime;
+
+#endif /* NEED_FTIME */
+
+ const DWORD NANOSEC_PER_MILLISEC = 1000000;
+ const DWORD MILLISEC_PER_SEC = 1000;
+ DWORD milliseconds;
+ DWORD status;
+
+ if (sem == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ if (abstime == NULL)
+ {
+ milliseconds = INFINITE;
+ }
+ else
+ {
+ /*
+ * Calculate timeout as milliseconds from current system time.
+ */
+
+ /* get current system time */
+
+#ifdef NEED_FTIME
+
+ {
+ FILETIME ft;
+ SYSTEMTIME st;
+
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &ft);
+ /*
+ * GetSystemTimeAsFileTime(&ft); would be faster,
+ * but it does not exist on WinCE
+ */
+
+ ptw32_filetime_to_timespec(&ft, &currSysTime);
+ }
+
+ /*
+ * subtract current system time from abstime
+ */
+ milliseconds = (abstime->tv_sec - currSysTime.tv_sec) * MILLISEC_PER_SEC;
+ milliseconds += ((abstime->tv_nsec - currSysTime.tv_nsec)
+ + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;
+
+#else /* NEED_FTIME */
+ _ftime(&currSysTime);
+
+ /*
+ * subtract current system time from abstime
+ */
+ milliseconds = (abstime->tv_sec - currSysTime.time) * MILLISEC_PER_SEC;
+ milliseconds += ((abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC)
+ - currSysTime.millitm;
+
+#endif /* NEED_FTIME */
+
+
+ if (((int) milliseconds) < 0)
+ {
+ return 2;
+ }
+ }
+
+#ifdef NEED_SEM
+
+ status = WaitForSingleObject( (*sem)->event, milliseconds );
+
+#else /* NEED_SEM */
+
+ status = WaitForSingleObject( (*sem)->sem, milliseconds );
+
+#endif
+
+ if (status == WAIT_OBJECT_0)
+ {
+
+#ifdef NEED_SEM
+
+ ptw32_decrease_semaphore(sem);
+
+#endif /* NEED_SEM */
+
+ return 0;
+ }
+ else if (status == WAIT_TIMEOUT)
+ {
+ return 1;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+ }
+
+ if (result != 0)
+ {
+ errno = result;
+ return -1;
+ }
+
+ return 0;
+
+} /* ptw32_timed_semwait */
+
+
+int
+pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime)
+{
+ int result = 0;
+ pthread_mutex_t mx;
+
+#ifdef NEED_SEM
+ errno = ENOTSUP;
+ return -1;
+#endif
+
+ if (mutex == NULL || *mutex == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static mutex. We check
+ * again inside the guarded section of ptw32_mutex_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*mutex == PTHREAD_MUTEX_INITIALIZER)
+ {
+ if ((result = ptw32_mutex_check_need_init(mutex)) != 0)
+ {
+ return(result);
+ }
+ }
+
+ mx = *mutex;
+
+ if( 0 == InterlockedIncrement( &mx->lock_idx ) )
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
+ ? pthread_self()
+ : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
+ }
+ else
+ {
+ if( mx->kind != PTHREAD_MUTEX_FAST_NP &&
+ pthread_equal( mx->ownerThread, pthread_self() ) )
+ {
+ (void) InterlockedDecrement( &mx->lock_idx );
+
+ if( mx->kind == PTHREAD_MUTEX_RECURSIVE_NP )
+ {
+ mx->recursive_count++;
+ }
+ else
+ {
+ result = EDEADLK;
+ }
+ }
+ else
+ {
+ if (abstime == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ switch (ptw32_timed_semwait( &mx->wait_sema, abstime ))
+ {
+ case 0: /* We got the mutex. */
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
+ ? pthread_self()
+ : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
+ break;
+ }
+ case 1: /* Timedout, try a second grab. */
+ {
+ EnterCriticalSection(&mx->wait_cs);
+
+ /*
+ * If we timeout, it is up to us to adjust lock_idx to say
+ * we're no longer waiting. If the mutex was also unlocked
+ * while we were timing out, and we simply return ETIMEDOUT,
+ * then wait_sema would be left in a state that is not consistent
+ * with the state of lock_idx.
+ *
+ * We must check to see if wait_sema has just been posted
+ * but we can't just call sem_getvalue - we must compete for
+ * the semaphore using sem_trywait(), otherwise we would need
+ * additional critical sections elsewhere, which would make the
+ * logic too inefficient.
+ *
+ * If sem_trywait returns EAGAIN then either wait_sema
+ * was given directly to another waiting thread or
+ * another thread has called sem_*wait() before us and
+ * taken the lock. Then we MUST decrement lock_idx and return
+ * ETIMEDOUT.
+ *
+ * Otherwise we MUST return success (because we have effectively
+ * acquired the lock that would have been ours had we not
+ * timed out), and NOT decrement lock_idx.
+ *
+ * We can almost guarrantee that EAGAIN is the only
+ * possible error, so no need to test errno.
+ */
+
+ if ( -1 == sem_trywait( &mx->wait_sema ) )
+ {
+ (void) InterlockedDecrement( &mx->lock_idx );
+ result = ETIMEDOUT;
+ }
+
+ LeaveCriticalSection(&mx->wait_cs);
+ break;
+ }
+ case 2: /* abstime passed before we started to wait. */
+ {
+ /*
+ * If we timeout, it is up to us to adjust lock_idx to say
+ * we're no longer waiting.
+ *
+ * The owner thread may still have posted wait_sema thinking
+ * we were waiting. I believe we must check but then NOT do any
+ * programmed work if we have acquired the mutex because
+ * we don't how long ago abstime was. We MUST just release it
+ * immediately.
+ */
+ EnterCriticalSection(&mx->wait_cs);
+
+ result = ETIMEDOUT;
+
+ if ( -1 == sem_trywait( &mx->wait_sema ) )
+ {
+ (void) InterlockedDecrement( &mx->lock_idx );
+ }
+ else
+ {
+ if ( InterlockedDecrement( &mx->lock_idx ) >= 0 )
+ {
+ /* Someone else is waiting on that mutex */
+ if ( sem_post( &mx->wait_sema ) != 0 )
+ {
+ result = errno;
+ }
+ }
+ }
+
+ LeaveCriticalSection(&mx->wait_cs);
+ break;
+ }
+ default:
+ {
+ result = errno;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return(result);
+}
diff --git a/pthread_mutex_trylock.c b/pthread_mutex_trylock.c
new file mode 100644
index 0000000..66eb96e
--- /dev/null
+++ b/pthread_mutex_trylock.c
@@ -0,0 +1,99 @@
+/*
+ * pthread_mutex_trylock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_trylock(pthread_mutex_t *mutex)
+{
+ int result = 0;
+ pthread_mutex_t mx;
+
+ if (mutex == NULL || *mutex == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static mutex. We check
+ * again inside the guarded section of ptw32_mutex_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*mutex == PTHREAD_MUTEX_INITIALIZER)
+ {
+ result = ptw32_mutex_check_need_init(mutex);
+ }
+
+ mx = *mutex;
+
+ if (result == 0)
+ {
+ if ( (PTW32_INTERLOCKED_LONG) PTW32_MUTEX_LOCK_IDX_INIT ==
+ ptw32_interlocked_compare_exchange((PTW32_INTERLOCKED_LPLONG) &mx->lock_idx,
+ (PTW32_INTERLOCKED_LONG) 0,
+ (PTW32_INTERLOCKED_LONG) PTW32_MUTEX_LOCK_IDX_INIT))
+ {
+ mx->recursive_count = 1;
+ mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP
+ ? pthread_self()
+ : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);
+ }
+ else
+ {
+ if( mx->kind != PTHREAD_MUTEX_FAST_NP &&
+ pthread_equal( mx->ownerThread, pthread_self() ) )
+ {
+ if( mx->kind == PTHREAD_MUTEX_RECURSIVE_NP )
+ {
+ mx->recursive_count++;
+ }
+ else
+ {
+ result = EDEADLK;
+ }
+ }
+ else
+ {
+ result = EBUSY;
+ }
+ }
+ }
+
+ return(result);
+}
diff --git a/pthread_mutex_unlock.c b/pthread_mutex_unlock.c
new file mode 100644
index 0000000..0c1ea5f
--- /dev/null
+++ b/pthread_mutex_unlock.c
@@ -0,0 +1,93 @@
+/*
+ * pthread_mutex_unlock.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+ int result = 0;
+ pthread_mutex_t mx;
+
+ if (mutex == NULL || *mutex == NULL)
+ {
+ return EINVAL;
+ }
+
+ mx = *mutex;
+
+ /*
+ * If the thread calling us holds the mutex then there is no
+ * race condition. If another thread holds the
+ * lock then we shouldn't be in here.
+ */
+ if (mx != PTHREAD_MUTEX_INITIALIZER)
+ {
+ if (mx->ownerThread == (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS
+ || pthread_equal(mx->ownerThread, pthread_self()))
+ {
+ if( mx->kind != PTHREAD_MUTEX_RECURSIVE_NP
+ || 0 == --mx->recursive_count )
+ {
+ mx->ownerThread = NULL;
+ EnterCriticalSection( &mx->wait_cs );
+
+ if( InterlockedDecrement( &mx->lock_idx ) >= 0 )
+ {
+ /* Someone is waiting on that mutex */
+ if (sem_post( &mx->wait_sema ) != 0)
+ {
+ result = errno;
+ }
+ }
+
+ LeaveCriticalSection( &mx->wait_cs );
+ }
+ }
+ else
+ {
+ result = EPERM;
+ }
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return(result);
+}
diff --git a/pthread_mutexattr_destroy.c b/pthread_mutexattr_destroy.c
new file mode 100644
index 0000000..d2b9865
--- /dev/null
+++ b/pthread_mutexattr_destroy.c
@@ -0,0 +1,83 @@
+/*
+ * pthread_mutexattr_destroy.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_destroy (pthread_mutexattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Destroys a mutex attributes object. The object can
+ * no longer be used.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ *
+ * DESCRIPTION
+ * Destroys a mutex attributes object. The object can
+ * no longer be used.
+ *
+ * NOTES:
+ * 1) Does not affect mutexes created using 'attr'
+ *
+ * RESULTS
+ * 0 successfully released attr,
+ * EINVAL 'attr' is invalid.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+ if (attr == NULL || *attr == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ pthread_mutexattr_t ma = *attr;
+
+ *attr = NULL;
+ free (ma);
+ }
+
+ return(result);
+} /* pthread_mutexattr_destroy */
diff --git a/np_mutexattr_setkind.c b/pthread_mutexattr_getkind_np.c
index df56ca6..cfa27b1 100644
--- a/np_mutexattr_setkind.c
+++ b/pthread_mutexattr_getkind_np.c
@@ -1,5 +1,5 @@
/*
- * np_mutexattr_setkind.c
+ * pthread_mutexattr_getkind_np.c
*
* Description:
* This translation unit implements non-portable thread functions.
@@ -37,19 +37,6 @@
#include "pthread.h"
#include "implement.h"
-/*
- * pthread_mutexattr_setkind_np()
- */
-int
-pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, int kind)
-{
- return pthread_mutexattr_settype( attr, kind );
-}
-
-
-/*
- * pthread_mutexattr_getkind_np()
- */
int
pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, int *kind)
{
diff --git a/pthread_mutexattr_getpshared.c b/pthread_mutexattr_getpshared.c
new file mode 100644
index 0000000..8a5c50b
--- /dev/null
+++ b/pthread_mutexattr_getpshared.c
@@ -0,0 +1,97 @@
+/*
+ * pthread_mutexattr_getpshared.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr,
+ int *pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Determine whether mutexes created with 'attr' can be
+ * shared between processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ * pshared
+ * will be set to one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ *
+ * DESCRIPTION
+ * Mutexes creatd with 'attr' can be shared between
+ * processes if pthread_mutex_t variable is allocated
+ * in memory shared by these processes.
+ * NOTES:
+ * 1) pshared mutexes MUST be allocated in shared
+ * memory.
+ * 2) The following macro is defined if shared mutexes
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully retrieved attribute,
+ * EINVAL 'attr' is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) &&
+ (pshared != NULL))
+ {
+ *pshared = (*attr)->pshared;
+ result = 0;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+
+} /* pthread_mutexattr_getpshared */
diff --git a/pthread_mutexattr_gettype.c b/pthread_mutexattr_gettype.c
new file mode 100644
index 0000000..c4232b0
--- /dev/null
+++ b/pthread_mutexattr_gettype.c
@@ -0,0 +1,57 @@
+/*
+ * pthread_mutexattr_gettype.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_gettype (pthread_mutexattr_t * attr,
+ int *kind)
+{
+ int result = 0;
+
+ if (attr != NULL && *attr != NULL && kind != NULL)
+ {
+ *kind = (*attr)->kind;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+}
diff --git a/pthread_mutexattr_init.c b/pthread_mutexattr_init.c
new file mode 100644
index 0000000..fa2da3e
--- /dev/null
+++ b/pthread_mutexattr_init.c
@@ -0,0 +1,86 @@
+/*
+ * pthread_mutexattr_init.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_init (pthread_mutexattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Initializes a mutex attributes object with default
+ * attributes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ *
+ * DESCRIPTION
+ * Initializes a mutex attributes object with default
+ * attributes.
+ *
+ * NOTES:
+ * 1) Used to define mutex types
+ *
+ * RESULTS
+ * 0 successfully initialized attr,
+ * ENOMEM insufficient memory for attr.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ pthread_mutexattr_t ma;
+
+ ma = (pthread_mutexattr_t) calloc (1, sizeof (*ma));
+
+ if (ma == NULL)
+ {
+ result = ENOMEM;
+ }
+ else
+ {
+ ma->pshared = PTHREAD_PROCESS_PRIVATE;
+ ma->kind = PTHREAD_MUTEX_DEFAULT;
+ }
+
+ *attr = ma;
+
+ return(result);
+} /* pthread_mutexattr_init */
diff --git a/pthread_mutexattr_setkind_np.c b/pthread_mutexattr_setkind_np.c
new file mode 100644
index 0000000..9abaacd
--- /dev/null
+++ b/pthread_mutexattr_setkind_np.c
@@ -0,0 +1,45 @@
+/*
+ * pthread_mutexattr_setkind_np.c
+ *
+ * Description:
+ * This translation unit implements non-portable thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, int kind)
+{
+ return pthread_mutexattr_settype( attr, kind );
+}
+
diff --git a/pthread_mutexattr_setpshared.c b/pthread_mutexattr_setpshared.c
new file mode 100644
index 0000000..d412573
--- /dev/null
+++ b/pthread_mutexattr_setpshared.c
@@ -0,0 +1,120 @@
+/*
+ * pthread_mutexattr_setpshared.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
+ int pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Mutexes created with 'attr' can be shared between
+ * processes if pthread_mutex_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ * pshared
+ * must be one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ * DESCRIPTION
+ * Mutexes creatd with 'attr' can be shared between
+ * processes if pthread_mutex_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * NOTES:
+ * 1) pshared mutexes MUST be allocated in shared
+ * memory.
+ *
+ * 2) The following macro is defined if shared mutexes
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully set attribute,
+ * EINVAL 'attr' or pshared is invalid,
+ * ENOSYS PTHREAD_PROCESS_SHARED not supported,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) &&
+ ((pshared == PTHREAD_PROCESS_SHARED) ||
+ (pshared == PTHREAD_PROCESS_PRIVATE)))
+ {
+ if (pshared == PTHREAD_PROCESS_SHARED)
+ {
+
+#if !defined( _POSIX_THREAD_PROCESS_SHARED )
+
+ result = ENOSYS;
+ pshared = PTHREAD_PROCESS_PRIVATE;
+
+#else
+
+ result = 0;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ }
+ else
+ {
+ result = 0;
+ }
+
+ (*attr)->pshared = pshared;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+
+} /* pthread_mutexattr_setpshared */
diff --git a/pthread_mutexattr_settype.c b/pthread_mutexattr_settype.c
new file mode 100644
index 0000000..a8b3511
--- /dev/null
+++ b/pthread_mutexattr_settype.c
@@ -0,0 +1,144 @@
+/*
+ * pthread_mutexattr_settype.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_mutexattr_settype (pthread_mutexattr_t * attr,
+ int kind)
+ /*
+ * ------------------------------------------------------
+ *
+ * DOCPUBLIC
+ * The pthread_mutexattr_settype() and
+ * pthread_mutexattr_gettype() functions respectively set and
+ * get the mutex type attribute. This attribute is set in the
+ * type parameter to these functions.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_mutexattr_t
+ *
+ * type
+ * must be one of:
+ *
+ * PTHREAD_MUTEX_DEFAULT
+ *
+ * PTHREAD_MUTEX_NORMAL
+ *
+ * PTHREAD_MUTEX_ERRORCHECK
+ *
+ * PTHREAD_MUTEX_RECURSIVE
+ *
+ * DESCRIPTION
+ * The pthread_mutexattr_settype() and
+ * pthread_mutexattr_gettype() functions respectively set and
+ * get the mutex type attribute. This attribute is set in the
+ * type parameter to these functions. The default value of the
+ * type attribute is PTHREAD_MUTEX_DEFAULT.
+ *
+ * The type of mutex is contained in the type attribute of the
+ * mutex attributes. Valid mutex types include:
+ *
+ * PTHREAD_MUTEX_NORMAL
+ * This type of mutex does not detect deadlock. A
+ * thread attempting to relock this mutex without
+ * first unlocking it will deadlock. Attempting to
+ * unlock a mutex locked by a different thread
+ * results in undefined behavior. Attempting to
+ * unlock an unlocked mutex results in undefined
+ * behavior.
+ *
+ * PTHREAD_MUTEX_ERRORCHECK
+ * This type of mutex provides error checking. A
+ * thread attempting to relock this mutex without
+ * first unlocking it will return with an error. A
+ * thread attempting to unlock a mutex which another
+ * thread has locked will return with an error. A
+ * thread attempting to unlock an unlocked mutex will
+ * return with an error.
+ *
+ * PTHREAD_MUTEX_DEFAULT
+ * Same as PTHREAD_MUTEX_NORMAL.
+ *
+ * PTHREAD_MUTEX_RECURSIVE
+ * A thread attempting to relock this mutex without
+ * first unlocking it will succeed in locking the
+ * mutex. The relocking deadlock which can occur with
+ * mutexes of type PTHREAD_MUTEX_NORMAL cannot occur
+ * with this type of mutex. Multiple locks of this
+ * mutex require the same number of unlocks to
+ * release the mutex before another thread can
+ * acquire the mutex. A thread attempting to unlock a
+ * mutex which another thread has locked will return
+ * with an error. A thread attempting to unlock an
+ * unlocked mutex will return with an error. This
+ * type of mutex is only supported for mutexes whose
+ * process shared attribute is
+ * PTHREAD_PROCESS_PRIVATE.
+ *
+ * RESULTS
+ * 0 successfully set attribute,
+ * EINVAL 'attr' or 'type' is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+ if ((attr != NULL && *attr != NULL))
+ {
+ switch (kind)
+ {
+ case PTHREAD_MUTEX_FAST_NP:
+ case PTHREAD_MUTEX_RECURSIVE_NP:
+ case PTHREAD_MUTEX_ERRORCHECK_NP:
+ (*attr)->kind = kind;
+ break;
+ default:
+ result = EINVAL;
+ break;
+ }
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+} /* pthread_mutexattr_settype */
diff --git a/np_num_processors.c b/pthread_num_processors_np.c
index 776e2f7..8d1deec 100644
--- a/np_num_processors.c
+++ b/pthread_num_processors_np.c
@@ -1,5 +1,5 @@
/*
- * np_num_processors.c
+ * pthread_num_processors_np.c
*
* Description:
* This translation unit implements non-portable thread functions.
diff --git a/pthread_rwlock_destroy.c b/pthread_rwlock_destroy.c
new file mode 100644
index 0000000..96feb0f
--- /dev/null
+++ b/pthread_rwlock_destroy.c
@@ -0,0 +1,140 @@
+/*
+ * pthread_rwlock_destroy.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include <errno.h>
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
+{
+ pthread_rwlock_t rwl;
+ int result = 0, result1 = 0, result2 = 0;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ if (*rwlock != PTHREAD_RWLOCK_INITIALIZER)
+ {
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result = pthread_mutex_lock(&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ if ((result = pthread_mutex_lock(&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ /*
+ * Check whether any threads own/wait for the lock (wait for ex.access);
+ * report "BUSY" if so.
+ */
+ if (rwl->nExclusiveAccessCount > 0
+ || rwl->nSharedAccessCount > rwl->nCompletedSharedAccessCount)
+ {
+ result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted));
+ result1 = pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
+ result2 = EBUSY;
+ }
+ else
+ {
+ rwl->nMagic = 0;
+
+ if ((result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ pthread_mutex_unlock(&rwl->mtxExclusiveAccess);
+ return result;
+ }
+
+ if ((result = pthread_mutex_unlock(&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ *rwlock = NULL; /* Invalidate rwlock before anything else */
+ result = pthread_cond_destroy(&(rwl->cndSharedAccessCompleted));
+ result1 = pthread_mutex_destroy(&(rwl->mtxSharedAccessCompleted));
+ result2 = pthread_mutex_destroy(&(rwl->mtxExclusiveAccess));
+ (void) free(rwl);
+ }
+ }
+ else
+ {
+ /*
+ * See notes in ptw32_rwlock_check_need_init() above also.
+ */
+ EnterCriticalSection(&ptw32_rwlock_test_init_lock);
+
+ /*
+ * Check again.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ /*
+ * This is all we need to do to destroy a statically
+ * initialised rwlock that has not yet been used (initialised).
+ * If we get to here, another thread
+ * waiting to initialise this rwlock will get an EINVAL.
+ */
+ *rwlock = NULL;
+ }
+ else
+ {
+ /*
+ * The rwlock has been initialised while we were waiting
+ * so assume it's in use.
+ */
+ result = EBUSY;
+ }
+
+ LeaveCriticalSection(&ptw32_rwlock_test_init_lock);
+ }
+
+ return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
+}
diff --git a/pthread_rwlock_init.c b/pthread_rwlock_init.c
new file mode 100644
index 0000000..6affbce
--- /dev/null
+++ b/pthread_rwlock_init.c
@@ -0,0 +1,109 @@
+/*
+ * pthread_rwlock_init.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include <errno.h>
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
+{
+ int result;
+ pthread_rwlock_t rwl = 0;
+
+ if (rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ if (attr != NULL && *attr != NULL)
+ {
+ result = EINVAL; /* Not supported */
+ goto DONE;
+ }
+
+ rwl = (pthread_rwlock_t) calloc(1, sizeof(*rwl));
+
+ if (rwl == NULL)
+ {
+ result = ENOMEM;
+ goto DONE;
+ }
+
+ rwl->nSharedAccessCount = 0;
+ rwl->nExclusiveAccessCount = 0;
+ rwl->nCompletedSharedAccessCount = 0;
+
+ result = pthread_mutex_init(&rwl->mtxExclusiveAccess, NULL);
+ if (result != 0)
+ {
+ goto FAIL0;
+ }
+
+ result = pthread_mutex_init(&rwl->mtxSharedAccessCompleted, NULL);
+ if (result != 0)
+ {
+ goto FAIL1;
+ }
+
+ result = pthread_cond_init(&rwl->cndSharedAccessCompleted, NULL);
+ if (result != 0)
+ {
+ goto FAIL2;
+ }
+
+ rwl->nMagic = PTW32_RWLOCK_MAGIC;
+
+ result = 0;
+ goto DONE;
+
+FAIL2:
+ (void) pthread_mutex_destroy(&(rwl->mtxSharedAccessCompleted));
+
+FAIL1:
+ (void) pthread_mutex_destroy(&(rwl->mtxExclusiveAccess));
+
+FAIL0:
+ (void) free(rwl);
+ rwl = NULL;
+
+DONE:
+ *rwlock = rwl;
+
+ return result;
+}
diff --git a/pthread_rwlock_rdlock.c b/pthread_rwlock_rdlock.c
new file mode 100644
index 0000000..a23a80d
--- /dev/null
+++ b/pthread_rwlock_rdlock.c
@@ -0,0 +1,101 @@
+/*
+ * pthread_rwlock_rdlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include <errno.h>
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
+{
+ int result;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static rwlock. We check
+ * again inside the guarded section of ptw32_rwlock_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = ptw32_rwlock_check_need_init(rwlock);
+
+ if (result != 0 && result != EBUSY)
+ {
+ return result;
+ }
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result = pthread_mutex_lock(&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ if (++rwl->nSharedAccessCount == INT_MAX)
+ {
+ if ((result = pthread_mutex_lock(&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+
+ if ((result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+ }
+
+ return (pthread_mutex_unlock(&(rwl->mtxExclusiveAccess)));
+}
diff --git a/pthread_rwlock_tryrdlock.c b/pthread_rwlock_tryrdlock.c
new file mode 100644
index 0000000..d3a6cf2
--- /dev/null
+++ b/pthread_rwlock_tryrdlock.c
@@ -0,0 +1,101 @@
+/*
+ * pthread_rwlock_tryrdlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include <errno.h>
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_tryrdlock(pthread_rwlock_t * rwlock)
+{
+ int result;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static rwlock. We check
+ * again inside the guarded section of ptw32_rwlock_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = ptw32_rwlock_check_need_init(rwlock);
+
+ if (result != 0 && result != EBUSY)
+ {
+ return result;
+ }
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result = pthread_mutex_trylock(&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ if (++rwl->nSharedAccessCount == INT_MAX)
+ {
+ if ((result = pthread_mutex_lock(&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+
+ if ((result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+ }
+
+ return (pthread_mutex_unlock(&rwl->mtxExclusiveAccess));
+}
diff --git a/pthread_rwlock_trywrlock.c b/pthread_rwlock_trywrlock.c
new file mode 100644
index 0000000..48bae9f
--- /dev/null
+++ b/pthread_rwlock_trywrlock.c
@@ -0,0 +1,120 @@
+/*
+ * pthread_rwlock_trywrlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include <errno.h>
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_trywrlock(pthread_rwlock_t * rwlock)
+{
+ int result, result1;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static rwlock. We check
+ * again inside the guarded section of ptw32_rwlock_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = ptw32_rwlock_check_need_init(rwlock);
+
+ if (result != 0 && result != EBUSY)
+ {
+ return result;
+ }
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result = pthread_mutex_trylock(&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ if ((result = pthread_mutex_trylock(&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ result1 = pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
+ return ((result1 != 0) ? result1 : result);
+ }
+
+ if (rwl->nExclusiveAccessCount == 0)
+ {
+ if (rwl->nCompletedSharedAccessCount > 0)
+ {
+ rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+ }
+
+ if (rwl->nSharedAccessCount > 0)
+ {
+ if ((result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ if ((result = pthread_mutex_unlock(&(rwl->mtxExclusiveAccess))) == 0)
+ {
+ result = EBUSY;
+ }
+ }
+ else
+ {
+ rwl->nExclusiveAccessCount = 1;
+ }
+ }
+ else
+ {
+ result = EBUSY;
+ }
+
+ return result;
+}
diff --git a/pthread_rwlock_unlock.c b/pthread_rwlock_unlock.c
new file mode 100644
index 0000000..1281f01
--- /dev/null
+++ b/pthread_rwlock_unlock.c
@@ -0,0 +1,93 @@
+/*
+ * pthread_rwlock_unlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include <errno.h>
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlock_unlock(pthread_rwlock_t * rwlock)
+{
+ int result, result1;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return(EINVAL);
+ }
+
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ /*
+ * Assume any race condition here is harmless.
+ */
+ return 0;
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if (rwl->nExclusiveAccessCount == 0)
+ {
+ if ((result = pthread_mutex_lock(&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ return result;
+ }
+
+ if (++rwl->nCompletedSharedAccessCount == 0)
+ {
+ result = pthread_cond_signal(&(rwl->cndSharedAccessCompleted));
+ }
+
+ result1 = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted));
+ }
+ else
+ {
+ rwl->nExclusiveAccessCount--;
+
+ result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted));
+ result1 = pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
+
+ }
+
+ return ((result != 0) ? result : result1);
+}
diff --git a/pthread_rwlock_wrlock.c b/pthread_rwlock_wrlock.c
new file mode 100644
index 0000000..6e85bf1
--- /dev/null
+++ b/pthread_rwlock_wrlock.c
@@ -0,0 +1,146 @@
+/*
+ * pthread_rwlock_wrlock.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include <errno.h>
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+static void
+ptw32_rwlock_cancelwrwait(void * arg)
+{
+ pthread_rwlock_t rwl = (pthread_rwlock_t) arg;
+
+ rwl->nSharedAccessCount = -rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+
+ (void) pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted));
+ (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
+}
+
+int
+pthread_rwlock_wrlock(pthread_rwlock_t * rwlock)
+{
+ int result;
+ pthread_rwlock_t rwl;
+
+ if (rwlock == NULL || *rwlock == NULL)
+ {
+ return EINVAL;
+ }
+
+ /*
+ * We do a quick check to see if we need to do more work
+ * to initialise a static rwlock. We check
+ * again inside the guarded section of ptw32_rwlock_check_need_init()
+ * to avoid race conditions.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = ptw32_rwlock_check_need_init(rwlock);
+
+ if (result != 0 && result != EBUSY)
+ {
+ return result;
+ }
+ }
+
+ rwl = *rwlock;
+
+ if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
+ {
+ return EINVAL;
+ }
+
+ if ((result = pthread_mutex_lock(&(rwl->mtxExclusiveAccess))) != 0)
+ {
+ return result;
+ }
+
+ if ((result = pthread_mutex_lock(&(rwl->mtxSharedAccessCompleted))) != 0)
+ {
+ (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
+ return result;
+ }
+
+ if (rwl->nExclusiveAccessCount == 0)
+ {
+ if (rwl->nCompletedSharedAccessCount > 0)
+ {
+ rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
+ rwl->nCompletedSharedAccessCount = 0;
+ }
+
+ if (rwl->nSharedAccessCount > 0)
+ {
+ rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;
+
+ /*
+ * This routine may be a cancelation point
+ * according to POSIX 1003.1j section 18.1.2.
+ */
+#ifdef _MSC_VER
+#pragma inline_depth(0)
+#endif
+ pthread_cleanup_push(ptw32_rwlock_cancelwrwait, (void*)rwl);
+
+ do
+ {
+ result = pthread_cond_wait(&(rwl->cndSharedAccessCompleted),
+ &(rwl->mtxSharedAccessCompleted));
+ }
+ while (result == 0 && rwl->nCompletedSharedAccessCount < 0);
+
+ pthread_cleanup_pop ((result != 0) ? 1 : 0);
+#ifdef _MSC_VER
+#pragma inline_depth()
+#endif
+
+ if (result == 0)
+ {
+ rwl->nSharedAccessCount = 0;
+ }
+ }
+ }
+
+ if (result == 0)
+ {
+ rwl->nExclusiveAccessCount++;
+ }
+
+ return result;
+}
diff --git a/pthread_rwlockattr_destroy.c b/pthread_rwlockattr_destroy.c
new file mode 100644
index 0000000..f1c1d2a
--- /dev/null
+++ b/pthread_rwlockattr_destroy.c
@@ -0,0 +1,85 @@
+/*
+ * pthread_rwlockattr_destroy.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include <errno.h>
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Destroys a rwlock attributes object. The object can
+ * no longer be used.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_rwlockattr_t
+ *
+ *
+ * DESCRIPTION
+ * Destroys a rwlock attributes object. The object can
+ * no longer be used.
+ *
+ * NOTES:
+ * 1) Does not affect rwlockss created using 'attr'
+ *
+ * RESULTS
+ * 0 successfully released attr,
+ * EINVAL 'attr' is invalid.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+
+ if (attr == NULL || *attr == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ pthread_rwlockattr_t rwa = *attr;
+
+ *attr = NULL;
+ free (rwa);
+ }
+
+ return(result);
+} /* pthread_rwlockattr_destroy */
diff --git a/pthread_rwlockattr_getpshared.c b/pthread_rwlockattr_getpshared.c
new file mode 100644
index 0000000..295caf5
--- /dev/null
+++ b/pthread_rwlockattr_getpshared.c
@@ -0,0 +1,99 @@
+/*
+ * pthread_rwlockattr_getpshared.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include <errno.h>
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
+ int *pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Determine whether rwlocks created with 'attr' can be
+ * shared between processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_rwlockattr_t
+ *
+ * pshared
+ * will be set to one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ *
+ * DESCRIPTION
+ * Rwlocks creatd with 'attr' can be shared between
+ * processes if pthread_rwlock_t variable is allocated
+ * in memory shared by these processes.
+ * NOTES:
+ * 1) pshared rwlocks MUST be allocated in shared
+ * memory.
+ * 2) The following macro is defined if shared rwlocks
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully retrieved attribute,
+ * EINVAL 'attr' is invalid,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) &&
+ (pshared != NULL))
+ {
+ *pshared = (*attr)->pshared;
+ result = 0;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+
+} /* pthread_rwlockattr_getpshared */
diff --git a/pthread_rwlockattr_init.c b/pthread_rwlockattr_init.c
new file mode 100644
index 0000000..f2e2823
--- /dev/null
+++ b/pthread_rwlockattr_init.c
@@ -0,0 +1,84 @@
+/*
+ * pthread_rwlockattr_init.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include <errno.h>
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_init (pthread_rwlockattr_t * attr)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Initializes a rwlock attributes object with default
+ * attributes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_rwlockattr_t
+ *
+ *
+ * DESCRIPTION
+ * Initializes a rwlock attributes object with default
+ * attributes.
+ *
+ * RESULTS
+ * 0 successfully initialized attr,
+ * ENOMEM insufficient memory for attr.
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ pthread_rwlockattr_t rwa;
+
+ rwa = (pthread_rwlockattr_t) calloc (1, sizeof (*rwa));
+
+ if (rwa == NULL)
+ {
+ result = ENOMEM;
+ }
+ else
+ {
+ rwa->pshared = PTHREAD_PROCESS_PRIVATE;
+ }
+
+ *attr = rwa;
+
+ return(result);
+} /* pthread_rwlockattr_init */
diff --git a/pthread_rwlockattr_setpshared.c b/pthread_rwlockattr_setpshared.c
new file mode 100644
index 0000000..128d2be
--- /dev/null
+++ b/pthread_rwlockattr_setpshared.c
@@ -0,0 +1,122 @@
+/*
+ * pthread_rwlockattr_setpshared.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include <errno.h>
+#include <limits.h>
+
+#include "pthread.h"
+#include "implement.h"
+
+int
+pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
+ int pshared)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Rwlocks created with 'attr' can be shared between
+ * processes if pthread_rwlock_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * PARAMETERS
+ * attr
+ * pointer to an instance of pthread_rwlockattr_t
+ *
+ * pshared
+ * must be one of:
+ *
+ * PTHREAD_PROCESS_SHARED
+ * May be shared if in shared memory
+ *
+ * PTHREAD_PROCESS_PRIVATE
+ * Cannot be shared.
+ *
+ * DESCRIPTION
+ * Rwlocks creatd with 'attr' can be shared between
+ * processes if pthread_rwlock_t variable is allocated
+ * in memory shared by these processes.
+ *
+ * NOTES:
+ * 1) pshared rwlocks MUST be allocated in shared
+ * memory.
+ *
+ * 2) The following macro is defined if shared rwlocks
+ * are supported:
+ * _POSIX_THREAD_PROCESS_SHARED
+ *
+ * RESULTS
+ * 0 successfully set attribute,
+ * EINVAL 'attr' or pshared is invalid,
+ * ENOSYS PTHREAD_PROCESS_SHARED not supported,
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result;
+
+ if ((attr != NULL && *attr != NULL) &&
+ ((pshared == PTHREAD_PROCESS_SHARED) ||
+ (pshared == PTHREAD_PROCESS_PRIVATE)))
+ {
+ if (pshared == PTHREAD_PROCESS_SHARED)
+ {
+
+#if !defined( _POSIX_THREAD_PROCESS_SHARED )
+
+ result = ENOSYS;
+ pshared = PTHREAD_PROCESS_PRIVATE;
+
+#else
+
+ result = 0;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ }
+ else
+ {
+ result = 0;
+ }
+
+ (*attr)->pshared = pshared;
+ }
+ else
+ {
+ result = EINVAL;
+ }
+
+ return (result);
+
+} /* pthread_rwlockattr_setpshared */
diff --git a/cancel_setcancelstate.c b/pthread_setcancelstate.c
index 8eaa720..dcf6537 100644
--- a/cancel_setcancelstate.c
+++ b/pthread_setcancelstate.c
@@ -1,5 +1,5 @@
/*
- * cancel_setcancelstate.c
+ * pthread_setcancelstate.c
*
* Description:
* POSIX thread functions related to thread cancellation.
diff --git a/cancel_setcanceltype.c b/pthread_setcanceltype.c
index 58b31da..fc0f259 100644
--- a/cancel_setcanceltype.c
+++ b/pthread_setcanceltype.c
@@ -1,5 +1,5 @@
/*
- * cancel_setcanceltype.c
+ * pthread_setcanceltype.c
*
* Description:
* POSIX thread functions related to thread cancellation.
diff --git a/pthread_setschedparam.c b/pthread_setschedparam.c
new file mode 100644
index 0000000..2e795b9
--- /dev/null
+++ b/pthread_setschedparam.c
@@ -0,0 +1,78 @@
+/*
+ * sched_setschedparam.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+pthread_setschedparam(pthread_t thread, int policy,
+ const struct sched_param *param)
+{
+ int prio;
+
+ /* Validate the thread id. */
+ if (thread == NULL || thread->threadH == 0)
+ {
+ return EINVAL;
+ }
+
+ /* Validate the scheduling policy. */
+ if (policy < SCHED_MIN || policy > SCHED_MAX)
+ {
+ return EINVAL;
+ }
+
+ /* Ensure the policy is SCHED_OTHER. */
+ if (policy != SCHED_OTHER)
+ {
+ return ENOTSUP;
+ }
+
+ prio = param->sched_priority;
+
+ /* Validate priority level. */
+ if (prio < sched_get_priority_min(policy) ||
+ prio > sched_get_priority_max(policy))
+ {
+ return EINVAL;
+ }
+
+ /* This is practically guaranteed to return TRUE. */
+ (void) SetThreadPriority(thread->threadH, prio);
+
+ return 0;
+}
diff --git a/pthread_setspecific.c b/pthread_setspecific.c
new file mode 100644
index 0000000..37ff975
--- /dev/null
+++ b/pthread_setspecific.c
@@ -0,0 +1,151 @@
+/*
+ * pthread_setspecific.c
+ *
+ * Description:
+ * POSIX thread functions which implement thread-specific data (TSD).
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_setspecific (pthread_key_t key, const void *value)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function sets the value of the thread specific
+ * key in the calling thread.
+ *
+ * PARAMETERS
+ * key
+ * an instance of pthread_key_t
+ * value
+ * the value to set key to
+ *
+ *
+ * DESCRIPTION
+ * This function sets the value of the thread specific
+ * key in the calling thread.
+ *
+ * RESULTS
+ * 0 successfully set value
+ * EAGAIN could not set value
+ * ENOENT SERIOUS!!
+ *
+ * ------------------------------------------------------
+ */
+{
+ pthread_t self;
+ int result = 0;
+
+ if (key != ptw32_selfThreadKey)
+ {
+ /*
+ * Using pthread_self will implicitly create
+ * an instance of pthread_t for the current
+ * thread if one wasn't explicitly created
+ */
+ self = pthread_self ();
+ if (self == NULL)
+ {
+ return ENOENT;
+ }
+ }
+ else
+ {
+ /*
+ * Resolve catch-22 of registering thread with threadSelf
+ * key
+ */
+ self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey);
+ if (self == NULL)
+ {
+ self = (pthread_t) value;
+ }
+ }
+
+ result = 0;
+
+ if (key != NULL)
+ {
+ ThreadKeyAssoc *assoc;
+
+ if (self != NULL &&
+ key->destructor != NULL &&
+ value != NULL)
+ {
+ /*
+ * Only require associations if we have to
+ * call user destroy routine.
+ * Don't need to locate an existing association
+ * when setting data to NULL for WIN32 since the
+ * data is stored with the operating system; not
+ * on the association; setting assoc to NULL short
+ * circuits the search.
+ */
+ assoc = (ThreadKeyAssoc *) self->keys;
+ /*
+ * Locate existing association
+ */
+ while (assoc != NULL)
+ {
+ if (assoc->key == key)
+ {
+ /*
+ * Association already exists
+ */
+ break;
+ }
+ assoc = assoc->nextKey;
+ }
+
+ /*
+ * create an association if not found
+ */
+ if (assoc == NULL)
+ {
+ result = ptw32_tkAssocCreate (&assoc, self, key);
+ }
+ }
+
+ if (result == 0)
+ {
+ if ( ! TlsSetValue (key->key, (LPVOID) value))
+ {
+ result = EAGAIN;
+ }
+ }
+ }
+
+ return (result);
+} /* pthread_setspecific */
diff --git a/pthread_spin_destroy.c b/pthread_spin_destroy.c
new file mode 100644
index 0000000..1f61930
--- /dev/null
+++ b/pthread_spin_destroy.c
@@ -0,0 +1,102 @@
+/*
+ * pthread_spin_destroy.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_destroy(pthread_spinlock_t *lock)
+{
+ register pthread_spinlock_t s;
+
+ if (lock == NULL || *lock == NULL)
+ {
+ return EINVAL;
+ }
+
+ if ((s = *lock) != PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ if (s->interlock == PTW32_SPIN_USE_MUTEX)
+ {
+ return pthread_mutex_destroy(&(s->u.mutex));
+ }
+
+ if ( (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED ==
+ ptw32_interlocked_compare_exchange((PTW32_INTERLOCKED_LPLONG) &(s->interlock),
+ (PTW32_INTERLOCKED_LONG) PTW32_OBJECT_INVALID,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED))
+ {
+ return 0;
+ }
+
+ return EINVAL;
+ }
+ else
+ {
+ int result = 0;
+
+ /*
+ * See notes in ptw32_spinlock_check_need_init() above also.
+ */
+ EnterCriticalSection(&ptw32_spinlock_test_init_lock);
+
+ /*
+ * Check again.
+ */
+ if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ /*
+ * This is all we need to do to destroy a statically
+ * initialised spinlock that has not yet been used (initialised).
+ * If we get to here, another thread
+ * waiting to initialise this mutex will get an EINVAL.
+ */
+ *lock = NULL;
+ }
+ else
+ {
+ /*
+ * The spinlock has been initialised while we were waiting
+ * so assume it's in use.
+ */
+ result = EBUSY;
+ }
+
+ LeaveCriticalSection(&ptw32_spinlock_test_init_lock);
+ return(result);
+ }
+}
diff --git a/pthread_spin_init.c b/pthread_spin_init.c
new file mode 100644
index 0000000..0d95b54
--- /dev/null
+++ b/pthread_spin_init.c
@@ -0,0 +1,123 @@
+/*
+ * pthread_spin_init.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+pthread_spin_init(pthread_spinlock_t *lock, int pshared)
+{
+ pthread_spinlock_t s;
+ int cpus = 0;
+ int result = 0;
+
+ if (lock == NULL)
+ {
+ return EINVAL;
+ }
+
+ if (0 != ptw32_getprocessors(&cpus))
+ {
+ cpus = 1;
+ }
+
+ if (cpus > 1)
+ {
+ if (pshared == PTHREAD_PROCESS_SHARED)
+ {
+ /*
+ * Creating spinlock that can be shared between
+ * processes.
+ */
+#if _POSIX_THREAD_PROCESS_SHARED
+
+ /*
+ * Not implemented yet.
+ */
+
+#error ERROR [__FILE__, line __LINE__]: Process shared spin locks are not supported yet.
+
+#else
+
+ return ENOSYS;
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+
+ }
+ }
+
+ s = (pthread_spinlock_t) calloc(1, sizeof(*s));
+
+ if (s == NULL)
+ {
+ return ENOMEM;
+ }
+
+ if (cpus > 1)
+ {
+ s->u.cpus = cpus;
+ s->interlock = PTW32_SPIN_UNLOCKED;
+ }
+ else
+ {
+ pthread_mutexattr_t ma;
+ result = pthread_mutexattr_init(&ma);
+
+ if (0 == result)
+ {
+ ma->pshared = pshared;
+ result = pthread_mutex_init(&(s->u.mutex), &ma);
+ if (0 == result)
+ {
+ s->interlock = PTW32_SPIN_USE_MUTEX;
+ }
+ }
+ (void) pthread_mutexattr_destroy(&ma);
+ }
+
+ if (0 == result)
+ {
+ *lock = s;
+ }
+ else
+ {
+ (void) free(s);
+ *lock = NULL;
+ }
+
+ return(result);
+}
diff --git a/pthread_spin_lock.c b/pthread_spin_lock.c
new file mode 100644
index 0000000..d3355d1
--- /dev/null
+++ b/pthread_spin_lock.c
@@ -0,0 +1,77 @@
+/*
+ * pthread_spin_lock.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * NOTE: For speed, these routines don't check if "lock" is valid.
+ */
+int
+pthread_spin_lock(pthread_spinlock_t *lock)
+{
+ register pthread_spinlock_t s;
+
+ if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ int result;
+
+ if ((result = ptw32_spinlock_check_need_init(lock)) != 0)
+ {
+ return(result);
+ }
+ }
+
+ s = *lock;
+
+ while ( (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED ==
+ ptw32_interlocked_compare_exchange((PTW32_INTERLOCKED_LPLONG) &(s->interlock),
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED) )
+ {}
+
+ if (s->interlock == PTW32_SPIN_LOCKED)
+ {
+ return 0;
+ }
+ else if (s->interlock == PTW32_SPIN_USE_MUTEX)
+ {
+ return pthread_mutex_lock(&(s->u.mutex));
+ }
+
+ return EINVAL;
+}
diff --git a/pthread_spin_trylock.c b/pthread_spin_trylock.c
new file mode 100644
index 0000000..39b7fd3
--- /dev/null
+++ b/pthread_spin_trylock.c
@@ -0,0 +1,69 @@
+/*
+ * pthread_spin_trylock.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * NOTE: For speed, these routines don't check if "lock" is valid.
+ */
+int
+pthread_spin_trylock(pthread_spinlock_t *lock)
+{
+ pthread_spinlock_t s = *lock;
+
+ if (s == PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ int result;
+
+ if ((result = ptw32_spinlock_check_need_init(lock)) != 0)
+ {
+ return(result);
+ }
+ }
+
+ switch ((long) ptw32_interlocked_compare_exchange((PTW32_INTERLOCKED_LPLONG) &(s->interlock),
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED ))
+ {
+ case PTW32_SPIN_UNLOCKED: return 0;
+ case PTW32_SPIN_LOCKED: return EBUSY;
+ case PTW32_SPIN_USE_MUTEX: return pthread_mutex_trylock(&(s->u.mutex));
+ }
+
+ return EINVAL;
+}
diff --git a/pthread_spin_unlock.c b/pthread_spin_unlock.c
new file mode 100644
index 0000000..30c11d4
--- /dev/null
+++ b/pthread_spin_unlock.c
@@ -0,0 +1,64 @@
+/*
+ * pthread_spin_unlock.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * NOTE: For speed, these routines don't check if "lock" is valid.
+ */
+int
+pthread_spin_unlock(pthread_spinlock_t *lock)
+{
+ register pthread_spinlock_t s = *lock;
+
+ if (s == PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ return EPERM;
+ }
+
+ switch ((long) ptw32_interlocked_compare_exchange((PTW32_INTERLOCKED_LPLONG) &(s->interlock),
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED,
+ (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED ))
+ {
+ case PTW32_SPIN_LOCKED: return 0;
+ case PTW32_SPIN_UNLOCKED: return EPERM;
+ case PTW32_SPIN_USE_MUTEX: return pthread_mutex_unlock(&(s->u.mutex));
+ }
+
+ return EINVAL;
+}
diff --git a/cancel_testcancel.c b/pthread_testcancel.c
index 4086565..2ba0a2c 100644
--- a/cancel_testcancel.c
+++ b/pthread_testcancel.c
@@ -1,5 +1,5 @@
/*
- * cancel_testcancel.c
+ * pthread_testcancel.c
*
* Description:
* POSIX thread functions related to thread cancellation.
diff --git a/pthread_timechange_handler_np.c b/pthread_timechange_handler_np.c
new file mode 100644
index 0000000..b7d432b
--- /dev/null
+++ b/pthread_timechange_handler_np.c
@@ -0,0 +1,108 @@
+/*
+ * pthread_timechange_handler_np.c
+ *
+ * Description:
+ * This translation unit implements miscellaneous thread functions.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+/*
+ * Notes on handling system time adjustments (especially negative ones).
+ * ---------------------------------------------------------------------
+ *
+ * This solution was suggested by Alexander Terekhov, but any errors
+ * in the implementation are mine - [Ross Johnson]
+ *
+ * 1) The problem: threads doing a timedwait on a CV may expect to timeout
+ * at a specific absolute time according to a system timer. If the
+ * system clock is adjusted backwards then those threads sleep longer than
+ * expected. Also, pthreads-win32 converts absolute times to intervals in
+ * order to make use of the underlying Win32, and so waiting threads may
+ * awake before their proper abstimes.
+ *
+ * 2) We aren't able to distinquish between threads on timed or untimed waits,
+ * so we wake them all at the time of the adjustment so that they can
+ * re-evaluate their conditions and re-compute their timeouts.
+ *
+ * 3) We rely on correctly written applications for this to work. Specifically,
+ * they must be able to deal properly with spurious wakeups. That is,
+ * they must re-test their condition upon wakeup and wait again if
+ * the condition is not satisfied.
+ */
+
+void *
+pthread_timechange_handler_np(void * arg)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Broadcasts all CVs to force re-evaluation and
+ * new timeouts if required.
+ *
+ * PARAMETERS
+ * NONE
+ *
+ *
+ * DESCRIPTION
+ * Broadcasts all CVs to force re-evaluation and
+ * new timeouts if required.
+ *
+ * This routine may be passed directly to pthread_create()
+ * as a new thread in order to run asynchronously.
+ *
+ *
+ * RESULTS
+ * 0 successfully broadcast all CVs
+ * EAGAIN Not all CVs were broadcast
+ *
+ * ------------------------------------------------------
+ */
+{
+ int result = 0;
+ pthread_cond_t cv;
+
+ EnterCriticalSection(&ptw32_cond_list_lock);
+
+ cv = ptw32_cond_list_head;
+
+ while (cv != NULL && 0 == result)
+ {
+ result = pthread_cond_broadcast(&cv);
+ cv = cv->next;
+ }
+
+ LeaveCriticalSection(&ptw32_cond_list_lock);
+
+ return (void *)(result != 0 ? EAGAIN : 0);
+}
+
diff --git a/np_win32_attach.c b/pthread_win32_attach_detach_np.c
index f7833ee..487bcbb 100644
--- a/np_win32_attach.c
+++ b/pthread_win32_attach_detach_np.c
@@ -1,5 +1,5 @@
/*
- * np_win32_attach.c
+ * pthread_win32_attach_detach_np.c
*
* Description:
* This translation unit implements non-portable thread functions.
diff --git a/ptw32_InterlockedCompareExchange.c b/ptw32_InterlockedCompareExchange.c
new file mode 100644
index 0000000..0e0ccfd
--- /dev/null
+++ b/ptw32_InterlockedCompareExchange.c
@@ -0,0 +1,108 @@
+/*
+ * ptw32_InterlockedCompareExchange.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * ptw32_InterlockedCompareExchange --
+ *
+ * Needed because W95 doesn't support InterlockedCompareExchange.
+ * It is only used when running the dll on W95. Other versions of
+ * Windows use the Win32 supported version, which may be running on
+ * different processor types.
+ *
+ * This can't be inlined because we need to know it's address so that
+ * we can call it through a pointer.
+ */
+PTW32_INTERLOCKED_LONG WINAPI
+ptw32_InterlockedCompareExchange(PTW32_INTERLOCKED_LPLONG location,
+ PTW32_INTERLOCKED_LONG value,
+ PTW32_INTERLOCKED_LONG comparand)
+{
+ PTW32_INTERLOCKED_LONG result;
+
+#if defined(_M_IX86) || defined(_X86_)
+
+#if defined(_MSC_VER)
+
+ _asm {
+ PUSH ecx
+ PUSH edx
+ MOV ecx,dword ptr [location]
+ MOV edx,dword ptr [value]
+ MOV eax,dword ptr [comparand]
+ LOCK CMPXCHG dword ptr [ecx],edx ; if (EAX == [ECX]),
+ ; [ECX] = EDX
+ ; else
+ ; EAX = [ECX]
+ MOV dword ptr [result], eax
+ POP edx
+ POP ecx
+ }
+
+#elif defined(__GNUC__)
+
+ __asm__
+ (
+ "lock\n\t"
+ "cmpxchgl %3,(%0)" /* if (EAX == [location]), */
+ /* [location] = value */
+ /* else */
+ /* EAX = [location] */
+ :"=r" (location), "=a" (result)
+ :"0" (location), "q" (value), "a" (comparand)
+ : "memory" );
+
+#endif
+
+#else
+
+ /*
+ * If execution gets to here then we should be running on a Win95 system
+ * but either running on something other than an X86 processor, or a
+ * compiler other than MSVC or GCC. Pthreads-win32 doesn't support that
+ * platform (yet).
+ */
+
+ result = 0;
+
+#endif
+
+ return result;
+}
diff --git a/ptw32_callUserDestroyRoutines.c b/ptw32_callUserDestroyRoutines.c
new file mode 100644
index 0000000..cef88cf
--- /dev/null
+++ b/ptw32_callUserDestroyRoutines.c
@@ -0,0 +1,155 @@
+/*
+ * ptw32_callUserDestroyRoutines.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+ptw32_callUserDestroyRoutines (pthread_t thread)
+ /*
+ * -------------------------------------------------------------------
+ * DOCPRIVATE
+ *
+ * This the routine runs through all thread keys and calls
+ * the destroy routines on the user's data for the current thread.
+ * It simulates the behaviour of POSIX Threads.
+ *
+ * PARAMETERS
+ * thread
+ * an instance of pthread_t
+ *
+ * RETURNS
+ * N/A
+ * -------------------------------------------------------------------
+ */
+{
+ ThreadKeyAssoc **nextP;
+ ThreadKeyAssoc *assoc;
+
+ if (thread != NULL)
+ {
+ /*
+ * Run through all Thread<-->Key associations
+ * for the current thread.
+ * If the pthread_key_t still exits (ie the assoc->key
+ * is not NULL) then call the user's TSD destroy routine.
+ * Notes:
+ * If assoc->key is NULL, then the user previously called
+ * PThreadKeyDestroy. The association is now only referenced
+ * by the current thread and must be released; otherwise
+ * the assoc will be destroyed when the key is destroyed.
+ */
+ nextP = (ThreadKeyAssoc **) & (thread->keys);
+ assoc = *nextP;
+
+ while (assoc != NULL)
+ {
+
+ if (pthread_mutex_lock (&(assoc->lock)) == 0)
+ {
+ pthread_key_t k;
+ if ((k = assoc->key) != NULL)
+ {
+ /*
+ * Key still active; pthread_key_delete
+ * will block on this same mutex before
+ * it can release actual key; therefore,
+ * key is valid and we can call the destroy
+ * routine;
+ */
+ void *value = NULL;
+
+ value = pthread_getspecific (k);
+ if (value != NULL && k->destructor != NULL)
+ {
+
+#ifdef __cplusplus
+
+ try
+ {
+ /*
+ * Run the caller's cleanup routine.
+ */
+ (*(k->destructor)) (value);
+ }
+ catch (...)
+ {
+ /*
+ * A system unexpected exception has occurred
+ * running the user's destructor.
+ * We get control back within this block in case
+ * the application has set up it's own terminate
+ * handler. Since we are leaving the thread we
+ * should not get any internal pthreads
+ * exceptions.
+ */
+ terminate();
+ }
+
+#else /* __cplusplus */
+
+ /*
+ * Run the caller's cleanup routine.
+ */
+ (*(k->destructor)) (value);
+
+#endif /* __cplusplus */
+ }
+ }
+
+ /*
+ * mark assoc->thread as NULL to indicate the
+ * thread no longer references this association
+ */
+ assoc->thread = NULL;
+
+ /*
+ * Remove association from the pthread_t chain
+ */
+ *nextP = assoc->nextKey;
+
+ pthread_mutex_unlock (&(assoc->lock));
+
+ ptw32_tkAssocDestroy (assoc);
+
+ assoc = *nextP;
+ }
+ }
+ }
+
+} /* ptw32_callUserDestroyRoutines */
diff --git a/condvar_check_need_init.c b/ptw32_cond_check_need_init.c
index 1f6bba7..85b6801 100644
--- a/condvar_check_need_init.c
+++ b/ptw32_cond_check_need_init.c
@@ -1,5 +1,5 @@
/*
- * condvar_check_need_init.c
+ * ptw32_cond_check_need_init.c
*
* Description:
* This translation unit implements condition variables and their primitives.
@@ -39,7 +39,7 @@
#include "implement.h"
-static INLINE int
+INLINE int
ptw32_cond_check_need_init (pthread_cond_t *cond)
{
int result = 0;
diff --git a/semaphore_decrease.c b/ptw32_decrease_semaphore.c
index 203d877..e16dfd6 100644
--- a/semaphore_decrease.c
+++ b/ptw32_decrease_semaphore.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_decrease.c
+ * Module: ptw32_decrease_semaphore.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/ptw32_getprocessors.c b/ptw32_getprocessors.c
new file mode 100644
index 0000000..79a7b7b
--- /dev/null
+++ b/ptw32_getprocessors.c
@@ -0,0 +1,84 @@
+/*
+ * ptw32_getprocessors.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+/*
+ * ptw32_getprocessors()
+ *
+ * Get the number of CPUs available to the process.
+ *
+ * If the available number of CPUs is 1 then pthread_spin_lock()
+ * will block rather than spin if the lock is already owned.
+ *
+ * pthread_spin_init() calls this routine when initialising
+ * a spinlock. If the number of available processors changes
+ * (after a call to SetProcessAffinityMask()) then only
+ * newly initialised spinlocks will notice.
+ */
+int
+ptw32_getprocessors(int * count)
+{
+ DWORD vProcessCPUs;
+ DWORD vSystemCPUs;
+ int result = 0;
+
+ if (GetProcessAffinityMask(GetCurrentProcess(),
+ &vProcessCPUs,
+ &vSystemCPUs))
+ {
+ DWORD bit;
+ int CPUs = 0;
+
+ for (bit = 1; bit != 0; bit <<= 1)
+ {
+ if (vProcessCPUs & bit)
+ {
+ CPUs++;
+ }
+ }
+ *count = CPUs;
+ }
+ else
+ {
+ result = EAGAIN;
+ }
+
+ return(result);
+}
diff --git a/semaphore_increase.c b/ptw32_increase_semaphore.c
index 5a67468..5f0bbcb 100644
--- a/semaphore_increase.c
+++ b/ptw32_increase_semaphore.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_increase.c
+ * Module: ptw32_increase_semaphore.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/attr_is_attr.c b/ptw32_is_attr.c
index 3d6ef4f..d1ffc3e 100644
--- a/attr_is_attr.c
+++ b/ptw32_is_attr.c
@@ -1,5 +1,5 @@
/*
- * attr_is_attr.c
+ * ptw32_is_attr.c
*
* Description:
* This translation unit implements operations on thread attribute objects.
@@ -9,7 +9,7 @@
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2002 Pthreads-win32 contributors
- *
+ *
* Contact Email: rpj@ise.canberra.edu.au
*
* The current list of contributors is contained
@@ -37,8 +37,8 @@
#include "pthread.h"
#include "implement.h"
-static INLINE int
-is_attr(const pthread_attr_t *attr)
+int
+ptw32_is_attr(const pthread_attr_t *attr)
{
/* Return 0 if the attr object is valid, non-zero otherwise. */
diff --git a/ptw32_mutex_check_need_init.c b/ptw32_mutex_check_need_init.c
new file mode 100644
index 0000000..753b214
--- /dev/null
+++ b/ptw32_mutex_check_need_init.c
@@ -0,0 +1,94 @@
+/*
+ * ptw32_mutex_check_need_init.c
+ *
+ * Description:
+ * This translation unit implements mutual exclusion (mutex) primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+INLINE int
+ptw32_mutex_check_need_init(pthread_mutex_t *mutex)
+{
+ int result = 0;
+
+ /*
+ * The following guarded test is specifically for statically
+ * initialised mutexes (via PTHREAD_MUTEX_INITIALIZER).
+ *
+ * Note that by not providing this synchronisation we risk
+ * introducing race conditions into applications which are
+ * correctly written.
+ *
+ * Approach
+ * --------
+ * We know that static mutexes will not be PROCESS_SHARED
+ * so we can serialise access to internal state using
+ * Win32 Critical Sections rather than Win32 Mutexes.
+ *
+ * If using a single global lock slows applications down too much,
+ * multiple global locks could be created and hashed on some random
+ * value associated with each mutex, the pointer perhaps. At a guess,
+ * a good value for the optimal number of global locks might be
+ * the number of processors + 1.
+ *
+ */
+ EnterCriticalSection(&ptw32_mutex_test_init_lock);
+
+ /*
+ * We got here possibly under race
+ * conditions. Check again inside the critical section
+ * and only initialise if the mutex is valid (not been destroyed).
+ * If a static mutex has been destroyed, the application can
+ * re-initialise it only by calling pthread_mutex_init()
+ * explicitly.
+ */
+ if (*mutex == PTHREAD_MUTEX_INITIALIZER)
+ {
+ result = pthread_mutex_init(mutex, NULL);
+ }
+ else if (*mutex == NULL)
+ {
+ /*
+ * The mutex has been destroyed while we were waiting to
+ * initialise it, so the operation that caused the
+ * auto-initialisation should fail.
+ */
+ result = EINVAL;
+ }
+
+ LeaveCriticalSection(&ptw32_mutex_test_init_lock);
+
+ return(result);
+}
diff --git a/ptw32_processInitialize.c b/ptw32_processInitialize.c
new file mode 100644
index 0000000..7c1818a
--- /dev/null
+++ b/ptw32_processInitialize.c
@@ -0,0 +1,100 @@
+/*
+ * ptw32_processInitialize.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+ptw32_processInitialize (void)
+ /*
+ * ------------------------------------------------------
+ * DOCPRIVATE
+ * This function performs process wide initialization for
+ * the pthread library.
+ *
+ * PARAMETERS
+ * N/A
+ *
+ * DESCRIPTION
+ * This function performs process wide initialization for
+ * the pthread library.
+ * If successful, this routine sets the global variable
+ * ptw32_processInitialized to TRUE.
+ *
+ * RESULTS
+ * TRUE if successful,
+ * FALSE otherwise
+ *
+ * ------------------------------------------------------
+ */
+{
+ if (ptw32_processInitialized) {
+ /*
+ * ignore if already initialized. this is useful for
+ * programs that uses a non-dll pthread
+ * library. such programs must call ptw32_processInitialize() explicitely,
+ * since this initialization routine is automatically called only when
+ * the dll is loaded.
+ */
+ return TRUE;
+ }
+
+ ptw32_processInitialized = TRUE;
+
+ /*
+ * Initialize Keys
+ */
+ if ((pthread_key_create (&ptw32_selfThreadKey, NULL) != 0) ||
+ (pthread_key_create (&ptw32_cleanupKey, NULL) != 0))
+ {
+
+ ptw32_processTerminate ();
+ }
+
+ /*
+ * Set up the global locks.
+ */
+ InitializeCriticalSection(&ptw32_mutex_test_init_lock);
+ InitializeCriticalSection(&ptw32_cond_list_lock);
+ InitializeCriticalSection(&ptw32_cond_test_init_lock);
+ InitializeCriticalSection(&ptw32_rwlock_test_init_lock);
+ InitializeCriticalSection(&ptw32_spinlock_test_init_lock);
+
+ return (ptw32_processInitialized);
+
+} /* processInitialize */
diff --git a/ptw32_processTerminate.c b/ptw32_processTerminate.c
new file mode 100644
index 0000000..d816a4b
--- /dev/null
+++ b/ptw32_processTerminate.c
@@ -0,0 +1,100 @@
+/*
+ * ptw32_processTerminate.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+ptw32_processTerminate (void)
+ /*
+ * ------------------------------------------------------
+ * DOCPRIVATE
+ * This function performs process wide termination for
+ * the pthread library.
+ *
+ * PARAMETERS
+ * N/A
+ *
+ * DESCRIPTION
+ * This function performs process wide termination for
+ * the pthread library.
+ * This routine sets the global variable
+ * ptw32_processInitialized to FALSE
+ *
+ * RESULTS
+ * N/A
+ *
+ * ------------------------------------------------------
+ */
+{
+ if (ptw32_processInitialized)
+ {
+
+ if (ptw32_selfThreadKey != NULL)
+ {
+ /*
+ * Release ptw32_selfThreadKey
+ */
+ pthread_key_delete (ptw32_selfThreadKey);
+
+ ptw32_selfThreadKey = NULL;
+ }
+
+ if (ptw32_cleanupKey != NULL)
+ {
+ /*
+ * Release ptw32_cleanupKey
+ */
+ pthread_key_delete (ptw32_cleanupKey);
+
+ ptw32_cleanupKey = NULL;
+ }
+
+ /*
+ * Destroy the global locks.
+ */
+ DeleteCriticalSection(&ptw32_spinlock_test_init_lock);
+ DeleteCriticalSection(&ptw32_rwlock_test_init_lock);
+ DeleteCriticalSection(&ptw32_cond_test_init_lock);
+ DeleteCriticalSection(&ptw32_cond_list_lock);
+ DeleteCriticalSection(&ptw32_mutex_test_init_lock);
+
+ ptw32_processInitialized = FALSE;
+ }
+
+} /* processTerminate */
diff --git a/ptw32_rwlock_check_need_init.c b/ptw32_rwlock_check_need_init.c
new file mode 100644
index 0000000..626cf23
--- /dev/null
+++ b/ptw32_rwlock_check_need_init.c
@@ -0,0 +1,93 @@
+/*
+ * pthread_rwlock_check_need_init.c
+ *
+ * Description:
+ * This translation unit implements read/write lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+INLINE int
+ptw32_rwlock_check_need_init(pthread_rwlock_t *rwlock)
+{
+ int result = 0;
+
+ /*
+ * The following guarded test is specifically for statically
+ * initialised rwlocks (via PTHREAD_RWLOCK_INITIALIZER).
+ *
+ * Note that by not providing this synchronisation we risk
+ * introducing race conditions into applications which are
+ * correctly written.
+ *
+ * Approach
+ * --------
+ * We know that static rwlocks will not be PROCESS_SHARED
+ * so we can serialise access to internal state using
+ * Win32 Critical Sections rather than Win32 Mutexes.
+ *
+ * If using a single global lock slows applications down too much,
+ * multiple global locks could be created and hashed on some random
+ * value associated with each mutex, the pointer perhaps. At a guess,
+ * a good value for the optimal number of global locks might be
+ * the number of processors + 1.
+ *
+ */
+ EnterCriticalSection(&ptw32_rwlock_test_init_lock);
+
+ /*
+ * We got here possibly under race
+ * conditions. Check again inside the critical section
+ * and only initialise if the rwlock is valid (not been destroyed).
+ * If a static rwlock has been destroyed, the application can
+ * re-initialise it only by calling pthread_rwlock_init()
+ * explicitly.
+ */
+ if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
+ {
+ result = pthread_rwlock_init(rwlock, NULL);
+ }
+ else if (*rwlock == NULL)
+ {
+ /*
+ * The rwlock has been destroyed while we were waiting to
+ * initialise it, so the operation that caused the
+ * auto-initialisation should fail.
+ */
+ result = EINVAL;
+ }
+
+ LeaveCriticalSection(&ptw32_rwlock_test_init_lock);
+
+ return result;
+}
diff --git a/ptw32_spinlock_check_need_init.c b/ptw32_spinlock_check_need_init.c
new file mode 100644
index 0000000..d8701cd
--- /dev/null
+++ b/ptw32_spinlock_check_need_init.c
@@ -0,0 +1,81 @@
+/*
+ * ptw32_spinlock_check_need_init.c
+ *
+ * Description:
+ * This translation unit implements spin lock primitives.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+INLINE int
+ptw32_spinlock_check_need_init(pthread_spinlock_t *lock)
+{
+ int result = 0;
+
+ /*
+ * The following guarded test is specifically for statically
+ * initialised spinlocks (via PTHREAD_SPINLOCK_INITIALIZER).
+ *
+ * Note that by not providing this synchronisation we risk
+ * introducing race conditions into applications which are
+ * correctly written.
+ */
+ EnterCriticalSection(&ptw32_spinlock_test_init_lock);
+
+ /*
+ * We got here possibly under race
+ * conditions. Check again inside the critical section
+ * and only initialise if the spinlock is valid (not been destroyed).
+ * If a static spinlock has been destroyed, the application can
+ * re-initialise it only by calling pthread_spin_init()
+ * explicitly.
+ */
+ if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
+ {
+ result = pthread_spin_init(lock, PTHREAD_PROCESS_PRIVATE);
+ }
+ else if (*lock == NULL)
+ {
+ /*
+ * The spinlock has been destroyed while we were waiting to
+ * initialise it, so the operation that caused the
+ * auto-initialisation should fail.
+ */
+ result = EINVAL;
+ }
+
+ LeaveCriticalSection(&ptw32_spinlock_test_init_lock);
+
+ return(result);
+}
diff --git a/ptw32_threadDestroy.c b/ptw32_threadDestroy.c
new file mode 100644
index 0000000..8293b76
--- /dev/null
+++ b/ptw32_threadDestroy.c
@@ -0,0 +1,66 @@
+/*
+ * ptw32_threadDestroy.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+ptw32_threadDestroy (pthread_t thread)
+{
+ if (thread != NULL)
+ {
+ ptw32_callUserDestroyRoutines (thread);
+
+ if (thread->cancelEvent != NULL)
+ {
+ CloseHandle (thread->cancelEvent);
+ }
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+ /* See documentation for endthread vs endthreadex. */
+ if( thread->threadH != 0 )
+ {
+ CloseHandle( thread->threadH );
+ }
+#endif
+
+ free (thread);
+ }
+
+} /* ptw32_threadDestroy */
+
diff --git a/ptw32_threadStart.c b/ptw32_threadStart.c
new file mode 100644
index 0000000..442e6ec
--- /dev/null
+++ b/ptw32_threadStart.c
@@ -0,0 +1,373 @@
+/*
+ * ptw32_threadStart.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#ifdef __CLEANUP_SEH
+
+static DWORD
+ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
+{
+ switch (ep->ExceptionRecord->ExceptionCode)
+ {
+ case EXCEPTION_PTW32_SERVICES:
+ {
+ DWORD param;
+ DWORD numParams = ep->ExceptionRecord->NumberParameters;
+
+ numParams = (numParams > 3) ? 3 : numParams;
+
+ for (param = 0; param < numParams; param++)
+ {
+ ei[param] = ep->ExceptionRecord->ExceptionInformation[param];
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+ break;
+ }
+ default:
+ {
+ /*
+ * A system unexpected exception has occurred running the user's
+ * routine. We need to cleanup before letting the exception
+ * out of thread scope.
+ */
+ pthread_t self = pthread_self();
+
+ (void) pthread_mutex_destroy(&self->cancelLock);
+ ptw32_callUserDestroyRoutines(self);
+
+ return EXCEPTION_CONTINUE_SEARCH;
+ break;
+ }
+ }
+}
+
+#elif defined(__CLEANUP_CXX)
+
+#if defined(_MSC_VER)
+#include <eh.h>
+static terminate_function ptw32_oldTerminate;
+#else
+#include <new.h>
+static terminate_handler ptw32_oldTerminate;
+#endif
+
+#if 0
+#include <stdio.h>
+static pthread_mutex_t termLock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+void
+ptw32_terminate ()
+{
+ pthread_t self = pthread_self();
+#if 0
+ FILE * fp;
+ pthread_mutex_lock(&termLock);
+ fp = fopen("pthread.log", "a");
+ fprintf(fp, "Terminate\n");
+ fclose(fp);
+ pthread_mutex_unlock(&termLock);
+#endif
+ set_terminate(ptw32_oldTerminate);
+ (void) pthread_mutex_destroy(&self->cancelLock);
+ ptw32_callUserDestroyRoutines(self);
+ terminate();
+}
+
+#endif /* _MSC_VER */
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+unsigned __stdcall
+#else
+void
+#endif
+ptw32_threadStart (void * vthreadParms)
+{
+ ThreadParms *threadParms = (ThreadParms *) vthreadParms;
+ pthread_t self;
+ void *(*start) (void *);
+ void *arg;
+
+#ifdef __CLEANUP_SEH
+ DWORD ei[] = {0,0,0};
+#endif
+
+#ifdef __CLEANUP_C
+ int setjmp_rc;
+#endif
+
+ void * status = (void *) 0;
+
+ self = threadParms->tid;
+ start = threadParms->start;
+ arg = threadParms->arg;
+
+ free (threadParms);
+
+#if defined (__MINGW32__) && ! defined (__MSVCRT__)
+ /*
+ * beginthread does not return the thread id and is running
+ * before it returns us the thread handle, and so we do it here.
+ */
+ self->thread = GetCurrentThreadId ();
+ /*
+ * Here we're using cancelLock as a general-purpose lock
+ * to make the new thread wait until the creating thread
+ * has the new handle.
+ */
+ if (pthread_mutex_lock(&self->cancelLock) == 0)
+ {
+ (void) pthread_mutex_unlock(&self->cancelLock);
+ }
+#endif
+
+ pthread_setspecific (ptw32_selfThreadKey, self);
+
+ self->state = PThreadStateRunning;
+
+#ifdef __CLEANUP_SEH
+
+ __try
+ {
+ /*
+ * Run the caller's routine;
+ */
+ status = self->exitStatus = (*start) (arg);
+
+#ifdef _UWIN
+ if (--pthread_count <= 0)
+ exit(0);
+#endif
+
+ }
+ __except (ExceptionFilter(GetExceptionInformation(), ei))
+ {
+ switch (ei[0])
+ {
+ case PTW32_EPS_CANCEL:
+ status = PTHREAD_CANCELED;
+#ifdef _UWIN
+ if (--pthread_count <= 0)
+ exit(0);
+#endif
+ break;
+ case PTW32_EPS_EXIT:
+ status = self->exitStatus;
+ break;
+ default:
+ status = PTHREAD_CANCELED;
+ break;
+ }
+ }
+
+#else /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_C
+
+ setjmp_rc = setjmp( self->start_mark );
+
+ if( 0 == setjmp_rc ) {
+
+ /*
+ * Run the caller's routine;
+ */
+ status = self->exitStatus = (*start) (arg);
+ }
+
+ else {
+
+ switch (setjmp_rc)
+ {
+ case PTW32_EPS_CANCEL:
+ status = PTHREAD_CANCELED;
+ break;
+ case PTW32_EPS_EXIT:
+ status = self->exitStatus;
+ break;
+ default:
+ status = PTHREAD_CANCELED;
+ break;
+ }
+ }
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
+
+ ptw32_oldTerminate = set_terminate(&ptw32_terminate);
+
+ try
+ {
+ /*
+ * Run the caller's routine in a nested try block so that we
+ * can run the user's terminate function, which may call
+ * pthread_exit() or be canceled.
+ */
+ try
+ {
+ status = self->exitStatus = (*start) (arg);
+ }
+ catch (ptw32_exception &)
+ {
+ /*
+ * Pass these through to the outer block.
+ */
+ throw;
+ }
+ catch(...)
+ {
+ /*
+ * We want to run the user's terminate function if supplied.
+ * That function may call pthread_exit() or be canceled, which will
+ * be handled by the outer try block.
+ *
+ * ptw32_terminate() will be called if there is no user
+ * supplied function.
+ */
+
+#if defined(_MSC_VER)
+ terminate_function term_func = set_terminate(0);
+#else
+ terminate_handler term_func = set_terminate(0);
+#endif
+
+ set_terminate(term_func);
+
+ if (term_func != 0) {
+ term_func();
+ }
+
+ throw;
+ }
+ }
+ catch (ptw32_exception_cancel &)
+ {
+ /*
+ * Thread was canceled.
+ */
+ status = self->exitStatus = PTHREAD_CANCELED;
+ }
+ catch (ptw32_exception_exit &)
+ {
+ /*
+ * Thread was exited via pthread_exit().
+ */
+ status = self->exitStatus;
+ }
+ catch (...)
+ {
+ /*
+ * A system unexpected exception has occurred running the user's
+ * terminate routine. We get control back within this block - cleanup
+ * and release the exception out of thread scope.
+ */
+ status = self->exitStatus = PTHREAD_CANCELED;
+ (void) pthread_mutex_lock(&self->cancelLock);
+ self->state = PThreadStateException;
+ (void) pthread_mutex_unlock(&self->cancelLock);
+ (void) pthread_mutex_destroy(&self->cancelLock);
+ (void) set_terminate(ptw32_oldTerminate);
+ ptw32_callUserDestroyRoutines(self);
+ throw;
+
+ /*
+ * Never reached.
+ */
+ }
+
+ (void) set_terminate(ptw32_oldTerminate);
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+#endif /* __CLEANUP_C */
+#endif /* __CLEANUP_SEH */
+
+ (void) pthread_mutex_lock(&self->cancelLock);
+ self->state = PThreadStateLast;
+ (void) pthread_mutex_unlock(&self->cancelLock);
+
+
+ (void) pthread_mutex_destroy(&self->cancelLock);
+
+#if 1
+ if (self->detachState == PTHREAD_CREATE_DETACHED)
+ {
+ /*
+ * We need to cleanup the pthread now in case we have
+ * been statically linked, in which case the cleanup
+ * in dllMain won't get done. Joinable threads will
+ * be cleaned up by pthread_join().
+ *
+ * Note that implicitly created pthreads (those created
+ * for Win32 threads which have called pthreads routines)
+ * must be cleaned up explicitly by the application
+ * (by calling pthread_win32_thread_detach_np()) if
+ * this library has been statically linked. For the dll,
+ * dllMain will do the cleanup automatically.
+ */
+ (void) pthread_win32_thread_detach_np ();
+ }
+ else
+ {
+ ptw32_callUserDestroyRoutines (self);
+ }
+#else
+ ptw32_callUserDestroyRoutines (self);
+#endif
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+ _endthreadex ((unsigned) status);
+#else
+ _endthread ();
+#endif
+
+ /*
+ * Never reached.
+ */
+
+#if ! defined (__MINGW32__) || defined (__MSVCRT__)
+ return (unsigned) status;
+#endif
+
+} /* ptw32_threadStart */
diff --git a/ptw32_throw.c b/ptw32_throw.c
new file mode 100644
index 0000000..6840ce6
--- /dev/null
+++ b/ptw32_throw.c
@@ -0,0 +1,130 @@
+/*
+ * ptw32_throw.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+ptw32_throw(DWORD exception)
+{
+#ifdef __CLEANUP_C
+ pthread_t self = pthread_self();
+#endif
+
+
+#ifdef __CLEANUP_SEH
+ DWORD exceptionInformation[3];
+#endif
+
+ if (exception != PTW32_EPS_CANCEL &&
+ exception != PTW32_EPS_EXIT)
+ {
+ /* Should never enter here */
+ exit(1);
+ }
+
+#ifdef __CLEANUP_SEH
+
+
+ exceptionInformation[0] = (DWORD) (exception);
+ exceptionInformation[1] = (DWORD) (0);
+ exceptionInformation[2] = (DWORD) (0);
+
+ RaiseException (
+ EXCEPTION_PTW32_SERVICES,
+ 0,
+ 3,
+ exceptionInformation);
+
+#else /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_C
+
+ ptw32_pop_cleanup_all( 1 );
+
+ longjmp( self->start_mark, exception );
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
+
+ switch (exception)
+ {
+ case PTW32_EPS_CANCEL:
+ throw ptw32_exception_cancel();
+ break;
+ case PTW32_EPS_EXIT:
+ throw ptw32_exception_exit();
+ break;
+ }
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
+
+ /* Never reached */
+}
+
+
+void
+ptw32_pop_cleanup_all(int execute)
+{
+ while( NULL != ptw32_pop_cleanup(execute) ) {
+ }
+}
+
+
+DWORD
+ptw32_get_exception_services_code(void)
+{
+#ifdef __CLEANUP_SEH
+
+ return EXCEPTION_PTW32_SERVICES;
+
+#else
+
+ return (DWORD) NULL;
+
+#endif
+}
diff --git a/ptw32_timespec.c b/ptw32_timespec.c
new file mode 100644
index 0000000..dedcc75
--- /dev/null
+++ b/ptw32_timespec.c
@@ -0,0 +1,81 @@
+/*
+ * ptw32_timespec.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+#ifdef NEED_FTIME
+
+/*
+ * time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds
+ */
+#define PTW32_TIMESPEC_TO_FILETIME_OFFSET \
+ ( ((LONGLONG) 27111902 << 32) + (LONGLONG) 3577643008 )
+
+INLINE void
+ptw32_timespec_to_filetime(const struct timespec *ts, FILETIME *ft)
+ /*
+ * -------------------------------------------------------------------
+ * converts struct timespec
+ * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
+ * into FILETIME (as set by GetSystemTimeAsFileTime), where the time is
+ * expressed in 100 nanoseconds from Jan 1, 1601,
+ * -------------------------------------------------------------------
+ */
+{
+ *(LONGLONG *)ft = ts->tv_sec * 10000000
+ + (ts->tv_nsec + 50) / 100
+ + PTW32_TIMESPEC_TO_FILETIME_OFFSET;
+}
+
+INLINE void
+ptw32_filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
+ /*
+ * -------------------------------------------------------------------
+ * converts FILETIME (as set by GetSystemTimeAsFileTime), where the time is
+ * expressed in 100 nanoseconds from Jan 1, 1601,
+ * into struct timespec
+ * where the time is expressed in seconds and nanoseconds from Jan 1, 1970.
+ * -------------------------------------------------------------------
+ */
+{
+ ts->tv_sec = (int)((*(LONGLONG *)ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
+ ts->tv_nsec = (int)((*(LONGLONG *)ft - PTW32_TIMESPEC_TO_FILETIME_OFFSET - ((LONGLONG)ts->tv_sec * (LONGLONG)10000000)) * 100);
+}
+
+#endif /* NEED_FTIME */
diff --git a/ptw32_tkAssocCreate.c b/ptw32_tkAssocCreate.c
new file mode 100644
index 0000000..f6f6563
--- /dev/null
+++ b/ptw32_tkAssocCreate.c
@@ -0,0 +1,142 @@
+/*
+ * ptw32_tkAssocCreate.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+int
+ptw32_tkAssocCreate (ThreadKeyAssoc ** assocP,
+ pthread_t thread,
+ pthread_key_t key)
+ /*
+ * -------------------------------------------------------------------
+ * This routine creates an association that
+ * is unique for the given (thread,key) combination.The association
+ * is referenced by both the thread and the key.
+ * This association allows us to determine what keys the
+ * current thread references and what threads a given key
+ * references.
+ * See the detailed description
+ * at the beginning of this file for further details.
+ *
+ * Notes:
+ * 1) New associations are pushed to the beginning of the
+ * chain so that the internal ptw32_selfThreadKey association
+ * is always last, thus allowing selfThreadExit to
+ * be implicitly called by pthread_exit last.
+ *
+ * Parameters:
+ * assocP
+ * address into which the association is returned.
+ * thread
+ * current running thread. If NULL, then association
+ * is only added to the key. A NULL thread indicates
+ * that the user called pthread_setspecific prior
+ * to starting a thread. That's ok.
+ * key
+ * key on which to create an association.
+ * Returns:
+ * 0 - if successful,
+ * ENOMEM - not enough memory to create assoc or other object
+ * EINVAL - an internal error occurred
+ * ENOSYS - an internal error occurred
+ * -------------------------------------------------------------------
+ */
+{
+ int result;
+ ThreadKeyAssoc *assoc;
+
+ /*
+ * Have to create an association and add it
+ * to both the key and the thread.
+ */
+ assoc = (ThreadKeyAssoc *) calloc (1, sizeof (*assoc));
+
+ if (assoc == NULL)
+ {
+ result = ENOMEM;
+ goto FAIL0;
+ }
+
+ /*
+ * Initialise only when used for the first time.
+ */
+ assoc->lock = PTHREAD_MUTEX_INITIALIZER;
+ assoc->thread = thread;
+ assoc->key = key;
+
+ /*
+ * Register assoc with key
+ */
+ if ((result = pthread_mutex_lock (&(key->threadsLock))) != 0)
+ {
+ goto FAIL2;
+ }
+
+ assoc->nextThread = (ThreadKeyAssoc *) key->threads;
+ key->threads = (void *) assoc;
+
+ pthread_mutex_unlock (&(key->threadsLock));
+
+ if (thread != NULL)
+ {
+ /*
+ * Register assoc with thread
+ */
+ assoc->nextKey = (ThreadKeyAssoc *) thread->keys;
+ thread->keys = (void *) assoc;
+ }
+
+ *assocP = assoc;
+
+ return (result);
+
+ /*
+ * -------------
+ * Failure Code
+ * -------------
+ */
+FAIL2:
+ pthread_mutex_destroy (&(assoc->lock));
+ free (assoc);
+
+FAIL0:
+
+ return (result);
+
+} /* ptw32_tkAssocCreate */
diff --git a/ptw32_tkAssocDestroy.c b/ptw32_tkAssocDestroy.c
new file mode 100644
index 0000000..589e6e3
--- /dev/null
+++ b/ptw32_tkAssocDestroy.c
@@ -0,0 +1,68 @@
+/*
+ * ptw32_tkAssocDestroy.c
+ *
+ * Description:
+ * This translation unit implements routines which are private to
+ * the implementation and may be used throughout it.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+
+
+void
+ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc)
+ /*
+ * -------------------------------------------------------------------
+ * This routine releases all resources for the given ThreadKeyAssoc
+ * once it is no longer being referenced
+ * ie) both the key and thread have stopped referencing it.
+ *
+ * Parameters:
+ * assoc
+ * an instance of ThreadKeyAssoc.
+ * Returns:
+ * N/A
+ * -------------------------------------------------------------------
+ */
+{
+
+ if ((assoc != NULL) &&
+ (assoc->key == NULL && assoc->thread == NULL))
+ {
+
+ pthread_mutex_destroy (&(assoc->lock));
+
+ free (assoc);
+ }
+
+} /* ptw32_tkAssocDestroy */
diff --git a/rwlock.c b/rwlock.c
index 96a85e4..381a2ad 100644
--- a/rwlock.c
+++ b/rwlock.c
@@ -34,817 +34,15 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
-#include <errno.h>
-#include <limits.h>
-
-#include "pthread.h"
-#include "implement.h"
-
-static INLINE int
-ptw32_rwlock_check_need_init(pthread_rwlock_t *rwlock)
-{
- int result = 0;
-
- /*
- * The following guarded test is specifically for statically
- * initialised rwlocks (via PTHREAD_RWLOCK_INITIALIZER).
- *
- * Note that by not providing this synchronisation we risk
- * introducing race conditions into applications which are
- * correctly written.
- *
- * Approach
- * --------
- * We know that static rwlocks will not be PROCESS_SHARED
- * so we can serialise access to internal state using
- * Win32 Critical Sections rather than Win32 Mutexes.
- *
- * If using a single global lock slows applications down too much,
- * multiple global locks could be created and hashed on some random
- * value associated with each mutex, the pointer perhaps. At a guess,
- * a good value for the optimal number of global locks might be
- * the number of processors + 1.
- *
- */
- EnterCriticalSection(&ptw32_rwlock_test_init_lock);
-
- /*
- * We got here possibly under race
- * conditions. Check again inside the critical section
- * and only initialise if the rwlock is valid (not been destroyed).
- * If a static rwlock has been destroyed, the application can
- * re-initialise it only by calling pthread_rwlock_init()
- * explicitly.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = pthread_rwlock_init(rwlock, NULL);
- }
- else if (*rwlock == NULL)
- {
- /*
- * The rwlock has been destroyed while we were waiting to
- * initialise it, so the operation that caused the
- * auto-initialisation should fail.
- */
- result = EINVAL;
- }
-
- LeaveCriticalSection(&ptw32_rwlock_test_init_lock);
-
- return result;
-}
-
-int
-pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
-{
- int result;
- pthread_rwlock_t rwl = 0;
-
- if (rwlock == NULL)
- {
- return EINVAL;
- }
-
- if (attr != NULL && *attr != NULL)
- {
- result = EINVAL; /* Not supported */
- goto DONE;
- }
-
- rwl = (pthread_rwlock_t) calloc(1, sizeof(*rwl));
-
- if (rwl == NULL)
- {
- result = ENOMEM;
- goto DONE;
- }
-
- rwl->nSharedAccessCount = 0;
- rwl->nExclusiveAccessCount = 0;
- rwl->nCompletedSharedAccessCount = 0;
-
- result = pthread_mutex_init(&rwl->mtxExclusiveAccess, NULL);
- if (result != 0)
- {
- goto FAIL0;
- }
-
- result = pthread_mutex_init(&rwl->mtxSharedAccessCompleted, NULL);
- if (result != 0)
- {
- goto FAIL1;
- }
-
- result = pthread_cond_init(&rwl->cndSharedAccessCompleted, NULL);
- if (result != 0)
- {
- goto FAIL2;
- }
-
- rwl->nMagic = PTW32_RWLOCK_MAGIC;
-
- result = 0;
- goto DONE;
-
-FAIL2:
- (void) pthread_mutex_destroy(&(rwl->mtxSharedAccessCompleted));
-
-FAIL1:
- (void) pthread_mutex_destroy(&(rwl->mtxExclusiveAccess));
-
-FAIL0:
- (void) free(rwl);
- rwl = NULL;
-
-DONE:
- *rwlock = rwl;
-
- return result;
-}
-
-int
-pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
-{
- pthread_rwlock_t rwl;
- int result = 0, result1 = 0, result2 = 0;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- if (*rwlock != PTHREAD_RWLOCK_INITIALIZER)
- {
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result = pthread_mutex_lock(&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- if ((result = pthread_mutex_lock(&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- /*
- * Check whether any threads own/wait for the lock (wait for ex.access);
- * report "BUSY" if so.
- */
- if (rwl->nExclusiveAccessCount > 0
- || rwl->nSharedAccessCount > rwl->nCompletedSharedAccessCount)
- {
- result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted));
- result1 = pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
- result2 = EBUSY;
- }
- else
- {
- rwl->nMagic = 0;
-
- if ((result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- pthread_mutex_unlock(&rwl->mtxExclusiveAccess);
- return result;
- }
-
- if ((result = pthread_mutex_unlock(&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- *rwlock = NULL; /* Invalidate rwlock before anything else */
- result = pthread_cond_destroy(&(rwl->cndSharedAccessCompleted));
- result1 = pthread_mutex_destroy(&(rwl->mtxSharedAccessCompleted));
- result2 = pthread_mutex_destroy(&(rwl->mtxExclusiveAccess));
- (void) free(rwl);
- }
- }
- else
- {
- /*
- * See notes in ptw32_rwlock_check_need_init() above also.
- */
- EnterCriticalSection(&ptw32_rwlock_test_init_lock);
-
- /*
- * Check again.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- /*
- * This is all we need to do to destroy a statically
- * initialised rwlock that has not yet been used (initialised).
- * If we get to here, another thread
- * waiting to initialise this rwlock will get an EINVAL.
- */
- *rwlock = NULL;
- }
- else
- {
- /*
- * The rwlock has been initialised while we were waiting
- * so assume it's in use.
- */
- result = EBUSY;
- }
-
- LeaveCriticalSection(&ptw32_rwlock_test_init_lock);
- }
-
- return ((result != 0) ? result : ((result1 != 0) ? result1 : result2));
-}
-
-
-int
-pthread_rwlockattr_init (pthread_rwlockattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Initializes a rwlock attributes object with default
- * attributes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_rwlockattr_t
- *
- *
- * DESCRIPTION
- * Initializes a rwlock attributes object with default
- * attributes.
- *
- * RESULTS
- * 0 successfully initialized attr,
- * ENOMEM insufficient memory for attr.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- pthread_rwlockattr_t rwa;
-
- rwa = (pthread_rwlockattr_t) calloc (1, sizeof (*rwa));
-
- if (rwa == NULL)
- {
- result = ENOMEM;
- }
- else
- {
- rwa->pshared = PTHREAD_PROCESS_PRIVATE;
- }
-
- *attr = rwa;
-
- return(result);
-} /* pthread_rwlockattr_init */
-
-
-int
-pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Destroys a rwlock attributes object. The object can
- * no longer be used.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_rwlockattr_t
- *
- *
- * DESCRIPTION
- * Destroys a rwlock attributes object. The object can
- * no longer be used.
- *
- * NOTES:
- * 1) Does not affect rwlockss created using 'attr'
- *
- * RESULTS
- * 0 successfully released attr,
- * EINVAL 'attr' is invalid.
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
-
- if (attr == NULL || *attr == NULL)
- {
- result = EINVAL;
- }
- else
- {
- pthread_rwlockattr_t rwa = *attr;
-
- *attr = NULL;
- free (rwa);
- }
-
- return(result);
-} /* pthread_rwlockattr_destroy */
-
-
-int
-pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
- int *pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Determine whether rwlocks created with 'attr' can be
- * shared between processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_rwlockattr_t
- *
- * pshared
- * will be set to one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- *
- * DESCRIPTION
- * Rwlocks creatd with 'attr' can be shared between
- * processes if pthread_rwlock_t variable is allocated
- * in memory shared by these processes.
- * NOTES:
- * 1) pshared rwlocks MUST be allocated in shared
- * memory.
- * 2) The following macro is defined if shared rwlocks
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully retrieved attribute,
- * EINVAL 'attr' is invalid,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL) &&
- (pshared != NULL))
- {
- *pshared = (*attr)->pshared;
- result = 0;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-
-} /* pthread_rwlockattr_getpshared */
-
-
-int
-pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
- int pshared)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * Rwlocks created with 'attr' can be shared between
- * processes if pthread_rwlock_t variable is allocated
- * in memory shared by these processes.
- *
- * PARAMETERS
- * attr
- * pointer to an instance of pthread_rwlockattr_t
- *
- * pshared
- * must be one of:
- *
- * PTHREAD_PROCESS_SHARED
- * May be shared if in shared memory
- *
- * PTHREAD_PROCESS_PRIVATE
- * Cannot be shared.
- *
- * DESCRIPTION
- * Rwlocks creatd with 'attr' can be shared between
- * processes if pthread_rwlock_t variable is allocated
- * in memory shared by these processes.
- *
- * NOTES:
- * 1) pshared rwlocks MUST be allocated in shared
- * memory.
- *
- * 2) The following macro is defined if shared rwlocks
- * are supported:
- * _POSIX_THREAD_PROCESS_SHARED
- *
- * RESULTS
- * 0 successfully set attribute,
- * EINVAL 'attr' or pshared is invalid,
- * ENOSYS PTHREAD_PROCESS_SHARED not supported,
- *
- * ------------------------------------------------------
- */
-{
- int result;
-
- if ((attr != NULL && *attr != NULL) &&
- ((pshared == PTHREAD_PROCESS_SHARED) ||
- (pshared == PTHREAD_PROCESS_PRIVATE)))
- {
- if (pshared == PTHREAD_PROCESS_SHARED)
- {
-
-#if !defined( _POSIX_THREAD_PROCESS_SHARED )
-
- result = ENOSYS;
- pshared = PTHREAD_PROCESS_PRIVATE;
-
-#else
-
- result = 0;
-
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
-
- }
- else
- {
- result = 0;
- }
-
- (*attr)->pshared = pshared;
- }
- else
- {
- result = EINVAL;
- }
-
- return (result);
-
-} /* pthread_rwlockattr_setpshared */
-
-
-int
-pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
-{
- int result;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static rwlock. We check
- * again inside the guarded section of ptw32_rwlock_check_need_init()
- * to avoid race conditions.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = ptw32_rwlock_check_need_init(rwlock);
-
- if (result != 0 && result != EBUSY)
- {
- return result;
- }
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result = pthread_mutex_lock(&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- if (++rwl->nSharedAccessCount == INT_MAX)
- {
- if ((result = pthread_mutex_lock(&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
-
- if ((result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
- return result;
- }
- }
-
- return (pthread_mutex_unlock(&(rwl->mtxExclusiveAccess)));
-}
-
-static void
-ptw32_rwlock_cancelwrwait(void * arg)
-{
- pthread_rwlock_t rwl = (pthread_rwlock_t) arg;
-
- rwl->nSharedAccessCount = -rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
-
- (void) pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted));
- (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
-}
-
-int
-pthread_rwlock_wrlock(pthread_rwlock_t * rwlock)
-{
- int result;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static rwlock. We check
- * again inside the guarded section of ptw32_rwlock_check_need_init()
- * to avoid race conditions.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = ptw32_rwlock_check_need_init(rwlock);
-
- if (result != 0 && result != EBUSY)
- {
- return result;
- }
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result = pthread_mutex_lock(&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- if ((result = pthread_mutex_lock(&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- if (rwl->nExclusiveAccessCount == 0)
- {
- if (rwl->nCompletedSharedAccessCount > 0)
- {
- rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
- }
-
- if (rwl->nSharedAccessCount > 0)
- {
- rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;
-
- /*
- * This routine may be a cancelation point
- * according to POSIX 1003.1j section 18.1.2.
- */
-#ifdef _MSC_VER
-#pragma inline_depth(0)
-#endif
- pthread_cleanup_push(ptw32_rwlock_cancelwrwait, (void*)rwl);
-
- do
- {
- result = pthread_cond_wait(&(rwl->cndSharedAccessCompleted),
- &(rwl->mtxSharedAccessCompleted));
- }
- while (result == 0 && rwl->nCompletedSharedAccessCount < 0);
-
- pthread_cleanup_pop ((result != 0) ? 1 : 0);
-#ifdef _MSC_VER
-#pragma inline_depth()
-#endif
-
- if (result == 0)
- {
- rwl->nSharedAccessCount = 0;
- }
- }
- }
-
- if (result == 0)
- {
- rwl->nExclusiveAccessCount++;
- }
-
- return result;
-}
-
-int
-pthread_rwlock_unlock(pthread_rwlock_t * rwlock)
-{
- int result, result1;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return(EINVAL);
- }
-
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- /*
- * Assume any race condition here is harmless.
- */
- return 0;
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if (rwl->nExclusiveAccessCount == 0)
- {
- if ((result = pthread_mutex_lock(&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- return result;
- }
-
- if (++rwl->nCompletedSharedAccessCount == 0)
- {
- result = pthread_cond_signal(&(rwl->cndSharedAccessCompleted));
- }
-
- result1 = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted));
- }
- else
- {
- rwl->nExclusiveAccessCount--;
-
- result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted));
- result1 = pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
-
- }
-
- return ((result != 0) ? result : result1);
-}
-
-int
-pthread_rwlock_tryrdlock(pthread_rwlock_t * rwlock)
-{
- int result;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static rwlock. We check
- * again inside the guarded section of ptw32_rwlock_check_need_init()
- * to avoid race conditions.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = ptw32_rwlock_check_need_init(rwlock);
-
- if (result != 0 && result != EBUSY)
- {
- return result;
- }
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result = pthread_mutex_trylock(&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- if (++rwl->nSharedAccessCount == INT_MAX)
- {
- if ((result = pthread_mutex_lock(&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
-
- if ((result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
- return result;
- }
- }
-
- return (pthread_mutex_unlock(&rwl->mtxExclusiveAccess));
-}
-
-int
-pthread_rwlock_trywrlock(pthread_rwlock_t * rwlock)
-{
- int result, result1;
- pthread_rwlock_t rwl;
-
- if (rwlock == NULL || *rwlock == NULL)
- {
- return EINVAL;
- }
-
- /*
- * We do a quick check to see if we need to do more work
- * to initialise a static rwlock. We check
- * again inside the guarded section of ptw32_rwlock_check_need_init()
- * to avoid race conditions.
- */
- if (*rwlock == PTHREAD_RWLOCK_INITIALIZER)
- {
- result = ptw32_rwlock_check_need_init(rwlock);
-
- if (result != 0 && result != EBUSY)
- {
- return result;
- }
- }
-
- rwl = *rwlock;
-
- if (rwl->nMagic != PTW32_RWLOCK_MAGIC)
- {
- return EINVAL;
- }
-
- if ((result = pthread_mutex_trylock(&(rwl->mtxExclusiveAccess))) != 0)
- {
- return result;
- }
-
- if ((result = pthread_mutex_trylock(&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- result1 = pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
- return ((result1 != 0) ? result1 : result);
- }
-
- if (rwl->nExclusiveAccessCount == 0)
- {
- if (rwl->nCompletedSharedAccessCount > 0)
- {
- rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
- rwl->nCompletedSharedAccessCount = 0;
- }
-
- if (rwl->nSharedAccessCount > 0)
- {
- if ((result = pthread_mutex_unlock(&(rwl->mtxSharedAccessCompleted))) != 0)
- {
- (void) pthread_mutex_unlock(&(rwl->mtxExclusiveAccess));
- return result;
- }
-
- if ((result = pthread_mutex_unlock(&(rwl->mtxExclusiveAccess))) == 0)
- {
- result = EBUSY;
- }
- }
- else
- {
- rwl->nExclusiveAccessCount = 1;
- }
- }
- else
- {
- result = EBUSY;
- }
-
- return result;
-}
+#include "ptw32_rwlock_check_need_init.c"
+#include "pthread_rwlock_init.c"
+#include "pthread_rwlock_destroy.c"
+#include "pthread_rwlockattr_init.c"
+#include "pthread_rwlockattr_destroy.c"
+#include "pthread_rwlockattr_getpshared.c"
+#include "pthread_rwlockattr_setpshared.c"
+#include "pthread_rwlock_rdlock.c"
+#include "pthread_rwlock_wrlock.c"
+#include "pthread_rwlock_unlock.c"
+#include "pthread_rwlock_tryrdlock.c"
+#include "pthread_rwlock_trywrlock.c"
diff --git a/sched.c b/sched.c
index 410e1df..ca00bef 100644
--- a/sched.c
+++ b/sched.c
@@ -38,351 +38,16 @@
#include "implement.h"
#include "sched.h"
-static int
-is_attr(const pthread_attr_t *attr)
-{
- return (attr == NULL ||
- *attr == NULL ||
- (*attr)->valid != PTW32_ATTR_VALID) ? 1 : 0;
-}
-
-
-int
-pthread_attr_setschedpolicy(pthread_attr_t *attr,
- int policy)
-{
- if (is_attr(attr) != 0)
- {
- return EINVAL;
- }
-
- if (policy != SCHED_OTHER)
- {
- return ENOTSUP;
- }
-
- return 0;
-}
-
-
-int
-pthread_attr_getschedpolicy(pthread_attr_t *attr,
- int * policy)
-{
- if (is_attr(attr) != 0 || policy == NULL)
- {
- return EINVAL;
- }
-
- /*
- * Validate the policy arg.
- * Check that a policy constant wasn't passed rather than &policy.
- */
- if (policy <= (int *) SCHED_MAX)
- {
- return EINVAL;
- }
-
- *policy = SCHED_OTHER;
-
- return 0;
-}
-
-
-int
-pthread_attr_setschedparam(pthread_attr_t *attr,
- const struct sched_param *param)
-{
- int priority;
-
- if (is_attr(attr) != 0 || param == NULL)
- {
- return EINVAL;
- }
-
- priority = param->sched_priority;
-
- /* Validate priority level. */
- if (priority < sched_get_priority_min(SCHED_OTHER) ||
- priority > sched_get_priority_max(SCHED_OTHER))
- {
- return EINVAL;
- }
-
- memcpy(&(*attr)->param, param, sizeof(*param));
- return 0;
-}
-
-
-int
-pthread_attr_getschedparam(const pthread_attr_t *attr,
- struct sched_param *param)
-{
- if (is_attr(attr) != 0 || param == NULL)
- {
- return EINVAL;
- }
-
- memcpy(param, &(*attr)->param, sizeof(*param));
- return 0;
-}
-
-
-int
-pthread_attr_setinheritsched(pthread_attr_t * attr,
- int inheritsched)
-{
- if (is_attr(attr) != 0)
- {
- return EINVAL;
- }
-
- if (PTHREAD_INHERIT_SCHED != inheritsched
- && PTHREAD_EXPLICIT_SCHED != inheritsched)
- {
- return EINVAL;
- }
-
- (*attr)->inheritsched = inheritsched;
- return 0;
-}
-
-
-int
-pthread_attr_getinheritsched(pthread_attr_t * attr,
- int * inheritsched)
-{
- if (is_attr(attr) != 0 || inheritsched == NULL)
- {
- return EINVAL;
- }
-
- *inheritsched = (*attr)->inheritsched;
- return 0;
-}
-
-
-int
-pthread_setschedparam(pthread_t thread, int policy,
- const struct sched_param *param)
-{
- int prio;
-
- /* Validate the thread id. */
- if (thread == NULL || thread->threadH == 0)
- {
- return EINVAL;
- }
-
- /* Validate the scheduling policy. */
- if (policy < SCHED_MIN || policy > SCHED_MAX)
- {
- return EINVAL;
- }
-
- /* Ensure the policy is SCHED_OTHER. */
- if (policy != SCHED_OTHER)
- {
- return ENOTSUP;
- }
-
- prio = param->sched_priority;
-
- /* Validate priority level. */
- if (prio < sched_get_priority_min(policy) ||
- prio > sched_get_priority_max(policy))
- {
- return EINVAL;
- }
-
- /* This is practically guaranteed to return TRUE. */
- (void) SetThreadPriority(thread->threadH, prio);
-
- return 0;
-}
-
-
-int
-pthread_getschedparam(pthread_t thread, int *policy,
- struct sched_param *param)
-{
- int prio;
-
- /* Validate the thread id. */
- if (thread == NULL || thread->threadH == 0)
- {
- return EINVAL;
- }
-
- /*
- * Validate the policy and param args.
- * Check that a policy constant wasn't passed rather than &policy.
- */
- if (policy <= (int *) SCHED_MAX || param == NULL)
- {
- return EINVAL;
- }
-
- /* Fill out the policy. */
- *policy = SCHED_OTHER;
-
- /* Fill out the sched_param structure. */
- prio = GetThreadPriority(thread->threadH);
- if (prio == THREAD_PRIORITY_ERROR_RETURN)
- {
- return EINVAL;
- }
-
- param->sched_priority = prio;
- return 0;
-}
-
-
-/*
- * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and
- * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine.
- *
- * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5
- * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny:
- * highest priority use smaller numbers) and the following happens:
- *
- * sched_get_priority_min() returns 5
- * sched_get_priority_max() returns 1
- */
-
-
-int
-sched_get_priority_max(int policy)
-{
- if (policy < SCHED_MIN || policy > SCHED_MAX)
- {
- return EINVAL;
- }
-
-#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
- /* WinCE? */
- return PTW32_MAX(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
-#else
- /* This is independent of scheduling policy in Win32. */
- return PTW32_MAX(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
-#endif
-}
-
-
-int
-sched_get_priority_min(int policy)
-{
- if (policy < SCHED_MIN || policy > SCHED_MAX)
- {
- return EINVAL;
- }
-
-#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
- /* WinCE? */
- return PTW32_MIN(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
-#else
- /* This is independent of scheduling policy in Win32. */
- return PTW32_MIN(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
-#endif
-}
-
-
-int
-sched_setscheduler(pid_t pid, int policy)
-{
- /*
- * Win32 only has one policy which we call SCHED_OTHER.
- * However, we try to provide other valid side-effects
- * such as EPERM and ESRCH errors. Choosing to check
- * for a valid policy last allows us to get the most value out
- * of this function.
- */
- if (0 != pid)
- {
- int selfPid = (int) GetCurrentProcessId();
-
- if (pid != selfPid)
- {
- HANDLE h = OpenProcess(PROCESS_SET_INFORMATION, FALSE, (DWORD) pid);
-
- if (NULL == h)
- {
- errno = (GetLastError() == (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
- return -1;
- }
- }
- }
-
- if (SCHED_OTHER != policy)
- {
- errno = ENOSYS;
- return -1;
- }
-
- /*
- * Don't set anything because there is nothing to set.
- * Just return the current (the only possible) value.
- */
- return SCHED_OTHER;
-}
-
-
-int
-sched_getscheduler(pid_t pid)
-{
- /*
- * Win32 only has one policy which we call SCHED_OTHER.
- * However, we try to provide other valid side-effects
- * such as EPERM and ESRCH errors.
- */
- if (0 != pid)
- {
- int selfPid = (int) GetCurrentProcessId();
-
- if (pid != selfPid)
- {
- HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, (DWORD) pid);
-
- if (NULL == h)
- {
- errno = (GetLastError() == (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
- return -1;
- }
- }
- }
-
- return SCHED_OTHER;
-}
-
-
-int
-sched_yield(void)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function indicates that the calling thread is
- * willing to give up some time slices to other threads.
- *
- * PARAMETERS
- * N/A
- *
- *
- * DESCRIPTION
- * This function indicates that the calling thread is
- * willing to give up some time slices to other threads.
- * NOTE: Since this is part of POSIX 1003.1b
- * (realtime extensions), it is defined as returning
- * -1 if an error occurs and sets errno to the actual
- * error.
- *
- * RESULTS
- * 0 successfully created semaphore,
- * ENOSYS sched_yield not supported,
- *
- * ------------------------------------------------------
- */
-{
- Sleep(0);
-
- return 0;
-}
+#include "pthread_attr_setschedpolicy.c"
+#include "pthread_attr_getschedpolicy.c"
+#include "pthread_attr_setschedparam.c"
+#include "pthread_attr_getschedparam.c"
+#include "pthread_attr_setinheritsched.c"
+#include "pthread_attr_getinheritsched.c"
+#include "pthread_setschedparam.c"
+#include "pthread_getschedparam.c"
+#include "sched_get_priority_max.c"
+#include "sched_get_priority_min.c"
+#include "sched_setscheduler.c"
+#include "sched_getscheduler.c"
+#include "sched_yield.c"
diff --git a/sched_get_priority_max.c b/sched_get_priority_max.c
new file mode 100644
index 0000000..8bffa64
--- /dev/null
+++ b/sched_get_priority_max.c
@@ -0,0 +1,69 @@
+/*
+ * sched_get_priority_max.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+/*
+ * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and
+ * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine.
+ *
+ * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5
+ * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny:
+ * highest priority use smaller numbers) and the following happens:
+ *
+ * sched_get_priority_min() returns 5
+ * sched_get_priority_max() returns 1
+ */
+
+
+int
+sched_get_priority_max(int policy)
+{
+ if (policy < SCHED_MIN || policy > SCHED_MAX)
+ {
+ return EINVAL;
+ }
+
+#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
+ /* WinCE? */
+ return PTW32_MAX(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#else
+ /* This is independent of scheduling policy in Win32. */
+ return PTW32_MAX(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#endif
+}
diff --git a/sched_get_priority_min.c b/sched_get_priority_min.c
new file mode 100644
index 0000000..2536ceb
--- /dev/null
+++ b/sched_get_priority_min.c
@@ -0,0 +1,69 @@
+/*
+ * sched_get_priority_min.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+/*
+ * On Windows98, THREAD_PRIORITY_LOWEST is (-2) and
+ * THREAD_PRIORITY_HIGHEST is 2, and everything works just fine.
+ *
+ * On WinCE 3.0, it so happen that THREAD_PRIORITY_LOWEST is 5
+ * and THREAD_PRIORITY_HIGHEST is 1 (yes, I know, it is funny:
+ * highest priority use smaller numbers) and the following happens:
+ *
+ * sched_get_priority_min() returns 5
+ * sched_get_priority_max() returns 1
+ */
+
+
+int
+sched_get_priority_min(int policy)
+{
+ if (policy < SCHED_MIN || policy > SCHED_MAX)
+ {
+ return EINVAL;
+ }
+
+#if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL)
+ /* WinCE? */
+ return PTW32_MIN(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#else
+ /* This is independent of scheduling policy in Win32. */
+ return PTW32_MIN(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
+#endif
+}
diff --git a/sched_getscheduler.c b/sched_getscheduler.c
new file mode 100644
index 0000000..9d0cb57
--- /dev/null
+++ b/sched_getscheduler.c
@@ -0,0 +1,66 @@
+/*
+ * sched_getscheduler.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+sched_getscheduler(pid_t pid)
+{
+ /*
+ * Win32 only has one policy which we call SCHED_OTHER.
+ * However, we try to provide other valid side-effects
+ * such as EPERM and ESRCH errors.
+ */
+ if (0 != pid)
+ {
+ int selfPid = (int) GetCurrentProcessId();
+
+ if (pid != selfPid)
+ {
+ HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, (DWORD) pid);
+
+ if (NULL == h)
+ {
+ errno = (GetLastError() == (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
+ return -1;
+ }
+ }
+ }
+
+ return SCHED_OTHER;
+}
diff --git a/sched_setscheduler.c b/sched_setscheduler.c
new file mode 100644
index 0000000..b92cd54
--- /dev/null
+++ b/sched_setscheduler.c
@@ -0,0 +1,78 @@
+/*
+ * sched_setscheduler.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+sched_setscheduler(pid_t pid, int policy)
+{
+ /*
+ * Win32 only has one policy which we call SCHED_OTHER.
+ * However, we try to provide other valid side-effects
+ * such as EPERM and ESRCH errors. Choosing to check
+ * for a valid policy last allows us to get the most value out
+ * of this function.
+ */
+ if (0 != pid)
+ {
+ int selfPid = (int) GetCurrentProcessId();
+
+ if (pid != selfPid)
+ {
+ HANDLE h = OpenProcess(PROCESS_SET_INFORMATION, FALSE, (DWORD) pid);
+
+ if (NULL == h)
+ {
+ errno = (GetLastError() == (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
+ return -1;
+ }
+ }
+ }
+
+ if (SCHED_OTHER != policy)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ /*
+ * Don't set anything because there is nothing to set.
+ * Just return the current (the only possible) value.
+ */
+ return SCHED_OTHER;
+}
diff --git a/sched_yield.c b/sched_yield.c
new file mode 100644
index 0000000..6136444
--- /dev/null
+++ b/sched_yield.c
@@ -0,0 +1,71 @@
+/*
+ * sched_yield.c
+ *
+ * Description:
+ * POSIX thread functions that deal with thread scheduling.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ */
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+sched_yield(void)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function indicates that the calling thread is
+ * willing to give up some time slices to other threads.
+ *
+ * PARAMETERS
+ * N/A
+ *
+ *
+ * DESCRIPTION
+ * This function indicates that the calling thread is
+ * willing to give up some time slices to other threads.
+ * NOTE: Since this is part of POSIX 1003.1b
+ * (realtime extensions), it is defined as returning
+ * -1 if an error occurs and sets errno to the actual
+ * error.
+ *
+ * RESULTS
+ * 0 successfully created semaphore,
+ * ENOSYS sched_yield not supported,
+ *
+ * ------------------------------------------------------
+ */
+{
+ Sleep(0);
+
+ return 0;
+}
diff --git a/semaphore_close.c b/sem_close.c
index bb93e96..0cc8f0f 100644
--- a/semaphore_close.c
+++ b/sem_close.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_close.c
+ * Module: sem_close.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/semaphore_destroy.c b/sem_destroy.c
index 539f83a..80358f8 100644
--- a/semaphore_destroy.c
+++ b/sem_destroy.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_destroy.c
+ * Module: sem_destroy.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/semaphore_getvalue.c b/sem_getvalue.c
index 185bcdb..abc76c0 100644
--- a/semaphore_getvalue.c
+++ b/sem_getvalue.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_getvalue.c
+ * Module: sem_getvalue.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/semaphore_init.c b/sem_init.c
index bda6849..e36678c 100644
--- a/semaphore_init.c
+++ b/sem_init.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_init.c
+ * Module: sem_init.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/semaphore_open.c b/sem_open.c
index 9de124a..79b9535 100644
--- a/semaphore_open.c
+++ b/sem_open.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_open.c
+ * Module: sem_open.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/semaphore_post.c b/sem_post.c
index b7ce8da..afa7533 100644
--- a/semaphore_post.c
+++ b/sem_post.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_post.c
+ * Module: sem_post.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/semaphore_postmultiple.c b/sem_post_multiple.c
index 3218896..92139b8 100644
--- a/semaphore_postmultiple.c
+++ b/sem_post_multiple.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_postmultiple.c
+ * Module: sem_post_multiple.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/semaphore_timedwait.c b/sem_timedwait.c
index 083ee78..11178f2 100644
--- a/semaphore_timedwait.c
+++ b/sem_timedwait.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_timedwait.c
+ * Module: sem_timedwait.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
@@ -140,14 +140,15 @@ sem_timedwait (sem_t * sem, const struct timespec * abstime)
* but it does not exist on WinCE
*/
- filetime_to_timespec(&ft, &currSysTime);
+ ptw32_filetime_to_timespec(&ft, &currSysTime);
}
/*
* subtract current system time from abstime
*/
milliseconds = (abstime->tv_sec - currSysTime.tv_sec) * MILLISEC_PER_SEC;
- milliseconds += ((abstime->tv_nsec - currSysTime.tv_nsec) + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;
+ milliseconds += ((abstime->tv_nsec - currSysTime.tv_nsec)
+ + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;
#else /* NEED_FTIME */
_ftime(&currSysTime);
@@ -156,8 +157,8 @@ sem_timedwait (sem_t * sem, const struct timespec * abstime)
* subtract current system time from abstime
*/
milliseconds = (abstime->tv_sec - currSysTime.time) * MILLISEC_PER_SEC;
- milliseconds += ((abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC) -
- currSysTime.millitm;
+ milliseconds += ((abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC)
+ - currSysTime.millitm;
#endif /* NEED_FTIME */
diff --git a/semaphore_trywait.c b/sem_trywait.c
index 6b20d38..aea1d06 100644
--- a/semaphore_trywait.c
+++ b/sem_trywait.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore.c
+ * Module: sem_trywait.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/semaphore_unlink.c b/sem_unlink.c
index 8f20746..7dae88e 100644
--- a/semaphore_unlink.c
+++ b/sem_unlink.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_unlink.c
+ * Module: sem_unlink.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/semaphore_wait.c b/sem_wait.c
index 33bdb9c..5095241 100644
--- a/semaphore_wait.c
+++ b/sem_wait.c
@@ -1,7 +1,7 @@
/*
* -------------------------------------------------------------
*
- * Module: semaphore_wait.c
+ * Module: sem_wait.c
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
diff --git a/semaphore.c b/semaphore.c
index 713a904..bb10926 100644
--- a/semaphore.c
+++ b/semaphore.c
@@ -59,19 +59,19 @@
#include "implement.h"
-#include "semaphore_init.c"
-#include "semaphore_destroy.c"
-#include "semaphore_trywait.c"
-#include "semaphore_wait.c"
-#include "semaphore_timedwait.c"
-#include "semaphore_post.c"
-#include "semaphore_postmultiple.c"
-#include "semaphore_getvalue.c"
-#include "semaphore_open.c"
-#include "semaphore_close.c"
-#include "semaphore_unlink.c"
+#include "sem_init.c"
+#include "sem_destroy.c"
+#include "sem_trywait.c"
+#include "sem_wait.c"
+#include "sem_timedwait.c"
+#include "sem_post.c"
+#include "sem_post_multiple.c"
+#include "sem_getvalue.c"
+#include "sem_open.c"
+#include "sem_close.c"
+#include "sem_unlink.c"
#ifdef NEED_SEM
-#include "semaphore_decrease.c"
-#include "semaphore_increase.c"
+#include "ptw32_decrease_semaphore.c"
+#include "ptw32_increase_semaphore.c"
#endif
diff --git a/spin.c b/spin.c
index 5d33214..8947164 100644
--- a/spin.c
+++ b/spin.c
@@ -38,279 +38,10 @@
#include "implement.h"
-static INLINE int
-ptw32_spinlock_check_need_init(pthread_spinlock_t *lock)
-{
- int result = 0;
+#include "ptw32_spinlock_check_need_init.c"
+#include "pthread_spin_init.c"
+#include "pthread_spin_destroy.c"
+#include "pthread_spin_lock.c"
+#include "pthread_spin_unlock.c"
+#include "pthread_spin_trylock.c"
- /*
- * The following guarded test is specifically for statically
- * initialised spinlocks (via PTHREAD_SPINLOCK_INITIALIZER).
- *
- * Note that by not providing this synchronisation we risk
- * introducing race conditions into applications which are
- * correctly written.
- */
- EnterCriticalSection(&ptw32_spinlock_test_init_lock);
-
- /*
- * We got here possibly under race
- * conditions. Check again inside the critical section
- * and only initialise if the spinlock is valid (not been destroyed).
- * If a static spinlock has been destroyed, the application can
- * re-initialise it only by calling pthread_spin_init()
- * explicitly.
- */
- if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
- {
- result = pthread_spin_init(lock, PTHREAD_PROCESS_PRIVATE);
- }
- else if (*lock == NULL)
- {
- /*
- * The spinlock has been destroyed while we were waiting to
- * initialise it, so the operation that caused the
- * auto-initialisation should fail.
- */
- result = EINVAL;
- }
-
- LeaveCriticalSection(&ptw32_spinlock_test_init_lock);
-
- return(result);
-}
-
-
-int
-pthread_spin_init(pthread_spinlock_t *lock, int pshared)
-{
- pthread_spinlock_t s;
- int cpus = 0;
- int result = 0;
-
- if (lock == NULL)
- {
- return EINVAL;
- }
-
- if (0 != ptw32_getprocessors(&cpus))
- {
- cpus = 1;
- }
-
- if (cpus > 1)
- {
- if (pshared == PTHREAD_PROCESS_SHARED)
- {
- /*
- * Creating spinlock that can be shared between
- * processes.
- */
-#if _POSIX_THREAD_PROCESS_SHARED
-
- /*
- * Not implemented yet.
- */
-
-#error ERROR [__FILE__, line __LINE__]: Process shared spin locks are not supported yet.
-
-#else
-
- return ENOSYS;
-
-#endif /* _POSIX_THREAD_PROCESS_SHARED */
-
- }
- }
-
- s = (pthread_spinlock_t) calloc(1, sizeof(*s));
-
- if (s == NULL)
- {
- return ENOMEM;
- }
-
- if (cpus > 1)
- {
- s->u.cpus = cpus;
- s->interlock = PTW32_SPIN_UNLOCKED;
- }
- else
- {
- pthread_mutexattr_t ma;
- result = pthread_mutexattr_init(&ma);
-
- if (0 == result)
- {
- ma->pshared = pshared;
- result = pthread_mutex_init(&(s->u.mutex), &ma);
- if (0 == result)
- {
- s->interlock = PTW32_SPIN_USE_MUTEX;
- }
- }
- (void) pthread_mutexattr_destroy(&ma);
- }
-
- if (0 == result)
- {
- *lock = s;
- }
- else
- {
- (void) free(s);
- *lock = NULL;
- }
-
- return(result);
-}
-
-int
-pthread_spin_destroy(pthread_spinlock_t *lock)
-{
- register pthread_spinlock_t s;
-
- if (lock == NULL || *lock == NULL)
- {
- return EINVAL;
- }
-
- if ((s = *lock) != PTHREAD_SPINLOCK_INITIALIZER)
- {
- if (s->interlock == PTW32_SPIN_USE_MUTEX)
- {
- return pthread_mutex_destroy(&(s->u.mutex));
- }
-
- if ( (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED ==
- ptw32_interlocked_compare_exchange((PTW32_INTERLOCKED_LPLONG) &(s->interlock),
- (PTW32_INTERLOCKED_LONG) PTW32_OBJECT_INVALID,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED))
- {
- return 0;
- }
-
- return EINVAL;
- }
- else
- {
- int result = 0;
-
- /*
- * See notes in ptw32_spinlock_check_need_init() above also.
- */
- EnterCriticalSection(&ptw32_spinlock_test_init_lock);
-
- /*
- * Check again.
- */
- if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
- {
- /*
- * This is all we need to do to destroy a statically
- * initialised spinlock that has not yet been used (initialised).
- * If we get to here, another thread
- * waiting to initialise this mutex will get an EINVAL.
- */
- *lock = NULL;
- }
- else
- {
- /*
- * The spinlock has been initialised while we were waiting
- * so assume it's in use.
- */
- result = EBUSY;
- }
-
- LeaveCriticalSection(&ptw32_spinlock_test_init_lock);
- return(result);
- }
-}
-
-/*
- * NOTE: For speed, these routines don't check if "lock" is valid.
- */
-int
-pthread_spin_lock(pthread_spinlock_t *lock)
-{
- register pthread_spinlock_t s;
-
- if (*lock == PTHREAD_SPINLOCK_INITIALIZER)
- {
- int result;
-
- if ((result = ptw32_spinlock_check_need_init(lock)) != 0)
- {
- return(result);
- }
- }
-
- s = *lock;
-
- while ( (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED ==
- ptw32_interlocked_compare_exchange((PTW32_INTERLOCKED_LPLONG) &(s->interlock),
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED) )
- {}
-
- if (s->interlock == PTW32_SPIN_LOCKED)
- {
- return 0;
- }
- else if (s->interlock == PTW32_SPIN_USE_MUTEX)
- {
- return pthread_mutex_lock(&(s->u.mutex));
- }
-
- return EINVAL;
-}
-
-int
-pthread_spin_unlock(pthread_spinlock_t *lock)
-{
- register pthread_spinlock_t s = *lock;
-
- if (s == PTHREAD_SPINLOCK_INITIALIZER)
- {
- return EPERM;
- }
-
- switch ((long) ptw32_interlocked_compare_exchange((PTW32_INTERLOCKED_LPLONG) &(s->interlock),
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED ))
- {
- case PTW32_SPIN_LOCKED: return 0;
- case PTW32_SPIN_UNLOCKED: return EPERM;
- case PTW32_SPIN_USE_MUTEX: return pthread_mutex_unlock(&(s->u.mutex));
- }
-
- return EINVAL;
-}
-
-int
-pthread_spin_trylock(pthread_spinlock_t *lock)
-{
- pthread_spinlock_t s = *lock;
-
- if (s == PTHREAD_SPINLOCK_INITIALIZER)
- {
- int result;
-
- if ((result = ptw32_spinlock_check_need_init(lock)) != 0)
- {
- return(result);
- }
- }
-
- switch ((long) ptw32_interlocked_compare_exchange((PTW32_INTERLOCKED_LPLONG) &(s->interlock),
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_LOCKED,
- (PTW32_INTERLOCKED_LONG) PTW32_SPIN_UNLOCKED ))
- {
- case PTW32_SPIN_UNLOCKED: return 0;
- case PTW32_SPIN_LOCKED: return EBUSY;
- case PTW32_SPIN_USE_MUTEX: return pthread_mutex_trylock(&(s->u.mutex));
- }
-
- return EINVAL;
-}
diff --git a/sync.c b/sync.c
index 3a093e0..e644910 100644
--- a/sync.c
+++ b/sync.c
@@ -38,162 +38,6 @@
#include "pthread.h"
#include "implement.h"
-int
-pthread_detach (pthread_t tid)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function detaches the given thread.
- *
- * PARAMETERS
- * thread
- * an instance of a pthread_t
- *
- *
- * DESCRIPTION
- * This function detaches the given thread. You may
- * detach the main thread or to detach a joinable thread
- * (You should have used pthread_attr_t to create the
- * thread as detached!)
- * NOTE: detached threads cannot be joined nor canceled;
- * storage is freed immediately on termination.
- *
- * RESULTS
- * 0 successfully detached the thread,
- * EINVAL thread is not a joinable thread,
- * ENOSPC a required resource has been exhausted,
- * ESRCH no thread could be found for 'thread',
- *
- * ------------------------------------------------------
- */
-{
- int result;
- if (tid == NULL ||
- tid->detachState == PTHREAD_CREATE_DETACHED)
- {
-
- result = EINVAL;
-
- }
- else
- {
- result = 0;
- tid->detachState = PTHREAD_CREATE_DETACHED;
- }
-
- return (result);
-
-} /* pthread_detach */
-
-int
-pthread_join (pthread_t thread, void **value_ptr)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function waits for 'thread' to terminate and
- * returns the thread's exit value if 'value_ptr' is not
- * NULL. This also detaches the thread on successful
- * completion.
- *
- * PARAMETERS
- * thread
- * an instance of pthread_t
- *
- * value_ptr
- * pointer to an instance of pointer to void
- *
- *
- * DESCRIPTION
- * This function waits for 'thread' to terminate and
- * returns the thread's exit value if 'value_ptr' is not
- * NULL. This also detaches the thread on successful
- * completion.
- * NOTE: detached threads cannot be joined or canceled
- *
- * RESULTS
- * 0 'thread' has completed
- * EINVAL thread is not a joinable thread,
- * ESRCH no thread could be found with ID 'thread',
- * ENOENT thread couldn't find it's own valid handle,
- * EDEADLK attempt to join thread with self
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- pthread_t self;
-
- self = pthread_self ();
- if (self == NULL)
- {
- return ENOENT;
- }
-
- if (pthread_equal (self, thread) != 0)
- {
- result = EDEADLK;
- }
- else if (thread->detachState == PTHREAD_CREATE_DETACHED)
- {
- result = EINVAL;
- }
- else
- {
- /*
- * Pthread_join is a cancelation point.
- * If we are canceled then our target thread must not be
- * detached (destroyed). This is guarranteed because
- * pthreadCancelableWait will not return if we
- * are canceled.
- */
- result = pthreadCancelableWait(thread->threadH);
-
- if (result == 0)
- {
-
-#if ! defined (__MINGW32__) || defined (__MSVCRT__)
-
- if (value_ptr != NULL
- && !GetExitCodeThread (thread->threadH, (LPDWORD) value_ptr))
- {
- result = ESRCH;
- }
- else
- {
- /*
- * The result of making multiple simultaneous calls to
- * pthread_join() specifying the same target is undefined.
- */
- ptw32_threadDestroy (thread);
- }
-
-#else /* __MINGW32__ && ! __MSVCRT__ */
-
- /*
- * If using CRTDLL, the thread may have exited, and endthread
- * will have closed the handle.
- */
- if (value_ptr != NULL)
- {
- *value_ptr = thread->exitStatus;
- }
-
- /*
- * The result of making multiple simultaneous calls to
- * pthread_join() specifying the same target is undefined.
- */
- ptw32_threadDestroy (thread);
-
-#endif /* __MINGW32__ && ! __MSVCRT__ */
-
- }
- else
- {
- result = ESRCH;
- }
- }
-
- return (result);
-
-} /* pthread_join */
+#include "pthread_detach.c"
+#include "pthread_join.c"
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 4a4883e..944961d 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2002-02-17 Ross Johnson <rpj@special.ise.canberra.edu.au>
+
+ * condvar1_1.c: New test.
+ * condvar1_2.c: New test.
+
2002-02-07 Ross Johnson <rpj@special.ise.canberra.edu.au>
* delay1.c: New test.
diff --git a/tests/GNUmakefile b/tests/GNUmakefile
index fc0a7e3..74bd6b3 100644
--- a/tests/GNUmakefile
+++ b/tests/GNUmakefile
@@ -67,9 +67,10 @@ COPYFILES = $(HDR) $(LIB) $(DLL)
TESTS = loadfree \
self1 mutex5 mutex1 mutex1e mutex1n mutex1r \
- condvar1 condvar2 condvar2_1 exit1 create1 equal1 \
+ condvar1 condvar1_1 condvar1_2 condvar2 condvar2_1 exit1 create1 equal1 \
exit2 exit3 \
- join0 join1 join2 mutex2 mutex3 mutex4 mutex6 mutex6n mutex6e mutex6r \
+ join0 join1 join2 \
+ mutex2 mutex3 mutex4 mutex6 mutex6n mutex6e mutex6r \
mutex7 mutex7n mutex7e mutex7r mutex8 mutex8n mutex8e mutex8r \
count1 once1 tsd1 self2 cancel1 cancel2 \
delay1 delay2 eyal1 \
@@ -148,6 +149,8 @@ cleanup1.pass: cleanup0.pass
cleanup2.pass: cleanup1.pass
cleanup3.pass: cleanup2.pass
condvar1.pass:
+condvar1_1.pass: condvar1.pass
+condvar1_2.pass: join2.pass
condvar2.pass: condvar1.pass
condvar2_1.pass: condvar2.pass join2.pass
condvar3.pass: create1.pass condvar2.pass
diff --git a/tests/Makefile b/tests/Makefile
index ad2a055..9532b41 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -73,7 +73,7 @@ EHFLAGS =
PASSES= loadfree.pass \
self1.pass mutex5.pass \
mutex1.pass mutex1n.pass mutex1e.pass mutex1r.pass mutex2.pass mutex3.pass \
- condvar1.pass condvar2.pass condvar2_1.pass \
+ condvar1.pass condvar1_1.pass condvar1_2.pass condvar2.pass condvar2_1.pass \
exit1.pass create1.pass equal1.pass \
exit2.pass exit3.pass \
join0.pass join1.pass join2.pass \
@@ -213,6 +213,8 @@ cleanup1.pass: cleanup0.pass
cleanup2.pass: cleanup1.pass
cleanup3.pass: cleanup2.pass
condvar1.pass:
+condvar1_1.pass: condvar1.pass
+condvar1_2.pass: join2.pass
condvar2.pass: condvar1.pass
condvar2_1.pass: condvar2.pass join2.pass
condvar3.pass: create1.pass condvar2.pass
diff --git a/tests/condvar1_1.c b/tests/condvar1_1.c
new file mode 100644
index 0000000..465c9df
--- /dev/null
+++ b/tests/condvar1_1.c
@@ -0,0 +1,117 @@
+/*
+ * File: condvar1_1.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Test Synopsis:
+ * - Test CV linked list management.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation:
+ * Initiate and destry several CVs in random order.
+ *
+ * Requirements Tested:
+ * -
+ *
+ * Features Tested:
+ * -
+ *
+ * Cases Tested:
+ * -
+ *
+ * Description:
+ * - Creates and then imediately destroys a CV. Does not
+ * test the CV.
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * -
+ *
+ * Pass Criteria:
+ * - All initialised CVs destroyed without segfault.
+ * - Successfully broadcasts all remaining CVs after
+ * each CV is removed.
+ *
+ * Fail Criteria:
+ */
+
+#include <stdlib.h>
+#include "test.h"
+
+enum {
+ NUM_CV = 100
+};
+
+static pthread_cond_t cv[NUM_CV];
+
+int
+main()
+{
+ int i, j;
+
+ for (i = 0; i < NUM_CV; i++)
+ {
+ /* Traverse the list before every init of a CV. */
+ assert(pthread_timechange_handler_np(NULL) == (void *) 0);
+ assert(pthread_cond_init(&cv[i], NULL) == 0);
+ }
+
+ j = NUM_CV;
+ (void) srand((unsigned)time(NULL));
+
+ do
+ {
+ i = (NUM_CV - 1) * rand() / RAND_MAX;
+ if (cv[i] != NULL)
+ {
+ j--;
+ assert(pthread_cond_destroy(&cv[i]) == 0);
+ /* Traverse the list every time we remove a CV. */
+ assert(pthread_timechange_handler_np(NULL) == (void *) 0);
+ }
+ }
+ while (j > 0);
+
+ return 0;
+}
diff --git a/tests/condvar1_2.c b/tests/condvar1_2.c
new file mode 100644
index 0000000..66237ba
--- /dev/null
+++ b/tests/condvar1_2.c
@@ -0,0 +1,122 @@
+/*
+ * File: condvar1_2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.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
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Test Synopsis:
+ * - Test CV linked list management and serialisation.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation:
+ * Initiate and destroy several CVs in random order.
+ * Asynchronously traverse the CV list and broadcast.
+ *
+ * Requirements Tested:
+ * -
+ *
+ * Features Tested:
+ * -
+ *
+ * Cases Tested:
+ * -
+ *
+ * Description:
+ * - Creates and then imediately destroys a CV. Does not
+ * test the CV.
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * -
+ *
+ * Pass Criteria:
+ * - All initialised CVs destroyed without segfault.
+ * - Successfully broadcasts all remaining CVs after
+ * each CV is removed.
+ *
+ * Fail Criteria:
+ */
+
+#include <stdlib.h>
+#include "test.h"
+
+enum {
+ NUM_CV = 100
+};
+
+static pthread_cond_t cv[NUM_CV];
+
+int
+main()
+{
+ int i, j;
+ int result = -1;
+ pthread_t t;
+
+ for (i = 0; i < NUM_CV; i++)
+ {
+ assert(pthread_cond_init(&cv[i], NULL) == 0);
+ }
+
+ j = NUM_CV;
+ (void) srand((unsigned)time(NULL));
+
+ /* Traverse the list asynchronously. */
+ assert(pthread_create(&t, NULL, pthread_timechange_handler_np, NULL) == 0);
+
+ do
+ {
+ i = (NUM_CV - 1) * rand() / RAND_MAX;
+ if (cv[i] != NULL)
+ {
+ j--;
+ assert(pthread_cond_destroy(&cv[i]) == 0);
+ }
+ }
+ while (j > 0);
+
+ assert(pthread_join(t, (void **) &result) == 0);
+ assert (result == 0);
+
+ return 0;
+}
diff --git a/tests/condvar3_1.c b/tests/condvar3_1.c
index e181c58..9c4e25b 100644
--- a/tests/condvar3_1.c
+++ b/tests/condvar3_1.c
@@ -161,6 +161,8 @@ main()
signaled++;
}
+ assert(pthread_cond_destroy(&cv1) == 0);
+
for (i = 1; i <= NUMTHREADS; i++)
{
assert(pthread_join(t[i], (void **) &result) == 0);
diff --git a/tests/exit4.c b/tests/exit4.c
index 3c0c8b1..480fc2e 100644
--- a/tests/exit4.c
+++ b/tests/exit4.c
@@ -64,21 +64,29 @@ void *
func(void * arg)
{
Guard g("func", counter);
+
#ifdef USE_PTHREAD_EXIT
+
pthread_exit(arg);
assert(0); //Never reached with pthread_exit
+
#endif //USE_PTHREAD_EXIT
+
return ret_value;
}
#endif /*__CLEANUP_CXX */
-int main(int, char **)
+int
+main()
{
#ifndef __CLEANUP_CXX
+
printf("Test requires C++ cleanup enabled. Skipped.\n");
+
#else
+
{
void *ret = 0;
Guard g("main", counter);
@@ -87,7 +95,10 @@ int main(int, char **)
assert(0 == pthread_join(id, &ret));
assert(ret == ret_value);
}
+
assert(counter == init_counter_value);
+
#endif /*__CLEANUP_CXX */
+
return 0;
}
diff --git a/tsd.c b/tsd.c
index 1fa9b5a..52c3517 100644
--- a/tsd.c
+++ b/tsd.c
@@ -37,310 +37,10 @@
#include "pthread.h"
#include "implement.h"
-/* TLS_OUT_OF_INDEXES not defined on WinCE */
-#ifndef TLS_OUT_OF_INDEXES
-#define TLS_OUT_OF_INDEXES 0xffffffff
-#endif
-int
-pthread_key_create (pthread_key_t * key, void (*destructor) (void *))
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function creates a thread-specific data key visible
- * to all threads. All existing and new threads have a value
- * NULL for key until set using pthread_setspecific. When any
- * thread with a non-NULL value for key terminates, 'destructor'
- * is called with key's current value for that thread.
- *
- * PARAMETERS
- * key
- * pointer to an instance of pthread_key_t
- *
- *
- * DESCRIPTION
- * This function creates a thread-specific data key visible
- * to all threads. All existing and new threads have a value
- * NULL for key until set using pthread_setspecific. When any
- * thread with a non-NULL value for key terminates, 'destructor'
- * is called with key's current value for that thread.
- *
- * RESULTS
- * 0 successfully created semaphore,
- * EAGAIN insufficient resources or PTHREAD_KEYS_MAX
- * exceeded,
- * ENOMEM insufficient memory to create the key,
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
- pthread_key_t newkey;
+#include "pthread_key_create.c"
+#include "pthread_key_delete.c"
+#include "pthread_setspecific.c"
+#include "pthread_getspecific.c"
- if ((newkey = (pthread_key_t) calloc (1, sizeof (*newkey))) == NULL)
- {
- result = ENOMEM;
- }
- else if ((newkey->key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
- {
- result = EAGAIN;
-
- free (newkey);
- newkey = NULL;
- }
- else if (destructor != NULL)
- {
- /*
- * Have to manage associations between thread and key;
- * Therefore, need a lock that allows multiple threads
- * to gain exclusive access to the key->threads list.
- *
- * The mutex will only be created when it is first locked.
- */
- newkey->threadsLock = PTHREAD_MUTEX_INITIALIZER;
- newkey->destructor = destructor;
- }
-
- *key = newkey;
-
- return (result);
-}
-
-int
-pthread_key_delete (pthread_key_t key)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function deletes a thread-specific data key. This
- * does not change the value of the thread spcific data key
- * for any thread and does not run the key's destructor
- * in any thread so it should be used with caution.
- *
- * PARAMETERS
- * key
- * pointer to an instance of pthread_key_t
- *
- *
- * DESCRIPTION
- * This function deletes a thread-specific data key. This
- * does not change the value of the thread spcific data key
- * for any thread and does not run the key's destructor
- * in any thread so it should be used with caution.
- *
- * RESULTS
- * 0 successfully deleted the key,
- * EINVAL key is invalid,
- *
- * ------------------------------------------------------
- */
-{
- int result = 0;
-
- if (key != NULL)
- {
- if (key->threads != NULL &&
- key->destructor != NULL &&
- pthread_mutex_lock (&(key->threadsLock)) == 0)
- {
- /*
- * Run through all Thread<-->Key associations
- * for this key.
- * If the pthread_t still exits (ie the assoc->thread
- * is not NULL) then leave the assoc for the thread to
- * destroy.
- * Notes:
- * If assoc->thread is NULL, then the associated thread
- * is no longer referencing this assoc.
- * The association is only referenced
- * by this key and must be released; otherwise
- * the assoc will be destroyed when the thread is destroyed.
- */
- ThreadKeyAssoc *assoc;
-
- assoc = (ThreadKeyAssoc *) key->threads;
-
- while (assoc != NULL)
- {
- if (pthread_mutex_lock (&(assoc->lock)) == 0)
- {
- ThreadKeyAssoc *next;
-
- assoc->key = NULL;
- next = assoc->nextThread;
- assoc->nextThread = NULL;
-
- pthread_mutex_unlock (&(assoc->lock));
-
- ptw32_tkAssocDestroy (assoc);
-
- assoc = next;
- }
- }
- pthread_mutex_unlock (&(key->threadsLock));
- }
-
- TlsFree (key->key);
- if (key->destructor != NULL)
- {
- pthread_mutex_destroy (&(key->threadsLock));
- }
-
-#if defined( _DEBUG )
- memset ((char *) key, 0, sizeof (*key));
-#endif
- free (key);
- }
-
- return (result);
-}
-
-
-int
-pthread_setspecific (pthread_key_t key, const void *value)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function sets the value of the thread specific
- * key in the calling thread.
- *
- * PARAMETERS
- * key
- * an instance of pthread_key_t
- * value
- * the value to set key to
- *
- *
- * DESCRIPTION
- * This function sets the value of the thread specific
- * key in the calling thread.
- *
- * RESULTS
- * 0 successfully set value
- * EAGAIN could not set value
- * ENOENT SERIOUS!!
- *
- * ------------------------------------------------------
- */
-{
- pthread_t self;
- int result = 0;
-
- if (key != ptw32_selfThreadKey)
- {
- /*
- * Using pthread_self will implicitly create
- * an instance of pthread_t for the current
- * thread if one wasn't explicitly created
- */
- self = pthread_self ();
- if (self == NULL)
- {
- return ENOENT;
- }
- }
- else
- {
- /*
- * Resolve catch-22 of registering thread with threadSelf
- * key
- */
- self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey);
- if (self == NULL)
- {
- self = (pthread_t) value;
- }
- }
-
- result = 0;
-
- if (key != NULL)
- {
- ThreadKeyAssoc *assoc;
-
- if (self != NULL &&
- key->destructor != NULL &&
- value != NULL)
- {
- /*
- * Only require associations if we have to
- * call user destroy routine.
- * Don't need to locate an existing association
- * when setting data to NULL for WIN32 since the
- * data is stored with the operating system; not
- * on the association; setting assoc to NULL short
- * circuits the search.
- */
- assoc = (ThreadKeyAssoc *) self->keys;
- /*
- * Locate existing association
- */
- while (assoc != NULL)
- {
- if (assoc->key == key)
- {
- /*
- * Association already exists
- */
- break;
- }
- assoc = assoc->nextKey;
- }
-
- /*
- * create an association if not found
- */
- if (assoc == NULL)
- {
- result = ptw32_tkAssocCreate (&assoc, self, key);
- }
- }
-
- if (result == 0)
- {
- if ( ! TlsSetValue (key->key, (LPVOID) value))
- {
- result = EAGAIN;
- }
- }
- }
-
- return (result);
-} /* pthread_setspecific */
-
-
-void *
-pthread_getspecific (pthread_key_t key)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function returns the current value of key in the
- * calling thread. If no value has been set for 'key' in
- * the thread, NULL is returned.
- *
- * PARAMETERS
- * key
- * an instance of pthread_key_t
- *
- *
- * DESCRIPTION
- * This function returns the current value of key in the
- * calling thread. If no value has been set for 'key' in
- * the thread, NULL is returned.
- *
- * RESULTS
- * key value or NULL on failure
- *
- * ------------------------------------------------------
- */
-{
- int lasterror = GetLastError();
- int lastWSAerror = WSAGetLastError();
-
- void *ptr = TlsGetValue (key->key);
-
- SetLastError( lasterror );
- WSASetLastError( lastWSAerror );
-
- return ptr;
-}