1 /* thread.cc: Locking and threading module functions
3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 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 if (MT_INTERFACE
->threadcount
<= 1)
83 paranoid_printf ("threadcount %d. not locking", MT_INTERFACE
->threadcount
);
86 paranoid_printf ("threadcount %d. locking", MT_INTERFACE
->threadcount
);
87 pthread_mutex_lock ((pthread_mutex_t
*) lock
);
92 __cygwin_lock_trylock (_LOCK_T
*lock
)
94 return pthread_mutex_trylock ((pthread_mutex_t
*) lock
);
99 __cygwin_lock_unlock (_LOCK_T
*lock
)
101 if (MT_INTERFACE
->threadcount
<= 1)
102 paranoid_printf ("threadcount %d. not unlocking", MT_INTERFACE
->threadcount
);
105 pthread_mutex_unlock ((pthread_mutex_t
*) lock
);
106 paranoid_printf ("threadcount %d. unlocked", MT_INTERFACE
->threadcount
);
110 inline LPCRITICAL_SECTION
111 ResourceLocks::Lock (int _resid
)
117 SetResourceLock (int _res_id
, int _mode
, const char *_function
)
119 EnterCriticalSection (user_data
->resourcelocks
->Lock (_res_id
));
123 ReleaseResourceLock (int _res_id
, int _mode
, const char *_function
)
125 LeaveCriticalSection (user_data
->resourcelocks
->Lock (_res_id
));
129 ResourceLocks::Init ()
131 InitializeCriticalSection (&lock
);
133 thread_printf ("lock %p inited by %p , %d", &lock
, user_data
, myself
->pid
);
137 ResourceLocks::Delete ()
141 thread_printf ("Close Resource Locks %p ", &lock
);
142 DeleteCriticalSection (&lock
);
150 pthread_mutex::init_mutex ();
151 pthread_cond::init_mutex ();
152 pthread_rwlock::init_mutex ();
156 MTinterface::fixup_before_fork (void)
158 pthread_key::fixup_before_fork ();
161 /* This function is called from a single threaded process */
163 MTinterface::fixup_after_fork (void)
165 pthread_key::fixup_after_fork ();
168 pthread::init_mainthread ();
170 pthread::fixup_after_fork ();
171 pthread_mutex::fixup_after_fork ();
172 pthread_cond::fixup_after_fork ();
173 pthread_rwlock::fixup_after_fork ();
174 semaphore::fixup_after_fork ();
181 pthread::init_mainthread ()
183 pthread
*thread
= get_tls_self_pointer ();
186 thread
= new pthread ();
188 api_fatal ("failed to create mainthread object");
191 set_tls_self_pointer (thread
);
192 thread
->thread_id
= GetCurrentThreadId ();
193 if (!DuplicateHandle (hMainProc
, GetCurrentThread (), hMainProc
,
194 &thread
->win32_obj_id
, 0, FALSE
, DUPLICATE_SAME_ACCESS
))
195 api_fatal ("failed to create mainthread handle");
196 if (!thread
->create_cancel_event ())
197 api_fatal ("couldn't create cancel event for main thread");
198 VerifyHandle (thread
->win32_obj_id
);
199 thread
->postcreate ();
205 pthread
*thread
= get_tls_self_pointer ();
208 thread
= pthread_null::get_null_pthread ();
209 set_tls_self_pointer (thread
);
215 pthread::get_tls_self_pointer ()
221 pthread::set_tls_self_pointer (pthread
*thread
)
223 thread
->cygtls
= &_my_tls
;
224 _my_tls
.tid
= thread
;
227 List
<pthread
> pthread::threads
;
230 pthread::pthread ():verifyable_object (PTHREAD_MAGIC
), win32_obj_id (0),
231 valid (false), suspended (false),
232 cancelstate (0), canceltype (0), cancel_event (0),
233 joiner (NULL
), next (NULL
), cleanup_stack (NULL
)
235 if (this != pthread_null::get_null_pthread ())
236 threads
.insert (this);
242 CloseHandle (win32_obj_id
);
244 CloseHandle (cancel_event
);
246 if (this != pthread_null::get_null_pthread ())
247 threads
.remove (this);
251 pthread::create_cancel_event ()
253 cancel_event
= ::CreateEvent (&sec_none_nih
, TRUE
, FALSE
, NULL
);
256 system_printf ("couldn't create cancel event, %E");
257 /* we need the event for correct behaviour */
264 pthread::precreate (pthread_attr
*newattr
)
266 pthread_mutex
*verifyable_mutex_obj
= &mutex
;
268 /* already running ? */
274 attr
.joinable
= newattr
->joinable
;
275 attr
.contentionscope
= newattr
->contentionscope
;
276 attr
.inheritsched
= newattr
->inheritsched
;
277 attr
.stacksize
= newattr
->stacksize
;
280 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
282 thread_printf ("New thread object access mutex is not valid. this %p",
287 /* Change the mutex type to NORMAL to speed up mutex operations */
288 mutex
.type
= PTHREAD_MUTEX_NORMAL
;
289 if (!create_cancel_event ())
294 pthread::create (void *(*func
) (void *), pthread_attr
*newattr
,
305 win32_obj_id
= ::CreateThread (&sec_none_nih
, attr
.stacksize
,
306 thread_init_wrapper
, this, 0, &thread_id
);
310 thread_printf ("CreateThread failed: this %p, %E", this);
316 if (WaitForSingleObject (cancel_event
, 5000) != WAIT_OBJECT_0
)
317 thread_printf ("event never arrived after CreateThread");
318 ResetEvent (cancel_event
);
324 pthread::postcreate ()
328 InterlockedIncrement (&MT_INTERFACE
->threadcount
);
329 /* FIXME: set the priority appropriately for system contention scope */
330 if (attr
.inheritsched
== PTHREAD_EXPLICIT_SCHED
)
332 /* FIXME: set the scheduling settings for the new thread */
333 /* sched_thread_setparam (win32_obj_id, attr.schedparam); */
338 pthread::exit (void *value_ptr
)
340 class pthread
*thread
= this;
342 // run cleanup handlers
343 pop_all_cleanup_handlers ();
345 pthread_key::run_all_destructors ();
348 // cleanup if thread is in detached state and not joined
349 if (equal (joiner
, thread
))
354 return_ptr
= value_ptr
;
358 if (_my_tls
.local_clib
.__sdidinit
< 0)
359 _my_tls
.local_clib
.__sdidinit
= 0;
360 (_reclaim_reent
) (_REENT
);
363 if (InterlockedDecrement (&MT_INTERFACE
->threadcount
) == 0)
367 _my_tls
.remove (INFINITE
);
373 pthread::cancel (void)
375 class pthread
*thread
= this;
376 class pthread
*self
= pthread::self ();
386 if (canceltype
== PTHREAD_CANCEL_DEFERRED
||
387 cancelstate
== PTHREAD_CANCEL_DISABLE
)
391 SetEvent (cancel_event
);
394 else if (equal (thread
, self
))
398 return 0; // Never reached
401 // cancel asynchronous
402 SuspendThread (win32_obj_id
);
403 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
406 context
.ContextFlags
= CONTEXT_CONTROL
;
407 GetThreadContext (win32_obj_id
, &context
);
408 context
.Eip
= (DWORD
) pthread::static_cancel_self
;
409 SetThreadContext (win32_obj_id
, &context
);
412 ResumeThread (win32_obj_id
);
416 TODO: insert pthread_testcancel into the required functions
417 the required function list is: *indicates done, X indicates not present in cygwin.
436 *pthread_cond_timedwait ()
437 *pthread_cond_wait ()
439 *pthread_testcancel ()
463 the optional list is:
583 Note, that for fcntl (), for any value of the cmd argument.
585 And we must not introduce cancellation points anywhere else that's part of the posix or
591 pthread::testcancel (void)
593 if (cancelstate
== PTHREAD_CANCEL_DISABLE
)
596 if (WaitForSingleObject (cancel_event
, 0) == WAIT_OBJECT_0
)
601 pthread::static_cancel_self (void)
603 pthread::self ()->cancel_self ();
607 cancelable_wait (HANDLE object
, DWORD timeout
, const bool do_cancel
,
608 const enum cw_sig_wait sig_wait
)
612 HANDLE wait_objects
[3];
613 pthread_t thread
= pthread::self ();
615 /* Do not change the wait order.
616 The object must have higher priority than the cancel event,
617 because WaitForMultipleObjects will return the smallest index
618 if both objects are signaled. */
619 wait_objects
[num
++] = object
;
621 if (!pthread::is_good_object (&thread
) ||
622 thread
->cancelstate
== PTHREAD_CANCEL_DISABLE
)
623 cancel_n
= (DWORD
) -1;
627 wait_objects
[cancel_n
] = thread
->cancel_event
;
631 if (sig_wait
== cw_sig_nosig
|| &_my_tls
!= _main_tls
)
636 wait_objects
[sig_n
] = signal_arrived
;
641 res
= WaitForMultipleObjects (num
, wait_objects
, FALSE
, timeout
);
642 res
-= WAIT_OBJECT_0
;
646 pthread::static_cancel_self ();
649 else if (res
!= sig_n
)
651 else if (sig_wait
== cw_sig_eintr
)
655 _my_tls
.call_signal_handler ();
664 pthread::setcancelstate (int state
, int *oldstate
)
670 if (state
!= PTHREAD_CANCEL_ENABLE
&& state
!= PTHREAD_CANCEL_DISABLE
)
675 *oldstate
= cancelstate
;
685 pthread::setcanceltype (int type
, int *oldtype
)
691 if (type
!= PTHREAD_CANCEL_DEFERRED
&& type
!= PTHREAD_CANCEL_ASYNCHRONOUS
)
696 *oldtype
= canceltype
;
706 pthread::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
710 api_fatal ("Attempt to push a cleanup handler across threads");
711 handler
->next
= cleanup_stack
;
712 cleanup_stack
= handler
;
716 pthread::pop_cleanup_handler (int const execute
)
719 // TODO: send a signal or something to the thread ?
720 api_fatal ("Attempt to execute a cleanup handler across threads");
724 if (cleanup_stack
!= NULL
)
726 __pthread_cleanup_handler
*handler
= cleanup_stack
;
729 (*handler
->function
) (handler
->arg
);
730 cleanup_stack
= handler
->next
;
737 pthread::pop_all_cleanup_handlers ()
739 while (cleanup_stack
!= NULL
)
740 pop_cleanup_handler (1);
744 pthread::cancel_self ()
746 exit (PTHREAD_CANCELED
);
750 pthread::get_thread_id ()
756 pthread::_fixup_after_fork ()
758 /* set thread to not running if it is not the forking thread */
759 if (this != pthread::self ())
769 pthread::suspend_except_self ()
771 if (valid
&& this != pthread::self ())
772 SuspendThread (win32_obj_id
);
779 ResumeThread (win32_obj_id
);
784 pthread_attr::is_good_object (pthread_attr_t
const *attr
)
786 if (verifyable_object_isvalid (attr
, PTHREAD_ATTR_MAGIC
) != VALID_OBJECT
)
791 /* instance members */
793 pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC
),
794 joinable (PTHREAD_CREATE_JOINABLE
), contentionscope (PTHREAD_SCOPE_PROCESS
),
795 inheritsched (PTHREAD_INHERIT_SCHED
), stacksize (0)
797 schedparam
.sched_priority
= 0;
800 pthread_attr::~pthread_attr ()
805 pthread_condattr::is_good_object (pthread_condattr_t
const *attr
)
807 if (verifyable_object_isvalid (attr
, PTHREAD_CONDATTR_MAGIC
) != VALID_OBJECT
)
812 pthread_condattr::pthread_condattr ():verifyable_object
813 (PTHREAD_CONDATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
817 pthread_condattr::~pthread_condattr ()
821 List
<pthread_cond
> pthread_cond::conds
;
823 /* This is used for cond creation protection within a single process only */
824 fast_mutex NO_COPY
pthread_cond::cond_initialization_lock
;
826 /* We can only be called once.
827 TODO: (no rush) use a non copied memory section to
828 hold an initialization flag. */
830 pthread_cond::init_mutex ()
832 if (!cond_initialization_lock
.init ())
833 api_fatal ("Could not create win32 Mutex for pthread cond static initializer support.");
836 pthread_cond::pthread_cond (pthread_condattr
*attr
) :
837 verifyable_object (PTHREAD_COND_MAGIC
),
838 shared (0), waiting (0), pending (0), sem_wait (NULL
),
839 mtx_cond(NULL
), next (NULL
)
841 pthread_mutex
*verifyable_mutex_obj
;
844 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
850 verifyable_mutex_obj
= &mtx_in
;
851 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
853 thread_printf ("Internal cond mutex is not valid. this %p", this);
858 * Change the mutex type to NORMAL.
859 * This mutex MUST be of type normal
861 mtx_in
.type
= PTHREAD_MUTEX_NORMAL
;
863 verifyable_mutex_obj
= &mtx_out
;
864 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
866 thread_printf ("Internal cond mutex is not valid. this %p", this);
870 /* Change the mutex type to NORMAL to speed up mutex operations */
871 mtx_out
.type
= PTHREAD_MUTEX_NORMAL
;
873 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
876 debug_printf ("CreateSemaphore failed. %E");
884 pthread_cond::~pthread_cond ()
887 CloseHandle (sem_wait
);
893 pthread_cond::unblock (const bool all
)
895 unsigned long releaseable
;
898 * Block outgoing threads (and avoid simultanous unblocks)
902 releaseable
= waiting
- pending
;
905 unsigned long released
;
910 * Block incoming threads until all waiting threads are released.
915 * Calculate releaseable again because threads can enter until
916 * the semaphore has been taken, but they can not leave, therefore pending
917 * is unchanged and releaseable can only get higher
919 releaseable
= waiting
- pending
;
922 released
= all
? releaseable
: 1;
927 ::ReleaseSemaphore (sem_wait
, released
, NULL
);
931 * And let the threads release.
937 pthread_cond::wait (pthread_mutex_t mutex
, DWORD dwMilliseconds
)
942 if (InterlockedIncrement ((long *)&waiting
) == 1)
944 else if (mtx_cond
!= mutex
)
946 InterlockedDecrement ((long *)&waiting
);
953 * Release the mutex and wait on semaphore
958 rv
= cancelable_wait (sem_wait
, dwMilliseconds
, false, cw_sig_eintr
);
962 if (rv
!= WAIT_OBJECT_0
)
965 * It might happen that a signal is sent while the thread got canceled
966 * or timed out. Try to take one.
967 * If the thread gets one than a signal|broadcast is in progress.
969 if (WaitForSingleObject (sem_wait
, 0) == WAIT_OBJECT_0
)
971 * thread got cancelled ot timed out while a signalling is in progress.
972 * Set wait result back to signaled
977 InterlockedDecrement ((long *)&waiting
);
979 if (rv
== WAIT_OBJECT_0
&& --pending
== 0)
981 * All signaled threads are released,
982 * new threads can enter Wait
991 if (rv
== WAIT_CANCELED
)
992 pthread::static_cancel_self ();
993 else if (rv
== WAIT_SIGNALED
)
994 /* SUSv3 states: If a signal is delivered to a thread waiting for a
995 condition variable, upon return from the signal handler the thread
996 resumes waiting for the condition variable as if it was not
997 interrupted, or it shall return zero due to spurious wakeup.
998 We opt for the latter choice here. */
1000 else if (rv
== WAIT_TIMEOUT
)
1007 pthread_cond::_fixup_after_fork ()
1009 waiting
= pending
= 0;
1012 /* Unlock eventually locked mutexes */
1016 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1018 api_fatal ("pthread_cond::_fixup_after_fork () failed to recreate win32 semaphore");
1022 pthread_rwlockattr::is_good_object (pthread_rwlockattr_t
const *attr
)
1024 if (verifyable_object_isvalid (attr
, PTHREAD_RWLOCKATTR_MAGIC
) != VALID_OBJECT
)
1029 pthread_rwlockattr::pthread_rwlockattr ():verifyable_object
1030 (PTHREAD_RWLOCKATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
1034 pthread_rwlockattr::~pthread_rwlockattr ()
1038 List
<pthread_rwlock
> pthread_rwlock::rwlocks
;
1040 /* This is used for rwlock creation protection within a single process only */
1041 fast_mutex NO_COPY
pthread_rwlock::rwlock_initialization_lock
;
1043 /* We can only be called once.
1044 TODO: (no rush) use a non copied memory section to
1045 hold an initialization flag. */
1047 pthread_rwlock::init_mutex ()
1049 if (!rwlock_initialization_lock
.init ())
1050 api_fatal ("Could not create win32 Mutex for pthread rwlock static initializer support.");
1053 pthread_rwlock::pthread_rwlock (pthread_rwlockattr
*attr
) :
1054 verifyable_object (PTHREAD_RWLOCK_MAGIC
),
1055 shared (0), waiting_readers (0), waiting_writers (0), writer (NULL
),
1056 readers (NULL
), readers_mx (), mtx (NULL
), cond_readers (NULL
), cond_writers (NULL
),
1059 pthread_mutex
*verifyable_mutex_obj
= &mtx
;
1060 pthread_cond
*verifyable_cond_obj
;
1062 if (!readers_mx
.init ())
1064 thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this);
1070 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
1076 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1078 thread_printf ("Internal rwlock mutex is not valid. this %p", this);
1082 /* Change the mutex type to NORMAL to speed up mutex operations */
1083 mtx
.type
= PTHREAD_MUTEX_NORMAL
;
1085 verifyable_cond_obj
= &cond_readers
;
1086 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1088 thread_printf ("Internal rwlock readers cond is not valid. this %p", this);
1093 verifyable_cond_obj
= &cond_writers
;
1094 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1096 thread_printf ("Internal rwlock writers cond is not valid. this %p", this);
1102 rwlocks
.insert (this);
1105 pthread_rwlock::~pthread_rwlock ()
1107 rwlocks
.remove (this);
1111 pthread_rwlock::rdlock ()
1114 struct RWLOCK_READER
*reader
;
1115 pthread_t self
= pthread::self ();
1119 if (lookup_reader (self
))
1125 reader
= new struct RWLOCK_READER
;
1132 while (writer
|| waiting_writers
)
1134 pthread_cleanup_push (pthread_rwlock::rdlock_cleanup
, this);
1137 cond_readers
.wait (&mtx
);
1140 pthread_cleanup_pop (0);
1143 reader
->thread
= self
;
1144 add_reader (reader
);
1153 pthread_rwlock::tryrdlock ()
1156 pthread_t self
= pthread::self ();
1160 if (writer
|| waiting_writers
|| lookup_reader (self
))
1164 struct RWLOCK_READER
*reader
= new struct RWLOCK_READER
;
1167 reader
->thread
= self
;
1168 add_reader (reader
);
1180 pthread_rwlock::wrlock ()
1183 pthread_t self
= pthread::self ();
1187 if (writer
== self
|| lookup_reader (self
))
1193 while (writer
|| readers
)
1195 pthread_cleanup_push (pthread_rwlock::wrlock_cleanup
, this);
1198 cond_writers
.wait (&mtx
);
1201 pthread_cleanup_pop (0);
1213 pthread_rwlock::trywrlock ()
1216 pthread_t self
= pthread::self ();
1220 if (writer
|| readers
)
1231 pthread_rwlock::unlock ()
1234 pthread_t self
= pthread::self ();
1250 struct RWLOCK_READER
*reader
= lookup_reader (self
);
1258 remove_reader (reader
);
1271 pthread_rwlock::add_reader (struct RWLOCK_READER
*rd
)
1273 List_insert (readers
, rd
);
1277 pthread_rwlock::remove_reader (struct RWLOCK_READER
*rd
)
1279 List_remove (readers_mx
, readers
, rd
);
1282 struct pthread_rwlock::RWLOCK_READER
*
1283 pthread_rwlock::lookup_reader (pthread_t thread
)
1287 struct RWLOCK_READER
*cur
= readers
;
1289 while (cur
&& cur
->thread
!= thread
)
1292 readers_mx
.unlock ();
1298 pthread_rwlock::rdlock_cleanup (void *arg
)
1300 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1302 --(rwlock
->waiting_readers
);
1304 rwlock
->mtx
.unlock ();
1308 pthread_rwlock::wrlock_cleanup (void *arg
)
1310 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1312 --(rwlock
->waiting_writers
);
1314 rwlock
->mtx
.unlock ();
1318 pthread_rwlock::_fixup_after_fork ()
1320 pthread_t self
= pthread::self ();
1321 struct RWLOCK_READER
**temp
= &readers
;
1323 waiting_readers
= 0;
1324 waiting_writers
= 0;
1326 if (!readers_mx
.init ())
1327 api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex");
1329 /* Unlock eventually locked mutex */
1332 * Remove all readers except self
1336 if ((*temp
)->thread
== self
)
1337 temp
= &((*temp
)->next
);
1340 struct RWLOCK_READER
*cur
= *temp
;
1341 *temp
= (*temp
)->next
;
1348 /* static members */
1349 /* This stores pthread_key information across fork() boundaries */
1350 List
<pthread_key
> pthread_key::keys
;
1353 pthread_key::is_good_object (pthread_key_t
const *key
)
1355 if (verifyable_object_isvalid (key
, PTHREAD_KEY_MAGIC
) != VALID_OBJECT
)
1360 /* non-static members */
1362 pthread_key::pthread_key (void (*aDestructor
) (void *)):verifyable_object (PTHREAD_KEY_MAGIC
), destructor (aDestructor
)
1364 tls_index
= TlsAlloc ();
1365 if (tls_index
== TLS_OUT_OF_INDEXES
)
1371 pthread_key::~pthread_key ()
1373 /* We may need to make the list code lock the list during operations
1378 TlsFree (tls_index
);
1383 pthread_key::_fixup_before_fork ()
1389 pthread_key::_fixup_after_fork ()
1391 tls_index
= TlsAlloc ();
1392 if (tls_index
== TLS_OUT_OF_INDEXES
)
1393 api_fatal ("pthread_key::recreate_key_from_buffer () failed to reallocate Tls storage");
1398 pthread_key::run_destructor ()
1402 void *oldValue
= get ();
1406 destructor (oldValue
);
1413 REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
1414 gymnastics can be a lot easier.
1416 the mutex_t (size 4) is not used as a verifyable object because we cannot
1417 guarantee the same address space for all processes.
1418 we use the following:
1419 high bit set (never a valid address).
1420 second byte is reserved for the priority.
1421 third byte is reserved
1422 fourth byte is the mutex id. (max 255 cygwin mutexs system wide).
1423 creating mutex's does get slower and slower, but as creation is a one time
1424 job, it should never become an issue
1426 And if you're looking at this and thinking, why not an array in cygwin for all mutexs,
1427 - you incur a penalty on _every_ mutex call and you have toserialise them all.
1430 option 2? put everything in userspace and update the ABI?
1431 - bad karma as well - the HANDLE, while identical across process's,
1432 Isn't duplicated, it's reopened. */
1434 /* static members */
1436 pthread_mutex::is_good_object (pthread_mutex_t
const *mutex
)
1438 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
) != VALID_OBJECT
)
1444 pthread_mutex::is_good_initializer (pthread_mutex_t
const *mutex
)
1446 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
1447 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
1448 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
1449 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) != VALID_STATIC_OBJECT
)
1455 pthread_mutex::is_good_initializer_or_object (pthread_mutex_t
const *mutex
)
1457 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
1458 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
1459 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
1460 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) == INVALID_OBJECT
)
1466 pthread_mutex::is_good_initializer_or_bad_object (pthread_mutex_t
const *mutex
)
1468 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
1469 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
1470 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
1471 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) == VALID_OBJECT
)
1477 pthread_mutex::can_be_unlocked (pthread_mutex_t
const *mutex
)
1479 pthread_t self
= pthread::self ();
1481 if (!is_good_object (mutex
))
1484 * Check if the mutex is owned by the current thread and can be unlocked
1486 return ((*mutex
)->recursion_counter
== 1 && pthread::equal ((*mutex
)->owner
, self
));
1489 List
<pthread_mutex
> pthread_mutex::mutexes
;
1491 /* This is used for mutex creation protection within a single process only */
1492 fast_mutex NO_COPY
pthread_mutex::mutex_initialization_lock
;
1494 /* We can only be called once.
1495 TODO: (no rush) use a non copied memory section to
1496 hold an initialization flag. */
1498 pthread_mutex::init_mutex ()
1500 if (!mutex_initialization_lock
.init ())
1501 api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support.");
1504 pthread_mutex::pthread_mutex (pthread_mutexattr
*attr
) :
1505 verifyable_object (PTHREAD_MUTEX_MAGIC
),
1507 win32_obj_id (NULL
), recursion_counter (0),
1508 condwaits (0), owner (NULL
), type (PTHREAD_MUTEX_DEFAULT
),
1509 pshared (PTHREAD_PROCESS_PRIVATE
)
1511 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1517 /*attr checked in the C call */
1520 if (attr
->pshared
== PTHREAD_PROCESS_SHARED
)
1527 type
= attr
->mutextype
;
1530 mutexes
.insert (this);
1533 pthread_mutex::~pthread_mutex ()
1536 CloseHandle (win32_obj_id
);
1538 mutexes
.remove (this);
1542 pthread_mutex::_lock (pthread_t self
)
1546 if (InterlockedIncrement ((long *)&lock_counter
) == 1)
1548 else if (type
!= PTHREAD_MUTEX_NORMAL
&& pthread::equal (owner
, self
))
1550 InterlockedDecrement ((long *) &lock_counter
);
1551 if (type
== PTHREAD_MUTEX_RECURSIVE
)
1552 result
= lock_recursive ();
1558 WaitForSingleObject (win32_obj_id
, INFINITE
);
1566 pthread_mutex::_trylock (pthread_t self
)
1570 if (InterlockedCompareExchange ((long *) &lock_counter
, 1, 0) == 0)
1572 else if (type
== PTHREAD_MUTEX_RECURSIVE
&& pthread::equal (owner
, self
))
1573 result
= lock_recursive ();
1581 pthread_mutex::_unlock (pthread_t self
)
1583 if (!pthread::equal (owner
, self
))
1586 if (--recursion_counter
== 0)
1589 if (InterlockedDecrement ((long *)&lock_counter
))
1590 // Another thread is waiting
1591 ::ReleaseSemaphore (win32_obj_id
, 1, NULL
);
1598 pthread_mutex::_destroy (pthread_t self
)
1600 if (condwaits
|| _trylock (self
))
1601 // Do not destroy a condwaited or locked mutex
1603 else if (recursion_counter
!= 1)
1605 // Do not destroy a recursive locked mutex
1606 --recursion_counter
;
1615 pthread_mutex::_fixup_after_fork ()
1617 debug_printf ("mutex %x in _fixup_after_fork", this);
1618 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1619 api_fatal ("pthread_mutex::_fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's");
1622 /* mutex has no owner, reset to initial */
1624 else if (lock_counter
!= 0)
1625 /* All waiting threads are gone after a fork */
1628 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1630 api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 semaphore for mutex");
1636 pthread_mutexattr::is_good_object (pthread_mutexattr_t
const * attr
)
1638 if (verifyable_object_isvalid (attr
, PTHREAD_MUTEXATTR_MAGIC
) != VALID_OBJECT
)
1643 pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC
),
1644 pshared (PTHREAD_PROCESS_PRIVATE
), mutextype (PTHREAD_MUTEX_DEFAULT
)
1648 pthread_mutexattr::~pthread_mutexattr ()
1652 List
<semaphore
> semaphore::semaphores
;
1654 semaphore::semaphore (int pshared
, unsigned int value
)
1655 : verifyable_object (SEM_MAGIC
),
1657 currentvalue (value
),
1660 SECURITY_ATTRIBUTES sa
= (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1661 ? sec_all
: sec_none_nih
;
1662 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, NULL
);
1663 if (!this->win32_obj_id
)
1666 semaphores
.insert (this);
1669 semaphore::semaphore (const char *sem_name
, int oflag
, mode_t mode
,
1671 : verifyable_object (SEM_MAGIC
),
1672 shared (PTHREAD_PROCESS_SHARED
),
1673 currentvalue (value
), /* Unused for named semaphores. */
1676 if (oflag
& O_CREAT
)
1678 SECURITY_ATTRIBUTES sa
= sec_all
;
1679 security_descriptor sd
;
1681 set_security_attribute (mode
, &sa
, sd
);
1682 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, sem_name
);
1683 if (!this->win32_obj_id
)
1685 if (GetLastError () == ERROR_ALREADY_EXISTS
&& (oflag
& O_EXCL
))
1688 CloseHandle (this->win32_obj_id
);
1694 this->win32_obj_id
= ::OpenSemaphore (SEMAPHORE_ALL_ACCESS
, FALSE
,
1696 if (!this->win32_obj_id
)
1704 name
= new char [strlen (sem_name
+ 1)];
1708 CloseHandle (this->win32_obj_id
);
1712 strcpy (name
, sem_name
);
1715 semaphores
.insert (this);
1718 semaphore::~semaphore ()
1721 CloseHandle (win32_obj_id
);
1725 semaphores
.remove (this);
1731 if (ReleaseSemaphore (win32_obj_id
, 1, ¤tvalue
))
1736 semaphore::_getvalue (int *sval
)
1740 switch (WaitForSingleObject (win32_obj_id
, 0))
1743 ReleaseSemaphore (win32_obj_id
, 1, &val
);
1757 semaphore::_trywait ()
1759 /* FIXME: signals should be able to interrupt semaphores...
1760 *We probably need WaitForMultipleObjects here.
1762 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
1772 semaphore::_timedwait (const struct timespec
*abstime
)
1777 if (__check_invalid_read_ptr (abstime
, sizeof *abstime
))
1779 /* According to SUSv3, abstime need not be checked for validity,
1780 if the semaphore can be locked immediately. */
1787 gettimeofday (&tv
, NULL
);
1788 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
1789 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
1792 switch (cancelable_wait (win32_obj_id
, waitlength
, true, cw_sig_eintr
))
1801 set_errno (ETIMEDOUT
);
1804 debug_printf ("cancelable_wait failed. %E");
1814 switch (cancelable_wait (win32_obj_id
, INFINITE
, true, cw_sig_eintr
))
1823 debug_printf ("cancelable_wait failed. %E");
1830 semaphore::_fixup_after_fork ()
1832 if (shared
== PTHREAD_PROCESS_PRIVATE
)
1834 debug_printf ("sem %x in _fixup_after_fork", this);
1835 /* FIXME: duplicate code here and in the constructor. */
1836 this->win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, currentvalue
,
1839 api_fatal ("failed to create new win32 semaphore, error %d");
1843 verifyable_object::verifyable_object (long verifyer
):
1848 verifyable_object::~verifyable_object ()
1853 /* Generic memory acccess routine - where should it live ? */
1855 check_valid_pointer (void const *pointer
)
1857 if (!pointer
|| IsBadWritePtr ((void *) pointer
, sizeof (verifyable_object
)))
1862 verifyable_object_state
1863 verifyable_object_isvalid (void const * objectptr
, long magic
, void *static_ptr1
,
1864 void *static_ptr2
, void *static_ptr3
)
1866 verifyable_object
**object
= (verifyable_object
**)objectptr
;
1867 if (check_valid_pointer (object
))
1868 return INVALID_OBJECT
;
1869 if ((static_ptr1
&& *object
== static_ptr1
) ||
1870 (static_ptr2
&& *object
== static_ptr2
) ||
1871 (static_ptr3
&& *object
== static_ptr3
))
1872 return VALID_STATIC_OBJECT
;
1874 return INVALID_OBJECT
;
1875 if (check_valid_pointer (*object
))
1876 return INVALID_OBJECT
;
1877 if ((*object
)->magic
!= magic
)
1878 return INVALID_OBJECT
;
1879 return VALID_OBJECT
;
1883 pthread::thread_init_wrapper (void *arg
)
1885 pthread
*thread
= (pthread
*) arg
;
1886 set_tls_self_pointer (thread
);
1887 SetEvent (thread
->cancel_event
);
1889 thread
->mutex
.lock ();
1891 // if thread is detached force cleanup on exit
1892 if (thread
->attr
.joinable
== PTHREAD_CREATE_DETACHED
&& thread
->joiner
== NULL
)
1893 thread
->joiner
= thread
;
1894 thread
->mutex
.unlock ();
1896 thread_printf ("started thread %p %p %p %p %p %p", arg
, &_my_tls
.local_clib
,
1897 _impure_ptr
, thread
, thread
->function
, thread
->arg
);
1899 // call the user's thread
1900 void *ret
= thread
->function (thread
->arg
);
1904 return 0; // just for show. Never returns.
1908 pthread::is_good_object (pthread_t
const *thread
)
1910 if (verifyable_object_isvalid (thread
, PTHREAD_MAGIC
) != VALID_OBJECT
)
1916 pthread::getsequence_np ()
1918 return get_thread_id ();
1922 pthread::create (pthread_t
*thread
, const pthread_attr_t
*attr
,
1923 void *(*start_routine
) (void *), void *arg
)
1925 if (attr
&& !pthread_attr::is_good_object (attr
))
1928 *thread
= new pthread ();
1929 (*thread
)->create (start_routine
, attr
? *attr
: NULL
, arg
);
1930 if (!is_good_object (thread
))
1941 pthread::once (pthread_once_t
*once_control
, void (*init_routine
) (void))
1944 if (once_control
->state
)
1947 pthread_mutex_lock (&once_control
->mutex
);
1948 /* Here we must set a cancellation handler to unlock the mutex if needed */
1949 /* but a cancellation handler is not the right thing. We need this in the thread
1950 *cleanup routine. Assumption: a thread can only be in one pthread_once routine
1951 *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
1952 *on pthread_exit ();
1954 if (!once_control
->state
)
1957 once_control
->state
= 1;
1959 /* Here we must remove our cancellation handler */
1960 pthread_mutex_unlock (&once_control
->mutex
);
1965 pthread::cancel (pthread_t thread
)
1967 if (!is_good_object (&thread
))
1970 return thread
->cancel ();
1974 pthread::atforkprepare (void)
1976 callback
*cb
= MT_INTERFACE
->pthread_prepare
;
1985 MT_INTERFACE
->fixup_before_fork ();
1989 pthread::atforkparent (void)
1993 callback
*cb
= MT_INTERFACE
->pthread_parent
;
2002 pthread::atforkchild (void)
2004 MT_INTERFACE
->fixup_after_fork ();
2008 callback
*cb
= MT_INTERFACE
->pthread_child
;
2016 /* Register a set of functions to run before and after fork.
2017 prepare calls are called in LI-FC order.
2018 parent and child calls are called in FI-FC order. */
2020 pthread::atfork (void (*prepare
)(void), void (*parent
)(void), void (*child
)(void))
2022 callback
*prepcb
= NULL
, *parentcb
= NULL
, *childcb
= NULL
;
2025 prepcb
= new callback
;
2031 parentcb
= new callback
;
2041 childcb
= new callback
;
2054 prepcb
->cb
= prepare
;
2055 List_insert (MT_INTERFACE
->pthread_prepare
, prepcb
);
2059 parentcb
->cb
= parent
;
2060 callback
**t
= &MT_INTERFACE
->pthread_parent
;
2063 /* t = pointer to last next in the list */
2064 List_insert (*t
, parentcb
);
2068 childcb
->cb
= child
;
2069 callback
**t
= &MT_INTERFACE
->pthread_child
;
2072 /* t = pointer to last next in the list */
2073 List_insert (*t
, childcb
);
2079 pthread_attr_init (pthread_attr_t
*attr
)
2081 if (pthread_attr::is_good_object (attr
))
2084 *attr
= new pthread_attr
;
2085 if (!pthread_attr::is_good_object (attr
))
2095 pthread_attr_getinheritsched (const pthread_attr_t
*attr
,
2098 if (!pthread_attr::is_good_object (attr
))
2100 *inheritsched
= (*attr
)->inheritsched
;
2105 pthread_attr_getschedparam (const pthread_attr_t
*attr
,
2106 struct sched_param
*param
)
2108 if (!pthread_attr::is_good_object (attr
))
2110 *param
= (*attr
)->schedparam
;
2114 /* From a pure code point of view, this should call a helper in sched.cc,
2115 to allow for someone adding scheduler policy changes to win32 in the future.
2116 However that's extremely unlikely, so short and sweet will do us */
2118 pthread_attr_getschedpolicy (const pthread_attr_t
*attr
, int *policy
)
2120 if (!pthread_attr::is_good_object (attr
))
2122 *policy
= SCHED_FIFO
;
2128 pthread_attr_getscope (const pthread_attr_t
*attr
, int *contentionscope
)
2130 if (!pthread_attr::is_good_object (attr
))
2132 *contentionscope
= (*attr
)->contentionscope
;
2137 pthread_attr_setdetachstate (pthread_attr_t
*attr
, int detachstate
)
2139 if (!pthread_attr::is_good_object (attr
))
2141 if (detachstate
< 0 || detachstate
> 1)
2143 (*attr
)->joinable
= detachstate
;
2148 pthread_attr_getdetachstate (const pthread_attr_t
*attr
, int *detachstate
)
2150 if (!pthread_attr::is_good_object (attr
))
2152 *detachstate
= (*attr
)->joinable
;
2157 pthread_attr_setinheritsched (pthread_attr_t
*attr
, int inheritsched
)
2159 if (!pthread_attr::is_good_object (attr
))
2161 if (inheritsched
!= PTHREAD_INHERIT_SCHED
2162 && inheritsched
!= PTHREAD_EXPLICIT_SCHED
)
2164 (*attr
)->inheritsched
= inheritsched
;
2169 pthread_attr_setschedparam (pthread_attr_t
*attr
,
2170 const struct sched_param
*param
)
2172 if (!pthread_attr::is_good_object (attr
))
2174 if (!valid_sched_parameters (param
))
2176 (*attr
)->schedparam
= *param
;
2180 /* See __pthread_attr_getschedpolicy for some notes */
2182 pthread_attr_setschedpolicy (pthread_attr_t
*attr
, int policy
)
2184 if (!pthread_attr::is_good_object (attr
))
2186 if (policy
!= SCHED_FIFO
)
2192 pthread_attr_setscope (pthread_attr_t
*attr
, int contentionscope
)
2194 if (!pthread_attr::is_good_object (attr
))
2196 if (contentionscope
!= PTHREAD_SCOPE_SYSTEM
2197 && contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2199 /* In future, we may be able to support system scope by escalating the thread
2200 priority to exceed the priority class. For now we only support PROCESS scope. */
2201 if (contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2203 (*attr
)->contentionscope
= contentionscope
;
2208 pthread_attr_setstacksize (pthread_attr_t
*attr
, size_t size
)
2210 if (!pthread_attr::is_good_object (attr
))
2212 (*attr
)->stacksize
= size
;
2217 pthread_attr_getstacksize (const pthread_attr_t
*attr
, size_t *size
)
2219 if (!pthread_attr::is_good_object (attr
))
2221 *size
= (*attr
)->stacksize
;
2226 pthread_attr_destroy (pthread_attr_t
*attr
)
2228 if (!pthread_attr::is_good_object (attr
))
2236 pthread::join (pthread_t
*thread
, void **return_val
)
2238 pthread_t joiner
= self ();
2240 joiner
->testcancel ();
2242 // Initialize return val with NULL
2246 if (!is_good_object (&joiner
))
2249 if (!is_good_object (thread
))
2252 if (equal (*thread
,joiner
))
2255 (*thread
)->mutex
.lock ();
2257 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2259 (*thread
)->mutex
.unlock ();
2264 (*thread
)->joiner
= joiner
;
2265 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2266 (*thread
)->mutex
.unlock ();
2268 switch (cancelable_wait ((*thread
)->win32_obj_id
, INFINITE
, false, cw_sig_resume
))
2272 *return_val
= (*thread
)->return_ptr
;
2276 // set joined thread back to joinable since we got canceled
2277 (*thread
)->joiner
= NULL
;
2278 (*thread
)->attr
.joinable
= PTHREAD_CREATE_JOINABLE
;
2279 joiner
->cancel_self ();
2283 // should never happen
2292 pthread::detach (pthread_t
*thread
)
2294 if (!is_good_object (thread
))
2297 (*thread
)->mutex
.lock ();
2298 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2300 (*thread
)->mutex
.unlock ();
2304 // check if thread is still alive
2305 if ((*thread
)->valid
&& WaitForSingleObject ((*thread
)->win32_obj_id
, 0) == WAIT_TIMEOUT
)
2307 // force cleanup on exit
2308 (*thread
)->joiner
= *thread
;
2309 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2310 (*thread
)->mutex
.unlock ();
2314 // thread has already terminated.
2315 (*thread
)->mutex
.unlock ();
2323 pthread::suspend (pthread_t
*thread
)
2325 if (!is_good_object (thread
))
2328 if ((*thread
)->suspended
== false)
2330 (*thread
)->suspended
= true;
2331 SuspendThread ((*thread
)->win32_obj_id
);
2339 pthread::resume (pthread_t
*thread
)
2341 if (!is_good_object (thread
))
2344 if ((*thread
)->suspended
== true)
2345 ResumeThread ((*thread
)->win32_obj_id
);
2346 (*thread
)->suspended
= false;
2351 /* provided for source level compatability.
2352 See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2355 pthread_getconcurrency (void)
2357 return MT_INTERFACE
->concurrency
;
2360 /* keep this in sync with sched.cc */
2362 pthread_getschedparam (pthread_t thread
, int *policy
,
2363 struct sched_param
*param
)
2365 if (!pthread::is_good_object (&thread
))
2367 *policy
= SCHED_FIFO
;
2368 /* we don't return the current effective priority, we return the current
2369 requested priority */
2370 *param
= thread
->attr
.schedparam
;
2374 /* Thread Specific Data */
2376 pthread_key_create (pthread_key_t
*key
, void (*destructor
) (void *))
2378 /* The opengroup docs don't define if we should check this or not,
2379 but creation is relatively rare. */
2380 if (pthread_key::is_good_object (key
))
2383 *key
= new pthread_key (destructor
);
2385 if (!pthread_key::is_good_object (key
))
2395 pthread_key_delete (pthread_key_t key
)
2397 if (!pthread_key::is_good_object (&key
))
2404 /* provided for source level compatability. See
2405 http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2408 pthread_setconcurrency (int new_level
)
2412 MT_INTERFACE
->concurrency
= new_level
;
2416 /* keep syncronised with sched.cc */
2418 pthread_setschedparam (pthread_t thread
, int policy
,
2419 const struct sched_param
*param
)
2421 if (!pthread::is_good_object (&thread
))
2423 if (policy
!= SCHED_FIFO
)
2428 sched_set_thread_priority (thread
->win32_obj_id
, param
->sched_priority
);
2430 thread
->attr
.schedparam
.sched_priority
= param
->sched_priority
;
2436 pthread_setspecific (pthread_key_t key
, const void *value
)
2438 if (!pthread_key::is_good_object (&key
))
2445 pthread_getspecific (pthread_key_t key
)
2447 if (!pthread_key::is_good_object (&key
))
2450 return (key
)->get ();
2454 /* Thread synchronisation */
2456 pthread_cond::is_good_object (pthread_cond_t
const *cond
)
2458 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
) != VALID_OBJECT
)
2464 pthread_cond::is_good_initializer (pthread_cond_t
const *cond
)
2466 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) != VALID_STATIC_OBJECT
)
2472 pthread_cond::is_good_initializer_or_object (pthread_cond_t
const *cond
)
2474 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) == INVALID_OBJECT
)
2480 pthread_cond::is_good_initializer_or_bad_object (pthread_cond_t
const *cond
)
2482 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) == VALID_OBJECT
)
2488 pthread_cond_destroy (pthread_cond_t
*cond
)
2490 if (pthread_cond::is_good_initializer (cond
))
2492 if (!pthread_cond::is_good_object (cond
))
2495 /* reads are atomic */
2496 if ((*cond
)->waiting
)
2506 pthread_cond::init (pthread_cond_t
*cond
, const pthread_condattr_t
*attr
)
2509 pthread_cond_t new_cond
;
2511 if (attr
&& !pthread_condattr::is_good_object (attr
))
2514 cond_initialization_lock
.lock ();
2516 if (!is_good_initializer_or_bad_object (cond
))
2518 cond_initialization_lock
.unlock ();
2522 new_cond
= new pthread_cond (attr
? (*attr
) : NULL
);
2523 if (!is_good_object (&new_cond
))
2526 cond_initialization_lock
.unlock ();
2531 cond_initialization_lock
.unlock ();
2537 pthread_cond_broadcast (pthread_cond_t
*cond
)
2539 if (pthread_cond::is_good_initializer (cond
))
2541 if (!pthread_cond::is_good_object (cond
))
2544 (*cond
)->unblock (true);
2550 pthread_cond_signal (pthread_cond_t
*cond
)
2552 if (pthread_cond::is_good_initializer (cond
))
2554 if (!pthread_cond::is_good_object (cond
))
2557 (*cond
)->unblock (false);
2563 __pthread_cond_dowait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2566 if (!pthread_mutex::is_good_object (mutex
))
2568 if (!pthread_mutex::can_be_unlocked (mutex
))
2571 if (pthread_cond::is_good_initializer (cond
))
2572 pthread_cond::init (cond
, NULL
);
2573 if (!pthread_cond::is_good_object (cond
))
2576 return (*cond
)->wait (*mutex
, waitlength
);
2580 pthread_cond_timedwait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2581 const struct timespec
*abstime
)
2586 pthread_testcancel ();
2588 if (check_valid_pointer (abstime
))
2591 gettimeofday (&tv
, NULL
);
2592 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
2593 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
2596 return __pthread_cond_dowait (cond
, mutex
, waitlength
);
2600 pthread_cond_wait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
2602 pthread_testcancel ();
2604 return __pthread_cond_dowait (cond
, mutex
, INFINITE
);
2608 pthread_condattr_init (pthread_condattr_t
*condattr
)
2610 if (pthread_condattr::is_good_object (condattr
))
2613 *condattr
= new pthread_condattr
;
2614 if (!pthread_condattr::is_good_object (condattr
))
2624 pthread_condattr_getpshared (const pthread_condattr_t
*attr
, int *pshared
)
2626 if (!pthread_condattr::is_good_object (attr
))
2628 *pshared
= (*attr
)->shared
;
2633 pthread_condattr_setpshared (pthread_condattr_t
*attr
, int pshared
)
2635 if (!pthread_condattr::is_good_object (attr
))
2637 if ((pshared
< 0) || (pshared
> 1))
2639 /* shared cond vars not currently supported */
2640 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2642 (*attr
)->shared
= pshared
;
2647 pthread_condattr_destroy (pthread_condattr_t
*condattr
)
2649 if (!pthread_condattr::is_good_object (condattr
))
2658 pthread_rwlock::is_good_object (pthread_rwlock_t
const *rwlock
)
2660 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
) != VALID_OBJECT
)
2666 pthread_rwlock::is_good_initializer (pthread_rwlock_t
const *rwlock
)
2668 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) != VALID_STATIC_OBJECT
)
2674 pthread_rwlock::is_good_initializer_or_object (pthread_rwlock_t
const *rwlock
)
2676 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) == INVALID_OBJECT
)
2682 pthread_rwlock::is_good_initializer_or_bad_object (pthread_rwlock_t
const *rwlock
)
2684 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) == VALID_OBJECT
)
2690 pthread_rwlock_destroy (pthread_rwlock_t
*rwlock
)
2692 if (pthread_rwlock::is_good_initializer (rwlock
))
2694 if (!pthread_rwlock::is_good_object (rwlock
))
2697 if ((*rwlock
)->writer
|| (*rwlock
)->readers
||
2698 (*rwlock
)->waiting_readers
|| (*rwlock
)->waiting_writers
)
2708 pthread_rwlock::init (pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*attr
)
2710 pthread_rwlock_t new_rwlock
;
2712 if (attr
&& !pthread_rwlockattr::is_good_object (attr
))
2715 rwlock_initialization_lock
.lock ();
2717 if (!is_good_initializer_or_bad_object (rwlock
))
2719 rwlock_initialization_lock
.unlock ();
2723 new_rwlock
= new pthread_rwlock (attr
? (*attr
) : NULL
);
2724 if (!is_good_object (&new_rwlock
))
2727 rwlock_initialization_lock
.unlock ();
2731 *rwlock
= new_rwlock
;
2732 rwlock_initialization_lock
.unlock ();
2738 pthread_rwlock_rdlock (pthread_rwlock_t
*rwlock
)
2740 pthread_testcancel ();
2742 if (pthread_rwlock::is_good_initializer (rwlock
))
2743 pthread_rwlock::init (rwlock
, NULL
);
2744 if (!pthread_rwlock::is_good_object (rwlock
))
2747 return (*rwlock
)->rdlock ();
2751 pthread_rwlock_tryrdlock (pthread_rwlock_t
*rwlock
)
2753 if (pthread_rwlock::is_good_initializer (rwlock
))
2754 pthread_rwlock::init (rwlock
, NULL
);
2755 if (!pthread_rwlock::is_good_object (rwlock
))
2758 return (*rwlock
)->tryrdlock ();
2762 pthread_rwlock_wrlock (pthread_rwlock_t
*rwlock
)
2764 pthread_testcancel ();
2766 if (pthread_rwlock::is_good_initializer (rwlock
))
2767 pthread_rwlock::init (rwlock
, NULL
);
2768 if (!pthread_rwlock::is_good_object (rwlock
))
2771 return (*rwlock
)->wrlock ();
2775 pthread_rwlock_trywrlock (pthread_rwlock_t
*rwlock
)
2777 if (pthread_rwlock::is_good_initializer (rwlock
))
2778 pthread_rwlock::init (rwlock
, NULL
);
2779 if (!pthread_rwlock::is_good_object (rwlock
))
2782 return (*rwlock
)->trywrlock ();
2786 pthread_rwlock_unlock (pthread_rwlock_t
*rwlock
)
2788 if (pthread_rwlock::is_good_initializer (rwlock
))
2790 if (!pthread_rwlock::is_good_object (rwlock
))
2793 return (*rwlock
)->unlock ();
2797 pthread_rwlockattr_init (pthread_rwlockattr_t
*rwlockattr
)
2799 if (pthread_rwlockattr::is_good_object (rwlockattr
))
2802 *rwlockattr
= new pthread_rwlockattr
;
2803 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2805 delete (*rwlockattr
);
2813 pthread_rwlockattr_getpshared (const pthread_rwlockattr_t
*attr
, int *pshared
)
2815 if (!pthread_rwlockattr::is_good_object (attr
))
2817 *pshared
= (*attr
)->shared
;
2822 pthread_rwlockattr_setpshared (pthread_rwlockattr_t
*attr
, int pshared
)
2824 if (!pthread_rwlockattr::is_good_object (attr
))
2826 if ((pshared
< 0) || (pshared
> 1))
2828 /* shared rwlock vars not currently supported */
2829 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2831 (*attr
)->shared
= pshared
;
2836 pthread_rwlockattr_destroy (pthread_rwlockattr_t
*rwlockattr
)
2838 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2840 delete (*rwlockattr
);
2847 pthread_kill (pthread_t thread
, int sig
)
2849 // lock myself, for the use of thread2signal
2850 // two different kills might clash: FIXME
2852 if (!pthread::is_good_object (&thread
))
2857 si
.si_code
= SI_USER
;
2858 si
.si_pid
= si
.si_uid
= si
.si_errno
= 0;
2859 thread
->cygtls
->set_threadkill ();
2860 int rval
= sig
? sig_send (NULL
, si
, thread
->cygtls
) : 0;
2867 pthread_sigmask (int operation
, const sigset_t
*set
, sigset_t
*old_set
)
2869 return handle_sigprocmask (operation
, set
, old_set
, _my_tls
.sigmask
);
2875 pthread_equal (pthread_t t1
, pthread_t t2
)
2877 return pthread::equal (t1
, t2
);
2883 pthread_mutex::init (pthread_mutex_t
*mutex
,
2884 const pthread_mutexattr_t
*attr
,
2885 const pthread_mutex_t initializer
)
2887 pthread_mutex_t new_mutex
;
2889 if (attr
&& !pthread_mutexattr::is_good_object (attr
) || check_valid_pointer (mutex
))
2892 mutex_initialization_lock
.lock ();
2894 if (!is_good_initializer_or_bad_object (mutex
))
2896 mutex_initialization_lock
.unlock ();
2900 new_mutex
= new pthread_mutex (attr
? (*attr
) : NULL
);
2901 if (!is_good_object (&new_mutex
))
2904 mutex_initialization_lock
.unlock ();
2908 if (!attr
&& initializer
)
2910 if (initializer
== PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
)
2911 new_mutex
->type
= PTHREAD_MUTEX_RECURSIVE
;
2912 else if (initializer
== PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
)
2913 new_mutex
->type
= PTHREAD_MUTEX_NORMAL
;
2914 else if (initializer
== PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
)
2915 new_mutex
->type
= PTHREAD_MUTEX_ERRORCHECK
;
2919 mutex_initialization_lock
.unlock ();
2925 pthread_mutex_getprioceiling (const pthread_mutex_t
*mutex
,
2928 /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
2931 We can support mutex priorities in the future though:
2932 Store a priority with each mutex.
2933 When the mutex is optained, set the thread priority as appropriate
2934 When the mutex is released, reset the thread priority. */
2939 pthread_mutex_lock (pthread_mutex_t
*mutex
)
2941 if (pthread_mutex::is_good_initializer (mutex
))
2942 pthread_mutex::init (mutex
, NULL
, *mutex
);
2943 if (!pthread_mutex::is_good_object (mutex
))
2945 return (*mutex
)->lock ();
2949 pthread_mutex_trylock (pthread_mutex_t
*mutex
)
2951 if (pthread_mutex::is_good_initializer (mutex
))
2952 pthread_mutex::init (mutex
, NULL
, *mutex
);
2953 if (!pthread_mutex::is_good_object (mutex
))
2955 return (*mutex
)->trylock ();
2959 pthread_mutex_unlock (pthread_mutex_t
*mutex
)
2961 if (pthread_mutex::is_good_initializer (mutex
))
2963 if (!pthread_mutex::is_good_object (mutex
))
2965 return (*mutex
)->unlock ();
2969 pthread_mutex_destroy (pthread_mutex_t
*mutex
)
2973 if (pthread_mutex::is_good_initializer (mutex
))
2975 if (!pthread_mutex::is_good_object (mutex
))
2978 rv
= (*mutex
)->destroy ();
2987 pthread_mutex_setprioceiling (pthread_mutex_t
*mutex
, int prioceiling
,
2993 /* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
2996 pthread_mutexattr_getprotocol (const pthread_mutexattr_t
*attr
,
2999 if (!pthread_mutexattr::is_good_object (attr
))
3005 pthread_mutexattr_getpshared (const pthread_mutexattr_t
*attr
,
3008 if (!pthread_mutexattr::is_good_object (attr
))
3010 *pshared
= (*attr
)->pshared
;
3015 pthread_mutexattr_gettype (const pthread_mutexattr_t
*attr
, int *type
)
3017 if (!pthread_mutexattr::is_good_object (attr
))
3019 *type
= (*attr
)->mutextype
;
3023 /* FIXME: write and test process shared mutex's. */
3025 pthread_mutexattr_init (pthread_mutexattr_t
*attr
)
3027 if (pthread_mutexattr::is_good_object (attr
))
3030 *attr
= new pthread_mutexattr ();
3031 if (!pthread_mutexattr::is_good_object (attr
))
3041 pthread_mutexattr_destroy (pthread_mutexattr_t
*attr
)
3043 if (!pthread_mutexattr::is_good_object (attr
))
3051 /* Win32 doesn't support mutex priorities */
3053 pthread_mutexattr_setprotocol (pthread_mutexattr_t
*attr
, int protocol
)
3055 if (!pthread_mutexattr::is_good_object (attr
))
3060 /* Win32 doesn't support mutex priorities */
3062 pthread_mutexattr_setprioceiling (pthread_mutexattr_t
*attr
,
3065 if (!pthread_mutexattr::is_good_object (attr
))
3071 pthread_mutexattr_getprioceiling (const pthread_mutexattr_t
*attr
,
3074 if (!pthread_mutexattr::is_good_object (attr
))
3080 pthread_mutexattr_setpshared (pthread_mutexattr_t
*attr
, int pshared
)
3082 if (!pthread_mutexattr::is_good_object (attr
))
3084 /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
3087 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
3089 (*attr
)->pshared
= pshared
;
3093 /* see pthread_mutex_gettype */
3095 pthread_mutexattr_settype (pthread_mutexattr_t
*attr
, int type
)
3097 if (!pthread_mutexattr::is_good_object (attr
))
3102 case PTHREAD_MUTEX_ERRORCHECK
:
3103 case PTHREAD_MUTEX_RECURSIVE
:
3104 case PTHREAD_MUTEX_NORMAL
:
3105 (*attr
)->mutextype
= type
;
3116 /* static members */
3118 semaphore::is_good_object (sem_t
const * sem
)
3120 if (verifyable_object_isvalid (sem
, SEM_MAGIC
) != VALID_OBJECT
)
3126 semaphore::init (sem_t
*sem
, int pshared
, unsigned int value
)
3128 /* opengroup calls this undefined */
3129 if (is_good_object (sem
))
3132 if (value
> SEM_VALUE_MAX
)
3135 *sem
= new semaphore (pshared
, value
);
3137 if (!is_good_object (sem
))
3147 semaphore::destroy (sem_t
*sem
)
3149 if (!is_good_object (sem
))
3152 /* FIXME - new feature - test for busy against threads... */
3160 semaphore::open (const char *name
, int oflag
, mode_t mode
, unsigned int value
)
3162 if (value
> SEM_VALUE_MAX
)
3168 sem_t
*sem
= new sem_t
;
3175 *sem
= new semaphore (name
, oflag
, mode
, value
);
3177 if (!is_good_object (sem
))
3187 semaphore::wait (sem_t
*sem
)
3189 pthread_testcancel ();
3191 if (!is_good_object (sem
))
3197 return (*sem
)->_wait ();
3201 semaphore::trywait (sem_t
*sem
)
3203 if (!is_good_object (sem
))
3209 return (*sem
)->_trywait ();
3213 semaphore::timedwait (sem_t
*sem
, const struct timespec
*abstime
)
3215 if (!is_good_object (sem
))
3221 return (*sem
)->_timedwait (abstime
);
3225 semaphore::post (sem_t
*sem
)
3227 if (!is_good_object (sem
))
3238 semaphore::getvalue (sem_t
*sem
, int *sval
)
3241 if (!is_good_object (sem
)
3242 || __check_null_invalid_struct (sval
, sizeof (int)))
3248 return (*sem
)->_getvalue (sval
);
3253 pthread_null::get_null_pthread ()
3255 /* because of weird entry points */
3256 _instance
.magic
= 0;
3260 pthread_null::pthread_null ()
3262 attr
.joinable
= PTHREAD_CREATE_DETACHED
;
3263 /* Mark ourselves as invalid */
3267 pthread_null::~pthread_null ()
3272 pthread_null::create (void *(*)(void *), pthread_attr
*, void *)
3277 pthread_null::exit (void *value_ptr
)
3279 _my_tls
.remove (INFINITE
);
3284 pthread_null::cancel ()
3290 pthread_null::testcancel ()
3295 pthread_null::setcancelstate (int state
, int *oldstate
)
3301 pthread_null::setcanceltype (int type
, int *oldtype
)
3307 pthread_null::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
3312 pthread_null::pop_cleanup_handler (int const execute
)
3317 pthread_null::getsequence_np ()
3322 pthread_null
pthread_null::_instance
;