diff options
| author | rpj <rpj> | 2002-02-18 03:16:52 +0000 | 
|---|---|---|
| committer | rpj <rpj> | 2002-02-18 03:16:52 +0000 | 
| commit | a416ab17ecf9f2cb0f1e3f7bd645a8d1ce690ca2 (patch) | |
| tree | 72f776cd64e48824a5578ff7a523bc69097143b4 | |
| parent | e6f1797e9e9925ae7f9dda54806ef8f52ae3ed07 (diff) | |
Major reorganisation of source code; new routine and tests added.
| -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; -} | 
