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 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 (_reclaim_reent
) (_REENT
);
361 if (InterlockedDecrement (&MT_INTERFACE
->threadcount
) == 0)
365 _my_tls
.remove (INFINITE
);
371 pthread::cancel (void)
373 class pthread
*thread
= this;
374 class pthread
*self
= pthread::self ();
384 if (canceltype
== PTHREAD_CANCEL_DEFERRED
||
385 cancelstate
== PTHREAD_CANCEL_DISABLE
)
389 SetEvent (cancel_event
);
392 else if (equal (thread
, self
))
396 return 0; // Never reached
399 // cancel asynchronous
400 SuspendThread (win32_obj_id
);
401 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
404 context
.ContextFlags
= CONTEXT_CONTROL
;
405 GetThreadContext (win32_obj_id
, &context
);
406 context
.Eip
= (DWORD
) pthread::static_cancel_self
;
407 SetThreadContext (win32_obj_id
, &context
);
410 ResumeThread (win32_obj_id
);
414 TODO: insert pthread_testcancel into the required functions
415 the required function list is: *indicates done, X indicates not present in cygwin.
434 *pthread_cond_timedwait ()
435 *pthread_cond_wait ()
437 *pthread_testcancel ()
461 the optional list is:
581 Note, that for fcntl (), for any value of the cmd argument.
583 And we must not introduce cancellation points anywhere else that's part of the posix or
589 pthread::testcancel (void)
591 if (cancelstate
== PTHREAD_CANCEL_DISABLE
)
594 if (WaitForSingleObject (cancel_event
, 0) == WAIT_OBJECT_0
)
599 pthread::static_cancel_self (void)
601 pthread::self ()->cancel_self ();
605 pthread::cancelable_wait (HANDLE object
, DWORD timeout
, const bool do_cancel
,
606 const bool do_sig_wait
)
610 HANDLE wait_objects
[3];
611 pthread_t thread
= self ();
613 /* Do not change the wait order.
614 The object must have higher priority than the cancel event,
615 because WaitForMultipleObjects will return the smallest index
616 if both objects are signaled. */
617 wait_objects
[num
++] = object
;
619 if (!is_good_object (&thread
) ||
620 thread
->cancelstate
== PTHREAD_CANCEL_DISABLE
)
621 cancel_n
= (DWORD
) -1;
625 wait_objects
[cancel_n
] = thread
->cancel_event
;
629 if (!do_sig_wait
|| &_my_tls
!= _main_tls
)
634 wait_objects
[sig_n
] = signal_arrived
;
637 res
= WaitForMultipleObjects (num
, wait_objects
, FALSE
, timeout
);
638 if (res
== sig_n
- WAIT_OBJECT_0
)
640 else if (res
== cancel_n
- WAIT_OBJECT_0
)
643 pthread::static_cancel_self ();
650 pthread::setcancelstate (int state
, int *oldstate
)
656 if (state
!= PTHREAD_CANCEL_ENABLE
&& state
!= PTHREAD_CANCEL_DISABLE
)
661 *oldstate
= cancelstate
;
671 pthread::setcanceltype (int type
, int *oldtype
)
677 if (type
!= PTHREAD_CANCEL_DEFERRED
&& type
!= PTHREAD_CANCEL_ASYNCHRONOUS
)
682 *oldtype
= canceltype
;
692 pthread::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
696 api_fatal ("Attempt to push a cleanup handler across threads");
697 handler
->next
= cleanup_stack
;
698 cleanup_stack
= handler
;
702 pthread::pop_cleanup_handler (int const execute
)
705 // TODO: send a signal or something to the thread ?
706 api_fatal ("Attempt to execute a cleanup handler across threads");
710 if (cleanup_stack
!= NULL
)
712 __pthread_cleanup_handler
*handler
= cleanup_stack
;
715 (*handler
->function
) (handler
->arg
);
716 cleanup_stack
= handler
->next
;
723 pthread::pop_all_cleanup_handlers ()
725 while (cleanup_stack
!= NULL
)
726 pop_cleanup_handler (1);
730 pthread::cancel_self ()
732 exit (PTHREAD_CANCELED
);
736 pthread::get_thread_id ()
742 pthread::_fixup_after_fork ()
744 /* set thread to not running if it is not the forking thread */
745 if (this != pthread::self ())
755 pthread::suspend_except_self ()
757 if (valid
&& this != pthread::self ())
758 SuspendThread (win32_obj_id
);
765 ResumeThread (win32_obj_id
);
770 pthread_attr::is_good_object (pthread_attr_t
const *attr
)
772 if (verifyable_object_isvalid (attr
, PTHREAD_ATTR_MAGIC
) != VALID_OBJECT
)
777 /* instance members */
779 pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC
),
780 joinable (PTHREAD_CREATE_JOINABLE
), contentionscope (PTHREAD_SCOPE_PROCESS
),
781 inheritsched (PTHREAD_INHERIT_SCHED
), stacksize (0)
783 schedparam
.sched_priority
= 0;
786 pthread_attr::~pthread_attr ()
791 pthread_condattr::is_good_object (pthread_condattr_t
const *attr
)
793 if (verifyable_object_isvalid (attr
, PTHREAD_CONDATTR_MAGIC
) != VALID_OBJECT
)
798 pthread_condattr::pthread_condattr ():verifyable_object
799 (PTHREAD_CONDATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
803 pthread_condattr::~pthread_condattr ()
807 List
<pthread_cond
> pthread_cond::conds
;
809 /* This is used for cond creation protection within a single process only */
810 fast_mutex NO_COPY
pthread_cond::cond_initialization_lock
;
812 /* We can only be called once.
813 TODO: (no rush) use a non copied memory section to
814 hold an initialization flag. */
816 pthread_cond::init_mutex ()
818 if (!cond_initialization_lock
.init ())
819 api_fatal ("Could not create win32 Mutex for pthread cond static initializer support.");
822 pthread_cond::pthread_cond (pthread_condattr
*attr
) :
823 verifyable_object (PTHREAD_COND_MAGIC
),
824 shared (0), waiting (0), pending (0), sem_wait (NULL
),
825 mtx_cond(NULL
), next (NULL
)
827 pthread_mutex
*verifyable_mutex_obj
;
830 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
836 verifyable_mutex_obj
= &mtx_in
;
837 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
839 thread_printf ("Internal cond mutex is not valid. this %p", this);
844 * Change the mutex type to NORMAL.
845 * This mutex MUST be of type normal
847 mtx_in
.type
= PTHREAD_MUTEX_NORMAL
;
849 verifyable_mutex_obj
= &mtx_out
;
850 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
852 thread_printf ("Internal cond mutex is not valid. this %p", this);
856 /* Change the mutex type to NORMAL to speed up mutex operations */
857 mtx_out
.type
= PTHREAD_MUTEX_NORMAL
;
859 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
862 debug_printf ("CreateSemaphore failed. %E");
870 pthread_cond::~pthread_cond ()
873 CloseHandle (sem_wait
);
879 pthread_cond::unblock (const bool all
)
881 unsigned long releaseable
;
884 * Block outgoing threads (and avoid simultanous unblocks)
888 releaseable
= waiting
- pending
;
891 unsigned long released
;
896 * Block incoming threads until all waiting threads are released.
901 * Calculate releaseable again because threads can enter until
902 * the semaphore has been taken, but they can not leave, therefore pending
903 * is unchanged and releaseable can only get higher
905 releaseable
= waiting
- pending
;
908 released
= all
? releaseable
: 1;
913 ::ReleaseSemaphore (sem_wait
, released
, NULL
);
917 * And let the threads release.
923 pthread_cond::wait (pthread_mutex_t mutex
, DWORD dwMilliseconds
)
928 if (InterlockedIncrement ((long *)&waiting
) == 1)
930 else if (mtx_cond
!= mutex
)
932 InterlockedDecrement ((long *)&waiting
);
939 * Release the mutex and wait on semaphore
944 rv
= pthread::cancelable_wait (sem_wait
, dwMilliseconds
, false, true);
948 if (rv
!= WAIT_OBJECT_0
)
951 * It might happen that a signal is sent while the thread got canceled
952 * or timed out. Try to take one.
953 * If the thread gets one than a signal|broadcast is in progress.
955 if (WaitForSingleObject (sem_wait
, 0) == WAIT_OBJECT_0
)
957 * thread got cancelled ot timed out while a signalling is in progress.
958 * Set wait result back to signaled
963 InterlockedDecrement ((long *)&waiting
);
965 if (rv
== WAIT_OBJECT_0
&& --pending
== 0)
967 * All signaled threads are released,
968 * new threads can enter Wait
977 if (rv
== WAIT_CANCELED
)
978 pthread::static_cancel_self ();
979 else if (rv
== WAIT_SIGNALED
)
980 /* SUSv3 states: If a signal is delivered to a thread waiting for a
981 condition variable, upon return from the signal handler the thread
982 resumes waiting for the condition variable as if it was not
983 interrupted, or it shall return zero due to spurious wakeup.
984 We opt for the latter choice here. */
986 else if (rv
== WAIT_TIMEOUT
)
993 pthread_cond::_fixup_after_fork ()
995 waiting
= pending
= 0;
998 /* Unlock eventually locked mutexes */
1002 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1004 api_fatal ("pthread_cond::_fixup_after_fork () failed to recreate win32 semaphore");
1008 pthread_rwlockattr::is_good_object (pthread_rwlockattr_t
const *attr
)
1010 if (verifyable_object_isvalid (attr
, PTHREAD_RWLOCKATTR_MAGIC
) != VALID_OBJECT
)
1015 pthread_rwlockattr::pthread_rwlockattr ():verifyable_object
1016 (PTHREAD_RWLOCKATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
1020 pthread_rwlockattr::~pthread_rwlockattr ()
1024 List
<pthread_rwlock
> pthread_rwlock::rwlocks
;
1026 /* This is used for rwlock creation protection within a single process only */
1027 fast_mutex NO_COPY
pthread_rwlock::rwlock_initialization_lock
;
1029 /* We can only be called once.
1030 TODO: (no rush) use a non copied memory section to
1031 hold an initialization flag. */
1033 pthread_rwlock::init_mutex ()
1035 if (!rwlock_initialization_lock
.init ())
1036 api_fatal ("Could not create win32 Mutex for pthread rwlock static initializer support.");
1039 pthread_rwlock::pthread_rwlock (pthread_rwlockattr
*attr
) :
1040 verifyable_object (PTHREAD_RWLOCK_MAGIC
),
1041 shared (0), waiting_readers (0), waiting_writers (0), writer (NULL
),
1042 readers (NULL
), readers_mx (), mtx (NULL
), cond_readers (NULL
), cond_writers (NULL
),
1045 pthread_mutex
*verifyable_mutex_obj
= &mtx
;
1046 pthread_cond
*verifyable_cond_obj
;
1048 if (!readers_mx
.init ())
1050 thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this);
1056 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
1062 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1064 thread_printf ("Internal rwlock mutex is not valid. this %p", this);
1068 /* Change the mutex type to NORMAL to speed up mutex operations */
1069 mtx
.type
= PTHREAD_MUTEX_NORMAL
;
1071 verifyable_cond_obj
= &cond_readers
;
1072 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1074 thread_printf ("Internal rwlock readers cond is not valid. this %p", this);
1079 verifyable_cond_obj
= &cond_writers
;
1080 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1082 thread_printf ("Internal rwlock writers cond is not valid. this %p", this);
1088 rwlocks
.insert (this);
1091 pthread_rwlock::~pthread_rwlock ()
1093 rwlocks
.remove (this);
1097 pthread_rwlock::rdlock ()
1100 struct RWLOCK_READER
*reader
;
1101 pthread_t self
= pthread::self ();
1105 if (lookup_reader (self
))
1111 reader
= new struct RWLOCK_READER
;
1118 while (writer
|| waiting_writers
)
1120 pthread_cleanup_push (pthread_rwlock::rdlock_cleanup
, this);
1123 cond_readers
.wait (&mtx
);
1126 pthread_cleanup_pop (0);
1129 reader
->thread
= self
;
1130 add_reader (reader
);
1139 pthread_rwlock::tryrdlock ()
1142 pthread_t self
= pthread::self ();
1146 if (writer
|| waiting_writers
|| lookup_reader (self
))
1150 struct RWLOCK_READER
*reader
= new struct RWLOCK_READER
;
1153 reader
->thread
= self
;
1154 add_reader (reader
);
1166 pthread_rwlock::wrlock ()
1169 pthread_t self
= pthread::self ();
1173 if (writer
== self
|| lookup_reader (self
))
1179 while (writer
|| readers
)
1181 pthread_cleanup_push (pthread_rwlock::wrlock_cleanup
, this);
1184 cond_writers
.wait (&mtx
);
1187 pthread_cleanup_pop (0);
1199 pthread_rwlock::trywrlock ()
1202 pthread_t self
= pthread::self ();
1206 if (writer
|| readers
)
1217 pthread_rwlock::unlock ()
1220 pthread_t self
= pthread::self ();
1236 struct RWLOCK_READER
*reader
= lookup_reader (self
);
1244 remove_reader (reader
);
1257 pthread_rwlock::add_reader (struct RWLOCK_READER
*rd
)
1259 List_insert (readers
, rd
);
1263 pthread_rwlock::remove_reader (struct RWLOCK_READER
*rd
)
1265 List_remove (readers_mx
, readers
, rd
);
1268 struct pthread_rwlock::RWLOCK_READER
*
1269 pthread_rwlock::lookup_reader (pthread_t thread
)
1273 struct RWLOCK_READER
*cur
= readers
;
1275 while (cur
&& cur
->thread
!= thread
)
1278 readers_mx
.unlock ();
1284 pthread_rwlock::rdlock_cleanup (void *arg
)
1286 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1288 --(rwlock
->waiting_readers
);
1290 rwlock
->mtx
.unlock ();
1294 pthread_rwlock::wrlock_cleanup (void *arg
)
1296 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1298 --(rwlock
->waiting_writers
);
1300 rwlock
->mtx
.unlock ();
1304 pthread_rwlock::_fixup_after_fork ()
1306 pthread_t self
= pthread::self ();
1307 struct RWLOCK_READER
**temp
= &readers
;
1309 waiting_readers
= 0;
1310 waiting_writers
= 0;
1312 if (!readers_mx
.init ())
1313 api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex");
1315 /* Unlock eventually locked mutex */
1318 * Remove all readers except self
1322 if ((*temp
)->thread
== self
)
1323 temp
= &((*temp
)->next
);
1326 struct RWLOCK_READER
*cur
= *temp
;
1327 *temp
= (*temp
)->next
;
1334 /* static members */
1335 /* This stores pthread_key information across fork() boundaries */
1336 List
<pthread_key
> pthread_key::keys
;
1339 pthread_key::is_good_object (pthread_key_t
const *key
)
1341 if (verifyable_object_isvalid (key
, PTHREAD_KEY_MAGIC
) != VALID_OBJECT
)
1346 /* non-static members */
1348 pthread_key::pthread_key (void (*aDestructor
) (void *)):verifyable_object (PTHREAD_KEY_MAGIC
), destructor (aDestructor
)
1350 tls_index
= TlsAlloc ();
1351 if (tls_index
== TLS_OUT_OF_INDEXES
)
1357 pthread_key::~pthread_key ()
1359 /* We may need to make the list code lock the list during operations
1364 TlsFree (tls_index
);
1369 pthread_key::set (const void *value
)
1371 /* the OS function doesn't perform error checking */
1372 TlsSetValue (tls_index
, (void *) value
);
1377 pthread_key::get () const
1379 int saved_error
= ::GetLastError ();
1380 void *result
= TlsGetValue (tls_index
);
1381 ::SetLastError (saved_error
);
1386 pthread_key::_fixup_before_fork ()
1392 pthread_key::_fixup_after_fork ()
1394 tls_index
= TlsAlloc ();
1395 if (tls_index
== TLS_OUT_OF_INDEXES
)
1396 api_fatal ("pthread_key::recreate_key_from_buffer () failed to reallocate Tls storage");
1401 pthread_key::run_destructor ()
1405 void *oldValue
= get ();
1409 destructor (oldValue
);
1416 REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
1417 gymnastics can be a lot easier.
1419 the mutex_t (size 4) is not used as a verifyable object because we cannot
1420 guarantee the same address space for all processes.
1421 we use the following:
1422 high bit set (never a valid address).
1423 second byte is reserved for the priority.
1424 third byte is reserved
1425 fourth byte is the mutex id. (max 255 cygwin mutexs system wide).
1426 creating mutex's does get slower and slower, but as creation is a one time
1427 job, it should never become an issue
1429 And if you're looking at this and thinking, why not an array in cygwin for all mutexs,
1430 - you incur a penalty on _every_ mutex call and you have toserialise them all.
1433 option 2? put everything in userspace and update the ABI?
1434 - bad karma as well - the HANDLE, while identical across process's,
1435 Isn't duplicated, it's reopened. */
1437 /* static members */
1439 pthread_mutex::is_good_object (pthread_mutex_t
const *mutex
)
1441 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
) != VALID_OBJECT
)
1447 pthread_mutex::is_good_initializer (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_STATIC_OBJECT
)
1458 pthread_mutex::is_good_initializer_or_object (pthread_mutex_t
const *mutex
)
1460 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
1461 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
1462 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
1463 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) == INVALID_OBJECT
)
1469 pthread_mutex::is_good_initializer_or_bad_object (pthread_mutex_t
const *mutex
)
1471 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
1472 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
1473 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
1474 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) == VALID_OBJECT
)
1480 pthread_mutex::can_be_unlocked (pthread_mutex_t
const *mutex
)
1482 pthread_t self
= pthread::self ();
1484 if (!is_good_object (mutex
))
1487 * Check if the mutex is owned by the current thread and can be unlocked
1489 return ((*mutex
)->recursion_counter
== 1 && pthread::equal ((*mutex
)->owner
, self
));
1492 List
<pthread_mutex
> pthread_mutex::mutexes
;
1494 /* This is used for mutex creation protection within a single process only */
1495 fast_mutex NO_COPY
pthread_mutex::mutex_initialization_lock
;
1497 /* We can only be called once.
1498 TODO: (no rush) use a non copied memory section to
1499 hold an initialization flag. */
1501 pthread_mutex::init_mutex ()
1503 if (!mutex_initialization_lock
.init ())
1504 api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support.");
1507 pthread_mutex::pthread_mutex (pthread_mutexattr
*attr
) :
1508 verifyable_object (PTHREAD_MUTEX_MAGIC
),
1510 win32_obj_id (NULL
), recursion_counter (0),
1511 condwaits (0), owner (NULL
), type (PTHREAD_MUTEX_DEFAULT
),
1512 pshared (PTHREAD_PROCESS_PRIVATE
)
1514 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1520 /*attr checked in the C call */
1523 if (attr
->pshared
== PTHREAD_PROCESS_SHARED
)
1530 type
= attr
->mutextype
;
1533 mutexes
.insert (this);
1536 pthread_mutex::~pthread_mutex ()
1539 CloseHandle (win32_obj_id
);
1541 mutexes
.remove (this);
1545 pthread_mutex::_lock (pthread_t self
)
1549 if (InterlockedIncrement ((long *)&lock_counter
) == 1)
1551 else if (type
!= PTHREAD_MUTEX_NORMAL
&& pthread::equal (owner
, self
))
1553 InterlockedDecrement ((long *) &lock_counter
);
1554 if (type
== PTHREAD_MUTEX_RECURSIVE
)
1555 result
= lock_recursive ();
1561 WaitForSingleObject (win32_obj_id
, INFINITE
);
1569 pthread_mutex::_trylock (pthread_t self
)
1573 if (InterlockedCompareExchange ((long *) &lock_counter
, 1, 0) == 0)
1575 else if (type
== PTHREAD_MUTEX_RECURSIVE
&& pthread::equal (owner
, self
))
1576 result
= lock_recursive ();
1584 pthread_mutex::_unlock (pthread_t self
)
1586 if (!pthread::equal (owner
, self
))
1589 if (--recursion_counter
== 0)
1592 if (InterlockedDecrement ((long *)&lock_counter
))
1593 // Another thread is waiting
1594 ::ReleaseSemaphore (win32_obj_id
, 1, NULL
);
1601 pthread_mutex::_destroy (pthread_t self
)
1603 if (condwaits
|| _trylock (self
))
1604 // Do not destroy a condwaited or locked mutex
1606 else if (recursion_counter
!= 1)
1608 // Do not destroy a recursive locked mutex
1609 --recursion_counter
;
1618 pthread_mutex::_fixup_after_fork ()
1620 debug_printf ("mutex %x in _fixup_after_fork", this);
1621 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1622 api_fatal ("pthread_mutex::_fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's");
1625 /* mutex has no owner, reset to initial */
1627 else if (lock_counter
!= 0)
1628 /* All waiting threads are gone after a fork */
1631 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1633 api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 semaphore for mutex");
1639 pthread_mutexattr::is_good_object (pthread_mutexattr_t
const * attr
)
1641 if (verifyable_object_isvalid (attr
, PTHREAD_MUTEXATTR_MAGIC
) != VALID_OBJECT
)
1646 pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC
),
1647 pshared (PTHREAD_PROCESS_PRIVATE
), mutextype (PTHREAD_MUTEX_DEFAULT
)
1651 pthread_mutexattr::~pthread_mutexattr ()
1655 List
<semaphore
> semaphore::semaphores
;
1657 semaphore::semaphore (int pshared
, unsigned int value
)
1658 : verifyable_object (SEM_MAGIC
),
1660 currentvalue (value
),
1663 SECURITY_ATTRIBUTES sa
= (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1664 ? sec_all
: sec_none_nih
;
1665 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, NULL
);
1666 if (!this->win32_obj_id
)
1669 semaphores
.insert (this);
1672 semaphore::semaphore (const char *sem_name
, int oflag
, mode_t mode
,
1674 : verifyable_object (SEM_MAGIC
),
1675 shared (PTHREAD_PROCESS_SHARED
),
1676 currentvalue (value
), /* Unused for named semaphores. */
1679 if (oflag
& O_CREAT
)
1681 SECURITY_ATTRIBUTES sa
= sec_all
;
1682 security_descriptor sd
;
1684 set_security_attribute (mode
, &sa
, sd
);
1685 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, sem_name
);
1686 if (!this->win32_obj_id
)
1688 if (GetLastError () == ERROR_ALREADY_EXISTS
&& (oflag
& O_EXCL
))
1691 CloseHandle (this->win32_obj_id
);
1697 this->win32_obj_id
= ::OpenSemaphore (SEMAPHORE_ALL_ACCESS
, FALSE
,
1699 if (!this->win32_obj_id
)
1707 name
= new char [strlen (sem_name
+ 1)];
1711 CloseHandle (this->win32_obj_id
);
1715 strcpy (name
, sem_name
);
1718 semaphores
.insert (this);
1721 semaphore::~semaphore ()
1724 CloseHandle (win32_obj_id
);
1728 semaphores
.remove (this);
1734 if (ReleaseSemaphore (win32_obj_id
, 1, ¤tvalue
))
1739 semaphore::_getvalue (int *sval
)
1743 switch (WaitForSingleObject (win32_obj_id
, 0))
1746 ReleaseSemaphore (win32_obj_id
, 1, &val
);
1760 semaphore::_trywait ()
1762 /* FIXME: signals should be able to interrupt semaphores...
1763 *We probably need WaitForMultipleObjects here.
1765 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
1775 semaphore::_timedwait (const struct timespec
*abstime
)
1780 if (__check_invalid_read_ptr (abstime
, sizeof *abstime
))
1782 /* According to SUSv3, abstime need not be checked for validity,
1783 if the semaphore can be locked immediately. */
1790 gettimeofday (&tv
, NULL
);
1791 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
1792 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
1795 switch (pthread::cancelable_wait (win32_obj_id
, waitlength
, true, true))
1804 set_errno (ETIMEDOUT
);
1807 debug_printf ("cancelable_wait failed. %E");
1817 switch (pthread::cancelable_wait (win32_obj_id
, INFINITE
, true, true))
1826 debug_printf ("cancelable_wait failed. %E");
1833 semaphore::_fixup_after_fork ()
1835 if (shared
== PTHREAD_PROCESS_PRIVATE
)
1837 debug_printf ("sem %x in _fixup_after_fork", this);
1838 /* FIXME: duplicate code here and in the constructor. */
1839 this->win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, currentvalue
,
1842 api_fatal ("failed to create new win32 semaphore, error %d");
1846 verifyable_object::verifyable_object (long verifyer
):
1851 verifyable_object::~verifyable_object ()
1856 /* Generic memory acccess routine - where should it live ? */
1858 check_valid_pointer (void const *pointer
)
1860 if (!pointer
|| IsBadWritePtr ((void *) pointer
, sizeof (verifyable_object
)))
1865 verifyable_object_state
1866 verifyable_object_isvalid (void const * objectptr
, long magic
, void *static_ptr1
,
1867 void *static_ptr2
, void *static_ptr3
)
1869 verifyable_object
**object
= (verifyable_object
**)objectptr
;
1870 if (check_valid_pointer (object
))
1871 return INVALID_OBJECT
;
1872 if ((static_ptr1
&& *object
== static_ptr1
) ||
1873 (static_ptr2
&& *object
== static_ptr2
) ||
1874 (static_ptr3
&& *object
== static_ptr3
))
1875 return VALID_STATIC_OBJECT
;
1877 return INVALID_OBJECT
;
1878 if (check_valid_pointer (*object
))
1879 return INVALID_OBJECT
;
1880 if ((*object
)->magic
!= magic
)
1881 return INVALID_OBJECT
;
1882 return VALID_OBJECT
;
1886 pthread::thread_init_wrapper (void *arg
)
1888 pthread
*thread
= (pthread
*) arg
;
1889 set_tls_self_pointer (thread
);
1890 SetEvent (thread
->cancel_event
);
1892 thread
->mutex
.lock ();
1894 // if thread is detached force cleanup on exit
1895 if (thread
->attr
.joinable
== PTHREAD_CREATE_DETACHED
&& thread
->joiner
== NULL
)
1896 thread
->joiner
= thread
;
1897 thread
->mutex
.unlock ();
1899 thread_printf ("started thread %p %p %p %p %p %p", arg
, &_my_tls
.local_clib
,
1900 _impure_ptr
, thread
, thread
->function
, thread
->arg
);
1902 // call the user's thread
1903 void *ret
= thread
->function (thread
->arg
);
1907 return 0; // just for show. Never returns.
1911 pthread::is_good_object (pthread_t
const *thread
)
1913 if (verifyable_object_isvalid (thread
, PTHREAD_MAGIC
) != VALID_OBJECT
)
1919 pthread::getsequence_np ()
1921 return get_thread_id ();
1925 pthread::create (pthread_t
*thread
, const pthread_attr_t
*attr
,
1926 void *(*start_routine
) (void *), void *arg
)
1928 if (attr
&& !pthread_attr::is_good_object (attr
))
1931 *thread
= new pthread ();
1932 (*thread
)->create (start_routine
, attr
? *attr
: NULL
, arg
);
1933 if (!is_good_object (thread
))
1944 pthread::once (pthread_once_t
*once_control
, void (*init_routine
) (void))
1947 if (once_control
->state
)
1950 pthread_mutex_lock (&once_control
->mutex
);
1951 /* Here we must set a cancellation handler to unlock the mutex if needed */
1952 /* but a cancellation handler is not the right thing. We need this in the thread
1953 *cleanup routine. Assumption: a thread can only be in one pthread_once routine
1954 *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
1955 *on pthread_exit ();
1957 if (!once_control
->state
)
1960 once_control
->state
= 1;
1962 /* Here we must remove our cancellation handler */
1963 pthread_mutex_unlock (&once_control
->mutex
);
1968 pthread::cancel (pthread_t thread
)
1970 if (!is_good_object (&thread
))
1973 return thread
->cancel ();
1977 pthread::atforkprepare (void)
1979 callback
*cb
= MT_INTERFACE
->pthread_prepare
;
1988 MT_INTERFACE
->fixup_before_fork ();
1992 pthread::atforkparent (void)
1996 callback
*cb
= MT_INTERFACE
->pthread_parent
;
2005 pthread::atforkchild (void)
2007 MT_INTERFACE
->fixup_after_fork ();
2011 callback
*cb
= MT_INTERFACE
->pthread_child
;
2019 /* Register a set of functions to run before and after fork.
2020 prepare calls are called in LI-FC order.
2021 parent and child calls are called in FI-FC order. */
2023 pthread::atfork (void (*prepare
)(void), void (*parent
)(void), void (*child
)(void))
2025 callback
*prepcb
= NULL
, *parentcb
= NULL
, *childcb
= NULL
;
2028 prepcb
= new callback
;
2034 parentcb
= new callback
;
2044 childcb
= new callback
;
2057 prepcb
->cb
= prepare
;
2058 List_insert (MT_INTERFACE
->pthread_prepare
, prepcb
);
2062 parentcb
->cb
= parent
;
2063 callback
**t
= &MT_INTERFACE
->pthread_parent
;
2066 /* t = pointer to last next in the list */
2067 List_insert (*t
, parentcb
);
2071 childcb
->cb
= child
;
2072 callback
**t
= &MT_INTERFACE
->pthread_child
;
2075 /* t = pointer to last next in the list */
2076 List_insert (*t
, childcb
);
2082 pthread_attr_init (pthread_attr_t
*attr
)
2084 if (pthread_attr::is_good_object (attr
))
2087 *attr
= new pthread_attr
;
2088 if (!pthread_attr::is_good_object (attr
))
2098 pthread_attr_getinheritsched (const pthread_attr_t
*attr
,
2101 if (!pthread_attr::is_good_object (attr
))
2103 *inheritsched
= (*attr
)->inheritsched
;
2108 pthread_attr_getschedparam (const pthread_attr_t
*attr
,
2109 struct sched_param
*param
)
2111 if (!pthread_attr::is_good_object (attr
))
2113 *param
= (*attr
)->schedparam
;
2117 /* From a pure code point of view, this should call a helper in sched.cc,
2118 to allow for someone adding scheduler policy changes to win32 in the future.
2119 However that's extremely unlikely, so short and sweet will do us */
2121 pthread_attr_getschedpolicy (const pthread_attr_t
*attr
, int *policy
)
2123 if (!pthread_attr::is_good_object (attr
))
2125 *policy
= SCHED_FIFO
;
2131 pthread_attr_getscope (const pthread_attr_t
*attr
, int *contentionscope
)
2133 if (!pthread_attr::is_good_object (attr
))
2135 *contentionscope
= (*attr
)->contentionscope
;
2140 pthread_attr_setdetachstate (pthread_attr_t
*attr
, int detachstate
)
2142 if (!pthread_attr::is_good_object (attr
))
2144 if (detachstate
< 0 || detachstate
> 1)
2146 (*attr
)->joinable
= detachstate
;
2151 pthread_attr_getdetachstate (const pthread_attr_t
*attr
, int *detachstate
)
2153 if (!pthread_attr::is_good_object (attr
))
2155 *detachstate
= (*attr
)->joinable
;
2160 pthread_attr_setinheritsched (pthread_attr_t
*attr
, int inheritsched
)
2162 if (!pthread_attr::is_good_object (attr
))
2164 if (inheritsched
!= PTHREAD_INHERIT_SCHED
2165 && inheritsched
!= PTHREAD_EXPLICIT_SCHED
)
2167 (*attr
)->inheritsched
= inheritsched
;
2172 pthread_attr_setschedparam (pthread_attr_t
*attr
,
2173 const struct sched_param
*param
)
2175 if (!pthread_attr::is_good_object (attr
))
2177 if (!valid_sched_parameters (param
))
2179 (*attr
)->schedparam
= *param
;
2183 /* See __pthread_attr_getschedpolicy for some notes */
2185 pthread_attr_setschedpolicy (pthread_attr_t
*attr
, int policy
)
2187 if (!pthread_attr::is_good_object (attr
))
2189 if (policy
!= SCHED_FIFO
)
2195 pthread_attr_setscope (pthread_attr_t
*attr
, int contentionscope
)
2197 if (!pthread_attr::is_good_object (attr
))
2199 if (contentionscope
!= PTHREAD_SCOPE_SYSTEM
2200 && contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2202 /* In future, we may be able to support system scope by escalating the thread
2203 priority to exceed the priority class. For now we only support PROCESS scope. */
2204 if (contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2206 (*attr
)->contentionscope
= contentionscope
;
2211 pthread_attr_setstacksize (pthread_attr_t
*attr
, size_t size
)
2213 if (!pthread_attr::is_good_object (attr
))
2215 (*attr
)->stacksize
= size
;
2220 pthread_attr_getstacksize (const pthread_attr_t
*attr
, size_t *size
)
2222 if (!pthread_attr::is_good_object (attr
))
2224 *size
= (*attr
)->stacksize
;
2229 pthread_attr_destroy (pthread_attr_t
*attr
)
2231 if (!pthread_attr::is_good_object (attr
))
2239 pthread::join (pthread_t
*thread
, void **return_val
)
2241 pthread_t joiner
= self ();
2243 joiner
->testcancel ();
2245 // Initialize return val with NULL
2249 if (!is_good_object (&joiner
))
2252 if (!is_good_object (thread
))
2255 if (equal (*thread
,joiner
))
2258 (*thread
)->mutex
.lock ();
2260 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2262 (*thread
)->mutex
.unlock ();
2267 (*thread
)->joiner
= joiner
;
2268 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2269 (*thread
)->mutex
.unlock ();
2273 switch (cancelable_wait ((*thread
)->win32_obj_id
, INFINITE
, false, true))
2277 *return_val
= (*thread
)->return_ptr
;
2281 _my_tls
.call_signal_handler ();
2285 // set joined thread back to joinable since we got canceled
2286 (*thread
)->joiner
= NULL
;
2287 (*thread
)->attr
.joinable
= PTHREAD_CREATE_JOINABLE
;
2288 joiner
->cancel_self ();
2292 // should never happen
2302 pthread::detach (pthread_t
*thread
)
2304 if (!is_good_object (thread
))
2307 (*thread
)->mutex
.lock ();
2308 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2310 (*thread
)->mutex
.unlock ();
2314 // check if thread is still alive
2315 if ((*thread
)->valid
&& WaitForSingleObject ((*thread
)->win32_obj_id
, 0) == WAIT_TIMEOUT
)
2317 // force cleanup on exit
2318 (*thread
)->joiner
= *thread
;
2319 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2320 (*thread
)->mutex
.unlock ();
2324 // thread has already terminated.
2325 (*thread
)->mutex
.unlock ();
2333 pthread::suspend (pthread_t
*thread
)
2335 if (!is_good_object (thread
))
2338 if ((*thread
)->suspended
== false)
2340 (*thread
)->suspended
= true;
2341 SuspendThread ((*thread
)->win32_obj_id
);
2349 pthread::resume (pthread_t
*thread
)
2351 if (!is_good_object (thread
))
2354 if ((*thread
)->suspended
== true)
2355 ResumeThread ((*thread
)->win32_obj_id
);
2356 (*thread
)->suspended
= false;
2361 /* provided for source level compatability.
2362 See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2365 pthread_getconcurrency (void)
2367 return MT_INTERFACE
->concurrency
;
2370 /* keep this in sync with sched.cc */
2372 pthread_getschedparam (pthread_t thread
, int *policy
,
2373 struct sched_param
*param
)
2375 if (!pthread::is_good_object (&thread
))
2377 *policy
= SCHED_FIFO
;
2378 /* we don't return the current effective priority, we return the current
2379 requested priority */
2380 *param
= thread
->attr
.schedparam
;
2384 /* Thread Specific Data */
2386 pthread_key_create (pthread_key_t
*key
, void (*destructor
) (void *))
2388 /* The opengroup docs don't define if we should check this or not,
2389 but creation is relatively rare. */
2390 if (pthread_key::is_good_object (key
))
2393 *key
= new pthread_key (destructor
);
2395 if (!pthread_key::is_good_object (key
))
2405 pthread_key_delete (pthread_key_t key
)
2407 if (!pthread_key::is_good_object (&key
))
2414 /* provided for source level compatability. See
2415 http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2418 pthread_setconcurrency (int new_level
)
2422 MT_INTERFACE
->concurrency
= new_level
;
2426 /* keep syncronised with sched.cc */
2428 pthread_setschedparam (pthread_t thread
, int policy
,
2429 const struct sched_param
*param
)
2431 if (!pthread::is_good_object (&thread
))
2433 if (policy
!= SCHED_FIFO
)
2438 sched_set_thread_priority (thread
->win32_obj_id
, param
->sched_priority
);
2440 thread
->attr
.schedparam
.sched_priority
= param
->sched_priority
;
2446 pthread_setspecific (pthread_key_t key
, const void *value
)
2448 if (!pthread_key::is_good_object (&key
))
2455 pthread_getspecific (pthread_key_t key
)
2457 if (!pthread_key::is_good_object (&key
))
2460 return (key
)->get ();
2464 /* Thread synchronisation */
2466 pthread_cond::is_good_object (pthread_cond_t
const *cond
)
2468 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
) != VALID_OBJECT
)
2474 pthread_cond::is_good_initializer (pthread_cond_t
const *cond
)
2476 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) != VALID_STATIC_OBJECT
)
2482 pthread_cond::is_good_initializer_or_object (pthread_cond_t
const *cond
)
2484 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) == INVALID_OBJECT
)
2490 pthread_cond::is_good_initializer_or_bad_object (pthread_cond_t
const *cond
)
2492 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) == VALID_OBJECT
)
2498 pthread_cond_destroy (pthread_cond_t
*cond
)
2500 if (pthread_cond::is_good_initializer (cond
))
2502 if (!pthread_cond::is_good_object (cond
))
2505 /* reads are atomic */
2506 if ((*cond
)->waiting
)
2516 pthread_cond::init (pthread_cond_t
*cond
, const pthread_condattr_t
*attr
)
2519 pthread_cond_t new_cond
;
2521 if (attr
&& !pthread_condattr::is_good_object (attr
))
2524 cond_initialization_lock
.lock ();
2526 if (!is_good_initializer_or_bad_object (cond
))
2528 cond_initialization_lock
.unlock ();
2532 new_cond
= new pthread_cond (attr
? (*attr
) : NULL
);
2533 if (!is_good_object (&new_cond
))
2536 cond_initialization_lock
.unlock ();
2541 cond_initialization_lock
.unlock ();
2547 pthread_cond_broadcast (pthread_cond_t
*cond
)
2549 if (pthread_cond::is_good_initializer (cond
))
2551 if (!pthread_cond::is_good_object (cond
))
2554 (*cond
)->unblock (true);
2560 pthread_cond_signal (pthread_cond_t
*cond
)
2562 if (pthread_cond::is_good_initializer (cond
))
2564 if (!pthread_cond::is_good_object (cond
))
2567 (*cond
)->unblock (false);
2573 __pthread_cond_dowait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2576 if (!pthread_mutex::is_good_object (mutex
))
2578 if (!pthread_mutex::can_be_unlocked (mutex
))
2581 if (pthread_cond::is_good_initializer (cond
))
2582 pthread_cond::init (cond
, NULL
);
2583 if (!pthread_cond::is_good_object (cond
))
2586 return (*cond
)->wait (*mutex
, waitlength
);
2590 pthread_cond_timedwait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2591 const struct timespec
*abstime
)
2596 pthread_testcancel ();
2598 if (check_valid_pointer (abstime
))
2601 gettimeofday (&tv
, NULL
);
2602 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
2603 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
2606 return __pthread_cond_dowait (cond
, mutex
, waitlength
);
2610 pthread_cond_wait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
2612 pthread_testcancel ();
2614 return __pthread_cond_dowait (cond
, mutex
, INFINITE
);
2618 pthread_condattr_init (pthread_condattr_t
*condattr
)
2620 if (pthread_condattr::is_good_object (condattr
))
2623 *condattr
= new pthread_condattr
;
2624 if (!pthread_condattr::is_good_object (condattr
))
2634 pthread_condattr_getpshared (const pthread_condattr_t
*attr
, int *pshared
)
2636 if (!pthread_condattr::is_good_object (attr
))
2638 *pshared
= (*attr
)->shared
;
2643 pthread_condattr_setpshared (pthread_condattr_t
*attr
, int pshared
)
2645 if (!pthread_condattr::is_good_object (attr
))
2647 if ((pshared
< 0) || (pshared
> 1))
2649 /* shared cond vars not currently supported */
2650 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2652 (*attr
)->shared
= pshared
;
2657 pthread_condattr_destroy (pthread_condattr_t
*condattr
)
2659 if (!pthread_condattr::is_good_object (condattr
))
2668 pthread_rwlock::is_good_object (pthread_rwlock_t
const *rwlock
)
2670 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
) != VALID_OBJECT
)
2676 pthread_rwlock::is_good_initializer (pthread_rwlock_t
const *rwlock
)
2678 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) != VALID_STATIC_OBJECT
)
2684 pthread_rwlock::is_good_initializer_or_object (pthread_rwlock_t
const *rwlock
)
2686 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) == INVALID_OBJECT
)
2692 pthread_rwlock::is_good_initializer_or_bad_object (pthread_rwlock_t
const *rwlock
)
2694 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) == VALID_OBJECT
)
2700 pthread_rwlock_destroy (pthread_rwlock_t
*rwlock
)
2702 if (pthread_rwlock::is_good_initializer (rwlock
))
2704 if (!pthread_rwlock::is_good_object (rwlock
))
2707 if ((*rwlock
)->writer
|| (*rwlock
)->readers
||
2708 (*rwlock
)->waiting_readers
|| (*rwlock
)->waiting_writers
)
2718 pthread_rwlock::init (pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*attr
)
2720 pthread_rwlock_t new_rwlock
;
2722 if (attr
&& !pthread_rwlockattr::is_good_object (attr
))
2725 rwlock_initialization_lock
.lock ();
2727 if (!is_good_initializer_or_bad_object (rwlock
))
2729 rwlock_initialization_lock
.unlock ();
2733 new_rwlock
= new pthread_rwlock (attr
? (*attr
) : NULL
);
2734 if (!is_good_object (&new_rwlock
))
2737 rwlock_initialization_lock
.unlock ();
2741 *rwlock
= new_rwlock
;
2742 rwlock_initialization_lock
.unlock ();
2748 pthread_rwlock_rdlock (pthread_rwlock_t
*rwlock
)
2750 pthread_testcancel ();
2752 if (pthread_rwlock::is_good_initializer (rwlock
))
2753 pthread_rwlock::init (rwlock
, NULL
);
2754 if (!pthread_rwlock::is_good_object (rwlock
))
2757 return (*rwlock
)->rdlock ();
2761 pthread_rwlock_tryrdlock (pthread_rwlock_t
*rwlock
)
2763 if (pthread_rwlock::is_good_initializer (rwlock
))
2764 pthread_rwlock::init (rwlock
, NULL
);
2765 if (!pthread_rwlock::is_good_object (rwlock
))
2768 return (*rwlock
)->tryrdlock ();
2772 pthread_rwlock_wrlock (pthread_rwlock_t
*rwlock
)
2774 pthread_testcancel ();
2776 if (pthread_rwlock::is_good_initializer (rwlock
))
2777 pthread_rwlock::init (rwlock
, NULL
);
2778 if (!pthread_rwlock::is_good_object (rwlock
))
2781 return (*rwlock
)->wrlock ();
2785 pthread_rwlock_trywrlock (pthread_rwlock_t
*rwlock
)
2787 if (pthread_rwlock::is_good_initializer (rwlock
))
2788 pthread_rwlock::init (rwlock
, NULL
);
2789 if (!pthread_rwlock::is_good_object (rwlock
))
2792 return (*rwlock
)->trywrlock ();
2796 pthread_rwlock_unlock (pthread_rwlock_t
*rwlock
)
2798 if (pthread_rwlock::is_good_initializer (rwlock
))
2800 if (!pthread_rwlock::is_good_object (rwlock
))
2803 return (*rwlock
)->unlock ();
2807 pthread_rwlockattr_init (pthread_rwlockattr_t
*rwlockattr
)
2809 if (pthread_rwlockattr::is_good_object (rwlockattr
))
2812 *rwlockattr
= new pthread_rwlockattr
;
2813 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2815 delete (*rwlockattr
);
2823 pthread_rwlockattr_getpshared (const pthread_rwlockattr_t
*attr
, int *pshared
)
2825 if (!pthread_rwlockattr::is_good_object (attr
))
2827 *pshared
= (*attr
)->shared
;
2832 pthread_rwlockattr_setpshared (pthread_rwlockattr_t
*attr
, int pshared
)
2834 if (!pthread_rwlockattr::is_good_object (attr
))
2836 if ((pshared
< 0) || (pshared
> 1))
2838 /* shared rwlock vars not currently supported */
2839 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2841 (*attr
)->shared
= pshared
;
2846 pthread_rwlockattr_destroy (pthread_rwlockattr_t
*rwlockattr
)
2848 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2850 delete (*rwlockattr
);
2857 pthread_kill (pthread_t thread
, int sig
)
2859 // lock myself, for the use of thread2signal
2860 // two different kills might clash: FIXME
2862 if (!pthread::is_good_object (&thread
))
2867 si
.si_code
= SI_USER
;
2868 si
.si_pid
= si
.si_uid
= si
.si_errno
= 0;
2869 thread
->cygtls
->set_threadkill ();
2870 int rval
= sig
? sig_send (NULL
, si
, thread
->cygtls
) : 0;
2877 pthread_sigmask (int operation
, const sigset_t
*set
, sigset_t
*old_set
)
2879 return handle_sigprocmask (operation
, set
, old_set
, _my_tls
.sigmask
);
2885 pthread_equal (pthread_t t1
, pthread_t t2
)
2887 return pthread::equal (t1
, t2
);
2893 pthread_mutex::init (pthread_mutex_t
*mutex
,
2894 const pthread_mutexattr_t
*attr
,
2895 const pthread_mutex_t initializer
)
2897 pthread_mutex_t new_mutex
;
2899 if (attr
&& !pthread_mutexattr::is_good_object (attr
) || check_valid_pointer (mutex
))
2902 mutex_initialization_lock
.lock ();
2904 if (!is_good_initializer_or_bad_object (mutex
))
2906 mutex_initialization_lock
.unlock ();
2910 new_mutex
= new pthread_mutex (attr
? (*attr
) : NULL
);
2911 if (!is_good_object (&new_mutex
))
2914 mutex_initialization_lock
.unlock ();
2918 if (!attr
&& initializer
)
2920 if (initializer
== PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
)
2921 new_mutex
->type
= PTHREAD_MUTEX_RECURSIVE
;
2922 else if (initializer
== PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
)
2923 new_mutex
->type
= PTHREAD_MUTEX_NORMAL
;
2924 else if (initializer
== PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
)
2925 new_mutex
->type
= PTHREAD_MUTEX_ERRORCHECK
;
2929 mutex_initialization_lock
.unlock ();
2935 pthread_mutex_getprioceiling (const pthread_mutex_t
*mutex
,
2938 /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
2941 We can support mutex priorities in the future though:
2942 Store a priority with each mutex.
2943 When the mutex is optained, set the thread priority as appropriate
2944 When the mutex is released, reset the thread priority. */
2949 pthread_mutex_lock (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
)->lock ();
2959 pthread_mutex_trylock (pthread_mutex_t
*mutex
)
2961 if (pthread_mutex::is_good_initializer (mutex
))
2962 pthread_mutex::init (mutex
, NULL
, *mutex
);
2963 if (!pthread_mutex::is_good_object (mutex
))
2965 return (*mutex
)->trylock ();
2969 pthread_mutex_unlock (pthread_mutex_t
*mutex
)
2971 if (pthread_mutex::is_good_initializer (mutex
))
2973 if (!pthread_mutex::is_good_object (mutex
))
2975 return (*mutex
)->unlock ();
2979 pthread_mutex_destroy (pthread_mutex_t
*mutex
)
2983 if (pthread_mutex::is_good_initializer (mutex
))
2985 if (!pthread_mutex::is_good_object (mutex
))
2988 rv
= (*mutex
)->destroy ();
2997 pthread_mutex_setprioceiling (pthread_mutex_t
*mutex
, int prioceiling
,
3003 /* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
3006 pthread_mutexattr_getprotocol (const pthread_mutexattr_t
*attr
,
3009 if (!pthread_mutexattr::is_good_object (attr
))
3015 pthread_mutexattr_getpshared (const pthread_mutexattr_t
*attr
,
3018 if (!pthread_mutexattr::is_good_object (attr
))
3020 *pshared
= (*attr
)->pshared
;
3025 pthread_mutexattr_gettype (const pthread_mutexattr_t
*attr
, int *type
)
3027 if (!pthread_mutexattr::is_good_object (attr
))
3029 *type
= (*attr
)->mutextype
;
3033 /* FIXME: write and test process shared mutex's. */
3035 pthread_mutexattr_init (pthread_mutexattr_t
*attr
)
3037 if (pthread_mutexattr::is_good_object (attr
))
3040 *attr
= new pthread_mutexattr ();
3041 if (!pthread_mutexattr::is_good_object (attr
))
3051 pthread_mutexattr_destroy (pthread_mutexattr_t
*attr
)
3053 if (!pthread_mutexattr::is_good_object (attr
))
3061 /* Win32 doesn't support mutex priorities */
3063 pthread_mutexattr_setprotocol (pthread_mutexattr_t
*attr
, int protocol
)
3065 if (!pthread_mutexattr::is_good_object (attr
))
3070 /* Win32 doesn't support mutex priorities */
3072 pthread_mutexattr_setprioceiling (pthread_mutexattr_t
*attr
,
3075 if (!pthread_mutexattr::is_good_object (attr
))
3081 pthread_mutexattr_getprioceiling (const pthread_mutexattr_t
*attr
,
3084 if (!pthread_mutexattr::is_good_object (attr
))
3090 pthread_mutexattr_setpshared (pthread_mutexattr_t
*attr
, int pshared
)
3092 if (!pthread_mutexattr::is_good_object (attr
))
3094 /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
3097 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
3099 (*attr
)->pshared
= pshared
;
3103 /* see pthread_mutex_gettype */
3105 pthread_mutexattr_settype (pthread_mutexattr_t
*attr
, int type
)
3107 if (!pthread_mutexattr::is_good_object (attr
))
3112 case PTHREAD_MUTEX_ERRORCHECK
:
3113 case PTHREAD_MUTEX_RECURSIVE
:
3114 case PTHREAD_MUTEX_NORMAL
:
3115 (*attr
)->mutextype
= type
;
3126 /* static members */
3128 semaphore::is_good_object (sem_t
const * sem
)
3130 if (verifyable_object_isvalid (sem
, SEM_MAGIC
) != VALID_OBJECT
)
3136 semaphore::init (sem_t
*sem
, int pshared
, unsigned int value
)
3138 /* opengroup calls this undefined */
3139 if (is_good_object (sem
))
3142 if (value
> SEM_VALUE_MAX
)
3145 *sem
= new semaphore (pshared
, value
);
3147 if (!is_good_object (sem
))
3157 semaphore::destroy (sem_t
*sem
)
3159 if (!is_good_object (sem
))
3162 /* FIXME - new feature - test for busy against threads... */
3170 semaphore::open (const char *name
, int oflag
, mode_t mode
, unsigned int value
)
3172 if (value
> SEM_VALUE_MAX
)
3178 sem_t
*sem
= new sem_t
;
3185 *sem
= new semaphore (name
, oflag
, mode
, value
);
3187 if (!is_good_object (sem
))
3197 semaphore::wait (sem_t
*sem
)
3199 pthread_testcancel ();
3201 if (!is_good_object (sem
))
3207 return (*sem
)->_wait ();
3211 semaphore::trywait (sem_t
*sem
)
3213 if (!is_good_object (sem
))
3219 return (*sem
)->_trywait ();
3223 semaphore::timedwait (sem_t
*sem
, const struct timespec
*abstime
)
3225 if (!is_good_object (sem
))
3231 return (*sem
)->_timedwait (abstime
);
3235 semaphore::post (sem_t
*sem
)
3237 if (!is_good_object (sem
))
3248 semaphore::getvalue (sem_t
*sem
, int *sval
)
3251 if (!is_good_object (sem
)
3252 || __check_null_invalid_struct (sval
, sizeof (int)))
3258 return (*sem
)->_getvalue (sval
);
3263 pthread_null::get_null_pthread ()
3265 /* because of weird entry points */
3266 _instance
.magic
= 0;
3270 pthread_null::pthread_null ()
3272 attr
.joinable
= PTHREAD_CREATE_DETACHED
;
3273 /* Mark ourselves as invalid */
3277 pthread_null::~pthread_null ()
3282 pthread_null::create (void *(*)(void *), pthread_attr
*, void *)
3287 pthread_null::exit (void *value_ptr
)
3293 pthread_null::cancel ()
3299 pthread_null::testcancel ()
3304 pthread_null::setcancelstate (int state
, int *oldstate
)
3310 pthread_null::setcanceltype (int type
, int *oldtype
)
3316 pthread_null::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
3321 pthread_null::pop_cleanup_handler (int const execute
)
3326 pthread_null::getsequence_np ()
3331 pthread_null
pthread_null::_instance
;