1 /* thread.cc: Locking and threading module functions
3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
5 Originally written by Marco Fuykschot <marco@ddi.nl>
6 Substantialy enhanced by Robert Collins <rbtcollins@hotmail.com>
8 This file is part of Cygwin.
10 This software is a copyrighted work licensed under the terms of the
11 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
14 /* Implementation overview and caveats:
16 Win32 puts some contraints on what can and cannot be implemented. Where
17 possible we work around those contrainsts. Where we cannot work around
18 the constraints we either pretend to be conformant, or return an error
21 Some caveats: PROCESS_SHARED objects while they pretend to be process
22 shared, may not actually work. Some test cases are needed to determine
23 win32's behaviour. My suspicion is that the win32 handle needs to be
24 opened with different flags for proper operation.
26 R.Collins, April 2001. */
39 #include "perprocess.h"
42 #include <semaphore.h>
44 #include <sys/timeb.h>
45 #include <exceptions.h>
46 #include <sys/fcntl.h>
49 extern "C" void __fp_lock_all ();
50 extern "C" void __fp_unlock_all ();
52 extern int threadsafe
;
55 extern "C" struct _reent
*
58 return &_my_tls
.local_clib
;
62 __cygwin_lock_init (_LOCK_T
*lock
)
64 *lock
= _LOCK_T_INITIALIZER
;
68 __cygwin_lock_init_recursive (_LOCK_T
*lock
)
70 *lock
= _LOCK_T_RECURSIVE_INITIALIZER
;
74 __cygwin_lock_fini (_LOCK_T
*lock
)
76 pthread_mutex_destroy ((pthread_mutex_t
*) lock
);
80 __cygwin_lock_lock (_LOCK_T
*lock
)
82 pthread_mutex_lock ((pthread_mutex_t
*) lock
);
86 __cygwin_lock_trylock (_LOCK_T
*lock
)
88 pthread_mutex_trylock ((pthread_mutex_t
*) lock
);
93 __cygwin_lock_unlock (_LOCK_T
*lock
)
95 pthread_mutex_unlock ((pthread_mutex_t
*) lock
);
98 inline LPCRITICAL_SECTION
99 ResourceLocks::Lock (int _resid
)
105 SetResourceLock (int _res_id
, int _mode
, const char *_function
)
107 EnterCriticalSection (user_data
->resourcelocks
->Lock (_res_id
));
111 ReleaseResourceLock (int _res_id
, int _mode
, const char *_function
)
113 LeaveCriticalSection (user_data
->resourcelocks
->Lock (_res_id
));
117 ResourceLocks::Init ()
119 InitializeCriticalSection (&lock
);
121 thread_printf ("lock %p inited by %p , %d", &lock
, user_data
, myself
->pid
);
125 ResourceLocks::Delete ()
129 thread_printf ("Close Resource Locks %p ", &lock
);
130 DeleteCriticalSection (&lock
);
138 pthread_mutex::init_mutex ();
139 pthread_cond::init_mutex ();
140 pthread_rwlock::init_mutex ();
144 MTinterface::fixup_before_fork (void)
146 pthread_key::fixup_before_fork ();
149 /* This function is called from a single threaded process */
151 MTinterface::fixup_after_fork (void)
153 pthread_key::fixup_after_fork ();
156 pthread::init_mainthread ();
158 pthread::fixup_after_fork ();
159 pthread_mutex::fixup_after_fork ();
160 pthread_cond::fixup_after_fork ();
161 pthread_rwlock::fixup_after_fork ();
162 semaphore::fixup_after_fork ();
169 pthread::init_mainthread ()
171 pthread
*thread
= get_tls_self_pointer ();
174 thread
= new pthread ();
176 api_fatal ("failed to create mainthread object");
179 set_tls_self_pointer (thread
);
180 thread
->thread_id
= GetCurrentThreadId ();
181 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
182 GetCurrentProcess (), &thread
->win32_obj_id
,
183 0, FALSE
, DUPLICATE_SAME_ACCESS
))
184 api_fatal ("failed to create mainthread handle");
185 if (!thread
->create_cancel_event ())
186 api_fatal ("couldn't create cancel event for main thread");
187 VerifyHandle (thread
->win32_obj_id
);
188 thread
->postcreate ();
194 pthread
*thread
= get_tls_self_pointer ();
197 thread
= pthread_null::get_null_pthread ();
198 set_tls_self_pointer (thread
);
204 pthread::get_tls_self_pointer ()
210 pthread::set_tls_self_pointer (pthread
*thread
)
212 thread
->cygtls
= &_my_tls
;
213 _my_tls
.tid
= thread
;
216 List
<pthread
> pthread::threads
;
219 pthread::pthread ():verifyable_object (PTHREAD_MAGIC
), win32_obj_id (0),
220 valid (false), suspended (false),
221 cancelstate (0), canceltype (0), cancel_event (0),
222 joiner (NULL
), next (NULL
), cleanup_stack (NULL
)
224 if (this != pthread_null::get_null_pthread ())
225 threads
.insert (this);
231 CloseHandle (win32_obj_id
);
233 CloseHandle (cancel_event
);
235 if (this != pthread_null::get_null_pthread ())
236 threads
.remove (this);
240 pthread::create_cancel_event ()
242 cancel_event
= ::CreateEvent (&sec_none_nih
, TRUE
, FALSE
, NULL
);
245 system_printf ("couldn't create cancel event, %E");
246 /* we need the event for correct behaviour */
253 pthread::precreate (pthread_attr
*newattr
)
255 pthread_mutex
*verifyable_mutex_obj
= &mutex
;
257 /* already running ? */
263 attr
.joinable
= newattr
->joinable
;
264 attr
.contentionscope
= newattr
->contentionscope
;
265 attr
.inheritsched
= newattr
->inheritsched
;
266 attr
.stacksize
= newattr
->stacksize
;
269 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
271 thread_printf ("New thread object access mutex is not valid. this %p",
276 /* Change the mutex type to NORMAL to speed up mutex operations */
277 mutex
.type
= PTHREAD_MUTEX_NORMAL
;
278 if (!create_cancel_event ())
283 pthread::create (void *(*func
) (void *), pthread_attr
*newattr
,
294 win32_obj_id
= ::CreateThread (&sec_none_nih
, attr
.stacksize
,
295 thread_init_wrapper
, this, 0, &thread_id
);
299 thread_printf ("CreateThread failed: this %p, %E", this);
304 if (WaitForSingleObject (cancel_event
, 5000) != WAIT_OBJECT_0
)
305 thread_printf ("event never arrived after CreateThread");
306 ResetEvent (cancel_event
);
313 pthread::postcreate ()
317 InterlockedIncrement (&MT_INTERFACE
->threadcount
);
318 /* FIXME: set the priority appropriately for system contention scope */
319 if (attr
.inheritsched
== PTHREAD_EXPLICIT_SCHED
)
321 /* FIXME: set the scheduling settings for the new thread */
322 /* sched_thread_setparam (win32_obj_id, attr.schedparam); */
327 pthread::exit (void *value_ptr
)
329 class pthread
*thread
= this;
331 // run cleanup handlers
332 pop_all_cleanup_handlers ();
334 pthread_key::run_all_destructors ();
337 // cleanup if thread is in detached state and not joined
338 if (equal (joiner
, thread
))
343 return_ptr
= value_ptr
;
347 (_reclaim_reent
) (_REENT
);
350 if (InterlockedDecrement (&MT_INTERFACE
->threadcount
) == 0)
354 _my_tls
.remove (INFINITE
);
360 pthread::cancel (void)
362 class pthread
*thread
= this;
363 class pthread
*self
= pthread::self ();
373 if (canceltype
== PTHREAD_CANCEL_DEFERRED
||
374 cancelstate
== PTHREAD_CANCEL_DISABLE
)
378 SetEvent (cancel_event
);
381 else if (equal (thread
, self
))
385 return 0; // Never reached
388 // cancel asynchronous
389 SuspendThread (win32_obj_id
);
390 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
393 context
.ContextFlags
= CONTEXT_CONTROL
;
394 GetThreadContext (win32_obj_id
, &context
);
395 context
.Eip
= (DWORD
) pthread::static_cancel_self
;
396 SetThreadContext (win32_obj_id
, &context
);
399 ResumeThread (win32_obj_id
);
403 TODO: insert pthread_testcancel into the required functions
404 the required function list is: *indicates done, X indicates not present in cygwin.
423 *pthread_cond_timedwait ()
424 *pthread_cond_wait ()
426 *pthread_testcancel ()
450 the optional list is:
570 Note, that for fcntl (), for any value of the cmd argument.
572 And we must not introduce cancellation points anywhere else that's part of the posix or
578 pthread::testcancel (void)
580 if (cancelstate
== PTHREAD_CANCEL_DISABLE
)
583 if (WaitForSingleObject (cancel_event
, 0) == WAIT_OBJECT_0
)
588 pthread::static_cancel_self (void)
590 pthread::self ()->cancel_self ();
594 pthread::cancelable_wait (HANDLE object
, DWORD timeout
, const bool do_cancel
,
595 const bool do_sig_wait
)
599 HANDLE wait_objects
[3];
600 pthread_t thread
= self ();
602 /* Do not change the wait order.
603 The object must have higher priority than the cancel event,
604 because WaitForMultipleObjects will return the smallest index
605 if both objects are signaled. */
606 wait_objects
[num
++] = object
;
607 if (is_good_object (&thread
) &&
608 thread
->cancelstate
!= PTHREAD_CANCEL_DISABLE
)
609 wait_objects
[num
++] = thread
->cancel_event
;
611 wait_objects
[num
++] = signal_arrived
;
613 res
= WaitForMultipleObjects (num
, wait_objects
, FALSE
, timeout
);
614 if (res
== WAIT_CANCELED
)
616 if (num
== 3 || !do_sig_wait
)
619 pthread::static_cancel_self ();
628 pthread::setcancelstate (int state
, int *oldstate
)
634 if (state
!= PTHREAD_CANCEL_ENABLE
&& state
!= PTHREAD_CANCEL_DISABLE
)
639 *oldstate
= cancelstate
;
649 pthread::setcanceltype (int type
, int *oldtype
)
655 if (type
!= PTHREAD_CANCEL_DEFERRED
&& type
!= PTHREAD_CANCEL_ASYNCHRONOUS
)
660 *oldtype
= canceltype
;
670 pthread::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
674 api_fatal ("Attempt to push a cleanup handler across threads");
675 handler
->next
= cleanup_stack
;
676 cleanup_stack
= handler
;
680 pthread::pop_cleanup_handler (int const execute
)
683 // TODO: send a signal or something to the thread ?
684 api_fatal ("Attempt to execute a cleanup handler across threads");
688 if (cleanup_stack
!= NULL
)
690 __pthread_cleanup_handler
*handler
= cleanup_stack
;
693 (*handler
->function
) (handler
->arg
);
694 cleanup_stack
= handler
->next
;
701 pthread::pop_all_cleanup_handlers ()
703 while (cleanup_stack
!= NULL
)
704 pop_cleanup_handler (1);
708 pthread::cancel_self ()
710 exit (PTHREAD_CANCELED
);
714 pthread::get_thread_id ()
720 pthread::_fixup_after_fork ()
722 /* set thread to not running if it is not the forking thread */
723 if (this != pthread::self ())
733 pthread::suspend_except_self ()
735 if (valid
&& this != pthread::self ())
736 SuspendThread (win32_obj_id
);
743 ResumeThread (win32_obj_id
);
748 pthread_attr::is_good_object (pthread_attr_t
const *attr
)
750 if (verifyable_object_isvalid (attr
, PTHREAD_ATTR_MAGIC
) != VALID_OBJECT
)
755 /* instance members */
757 pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC
),
758 joinable (PTHREAD_CREATE_JOINABLE
), contentionscope (PTHREAD_SCOPE_PROCESS
),
759 inheritsched (PTHREAD_INHERIT_SCHED
), stacksize (0)
761 schedparam
.sched_priority
= 0;
764 pthread_attr::~pthread_attr ()
769 pthread_condattr::is_good_object (pthread_condattr_t
const *attr
)
771 if (verifyable_object_isvalid (attr
, PTHREAD_CONDATTR_MAGIC
) != VALID_OBJECT
)
776 pthread_condattr::pthread_condattr ():verifyable_object
777 (PTHREAD_CONDATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
781 pthread_condattr::~pthread_condattr ()
785 List
<pthread_cond
> pthread_cond::conds
;
787 /* This is used for cond creation protection within a single process only */
788 fast_mutex NO_COPY
pthread_cond::cond_initialization_lock
;
790 /* We can only be called once.
791 TODO: (no rush) use a non copied memory section to
792 hold an initialization flag. */
794 pthread_cond::init_mutex ()
796 if (!cond_initialization_lock
.init ())
797 api_fatal ("Could not create win32 Mutex for pthread cond static initializer support.");
800 pthread_cond::pthread_cond (pthread_condattr
*attr
) :
801 verifyable_object (PTHREAD_COND_MAGIC
),
802 shared (0), waiting (0), pending (0), sem_wait (NULL
),
803 mtx_cond(NULL
), next (NULL
)
805 pthread_mutex
*verifyable_mutex_obj
;
808 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
814 verifyable_mutex_obj
= &mtx_in
;
815 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
817 thread_printf ("Internal cond mutex is not valid. this %p", this);
822 * Change the mutex type to NORMAL.
823 * This mutex MUST be of type normal
825 mtx_in
.type
= PTHREAD_MUTEX_NORMAL
;
827 verifyable_mutex_obj
= &mtx_out
;
828 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
830 thread_printf ("Internal cond mutex is not valid. this %p", this);
834 /* Change the mutex type to NORMAL to speed up mutex operations */
835 mtx_out
.type
= PTHREAD_MUTEX_NORMAL
;
837 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
840 debug_printf ("CreateSemaphore failed. %E");
848 pthread_cond::~pthread_cond ()
851 CloseHandle (sem_wait
);
857 pthread_cond::unblock (const bool all
)
859 unsigned long releaseable
;
862 * Block outgoing threads (and avoid simultanous unblocks)
866 releaseable
= waiting
- pending
;
869 unsigned long released
;
874 * Block incoming threads until all waiting threads are released.
879 * Calculate releaseable again because threads can enter until
880 * the semaphore has been taken, but they can not leave, therefore pending
881 * is unchanged and releaseable can only get higher
883 releaseable
= waiting
- pending
;
886 released
= all
? releaseable
: 1;
891 ::ReleaseSemaphore (sem_wait
, released
, NULL
);
895 * And let the threads release.
901 pthread_cond::wait (pthread_mutex_t mutex
, DWORD dwMilliseconds
)
906 if (InterlockedIncrement ((long *)&waiting
) == 1)
908 else if (mtx_cond
!= mutex
)
910 InterlockedDecrement ((long *)&waiting
);
917 * Release the mutex and wait on semaphore
922 rv
= pthread::cancelable_wait (sem_wait
, dwMilliseconds
, false, true);
926 if (rv
!= WAIT_OBJECT_0
)
929 * It might happen that a signal is sent while the thread got canceled
930 * or timed out. Try to take one.
931 * If the thread gets one than a signal|broadcast is in progress.
933 if (WaitForSingleObject (sem_wait
, 0) == WAIT_OBJECT_0
)
935 * thread got cancelled ot timed out while a signalling is in progress.
936 * Set wait result back to signaled
941 InterlockedDecrement ((long *)&waiting
);
943 if (rv
== WAIT_OBJECT_0
&& --pending
== 0)
945 * All signaled threads are released,
946 * new threads can enter Wait
955 if (rv
== WAIT_CANCELED
)
956 pthread::static_cancel_self ();
957 else if (rv
== WAIT_SIGNALED
)
958 /* SUSv3 states: If a signal is delivered to a thread waiting for a
959 condition variable, upon return from the signal handler the thread
960 resumes waiting for the condition variable as if it was not
961 interrupted, or it shall return zero due to spurious wakeup.
962 We opt for the latter choice here. */
964 else if (rv
== WAIT_TIMEOUT
)
971 pthread_cond::_fixup_after_fork ()
973 waiting
= pending
= 0;
976 /* Unlock eventually locked mutexes */
980 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
982 api_fatal ("pthread_cond::_fixup_after_fork () failed to recreate win32 semaphore");
986 pthread_rwlockattr::is_good_object (pthread_rwlockattr_t
const *attr
)
988 if (verifyable_object_isvalid (attr
, PTHREAD_RWLOCKATTR_MAGIC
) != VALID_OBJECT
)
993 pthread_rwlockattr::pthread_rwlockattr ():verifyable_object
994 (PTHREAD_RWLOCKATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
998 pthread_rwlockattr::~pthread_rwlockattr ()
1002 List
<pthread_rwlock
> pthread_rwlock::rwlocks
;
1004 /* This is used for rwlock creation protection within a single process only */
1005 fast_mutex NO_COPY
pthread_rwlock::rwlock_initialization_lock
;
1007 /* We can only be called once.
1008 TODO: (no rush) use a non copied memory section to
1009 hold an initialization flag. */
1011 pthread_rwlock::init_mutex ()
1013 if (!rwlock_initialization_lock
.init ())
1014 api_fatal ("Could not create win32 Mutex for pthread rwlock static initializer support.");
1017 pthread_rwlock::pthread_rwlock (pthread_rwlockattr
*attr
) :
1018 verifyable_object (PTHREAD_RWLOCK_MAGIC
),
1019 shared (0), waiting_readers (0), waiting_writers (0), writer (NULL
),
1020 readers (NULL
), readers_mx (), mtx (NULL
), cond_readers (NULL
), cond_writers (NULL
),
1023 pthread_mutex
*verifyable_mutex_obj
= &mtx
;
1024 pthread_cond
*verifyable_cond_obj
;
1026 if (!readers_mx
.init ())
1028 thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this);
1034 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
1040 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1042 thread_printf ("Internal rwlock mutex is not valid. this %p", this);
1046 /* Change the mutex type to NORMAL to speed up mutex operations */
1047 mtx
.type
= PTHREAD_MUTEX_NORMAL
;
1049 verifyable_cond_obj
= &cond_readers
;
1050 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1052 thread_printf ("Internal rwlock readers cond is not valid. this %p", this);
1057 verifyable_cond_obj
= &cond_writers
;
1058 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1060 thread_printf ("Internal rwlock writers cond is not valid. this %p", this);
1066 rwlocks
.insert (this);
1069 pthread_rwlock::~pthread_rwlock ()
1071 rwlocks
.remove (this);
1075 pthread_rwlock::rdlock ()
1078 struct RWLOCK_READER
*reader
;
1079 pthread_t self
= pthread::self ();
1083 if (lookup_reader (self
))
1089 reader
= new struct RWLOCK_READER
;
1096 while (writer
|| waiting_writers
)
1098 pthread_cleanup_push (pthread_rwlock::rdlock_cleanup
, this);
1101 cond_readers
.wait (&mtx
);
1104 pthread_cleanup_pop (0);
1107 reader
->thread
= self
;
1108 add_reader (reader
);
1117 pthread_rwlock::tryrdlock ()
1120 pthread_t self
= pthread::self ();
1124 if (writer
|| waiting_writers
|| lookup_reader (self
))
1128 struct RWLOCK_READER
*reader
= new struct RWLOCK_READER
;
1131 reader
->thread
= self
;
1132 add_reader (reader
);
1144 pthread_rwlock::wrlock ()
1147 pthread_t self
= pthread::self ();
1151 if (writer
== self
|| lookup_reader (self
))
1157 while (writer
|| readers
)
1159 pthread_cleanup_push (pthread_rwlock::wrlock_cleanup
, this);
1162 cond_writers
.wait (&mtx
);
1165 pthread_cleanup_pop (0);
1177 pthread_rwlock::trywrlock ()
1180 pthread_t self
= pthread::self ();
1184 if (writer
|| readers
)
1195 pthread_rwlock::unlock ()
1198 pthread_t self
= pthread::self ();
1214 struct RWLOCK_READER
*reader
= lookup_reader (self
);
1222 remove_reader (reader
);
1235 pthread_rwlock::add_reader (struct RWLOCK_READER
*rd
)
1237 List_insert (readers
, rd
);
1241 pthread_rwlock::remove_reader (struct RWLOCK_READER
*rd
)
1243 List_remove (readers_mx
, readers
, rd
);
1246 struct pthread_rwlock::RWLOCK_READER
*
1247 pthread_rwlock::lookup_reader (pthread_t thread
)
1251 struct RWLOCK_READER
*cur
= readers
;
1253 while (cur
&& cur
->thread
!= thread
)
1256 readers_mx
.unlock ();
1262 pthread_rwlock::rdlock_cleanup (void *arg
)
1264 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1266 --(rwlock
->waiting_readers
);
1268 rwlock
->mtx
.unlock ();
1272 pthread_rwlock::wrlock_cleanup (void *arg
)
1274 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1276 --(rwlock
->waiting_writers
);
1278 rwlock
->mtx
.unlock ();
1282 pthread_rwlock::_fixup_after_fork ()
1284 pthread_t self
= pthread::self ();
1285 struct RWLOCK_READER
**temp
= &readers
;
1287 waiting_readers
= 0;
1288 waiting_writers
= 0;
1290 if (!readers_mx
.init ())
1291 api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex");
1293 /* Unlock eventually locked mutex */
1296 * Remove all readers except self
1300 if ((*temp
)->thread
== self
)
1301 temp
= &((*temp
)->next
);
1304 struct RWLOCK_READER
*cur
= *temp
;
1305 *temp
= (*temp
)->next
;
1312 /* static members */
1313 /* This stores pthread_key information across fork() boundaries */
1314 List
<pthread_key
> pthread_key::keys
;
1317 pthread_key::is_good_object (pthread_key_t
const *key
)
1319 if (verifyable_object_isvalid (key
, PTHREAD_KEY_MAGIC
) != VALID_OBJECT
)
1324 /* non-static members */
1326 pthread_key::pthread_key (void (*aDestructor
) (void *)):verifyable_object (PTHREAD_KEY_MAGIC
), destructor (aDestructor
)
1328 tls_index
= TlsAlloc ();
1329 if (tls_index
== TLS_OUT_OF_INDEXES
)
1335 pthread_key::~pthread_key ()
1337 /* We may need to make the list code lock the list during operations
1342 TlsFree (tls_index
);
1347 pthread_key::set (const void *value
)
1349 /* the OS function doesn't perform error checking */
1350 TlsSetValue (tls_index
, (void *) value
);
1355 pthread_key::get () const
1357 int saved_error
= ::GetLastError ();
1358 void *result
= TlsGetValue (tls_index
);
1359 ::SetLastError (saved_error
);
1364 pthread_key::_fixup_before_fork ()
1370 pthread_key::_fixup_after_fork ()
1372 tls_index
= TlsAlloc ();
1373 if (tls_index
== TLS_OUT_OF_INDEXES
)
1374 api_fatal ("pthread_key::recreate_key_from_buffer () failed to reallocate Tls storage");
1379 pthread_key::run_destructor ()
1383 void *oldValue
= get ();
1387 destructor (oldValue
);
1394 REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
1395 gymnastics can be a lot easier.
1397 the mutex_t (size 4) is not used as a verifyable object because we cannot
1398 guarantee the same address space for all processes.
1399 we use the following:
1400 high bit set (never a valid address).
1401 second byte is reserved for the priority.
1402 third byte is reserved
1403 fourth byte is the mutex id. (max 255 cygwin mutexs system wide).
1404 creating mutex's does get slower and slower, but as creation is a one time
1405 job, it should never become an issue
1407 And if you're looking at this and thinking, why not an array in cygwin for all mutexs,
1408 - you incur a penalty on _every_ mutex call and you have toserialise them all.
1411 option 2? put everything in userspace and update the ABI?
1412 - bad karma as well - the HANDLE, while identical across process's,
1413 Isn't duplicated, it's reopened. */
1415 /* static members */
1417 pthread_mutex::is_good_object (pthread_mutex_t
const *mutex
)
1419 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
) != VALID_OBJECT
)
1425 pthread_mutex::is_good_initializer (pthread_mutex_t
const *mutex
)
1427 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
1428 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
1429 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
1430 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) != VALID_STATIC_OBJECT
)
1436 pthread_mutex::is_good_initializer_or_object (pthread_mutex_t
const *mutex
)
1438 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
1439 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
1440 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
1441 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) == INVALID_OBJECT
)
1447 pthread_mutex::is_good_initializer_or_bad_object (pthread_mutex_t
const *mutex
)
1449 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
1450 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
1451 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
1452 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) == VALID_OBJECT
)
1458 pthread_mutex::can_be_unlocked (pthread_mutex_t
const *mutex
)
1460 pthread_t self
= pthread::self ();
1462 if (!is_good_object (mutex
))
1465 * Check if the mutex is owned by the current thread and can be unlocked
1467 return ((*mutex
)->recursion_counter
== 1 && pthread::equal ((*mutex
)->owner
, self
));
1470 List
<pthread_mutex
> pthread_mutex::mutexes
;
1472 /* This is used for mutex creation protection within a single process only */
1473 fast_mutex NO_COPY
pthread_mutex::mutex_initialization_lock
;
1475 /* We can only be called once.
1476 TODO: (no rush) use a non copied memory section to
1477 hold an initialization flag. */
1479 pthread_mutex::init_mutex ()
1481 if (!mutex_initialization_lock
.init ())
1482 api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support.");
1485 pthread_mutex::pthread_mutex (pthread_mutexattr
*attr
) :
1486 verifyable_object (PTHREAD_MUTEX_MAGIC
),
1488 win32_obj_id (NULL
), recursion_counter (0),
1489 condwaits (0), owner (NULL
), type (PTHREAD_MUTEX_DEFAULT
),
1490 pshared (PTHREAD_PROCESS_PRIVATE
)
1492 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1498 /*attr checked in the C call */
1501 if (attr
->pshared
== PTHREAD_PROCESS_SHARED
)
1508 type
= attr
->mutextype
;
1511 mutexes
.insert (this);
1514 pthread_mutex::~pthread_mutex ()
1517 CloseHandle (win32_obj_id
);
1519 mutexes
.remove (this);
1523 pthread_mutex::_lock (pthread_t self
)
1527 if (InterlockedIncrement ((long *)&lock_counter
) == 1)
1529 else if (type
!= PTHREAD_MUTEX_NORMAL
&& pthread::equal (owner
, self
))
1531 InterlockedDecrement ((long *) &lock_counter
);
1532 if (type
== PTHREAD_MUTEX_RECURSIVE
)
1533 result
= lock_recursive ();
1539 WaitForSingleObject (win32_obj_id
, INFINITE
);
1547 pthread_mutex::_trylock (pthread_t self
)
1551 if (InterlockedCompareExchange ((long *) &lock_counter
, 1, 0) == 0)
1553 else if (type
== PTHREAD_MUTEX_RECURSIVE
&& pthread::equal (owner
, self
))
1554 result
= lock_recursive ();
1562 pthread_mutex::_unlock (pthread_t self
)
1564 if (!pthread::equal (owner
, self
))
1567 if (--recursion_counter
== 0)
1570 if (InterlockedDecrement ((long *)&lock_counter
))
1571 // Another thread is waiting
1572 ::ReleaseSemaphore (win32_obj_id
, 1, NULL
);
1579 pthread_mutex::_destroy (pthread_t self
)
1581 if (condwaits
|| _trylock (self
))
1582 // Do not destroy a condwaited or locked mutex
1584 else if (recursion_counter
!= 1)
1586 // Do not destroy a recursive locked mutex
1587 --recursion_counter
;
1596 pthread_mutex::_fixup_after_fork ()
1598 debug_printf ("mutex %x in _fixup_after_fork", this);
1599 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1600 api_fatal ("pthread_mutex::_fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's");
1603 /* mutex has no owner, reset to initial */
1605 else if (lock_counter
!= 0)
1606 /* All waiting threads are gone after a fork */
1609 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1611 api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 semaphore for mutex");
1617 pthread_mutexattr::is_good_object (pthread_mutexattr_t
const * attr
)
1619 if (verifyable_object_isvalid (attr
, PTHREAD_MUTEXATTR_MAGIC
) != VALID_OBJECT
)
1624 pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC
),
1625 pshared (PTHREAD_PROCESS_PRIVATE
), mutextype (PTHREAD_MUTEX_DEFAULT
)
1629 pthread_mutexattr::~pthread_mutexattr ()
1633 List
<semaphore
> semaphore::semaphores
;
1635 semaphore::semaphore (int pshared
, unsigned int value
)
1636 : verifyable_object (SEM_MAGIC
),
1638 currentvalue (value
),
1641 SECURITY_ATTRIBUTES sa
= (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1642 ? sec_all
: sec_none_nih
;
1643 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, NULL
);
1644 if (!this->win32_obj_id
)
1647 semaphores
.insert (this);
1650 semaphore::semaphore (const char *sem_name
, int oflag
, mode_t mode
,
1652 : verifyable_object (SEM_MAGIC
),
1653 shared (PTHREAD_PROCESS_SHARED
),
1654 currentvalue (value
), /* Unused for named semaphores. */
1657 if (oflag
& O_CREAT
)
1659 SECURITY_ATTRIBUTES sa
= sec_all
;
1660 security_descriptor sd
;
1662 set_security_attribute (mode
, &sa
, sd
);
1663 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, sem_name
);
1664 if (!this->win32_obj_id
)
1666 if (GetLastError () == ERROR_ALREADY_EXISTS
&& (oflag
& O_EXCL
))
1669 CloseHandle (this->win32_obj_id
);
1675 this->win32_obj_id
= ::OpenSemaphore (SEMAPHORE_ALL_ACCESS
, FALSE
,
1677 if (!this->win32_obj_id
)
1685 name
= new char [strlen (sem_name
+ 1)];
1689 CloseHandle (this->win32_obj_id
);
1693 strcpy (name
, sem_name
);
1696 semaphores
.insert (this);
1699 semaphore::~semaphore ()
1702 CloseHandle (win32_obj_id
);
1706 semaphores
.remove (this);
1712 if (ReleaseSemaphore (win32_obj_id
, 1, ¤tvalue
))
1717 semaphore::_getvalue (int *sval
)
1721 switch (WaitForSingleObject (win32_obj_id
, 0))
1724 ReleaseSemaphore (win32_obj_id
, 1, &val
);
1738 semaphore::_trywait ()
1740 /* FIXME: signals should be able to interrupt semaphores...
1741 *We probably need WaitForMultipleObjects here.
1743 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
1753 semaphore::_timedwait (const struct timespec
*abstime
)
1758 if (__check_invalid_read_ptr (abstime
, sizeof *abstime
))
1760 /* According to SUSv3, abstime need not be checked for validity,
1761 if the semaphore can be locked immediately. */
1768 gettimeofday (&tv
, NULL
);
1769 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
1770 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
1773 switch (pthread::cancelable_wait (win32_obj_id
, waitlength
, true, true))
1782 set_errno (ETIMEDOUT
);
1785 debug_printf ("cancelable_wait failed. %E");
1795 switch (pthread::cancelable_wait (win32_obj_id
, INFINITE
, true, true))
1804 debug_printf ("cancelable_wait failed. %E");
1811 semaphore::_fixup_after_fork ()
1813 if (shared
== PTHREAD_PROCESS_PRIVATE
)
1815 debug_printf ("sem %x in _fixup_after_fork", this);
1816 /* FIXME: duplicate code here and in the constructor. */
1817 this->win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, currentvalue
,
1820 api_fatal ("failed to create new win32 semaphore, error %d");
1824 verifyable_object::verifyable_object (long verifyer
):
1829 verifyable_object::~verifyable_object ()
1834 /* Generic memory acccess routine - where should it live ? */
1836 check_valid_pointer (void const *pointer
)
1838 if (!pointer
|| IsBadWritePtr ((void *) pointer
, sizeof (verifyable_object
)))
1843 verifyable_object_state
1844 verifyable_object_isvalid (void const * objectptr
, long magic
, void *static_ptr1
,
1845 void *static_ptr2
, void *static_ptr3
)
1847 verifyable_object
**object
= (verifyable_object
**)objectptr
;
1848 if (check_valid_pointer (object
))
1849 return INVALID_OBJECT
;
1850 if ((static_ptr1
&& *object
== static_ptr1
) ||
1851 (static_ptr2
&& *object
== static_ptr2
) ||
1852 (static_ptr3
&& *object
== static_ptr3
))
1853 return VALID_STATIC_OBJECT
;
1855 return INVALID_OBJECT
;
1856 if (check_valid_pointer (*object
))
1857 return INVALID_OBJECT
;
1858 if ((*object
)->magic
!= magic
)
1859 return INVALID_OBJECT
;
1860 return VALID_OBJECT
;
1864 pthread::thread_init_wrapper (void *arg
)
1866 pthread
*thread
= (pthread
*) arg
;
1867 set_tls_self_pointer (thread
);
1868 SetEvent (thread
->cancel_event
);
1870 thread
->mutex
.lock ();
1872 // if thread is detached force cleanup on exit
1873 if (thread
->attr
.joinable
== PTHREAD_CREATE_DETACHED
&& thread
->joiner
== NULL
)
1874 thread
->joiner
= thread
;
1875 thread
->mutex
.unlock ();
1877 thread_printf ("started thread %p %p %p %p %p %p", arg
, &_my_tls
.local_clib
,
1878 _impure_ptr
, thread
, thread
->function
, thread
->arg
);
1880 // call the user's thread
1881 void *ret
= thread
->function (thread
->arg
);
1885 return 0; // just for show. Never returns.
1889 pthread::is_good_object (pthread_t
const *thread
)
1891 if (verifyable_object_isvalid (thread
, PTHREAD_MAGIC
) != VALID_OBJECT
)
1897 pthread::getsequence_np ()
1899 return get_thread_id ();
1903 pthread::create (pthread_t
*thread
, const pthread_attr_t
*attr
,
1904 void *(*start_routine
) (void *), void *arg
)
1906 if (attr
&& !pthread_attr::is_good_object (attr
))
1909 *thread
= new pthread ();
1910 (*thread
)->create (start_routine
, attr
? *attr
: NULL
, arg
);
1911 if (!is_good_object (thread
))
1922 pthread::once (pthread_once_t
*once_control
, void (*init_routine
) (void))
1925 if (once_control
->state
)
1928 pthread_mutex_lock (&once_control
->mutex
);
1929 /* Here we must set a cancellation handler to unlock the mutex if needed */
1930 /* but a cancellation handler is not the right thing. We need this in the thread
1931 *cleanup routine. Assumption: a thread can only be in one pthread_once routine
1932 *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
1933 *on pthread_exit ();
1935 if (!once_control
->state
)
1938 once_control
->state
= 1;
1940 /* Here we must remove our cancellation handler */
1941 pthread_mutex_unlock (&once_control
->mutex
);
1946 pthread::cancel (pthread_t thread
)
1948 if (!is_good_object (&thread
))
1951 return thread
->cancel ();
1955 pthread::atforkprepare (void)
1957 callback
*cb
= MT_INTERFACE
->pthread_prepare
;
1966 MT_INTERFACE
->fixup_before_fork ();
1970 pthread::atforkparent (void)
1974 callback
*cb
= MT_INTERFACE
->pthread_parent
;
1983 pthread::atforkchild (void)
1985 MT_INTERFACE
->fixup_after_fork ();
1989 callback
*cb
= MT_INTERFACE
->pthread_child
;
1997 /* Register a set of functions to run before and after fork.
1998 prepare calls are called in LI-FC order.
1999 parent and child calls are called in FI-FC order. */
2001 pthread::atfork (void (*prepare
)(void), void (*parent
)(void), void (*child
)(void))
2003 callback
*prepcb
= NULL
, *parentcb
= NULL
, *childcb
= NULL
;
2006 prepcb
= new callback
;
2012 parentcb
= new callback
;
2022 childcb
= new callback
;
2035 prepcb
->cb
= prepare
;
2036 List_insert (MT_INTERFACE
->pthread_prepare
, prepcb
);
2040 parentcb
->cb
= parent
;
2041 callback
**t
= &MT_INTERFACE
->pthread_parent
;
2044 /* t = pointer to last next in the list */
2045 List_insert (*t
, parentcb
);
2049 childcb
->cb
= child
;
2050 callback
**t
= &MT_INTERFACE
->pthread_child
;
2053 /* t = pointer to last next in the list */
2054 List_insert (*t
, childcb
);
2060 pthread_attr_init (pthread_attr_t
*attr
)
2062 if (pthread_attr::is_good_object (attr
))
2065 *attr
= new pthread_attr
;
2066 if (!pthread_attr::is_good_object (attr
))
2076 pthread_attr_getinheritsched (const pthread_attr_t
*attr
,
2079 if (!pthread_attr::is_good_object (attr
))
2081 *inheritsched
= (*attr
)->inheritsched
;
2086 pthread_attr_getschedparam (const pthread_attr_t
*attr
,
2087 struct sched_param
*param
)
2089 if (!pthread_attr::is_good_object (attr
))
2091 *param
= (*attr
)->schedparam
;
2095 /* From a pure code point of view, this should call a helper in sched.cc,
2096 to allow for someone adding scheduler policy changes to win32 in the future.
2097 However that's extremely unlikely, so short and sweet will do us */
2099 pthread_attr_getschedpolicy (const pthread_attr_t
*attr
, int *policy
)
2101 if (!pthread_attr::is_good_object (attr
))
2103 *policy
= SCHED_FIFO
;
2109 pthread_attr_getscope (const pthread_attr_t
*attr
, int *contentionscope
)
2111 if (!pthread_attr::is_good_object (attr
))
2113 *contentionscope
= (*attr
)->contentionscope
;
2118 pthread_attr_setdetachstate (pthread_attr_t
*attr
, int detachstate
)
2120 if (!pthread_attr::is_good_object (attr
))
2122 if (detachstate
< 0 || detachstate
> 1)
2124 (*attr
)->joinable
= detachstate
;
2129 pthread_attr_getdetachstate (const pthread_attr_t
*attr
, int *detachstate
)
2131 if (!pthread_attr::is_good_object (attr
))
2133 *detachstate
= (*attr
)->joinable
;
2138 pthread_attr_setinheritsched (pthread_attr_t
*attr
, int inheritsched
)
2140 if (!pthread_attr::is_good_object (attr
))
2142 if (inheritsched
!= PTHREAD_INHERIT_SCHED
2143 && inheritsched
!= PTHREAD_EXPLICIT_SCHED
)
2145 (*attr
)->inheritsched
= inheritsched
;
2150 pthread_attr_setschedparam (pthread_attr_t
*attr
,
2151 const struct sched_param
*param
)
2153 if (!pthread_attr::is_good_object (attr
))
2155 if (!valid_sched_parameters (param
))
2157 (*attr
)->schedparam
= *param
;
2161 /* See __pthread_attr_getschedpolicy for some notes */
2163 pthread_attr_setschedpolicy (pthread_attr_t
*attr
, int policy
)
2165 if (!pthread_attr::is_good_object (attr
))
2167 if (policy
!= SCHED_FIFO
)
2173 pthread_attr_setscope (pthread_attr_t
*attr
, int contentionscope
)
2175 if (!pthread_attr::is_good_object (attr
))
2177 if (contentionscope
!= PTHREAD_SCOPE_SYSTEM
2178 && contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2180 /* In future, we may be able to support system scope by escalating the thread
2181 priority to exceed the priority class. For now we only support PROCESS scope. */
2182 if (contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2184 (*attr
)->contentionscope
= contentionscope
;
2189 pthread_attr_setstacksize (pthread_attr_t
*attr
, size_t size
)
2191 if (!pthread_attr::is_good_object (attr
))
2193 (*attr
)->stacksize
= size
;
2198 pthread_attr_getstacksize (const pthread_attr_t
*attr
, size_t *size
)
2200 if (!pthread_attr::is_good_object (attr
))
2202 *size
= (*attr
)->stacksize
;
2207 pthread_attr_destroy (pthread_attr_t
*attr
)
2209 if (!pthread_attr::is_good_object (attr
))
2217 pthread::join (pthread_t
*thread
, void **return_val
)
2219 pthread_t joiner
= self ();
2221 joiner
->testcancel ();
2223 // Initialize return val with NULL
2227 if (!is_good_object (&joiner
))
2230 if (!is_good_object (thread
))
2233 if (equal (*thread
,joiner
))
2236 (*thread
)->mutex
.lock ();
2238 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2240 (*thread
)->mutex
.unlock ();
2245 (*thread
)->joiner
= joiner
;
2246 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2247 (*thread
)->mutex
.unlock ();
2251 switch (cancelable_wait ((*thread
)->win32_obj_id
, INFINITE
, false, true))
2255 *return_val
= (*thread
)->return_ptr
;
2259 _my_tls
.call_signal_handler ();
2263 // set joined thread back to joinable since we got canceled
2264 (*thread
)->joiner
= NULL
;
2265 (*thread
)->attr
.joinable
= PTHREAD_CREATE_JOINABLE
;
2266 joiner
->cancel_self ();
2270 // should never happen
2280 pthread::detach (pthread_t
*thread
)
2282 if (!is_good_object (thread
))
2285 (*thread
)->mutex
.lock ();
2286 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2288 (*thread
)->mutex
.unlock ();
2292 // check if thread is still alive
2293 if ((*thread
)->valid
&& WaitForSingleObject ((*thread
)->win32_obj_id
, 0) == WAIT_TIMEOUT
)
2295 // force cleanup on exit
2296 (*thread
)->joiner
= *thread
;
2297 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2298 (*thread
)->mutex
.unlock ();
2302 // thread has already terminated.
2303 (*thread
)->mutex
.unlock ();
2311 pthread::suspend (pthread_t
*thread
)
2313 if (!is_good_object (thread
))
2316 if ((*thread
)->suspended
== false)
2318 (*thread
)->suspended
= true;
2319 SuspendThread ((*thread
)->win32_obj_id
);
2327 pthread::resume (pthread_t
*thread
)
2329 if (!is_good_object (thread
))
2332 if ((*thread
)->suspended
== true)
2333 ResumeThread ((*thread
)->win32_obj_id
);
2334 (*thread
)->suspended
= false;
2339 /* provided for source level compatability.
2340 See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2343 pthread_getconcurrency (void)
2345 return MT_INTERFACE
->concurrency
;
2348 /* keep this in sync with sched.cc */
2350 pthread_getschedparam (pthread_t thread
, int *policy
,
2351 struct sched_param
*param
)
2353 if (!pthread::is_good_object (&thread
))
2355 *policy
= SCHED_FIFO
;
2356 /* we don't return the current effective priority, we return the current
2357 requested priority */
2358 *param
= thread
->attr
.schedparam
;
2362 /* Thread Specific Data */
2364 pthread_key_create (pthread_key_t
*key
, void (*destructor
) (void *))
2366 /* The opengroup docs don't define if we should check this or not,
2367 but creation is relatively rare. */
2368 if (pthread_key::is_good_object (key
))
2371 *key
= new pthread_key (destructor
);
2373 if (!pthread_key::is_good_object (key
))
2383 pthread_key_delete (pthread_key_t key
)
2385 if (!pthread_key::is_good_object (&key
))
2392 /* provided for source level compatability. See
2393 http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2396 pthread_setconcurrency (int new_level
)
2400 MT_INTERFACE
->concurrency
= new_level
;
2404 /* keep syncronised with sched.cc */
2406 pthread_setschedparam (pthread_t thread
, int policy
,
2407 const struct sched_param
*param
)
2409 if (!pthread::is_good_object (&thread
))
2411 if (policy
!= SCHED_FIFO
)
2416 sched_set_thread_priority (thread
->win32_obj_id
, param
->sched_priority
);
2418 thread
->attr
.schedparam
.sched_priority
= param
->sched_priority
;
2424 pthread_setspecific (pthread_key_t key
, const void *value
)
2426 if (!pthread_key::is_good_object (&key
))
2433 pthread_getspecific (pthread_key_t key
)
2435 if (!pthread_key::is_good_object (&key
))
2438 return (key
)->get ();
2442 /* Thread synchronisation */
2444 pthread_cond::is_good_object (pthread_cond_t
const *cond
)
2446 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
) != VALID_OBJECT
)
2452 pthread_cond::is_good_initializer (pthread_cond_t
const *cond
)
2454 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) != VALID_STATIC_OBJECT
)
2460 pthread_cond::is_good_initializer_or_object (pthread_cond_t
const *cond
)
2462 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) == INVALID_OBJECT
)
2468 pthread_cond::is_good_initializer_or_bad_object (pthread_cond_t
const *cond
)
2470 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) == VALID_OBJECT
)
2476 pthread_cond_destroy (pthread_cond_t
*cond
)
2478 if (pthread_cond::is_good_initializer (cond
))
2480 if (!pthread_cond::is_good_object (cond
))
2483 /* reads are atomic */
2484 if ((*cond
)->waiting
)
2494 pthread_cond::init (pthread_cond_t
*cond
, const pthread_condattr_t
*attr
)
2497 pthread_cond_t new_cond
;
2499 if (attr
&& !pthread_condattr::is_good_object (attr
))
2502 cond_initialization_lock
.lock ();
2504 if (!is_good_initializer_or_bad_object (cond
))
2506 cond_initialization_lock
.unlock ();
2510 new_cond
= new pthread_cond (attr
? (*attr
) : NULL
);
2511 if (!is_good_object (&new_cond
))
2514 cond_initialization_lock
.unlock ();
2519 cond_initialization_lock
.unlock ();
2525 pthread_cond_broadcast (pthread_cond_t
*cond
)
2527 if (pthread_cond::is_good_initializer (cond
))
2529 if (!pthread_cond::is_good_object (cond
))
2532 (*cond
)->unblock (true);
2538 pthread_cond_signal (pthread_cond_t
*cond
)
2540 if (pthread_cond::is_good_initializer (cond
))
2542 if (!pthread_cond::is_good_object (cond
))
2545 (*cond
)->unblock (false);
2551 __pthread_cond_dowait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2554 if (!pthread_mutex::is_good_object (mutex
))
2556 if (!pthread_mutex::can_be_unlocked (mutex
))
2559 if (pthread_cond::is_good_initializer (cond
))
2560 pthread_cond::init (cond
, NULL
);
2561 if (!pthread_cond::is_good_object (cond
))
2564 return (*cond
)->wait (*mutex
, waitlength
);
2568 pthread_cond_timedwait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2569 const struct timespec
*abstime
)
2574 pthread_testcancel ();
2576 if (check_valid_pointer (abstime
))
2579 gettimeofday (&tv
, NULL
);
2580 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
2581 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
2584 return __pthread_cond_dowait (cond
, mutex
, waitlength
);
2588 pthread_cond_wait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
2590 pthread_testcancel ();
2592 return __pthread_cond_dowait (cond
, mutex
, INFINITE
);
2596 pthread_condattr_init (pthread_condattr_t
*condattr
)
2598 if (pthread_condattr::is_good_object (condattr
))
2601 *condattr
= new pthread_condattr
;
2602 if (!pthread_condattr::is_good_object (condattr
))
2612 pthread_condattr_getpshared (const pthread_condattr_t
*attr
, int *pshared
)
2614 if (!pthread_condattr::is_good_object (attr
))
2616 *pshared
= (*attr
)->shared
;
2621 pthread_condattr_setpshared (pthread_condattr_t
*attr
, int pshared
)
2623 if (!pthread_condattr::is_good_object (attr
))
2625 if ((pshared
< 0) || (pshared
> 1))
2627 /* shared cond vars not currently supported */
2628 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2630 (*attr
)->shared
= pshared
;
2635 pthread_condattr_destroy (pthread_condattr_t
*condattr
)
2637 if (!pthread_condattr::is_good_object (condattr
))
2646 pthread_rwlock::is_good_object (pthread_rwlock_t
const *rwlock
)
2648 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
) != VALID_OBJECT
)
2654 pthread_rwlock::is_good_initializer (pthread_rwlock_t
const *rwlock
)
2656 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) != VALID_STATIC_OBJECT
)
2662 pthread_rwlock::is_good_initializer_or_object (pthread_rwlock_t
const *rwlock
)
2664 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) == INVALID_OBJECT
)
2670 pthread_rwlock::is_good_initializer_or_bad_object (pthread_rwlock_t
const *rwlock
)
2672 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) == VALID_OBJECT
)
2678 pthread_rwlock_destroy (pthread_rwlock_t
*rwlock
)
2680 if (pthread_rwlock::is_good_initializer (rwlock
))
2682 if (!pthread_rwlock::is_good_object (rwlock
))
2685 if ((*rwlock
)->writer
|| (*rwlock
)->readers
||
2686 (*rwlock
)->waiting_readers
|| (*rwlock
)->waiting_writers
)
2696 pthread_rwlock::init (pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*attr
)
2698 pthread_rwlock_t new_rwlock
;
2700 if (attr
&& !pthread_rwlockattr::is_good_object (attr
))
2703 rwlock_initialization_lock
.lock ();
2705 if (!is_good_initializer_or_bad_object (rwlock
))
2707 rwlock_initialization_lock
.unlock ();
2711 new_rwlock
= new pthread_rwlock (attr
? (*attr
) : NULL
);
2712 if (!is_good_object (&new_rwlock
))
2715 rwlock_initialization_lock
.unlock ();
2719 *rwlock
= new_rwlock
;
2720 rwlock_initialization_lock
.unlock ();
2726 pthread_rwlock_rdlock (pthread_rwlock_t
*rwlock
)
2728 pthread_testcancel ();
2730 if (pthread_rwlock::is_good_initializer (rwlock
))
2731 pthread_rwlock::init (rwlock
, NULL
);
2732 if (!pthread_rwlock::is_good_object (rwlock
))
2735 return (*rwlock
)->rdlock ();
2739 pthread_rwlock_tryrdlock (pthread_rwlock_t
*rwlock
)
2741 if (pthread_rwlock::is_good_initializer (rwlock
))
2742 pthread_rwlock::init (rwlock
, NULL
);
2743 if (!pthread_rwlock::is_good_object (rwlock
))
2746 return (*rwlock
)->tryrdlock ();
2750 pthread_rwlock_wrlock (pthread_rwlock_t
*rwlock
)
2752 pthread_testcancel ();
2754 if (pthread_rwlock::is_good_initializer (rwlock
))
2755 pthread_rwlock::init (rwlock
, NULL
);
2756 if (!pthread_rwlock::is_good_object (rwlock
))
2759 return (*rwlock
)->wrlock ();
2763 pthread_rwlock_trywrlock (pthread_rwlock_t
*rwlock
)
2765 if (pthread_rwlock::is_good_initializer (rwlock
))
2766 pthread_rwlock::init (rwlock
, NULL
);
2767 if (!pthread_rwlock::is_good_object (rwlock
))
2770 return (*rwlock
)->trywrlock ();
2774 pthread_rwlock_unlock (pthread_rwlock_t
*rwlock
)
2776 if (pthread_rwlock::is_good_initializer (rwlock
))
2778 if (!pthread_rwlock::is_good_object (rwlock
))
2781 return (*rwlock
)->unlock ();
2785 pthread_rwlockattr_init (pthread_rwlockattr_t
*rwlockattr
)
2787 if (pthread_rwlockattr::is_good_object (rwlockattr
))
2790 *rwlockattr
= new pthread_rwlockattr
;
2791 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2793 delete (*rwlockattr
);
2801 pthread_rwlockattr_getpshared (const pthread_rwlockattr_t
*attr
, int *pshared
)
2803 if (!pthread_rwlockattr::is_good_object (attr
))
2805 *pshared
= (*attr
)->shared
;
2810 pthread_rwlockattr_setpshared (pthread_rwlockattr_t
*attr
, int pshared
)
2812 if (!pthread_rwlockattr::is_good_object (attr
))
2814 if ((pshared
< 0) || (pshared
> 1))
2816 /* shared rwlock vars not currently supported */
2817 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2819 (*attr
)->shared
= pshared
;
2824 pthread_rwlockattr_destroy (pthread_rwlockattr_t
*rwlockattr
)
2826 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2828 delete (*rwlockattr
);
2835 pthread_kill (pthread_t thread
, int sig
)
2837 // lock myself, for the use of thread2signal
2838 // two different kills might clash: FIXME
2840 if (!pthread::is_good_object (&thread
))
2845 si
.si_code
= SI_USER
;
2846 si
.si_pid
= si
.si_uid
= si
.si_errno
= 0;
2847 thread
->cygtls
->set_threadkill ();
2848 int rval
= sig
? sig_send (NULL
, si
, thread
->cygtls
) : 0;
2855 pthread_sigmask (int operation
, const sigset_t
*set
, sigset_t
*old_set
)
2857 return handle_sigprocmask (operation
, set
, old_set
, _my_tls
.sigmask
);
2863 pthread_equal (pthread_t t1
, pthread_t t2
)
2865 return pthread::equal (t1
, t2
);
2871 pthread_mutex::init (pthread_mutex_t
*mutex
,
2872 const pthread_mutexattr_t
*attr
,
2873 const pthread_mutex_t initializer
)
2875 pthread_mutex_t new_mutex
;
2877 if (attr
&& !pthread_mutexattr::is_good_object (attr
) || check_valid_pointer (mutex
))
2880 mutex_initialization_lock
.lock ();
2882 if (!is_good_initializer_or_bad_object (mutex
))
2884 mutex_initialization_lock
.unlock ();
2888 new_mutex
= new pthread_mutex (attr
? (*attr
) : NULL
);
2889 if (!is_good_object (&new_mutex
))
2892 mutex_initialization_lock
.unlock ();
2896 if (!attr
&& initializer
)
2898 if (initializer
== PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
)
2899 new_mutex
->type
= PTHREAD_MUTEX_RECURSIVE
;
2900 else if (initializer
== PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
)
2901 new_mutex
->type
= PTHREAD_MUTEX_NORMAL
;
2902 else if (initializer
== PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
)
2903 new_mutex
->type
= PTHREAD_MUTEX_ERRORCHECK
;
2907 mutex_initialization_lock
.unlock ();
2913 pthread_mutex_getprioceiling (const pthread_mutex_t
*mutex
,
2916 /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
2919 We can support mutex priorities in the future though:
2920 Store a priority with each mutex.
2921 When the mutex is optained, set the thread priority as appropriate
2922 When the mutex is released, reset the thread priority. */
2927 pthread_mutex_lock (pthread_mutex_t
*mutex
)
2929 if (pthread_mutex::is_good_initializer (mutex
))
2930 pthread_mutex::init (mutex
, NULL
, *mutex
);
2931 if (!pthread_mutex::is_good_object (mutex
))
2933 return (*mutex
)->lock ();
2937 pthread_mutex_trylock (pthread_mutex_t
*mutex
)
2939 if (pthread_mutex::is_good_initializer (mutex
))
2940 pthread_mutex::init (mutex
, NULL
, *mutex
);
2941 if (!pthread_mutex::is_good_object (mutex
))
2943 return (*mutex
)->trylock ();
2947 pthread_mutex_unlock (pthread_mutex_t
*mutex
)
2949 if (pthread_mutex::is_good_initializer (mutex
))
2951 if (!pthread_mutex::is_good_object (mutex
))
2953 return (*mutex
)->unlock ();
2957 pthread_mutex_destroy (pthread_mutex_t
*mutex
)
2961 if (pthread_mutex::is_good_initializer (mutex
))
2963 if (!pthread_mutex::is_good_object (mutex
))
2966 rv
= (*mutex
)->destroy ();
2975 pthread_mutex_setprioceiling (pthread_mutex_t
*mutex
, int prioceiling
,
2981 /* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
2984 pthread_mutexattr_getprotocol (const pthread_mutexattr_t
*attr
,
2987 if (!pthread_mutexattr::is_good_object (attr
))
2993 pthread_mutexattr_getpshared (const pthread_mutexattr_t
*attr
,
2996 if (!pthread_mutexattr::is_good_object (attr
))
2998 *pshared
= (*attr
)->pshared
;
3003 pthread_mutexattr_gettype (const pthread_mutexattr_t
*attr
, int *type
)
3005 if (!pthread_mutexattr::is_good_object (attr
))
3007 *type
= (*attr
)->mutextype
;
3011 /* FIXME: write and test process shared mutex's. */
3013 pthread_mutexattr_init (pthread_mutexattr_t
*attr
)
3015 if (pthread_mutexattr::is_good_object (attr
))
3018 *attr
= new pthread_mutexattr ();
3019 if (!pthread_mutexattr::is_good_object (attr
))
3029 pthread_mutexattr_destroy (pthread_mutexattr_t
*attr
)
3031 if (!pthread_mutexattr::is_good_object (attr
))
3039 /* Win32 doesn't support mutex priorities */
3041 pthread_mutexattr_setprotocol (pthread_mutexattr_t
*attr
, int protocol
)
3043 if (!pthread_mutexattr::is_good_object (attr
))
3048 /* Win32 doesn't support mutex priorities */
3050 pthread_mutexattr_setprioceiling (pthread_mutexattr_t
*attr
,
3053 if (!pthread_mutexattr::is_good_object (attr
))
3059 pthread_mutexattr_getprioceiling (const pthread_mutexattr_t
*attr
,
3062 if (!pthread_mutexattr::is_good_object (attr
))
3068 pthread_mutexattr_setpshared (pthread_mutexattr_t
*attr
, int pshared
)
3070 if (!pthread_mutexattr::is_good_object (attr
))
3072 /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
3075 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
3077 (*attr
)->pshared
= pshared
;
3081 /* see pthread_mutex_gettype */
3083 pthread_mutexattr_settype (pthread_mutexattr_t
*attr
, int type
)
3085 if (!pthread_mutexattr::is_good_object (attr
))
3090 case PTHREAD_MUTEX_ERRORCHECK
:
3091 case PTHREAD_MUTEX_RECURSIVE
:
3092 case PTHREAD_MUTEX_NORMAL
:
3093 (*attr
)->mutextype
= type
;
3104 /* static members */
3106 semaphore::is_good_object (sem_t
const * sem
)
3108 if (verifyable_object_isvalid (sem
, SEM_MAGIC
) != VALID_OBJECT
)
3114 semaphore::init (sem_t
*sem
, int pshared
, unsigned int value
)
3116 /* opengroup calls this undefined */
3117 if (is_good_object (sem
))
3120 if (value
> SEM_VALUE_MAX
)
3123 *sem
= new semaphore (pshared
, value
);
3125 if (!is_good_object (sem
))
3135 semaphore::destroy (sem_t
*sem
)
3137 if (!is_good_object (sem
))
3140 /* FIXME - new feature - test for busy against threads... */
3148 semaphore::open (const char *name
, int oflag
, mode_t mode
, unsigned int value
)
3150 if (value
> SEM_VALUE_MAX
)
3156 sem_t
*sem
= new sem_t
;
3163 *sem
= new semaphore (name
, oflag
, mode
, value
);
3165 if (!is_good_object (sem
))
3175 semaphore::wait (sem_t
*sem
)
3177 pthread_testcancel ();
3179 if (!is_good_object (sem
))
3185 return (*sem
)->_wait ();
3189 semaphore::trywait (sem_t
*sem
)
3191 if (!is_good_object (sem
))
3197 return (*sem
)->_trywait ();
3201 semaphore::timedwait (sem_t
*sem
, const struct timespec
*abstime
)
3203 if (!is_good_object (sem
))
3209 return (*sem
)->_timedwait (abstime
);
3213 semaphore::post (sem_t
*sem
)
3215 if (!is_good_object (sem
))
3226 semaphore::getvalue (sem_t
*sem
, int *sval
)
3229 if (!is_good_object (sem
)
3230 || __check_null_invalid_struct (sval
, sizeof (int)))
3236 return (*sem
)->_getvalue (sval
);
3241 pthread_null::get_null_pthread ()
3243 /* because of weird entry points */
3244 _instance
.magic
= 0;
3248 pthread_null::pthread_null ()
3250 attr
.joinable
= PTHREAD_CREATE_DETACHED
;
3251 /* Mark ourselves as invalid */
3255 pthread_null::~pthread_null ()
3260 pthread_null::create (void *(*)(void *), pthread_attr
*, void *)
3265 pthread_null::exit (void *value_ptr
)
3271 pthread_null::cancel ()
3277 pthread_null::testcancel ()
3282 pthread_null::setcancelstate (int state
, int *oldstate
)
3288 pthread_null::setcanceltype (int type
, int *oldtype
)
3294 pthread_null::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
3299 pthread_null::pop_cleanup_handler (int const execute
)
3304 pthread_null::getsequence_np ()
3309 pthread_null
pthread_null::_instance
;