diff options
-rw-r--r-- | ChangeLog | 213 | ||||
-rw-r--r-- | GNUmakefile | 353 | ||||
-rw-r--r-- | Makefile | 644 | ||||
-rw-r--r-- | Nmakefile.tests | 396 | ||||
-rw-r--r-- | attr.c | 21 | ||||
-rw-r--r-- | barrier.c | 14 | ||||
-rw-r--r-- | cancel.c | 8 | ||||
-rw-r--r-- | condvar.c | 20 | ||||
-rw-r--r-- | global.c | 9 | ||||
-rw-r--r-- | implement.h | 259 | ||||
-rw-r--r-- | misc.c | 2 | ||||
-rw-r--r-- | mutex.c | 1080 | ||||
-rw-r--r-- | nonportable.c | 14 | ||||
-rw-r--r-- | private.c | 980 | ||||
-rw-r--r-- | pthread.c | 7 | ||||
-rw-r--r-- | pthread.def | 325 | ||||
-rw-r--r-- | pthread.h | 61 | ||||
-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.c | 52 | ||||
-rw-r--r-- | pthread_attr_getschedparam.c | 52 | ||||
-rw-r--r-- | pthread_attr_getschedpolicy.c | 62 | ||||
-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.c | 58 | ||||
-rw-r--r-- | pthread_attr_setschedparam.c | 63 | ||||
-rw-r--r-- | pthread_attr_setschedpolicy.c | 56 | ||||
-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.c | 88 | ||||
-rw-r--r-- | pthread_getschedparam.c | 74 | ||||
-rw-r--r-- | pthread_getspecific.c | 75 | ||||
-rw-r--r-- | pthread_getw32threadhandle_np.c (renamed from np_getw32threadhandle.c) | 2 | ||||
-rw-r--r-- | pthread_join.c | 152 | ||||
-rw-r--r-- | pthread_key_create.c | 108 | ||||
-rw-r--r-- | pthread_key_delete.c | 127 | ||||
-rw-r--r-- | pthread_mutex_destroy.c | 134 | ||||
-rw-r--r-- | pthread_mutex_init.c | 107 | ||||
-rw-r--r-- | pthread_mutex_lock.c | 105 | ||||
-rw-r--r-- | pthread_mutex_timedlock.c | 356 | ||||
-rw-r--r-- | pthread_mutex_trylock.c | 99 | ||||
-rw-r--r-- | pthread_mutex_unlock.c | 93 | ||||
-rw-r--r-- | pthread_mutexattr_destroy.c | 83 | ||||
-rw-r--r-- | pthread_mutexattr_getkind_np.c (renamed from np_mutexattr_setkind.c) | 15 | ||||
-rw-r--r-- | pthread_mutexattr_getpshared.c | 97 | ||||
-rw-r--r-- | pthread_mutexattr_gettype.c | 57 | ||||
-rw-r--r-- | pthread_mutexattr_init.c | 86 | ||||
-rw-r--r-- | pthread_mutexattr_setkind_np.c | 45 | ||||
-rw-r--r-- | pthread_mutexattr_setpshared.c | 120 | ||||
-rw-r--r-- | pthread_mutexattr_settype.c | 144 | ||||
-rw-r--r-- | pthread_num_processors_np.c (renamed from np_num_processors.c) | 2 | ||||
-rw-r--r-- | pthread_rwlock_destroy.c | 140 | ||||
-rw-r--r-- | pthread_rwlock_init.c | 109 | ||||
-rw-r--r-- | pthread_rwlock_rdlock.c | 101 | ||||
-rw-r--r-- | pthread_rwlock_tryrdlock.c | 101 | ||||
-rw-r--r-- | pthread_rwlock_trywrlock.c | 120 | ||||
-rw-r--r-- | pthread_rwlock_unlock.c | 93 | ||||
-rw-r--r-- | pthread_rwlock_wrlock.c | 146 | ||||
-rw-r--r-- | pthread_rwlockattr_destroy.c | 85 | ||||
-rw-r--r-- | pthread_rwlockattr_getpshared.c | 99 | ||||
-rw-r--r-- | pthread_rwlockattr_init.c | 84 | ||||
-rw-r--r-- | pthread_rwlockattr_setpshared.c | 122 | ||||
-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.c | 78 | ||||
-rw-r--r-- | pthread_setspecific.c | 151 | ||||
-rw-r--r-- | pthread_spin_destroy.c | 102 | ||||
-rw-r--r-- | pthread_spin_init.c | 123 | ||||
-rw-r--r-- | pthread_spin_lock.c | 77 | ||||
-rw-r--r-- | pthread_spin_trylock.c | 69 | ||||
-rw-r--r-- | pthread_spin_unlock.c | 64 | ||||
-rw-r--r-- | pthread_testcancel.c (renamed from cancel_testcancel.c) | 2 | ||||
-rw-r--r-- | pthread_timechange_handler_np.c | 108 | ||||
-rw-r--r-- | pthread_win32_attach_detach_np.c (renamed from np_win32_attach.c) | 2 | ||||
-rw-r--r-- | ptw32_InterlockedCompareExchange.c | 108 | ||||
-rw-r--r-- | ptw32_callUserDestroyRoutines.c | 155 | ||||
-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.c | 84 | ||||
-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.c | 94 | ||||
-rw-r--r-- | ptw32_processInitialize.c | 100 | ||||
-rw-r--r-- | ptw32_processTerminate.c | 100 | ||||
-rw-r--r-- | ptw32_rwlock_check_need_init.c | 93 | ||||
-rw-r--r-- | ptw32_spinlock_check_need_init.c | 81 | ||||
-rw-r--r-- | ptw32_threadDestroy.c | 66 | ||||
-rw-r--r-- | ptw32_threadStart.c | 373 | ||||
-rw-r--r-- | ptw32_throw.c | 130 | ||||
-rw-r--r-- | ptw32_timespec.c | 81 | ||||
-rw-r--r-- | ptw32_tkAssocCreate.c | 142 | ||||
-rw-r--r-- | ptw32_tkAssocDestroy.c | 68 | ||||
-rw-r--r-- | rwlock.c | 826 | ||||
-rw-r--r-- | sched.c | 361 | ||||
-rw-r--r-- | sched_get_priority_max.c | 69 | ||||
-rw-r--r-- | sched_get_priority_min.c | 69 | ||||
-rw-r--r-- | sched_getscheduler.c | 66 | ||||
-rw-r--r-- | sched_setscheduler.c | 78 | ||||
-rw-r--r-- | sched_yield.c | 71 | ||||
-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.c | 26 | ||||
-rw-r--r-- | spin.c | 281 | ||||
-rw-r--r-- | sync.c | 160 | ||||
-rw-r--r-- | tests/ChangeLog | 5 | ||||
-rw-r--r-- | tests/GNUmakefile | 7 | ||||
-rw-r--r-- | tests/Makefile | 4 | ||||
-rw-r--r-- | tests/condvar1_1.c | 117 | ||||
-rw-r--r-- | tests/condvar1_2.c | 122 | ||||
-rw-r--r-- | tests/condvar3_1.c | 2 | ||||
-rw-r--r-- | tests/exit4.c | 13 | ||||
-rw-r--r-- | tsd.c | 308 |
142 files changed, 8341 insertions, 4981 deletions
@@ -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) @@ -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
+
@@ -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" @@ -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" @@ -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" @@ -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" @@ -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, \ @@ -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" @@ -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" + @@ -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" @@ -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
@@ -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 */ @@ -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" @@ -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 @@ -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; -} @@ -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; } @@ -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; -} |