1 /* thread.cc: Locking and threading module functions
3 Copyright 1998, 1999, 2000, 2001, 2002, 2003 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. */
40 #include "perprocess.h"
43 #include <semaphore.h>
45 #include <sys/timeb.h>
46 #include <exceptions.h>
47 #include <sys/fcntl.h>
49 extern int threadsafe
;
51 extern "C" struct _reent
*
54 struct __reent_t
*_r
=
55 (struct __reent_t
*) MT_INTERFACE
->reent_key
.get ();
59 #ifdef _CYG_THREAD_FAILSAFE
60 system_printf ("local thread storage not inited");
62 /* Return _impure_ptr as long as MTinterface is not initialized */
72 struct __reent_t
*_r
=
73 (struct __reent_t
*) MT_INTERFACE
->reent_key
.get ();
77 #ifdef _CYG_THREAD_FAILSAFE
78 system_printf ("local thread storage not inited");
86 inline LPCRITICAL_SECTION
87 ResourceLocks::Lock (int _resid
)
89 #ifdef _CYG_THREAD_FAILSAFE
91 system_printf ("lock called before initialization");
94 ("Get Resource lock %d ==> %p for %p , real : %d , threadid %d ", _resid
,
95 &lock
, user_data
, myself
->pid
, GetCurrentThreadId ());
101 SetResourceLock (int _res_id
, int _mode
, const char *_function
)
103 #ifdef _CYG_THREAD_FAILSAFE
104 thread_printf ("Set resource lock %d mode %d for %s start",
105 _res_id
, _mode
, _function
);
107 EnterCriticalSection (user_data
->resourcelocks
->Lock (_res_id
));
109 #ifdef _CYG_THREAD_FAILSAFE
110 user_data
->resourcelocks
->owner
= GetCurrentThreadId ();
111 user_data
->resourcelocks
->count
++;
116 ReleaseResourceLock (int _res_id
, int _mode
, const char *_function
)
118 #ifdef _CYG_THREAD_FAILSAFE
119 thread_printf ("Release resource lock %d mode %d for %s done", _res_id
,
122 AssertResourceOwner (_res_id
, _mode
);
123 user_data
->resourcelocks
->count
--;
124 if (user_data
->resourcelocks
->count
== 0)
125 user_data
->resourcelocks
->owner
= 0;
128 LeaveCriticalSection (user_data
->resourcelocks
->Lock (_res_id
));
131 #ifdef _CYG_THREAD_FAILSAFE
133 AssertResourceOwner (int _res_id
, int _mode
)
137 ("Assert Resource lock %d ==> for %p , real : %d , threadid %d count %d owner %d",
138 _res_id
, user_data
, myself
->pid
, GetCurrentThreadId (),
139 user_data
->resourcelocks
->count
, user_data
->resourcelocks
->owner
);
140 if (user_data
&& (user_data
->resourcelocks
->owner
!= GetCurrentThreadId ()))
141 system_printf ("assertion failed, not the resource owner");
147 ResourceLocks::Init ()
149 InitializeCriticalSection (&lock
);
152 #ifdef _CYG_THREAD_FAILSAFE
157 thread_printf ("lock %p inited by %p , %d", &lock
, user_data
, myself
->pid
);
161 ResourceLocks::Delete ()
165 thread_printf ("Close Resource Locks %p ", &lock
);
166 DeleteCriticalSection (&lock
);
174 reents
._clib
= _impure_ptr
;
175 reents
._winsup
= &winsup_reent
;
176 winsup_reent
._process_logmask
= LOG_UPTO (LOG_DEBUG
);
177 reent_key
.set (&reents
);
179 pthread_mutex::init_mutex ();
180 pthread_cond::init_mutex ();
181 pthread_rwlock::init_mutex ();
185 MTinterface::fixup_before_fork (void)
187 pthread_key::fixup_before_fork ();
190 /* This function is called from a single threaded process */
192 MTinterface::fixup_after_fork (void)
194 pthread_key::fixup_after_fork ();
196 /* As long as the signal handling not multithreaded
197 switch reents storage back to _impure_ptr for the mainthread
198 to support fork from threads other than the mainthread */
199 reents
._clib
= _impure_ptr
;
200 reents
._winsup
= &winsup_reent
;
201 winsup_reent
._process_logmask
= LOG_UPTO (LOG_DEBUG
);
202 reent_key
.set (&reents
);
205 pthread::init_mainthread ();
207 pthread::fixup_after_fork ();
208 pthread_mutex::fixup_after_fork ();
209 pthread_cond::fixup_after_fork ();
210 pthread_rwlock::fixup_after_fork ();
211 semaphore::fixup_after_fork ();
218 pthread::init_mainthread ()
220 pthread
*thread
= get_tls_self_pointer ();
223 thread
= new pthread ();
225 api_fatal ("failed to create mainthread object");
228 thread
->cygtls
= &_my_tls
;
229 _my_tls
.tid
= thread
;
230 thread
->thread_id
= GetCurrentThreadId ();
231 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
232 GetCurrentProcess (), &thread
->win32_obj_id
,
233 0, FALSE
, DUPLICATE_SAME_ACCESS
))
234 thread
->win32_obj_id
= NULL
;
235 thread
->set_tls_self_pointer ();
236 thread
->postcreate ();
242 pthread
*thread
= get_tls_self_pointer ();
245 return pthread_null::get_null_pthread ();
249 pthread::set_tls_self_pointer ()
251 MT_INTERFACE
->thread_self_key
.set (this);
255 pthread::get_tls_self_pointer ()
257 return (pthread
*) MT_INTERFACE
->thread_self_key
.get ();
262 List
<pthread
> pthread::threads
;
265 pthread::pthread ():verifyable_object (PTHREAD_MAGIC
), win32_obj_id (0),
266 valid (false), suspended (false),
267 cancelstate (0), canceltype (0), cancel_event (0),
268 joiner (NULL
), next (NULL
), cleanup_stack (NULL
)
270 if (this != pthread_null::get_null_pthread ())
271 threads
.insert (this);
277 CloseHandle (win32_obj_id
);
279 CloseHandle (cancel_event
);
281 if (this != pthread_null::get_null_pthread ())
282 threads
.remove (this);
286 pthread::precreate (pthread_attr
*newattr
)
288 pthread_mutex
*verifyable_mutex_obj
= &mutex
;
290 /* already running ? */
296 attr
.joinable
= newattr
->joinable
;
297 attr
.contentionscope
= newattr
->contentionscope
;
298 attr
.inheritsched
= newattr
->inheritsched
;
299 attr
.stacksize
= newattr
->stacksize
;
302 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
304 thread_printf ("New thread object access mutex is not valid. this %p",
309 /* Change the mutex type to NORMAL to speed up mutex operations */
310 mutex
.type
= PTHREAD_MUTEX_NORMAL
;
312 cancel_event
= ::CreateEvent (&sec_none_nih
, TRUE
, FALSE
, NULL
);
315 system_printf ("couldn't create cancel event, this %p LastError %E", this);
316 /* we need the event for correct behaviour */
323 pthread::create (void *(*func
) (void *), pthread_attr
*newattr
,
333 win32_obj_id
= ::CreateThread (&sec_none_nih
, attr
.stacksize
,
334 (LPTHREAD_START_ROUTINE
) thread_init_wrapper
,
335 this, CREATE_SUSPENDED
, &thread_id
);
339 thread_printf ("CreateThread failed: this %p, %E", this);
345 ResumeThread (win32_obj_id
);
350 pthread::postcreate ()
352 cancel_event
= ::CreateEvent (&sec_none_nih
, TRUE
, FALSE
, NULL
);
355 system_printf ("couldn't create cancel event for main thread, %E");
356 /* we need the event for correct behaviour */
363 InterlockedIncrement (&MT_INTERFACE
->threadcount
);
364 /* FIXME: set the priority appropriately for system contention scope */
365 if (attr
.inheritsched
== PTHREAD_EXPLICIT_SCHED
)
367 /* FIXME: set the scheduling settings for the new thread */
368 /* sched_thread_setparam (win32_obj_id, attr.schedparam); */
373 pthread::exit (void *value_ptr
)
375 class pthread
*thread
= this;
377 // run cleanup handlers
378 pop_all_cleanup_handlers ();
380 pthread_key::run_all_destructors ();
383 // cleanup if thread is in detached state and not joined
384 if (equal (joiner
, thread
))
389 return_ptr
= value_ptr
;
393 (_reclaim_reent
) (_REENT
);
395 if (InterlockedDecrement (&MT_INTERFACE
->threadcount
) == 0)
402 pthread::cancel (void)
404 class pthread
*thread
= this;
405 class pthread
*self
= pthread::self ();
415 if (canceltype
== PTHREAD_CANCEL_DEFERRED
||
416 cancelstate
== PTHREAD_CANCEL_DISABLE
)
420 SetEvent (cancel_event
);
423 else if (equal (thread
, self
))
427 return 0; // Never reached
430 // cancel asynchronous
431 SuspendThread (win32_obj_id
);
432 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
435 context
.ContextFlags
= CONTEXT_CONTROL
;
436 GetThreadContext (win32_obj_id
, &context
);
437 context
.Eip
= (DWORD
) pthread::static_cancel_self
;
438 SetThreadContext (win32_obj_id
, &context
);
441 ResumeThread (win32_obj_id
);
445 TODO: insert pthread_testcancel into the required functions
446 the required function list is: *indicates done, X indicates not present in cygwin.
465 *pthread_cond_timedwait ()
466 *pthread_cond_wait ()
468 *pthread_testcancel ()
492 the optional list is:
612 Note, that for fcntl (), for any value of the cmd argument.
614 And we must not introduce cancellation points anywhere else that's part of the posix or
620 pthread::testcancel (void)
622 if (cancelstate
== PTHREAD_CANCEL_DISABLE
)
625 if (WaitForSingleObject (cancel_event
, 0) == WAIT_OBJECT_0
)
630 pthread::static_cancel_self (void)
632 pthread::self ()->cancel_self ();
637 pthread::cancelable_wait (HANDLE object
, DWORD timeout
, const bool do_cancel
)
640 HANDLE wait_objects
[2];
641 pthread_t thread
= self ();
643 if (!is_good_object (&thread
) || thread
->cancelstate
== PTHREAD_CANCEL_DISABLE
)
644 return WaitForSingleObject (object
, timeout
);
646 // Do not change the wait order
647 // The object must have higher priority than the cancel event,
648 // because WaitForMultipleObjects will return the smallest index
649 // if both objects are signaled
650 wait_objects
[0] = object
;
651 wait_objects
[1] = thread
->cancel_event
;
653 res
= WaitForMultipleObjects (2, wait_objects
, FALSE
, timeout
);
654 if (do_cancel
&& res
== WAIT_CANCELED
)
655 pthread::static_cancel_self ();
660 pthread::setcancelstate (int state
, int *oldstate
)
666 if (state
!= PTHREAD_CANCEL_ENABLE
&& state
!= PTHREAD_CANCEL_DISABLE
)
671 *oldstate
= cancelstate
;
681 pthread::setcanceltype (int type
, int *oldtype
)
687 if (type
!= PTHREAD_CANCEL_DEFERRED
&& type
!= PTHREAD_CANCEL_ASYNCHRONOUS
)
692 *oldtype
= canceltype
;
702 pthread::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
706 api_fatal ("Attempt to push a cleanup handler across threads");
707 handler
->next
= cleanup_stack
;
708 cleanup_stack
= handler
;
712 pthread::pop_cleanup_handler (int const execute
)
715 // TODO: send a signal or something to the thread ?
716 api_fatal ("Attempt to execute a cleanup handler across threads");
720 if (cleanup_stack
!= NULL
)
722 __pthread_cleanup_handler
*handler
= cleanup_stack
;
725 (*handler
->function
) (handler
->arg
);
726 cleanup_stack
= handler
->next
;
733 pthread::pop_all_cleanup_handlers ()
735 while (cleanup_stack
!= NULL
)
736 pop_cleanup_handler (1);
740 pthread::cancel_self ()
742 exit (PTHREAD_CANCELED
);
746 pthread::get_thread_id ()
752 pthread::_fixup_after_fork ()
754 /* set thread to not running if it is not the forking thread */
755 if (this != pthread::self ())
765 pthread::suspend_except_self ()
767 if (valid
&& this != pthread::self ())
768 SuspendThread (win32_obj_id
);
775 ResumeThread (win32_obj_id
);
780 pthread_attr::is_good_object (pthread_attr_t
const *attr
)
782 if (verifyable_object_isvalid (attr
, PTHREAD_ATTR_MAGIC
) != VALID_OBJECT
)
787 /* instance members */
789 pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC
),
790 joinable (PTHREAD_CREATE_JOINABLE
), contentionscope (PTHREAD_SCOPE_PROCESS
),
791 inheritsched (PTHREAD_INHERIT_SCHED
), stacksize (0)
793 schedparam
.sched_priority
= 0;
796 pthread_attr::~pthread_attr ()
801 pthread_condattr::is_good_object (pthread_condattr_t
const *attr
)
803 if (verifyable_object_isvalid (attr
, PTHREAD_CONDATTR_MAGIC
) != VALID_OBJECT
)
808 pthread_condattr::pthread_condattr ():verifyable_object
809 (PTHREAD_CONDATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
813 pthread_condattr::~pthread_condattr ()
817 List
<pthread_cond
> pthread_cond::conds
;
819 /* This is used for cond creation protection within a single process only */
820 fast_mutex NO_COPY
pthread_cond::cond_initialization_lock
;
822 /* We can only be called once.
823 TODO: (no rush) use a non copied memory section to
824 hold an initialization flag. */
826 pthread_cond::init_mutex ()
828 if (!cond_initialization_lock
.init ())
829 api_fatal ("Could not create win32 Mutex for pthread cond static initializer support.");
832 pthread_cond::pthread_cond (pthread_condattr
*attr
) :
833 verifyable_object (PTHREAD_COND_MAGIC
),
834 shared (0), waiting (0), pending (0), sem_wait (NULL
),
835 mtx_cond(NULL
), next (NULL
)
837 pthread_mutex
*verifyable_mutex_obj
;
840 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
846 verifyable_mutex_obj
= &mtx_in
;
847 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
849 thread_printf ("Internal cond mutex is not valid. this %p", this);
854 * Change the mutex type to NORMAL.
855 * This mutex MUST be of type normal
857 mtx_in
.type
= PTHREAD_MUTEX_NORMAL
;
859 verifyable_mutex_obj
= &mtx_out
;
860 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
862 thread_printf ("Internal cond mutex is not valid. this %p", this);
866 /* Change the mutex type to NORMAL to speed up mutex operations */
867 mtx_out
.type
= PTHREAD_MUTEX_NORMAL
;
869 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
872 debug_printf ("CreateSemaphore failed. %E");
880 pthread_cond::~pthread_cond ()
883 CloseHandle (sem_wait
);
889 pthread_cond::unblock (const bool all
)
891 unsigned long releaseable
;
894 * Block outgoing threads (and avoid simultanous unblocks)
898 releaseable
= waiting
- pending
;
901 unsigned long released
;
906 * Block incoming threads until all waiting threads are released.
911 * Calculate releaseable again because threads can enter until
912 * the semaphore has been taken, but they can not leave, therefore pending
913 * is unchanged and releaseable can only get higher
915 releaseable
= waiting
- pending
;
918 released
= all
? releaseable
: 1;
923 ::ReleaseSemaphore (sem_wait
, released
, NULL
);
927 * And let the threads release.
933 pthread_cond::wait (pthread_mutex_t mutex
, DWORD dwMilliseconds
)
938 if (InterlockedIncrement ((long *)&waiting
) == 1)
940 else if (mtx_cond
!= mutex
)
942 InterlockedDecrement ((long *)&waiting
);
949 * Release the mutex and wait on semaphore
954 rv
= pthread::cancelable_wait (sem_wait
, dwMilliseconds
, false);
958 if (rv
!= WAIT_OBJECT_0
)
961 * It might happen that a signal is sent while the thread got canceled
962 * or timed out. Try to take one.
963 * If the thread gets one than a signal|broadcast is in progress.
965 if (WaitForSingleObject (sem_wait
, 0) == WAIT_OBJECT_0
)
967 * thread got cancelled ot timed out while a signalling is in progress.
968 * Set wait result back to signaled
973 InterlockedDecrement ((long *)&waiting
);
975 if (rv
== WAIT_OBJECT_0
&& --pending
== 0)
977 * All signaled threads are released,
978 * new threads can enter Wait
987 if (rv
== WAIT_CANCELED
)
988 pthread::static_cancel_self ();
989 else if (rv
== WAIT_TIMEOUT
)
996 pthread_cond::_fixup_after_fork ()
998 waiting
= pending
= 0;
1001 /* Unlock eventually locked mutexes */
1005 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1007 api_fatal ("pthread_cond::_fixup_after_fork () failed to recreate win32 semaphore");
1011 pthread_rwlockattr::is_good_object (pthread_rwlockattr_t
const *attr
)
1013 if (verifyable_object_isvalid (attr
, PTHREAD_RWLOCKATTR_MAGIC
) != VALID_OBJECT
)
1018 pthread_rwlockattr::pthread_rwlockattr ():verifyable_object
1019 (PTHREAD_RWLOCKATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
1023 pthread_rwlockattr::~pthread_rwlockattr ()
1027 List
<pthread_rwlock
> pthread_rwlock::rwlocks
;
1029 /* This is used for rwlock creation protection within a single process only */
1030 fast_mutex NO_COPY
pthread_rwlock::rwlock_initialization_lock
;
1032 /* We can only be called once.
1033 TODO: (no rush) use a non copied memory section to
1034 hold an initialization flag. */
1036 pthread_rwlock::init_mutex ()
1038 if (!rwlock_initialization_lock
.init ())
1039 api_fatal ("Could not create win32 Mutex for pthread rwlock static initializer support.");
1042 pthread_rwlock::pthread_rwlock (pthread_rwlockattr
*attr
) :
1043 verifyable_object (PTHREAD_RWLOCK_MAGIC
),
1044 shared (0), waiting_readers (0), waiting_writers (0), writer (NULL
),
1045 readers (NULL
), readers_mx (), mtx (NULL
), cond_readers (NULL
), cond_writers (NULL
),
1048 pthread_mutex
*verifyable_mutex_obj
= &mtx
;
1049 pthread_cond
*verifyable_cond_obj
;
1051 if (!readers_mx
.init ())
1053 thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this);
1059 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
1065 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1067 thread_printf ("Internal rwlock mutex is not valid. this %p", this);
1071 /* Change the mutex type to NORMAL to speed up mutex operations */
1072 mtx
.type
= PTHREAD_MUTEX_NORMAL
;
1074 verifyable_cond_obj
= &cond_readers
;
1075 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1077 thread_printf ("Internal rwlock readers cond is not valid. this %p", this);
1082 verifyable_cond_obj
= &cond_writers
;
1083 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1085 thread_printf ("Internal rwlock writers cond is not valid. this %p", this);
1091 rwlocks
.insert (this);
1094 pthread_rwlock::~pthread_rwlock ()
1096 rwlocks
.remove (this);
1100 pthread_rwlock::rdlock ()
1103 struct RWLOCK_READER
*reader
;
1104 pthread_t self
= pthread::self ();
1108 if (lookup_reader (self
))
1114 reader
= new struct RWLOCK_READER
;
1121 while (writer
|| waiting_writers
)
1123 pthread_cleanup_push (pthread_rwlock::rdlock_cleanup
, this);
1126 cond_readers
.wait (&mtx
);
1129 pthread_cleanup_pop (0);
1132 reader
->thread
= self
;
1133 add_reader (reader
);
1142 pthread_rwlock::tryrdlock ()
1145 pthread_t self
= pthread::self ();
1149 if (writer
|| waiting_writers
|| lookup_reader (self
))
1153 struct RWLOCK_READER
*reader
= new struct RWLOCK_READER
;
1156 reader
->thread
= self
;
1157 add_reader (reader
);
1169 pthread_rwlock::wrlock ()
1172 pthread_t self
= pthread::self ();
1176 if (writer
== self
|| lookup_reader (self
))
1182 while (writer
|| readers
)
1184 pthread_cleanup_push (pthread_rwlock::wrlock_cleanup
, this);
1187 cond_writers
.wait (&mtx
);
1190 pthread_cleanup_pop (0);
1202 pthread_rwlock::trywrlock ()
1205 pthread_t self
= pthread::self ();
1209 if (writer
|| readers
)
1220 pthread_rwlock::unlock ()
1223 pthread_t self
= pthread::self ();
1239 struct RWLOCK_READER
*reader
= lookup_reader (self
);
1247 remove_reader (reader
);
1260 pthread_rwlock::add_reader (struct RWLOCK_READER
*rd
)
1262 List_insert (readers
, rd
);
1266 pthread_rwlock::remove_reader (struct RWLOCK_READER
*rd
)
1268 List_remove (readers_mx
, readers
, rd
);
1271 struct pthread_rwlock::RWLOCK_READER
*
1272 pthread_rwlock::lookup_reader (pthread_t thread
)
1276 struct RWLOCK_READER
*cur
= readers
;
1278 while (cur
&& cur
->thread
!= thread
)
1281 readers_mx
.unlock ();
1287 pthread_rwlock::rdlock_cleanup (void *arg
)
1289 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1291 --(rwlock
->waiting_readers
);
1293 rwlock
->mtx
.unlock ();
1297 pthread_rwlock::wrlock_cleanup (void *arg
)
1299 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1301 --(rwlock
->waiting_writers
);
1303 rwlock
->mtx
.unlock ();
1307 pthread_rwlock::_fixup_after_fork ()
1309 pthread_t self
= pthread::self ();
1310 struct RWLOCK_READER
**temp
= &readers
;
1312 waiting_readers
= 0;
1313 waiting_writers
= 0;
1315 if (!readers_mx
.init ())
1316 api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex");
1318 /* Unlock eventually locked mutex */
1321 * Remove all readers except self
1325 if ((*temp
)->thread
== self
)
1326 temp
= &((*temp
)->next
);
1329 struct RWLOCK_READER
*cur
= *temp
;
1330 *temp
= (*temp
)->next
;
1337 /* static members */
1338 /* This stores pthread_key information across fork() boundaries */
1339 List
<pthread_key
> pthread_key::keys
;
1342 pthread_key::is_good_object (pthread_key_t
const *key
)
1344 if (verifyable_object_isvalid (key
, PTHREAD_KEY_MAGIC
) != VALID_OBJECT
)
1349 /* non-static members */
1351 pthread_key::pthread_key (void (*aDestructor
) (void *)):verifyable_object (PTHREAD_KEY_MAGIC
), destructor (aDestructor
)
1353 tls_index
= TlsAlloc ();
1354 if (tls_index
== TLS_OUT_OF_INDEXES
)
1360 pthread_key::~pthread_key ()
1362 /* We may need to make the list code lock the list during operations
1367 TlsFree (tls_index
);
1372 pthread_key::set (const void *value
)
1374 /* the OS function doesn't perform error checking */
1375 TlsSetValue (tls_index
, (void *) value
);
1380 pthread_key::get () const
1382 int saved_error
= ::GetLastError ();
1383 void *result
= TlsGetValue (tls_index
);
1384 ::SetLastError (saved_error
);
1389 pthread_key::_fixup_before_fork ()
1395 pthread_key::_fixup_after_fork ()
1397 tls_index
= TlsAlloc ();
1398 if (tls_index
== TLS_OUT_OF_INDEXES
)
1399 api_fatal ("pthread_key::recreate_key_from_buffer () failed to reallocate Tls storage");
1404 pthread_key::run_destructor ()
1408 void *oldValue
= get ();
1412 destructor (oldValue
);
1419 REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
1420 gymnastics can be a lot easier.
1422 the mutex_t (size 4) is not used as a verifyable object because we cannot
1423 guarantee the same address space for all processes.
1424 we use the following:
1425 high bit set (never a valid address).
1426 second byte is reserved for the priority.
1427 third byte is reserved
1428 fourth byte is the mutex id. (max 255 cygwin mutexs system wide).
1429 creating mutex's does get slower and slower, but as creation is a one time
1430 job, it should never become an issue
1432 And if you're looking at this and thinking, why not an array in cygwin for all mutexs,
1433 - you incur a penalty on _every_ mutex call and you have toserialise them all.
1436 option 2? put everything in userspace and update the ABI?
1437 - bad karma as well - the HANDLE, while identical across process's,
1438 Isn't duplicated, it's reopened. */
1440 /* static members */
1442 pthread_mutex::is_good_object (pthread_mutex_t
const *mutex
)
1444 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
) != VALID_OBJECT
)
1450 pthread_mutex::is_good_initializer (pthread_mutex_t
const *mutex
)
1452 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
, PTHREAD_MUTEX_INITIALIZER
) != 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
, PTHREAD_MUTEX_INITIALIZER
) == INVALID_OBJECT
)
1466 pthread_mutex::is_good_initializer_or_bad_object (pthread_mutex_t
const *mutex
)
1468 verifyable_object_state objectState
= verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
, PTHREAD_MUTEX_INITIALIZER
);
1469 if (objectState
== VALID_OBJECT
)
1475 pthread_mutex::can_be_unlocked (pthread_mutex_t
const *mutex
)
1477 pthread_t self
= pthread::self ();
1479 if (!is_good_object (mutex
))
1482 * Check if the mutex is owned by the current thread and can be unlocked
1484 return ((*mutex
)->recursion_counter
== 1 && pthread::equal ((*mutex
)->owner
, self
));
1487 List
<pthread_mutex
> pthread_mutex::mutexes
;
1489 /* This is used for mutex creation protection within a single process only */
1490 fast_mutex NO_COPY
pthread_mutex::mutex_initialization_lock
;
1492 /* We can only be called once.
1493 TODO: (no rush) use a non copied memory section to
1494 hold an initialization flag. */
1496 pthread_mutex::init_mutex ()
1498 if (!mutex_initialization_lock
.init ())
1499 api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support.");
1502 pthread_mutex::pthread_mutex (pthread_mutexattr
*attr
) :
1503 verifyable_object (PTHREAD_MUTEX_MAGIC
),
1505 win32_obj_id (NULL
), recursion_counter (0),
1506 condwaits (0), owner (NULL
), type (PTHREAD_MUTEX_DEFAULT
),
1507 pshared (PTHREAD_PROCESS_PRIVATE
)
1509 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1515 /*attr checked in the C call */
1518 if (attr
->pshared
== PTHREAD_PROCESS_SHARED
)
1525 type
= attr
->mutextype
;
1528 mutexes
.insert (this);
1531 pthread_mutex::~pthread_mutex ()
1534 CloseHandle (win32_obj_id
);
1536 mutexes
.remove (this);
1540 pthread_mutex::_lock (pthread_t self
)
1544 if (InterlockedIncrement ((long *)&lock_counter
) == 1)
1546 else if (type
!= PTHREAD_MUTEX_NORMAL
&& pthread::equal (owner
, self
))
1548 InterlockedDecrement ((long *) &lock_counter
);
1549 if (type
== PTHREAD_MUTEX_RECURSIVE
)
1550 result
= lock_recursive ();
1556 WaitForSingleObject (win32_obj_id
, INFINITE
);
1564 pthread_mutex::_trylock (pthread_t self
)
1568 if (InterlockedCompareExchange ((long *) &lock_counter
, 1, 0) == 0)
1570 else if (type
== PTHREAD_MUTEX_RECURSIVE
&& pthread::equal (owner
, self
))
1571 result
= lock_recursive ();
1579 pthread_mutex::_unlock (pthread_t self
)
1581 if (!pthread::equal (owner
, self
))
1584 if (--recursion_counter
== 0)
1587 if (InterlockedDecrement ((long *)&lock_counter
))
1588 // Another thread is waiting
1589 ::ReleaseSemaphore (win32_obj_id
, 1, NULL
);
1596 pthread_mutex::_destroy (pthread_t self
)
1598 if (condwaits
|| _trylock (self
))
1599 // Do not destroy a condwaited or locked mutex
1601 else if (recursion_counter
!= 1)
1603 // Do not destroy a recursive locked mutex
1604 --recursion_counter
;
1613 pthread_mutex::_fixup_after_fork ()
1615 debug_printf ("mutex %x in _fixup_after_fork", this);
1616 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1617 api_fatal ("pthread_mutex::_fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's");
1620 /* mutex has no owner, reset to initial */
1622 else if (lock_counter
!= 0)
1623 /* All waiting threads are gone after a fork */
1626 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1628 api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 semaphore for mutex");
1634 pthread_mutexattr::is_good_object (pthread_mutexattr_t
const * attr
)
1636 if (verifyable_object_isvalid (attr
, PTHREAD_MUTEXATTR_MAGIC
) != VALID_OBJECT
)
1641 pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC
),
1642 pshared (PTHREAD_PROCESS_PRIVATE
), mutextype (PTHREAD_MUTEX_DEFAULT
)
1646 pthread_mutexattr::~pthread_mutexattr ()
1650 List
<semaphore
> semaphore::semaphores
;
1652 semaphore::semaphore (int pshared
, unsigned int value
)
1653 : verifyable_object (SEM_MAGIC
),
1655 currentvalue (value
),
1658 SECURITY_ATTRIBUTES sa
= (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1659 ? sec_all
: sec_none_nih
;
1660 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, NULL
);
1661 if (!this->win32_obj_id
)
1664 semaphores
.insert (this);
1667 semaphore::semaphore (const char *sem_name
, int oflag
, mode_t mode
,
1669 : verifyable_object (SEM_MAGIC
),
1670 shared (PTHREAD_PROCESS_SHARED
),
1671 currentvalue (value
), /* Unused for named semaphores. */
1674 if (oflag
& O_CREAT
)
1676 SECURITY_ATTRIBUTES sa
= sec_all
;
1677 security_descriptor sd
;
1679 set_security_attribute (mode
, &sa
, sd
);
1680 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, sem_name
);
1681 if (!this->win32_obj_id
)
1683 if (GetLastError () == ERROR_ALREADY_EXISTS
&& (oflag
& O_EXCL
))
1686 CloseHandle (this->win32_obj_id
);
1692 this->win32_obj_id
= ::OpenSemaphore (SEMAPHORE_ALL_ACCESS
, FALSE
,
1694 if (!this->win32_obj_id
)
1702 name
= new char [strlen (sem_name
+ 1)];
1706 CloseHandle (this->win32_obj_id
);
1710 strcpy (name
, sem_name
);
1713 semaphores
.insert (this);
1716 semaphore::~semaphore ()
1719 CloseHandle (win32_obj_id
);
1723 semaphores
.remove (this);
1729 if (ReleaseSemaphore (win32_obj_id
, 1, ¤tvalue
))
1734 semaphore::_getvalue (int *sval
)
1738 switch (WaitForSingleObject (win32_obj_id
, 0))
1741 ReleaseSemaphore (win32_obj_id
, 1, &val
);
1755 semaphore::_trywait ()
1757 /* FIXME: signals should be able to interrupt semaphores...
1758 *We probably need WaitForMultipleObjects here.
1760 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
1770 semaphore::_timedwait (const struct timespec
*abstime
)
1775 if (__check_invalid_read_ptr (abstime
, sizeof *abstime
))
1777 /* According to SUSv3, abstime need not be checked for validity,
1778 if the semaphore can be locked immediately. */
1785 gettimeofday (&tv
, NULL
);
1786 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
1787 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
1790 switch (pthread::cancelable_wait (win32_obj_id
, waitlength
))
1796 set_errno (ETIMEDOUT
);
1799 debug_printf ("cancelable_wait failed. %E");
1809 switch (pthread::cancelable_wait (win32_obj_id
, INFINITE
))
1815 debug_printf ("cancelable_wait failed. %E");
1821 semaphore::_fixup_after_fork ()
1823 if (shared
== PTHREAD_PROCESS_PRIVATE
)
1825 debug_printf ("sem %x in _fixup_after_fork", this);
1826 /* FIXME: duplicate code here and in the constructor. */
1827 this->win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, currentvalue
,
1830 api_fatal ("failed to create new win32 semaphore, error %d");
1834 verifyable_object::verifyable_object (long verifyer
):
1839 verifyable_object::~verifyable_object ()
1844 /* Generic memory acccess routine - where should it live ? */
1846 check_valid_pointer (void const *pointer
)
1848 if (!pointer
|| IsBadWritePtr ((void *) pointer
, sizeof (verifyable_object
)))
1853 verifyable_object_state
1854 verifyable_object_isvalid (void const * objectptr
, long magic
, void *static_ptr
)
1856 verifyable_object
**object
= (verifyable_object
**)objectptr
;
1857 if (check_valid_pointer (object
))
1858 return INVALID_OBJECT
;
1859 if (static_ptr
&& *object
== static_ptr
)
1860 return VALID_STATIC_OBJECT
;
1862 return INVALID_OBJECT
;
1863 if (check_valid_pointer (*object
))
1864 return INVALID_OBJECT
;
1865 if ((*object
)->magic
!= magic
)
1866 return INVALID_OBJECT
;
1867 return VALID_OBJECT
;
1870 verifyable_object_state
1871 verifyable_object_isvalid (void const * objectptr
, long magic
)
1873 return verifyable_object_isvalid (objectptr
, magic
, NULL
);
1877 __reent_t::init_clib (struct _reent
& var
)
1879 var
= ((struct _reent
) _REENT_INIT (var
));
1880 var
._stdin
= _GLOBAL_REENT
->_stdin
;
1881 var
._stdout
= _GLOBAL_REENT
->_stdout
;
1882 var
._stderr
= _GLOBAL_REENT
->_stderr
;
1883 var
.__sdidinit
= _GLOBAL_REENT
->__sdidinit
;
1884 var
.__cleanup
= _GLOBAL_REENT
->__cleanup
;
1890 pthread::thread_init_wrapper (void *_arg
)
1892 // Setup the local/global storage of this thread
1893 __uint64_t padding
[CYGTLS_PADSIZE
];
1894 pthread
*thread
= (pthread
*) _arg
;
1895 thread
->cygtls
= _my_tls
.init (padding
, &thread
);
1896 _my_tls
.tid
= thread
;
1898 exception_list cygwin_except_entry
;
1899 init_exceptions (&cygwin_except_entry
); /* Initialize SIGSEGV handling, etc. */
1901 thread
->set_tls_self_pointer ();
1902 struct __reent_t local_reent
;
1903 struct _winsup_t local_winsup
;
1904 struct _reent local_clib
;
1906 memset (&local_winsup
, 0, sizeof (struct _winsup_t
));
1908 local_reent
.init_clib (local_clib
);
1909 local_reent
._winsup
= &local_winsup
;
1911 local_winsup
._process_logmask
= LOG_UPTO (LOG_DEBUG
);
1913 MT_INTERFACE
->reent_key
.set (&local_reent
);
1915 thread
->mutex
.lock ();
1916 // if thread is detached force cleanup on exit
1917 if (thread
->attr
.joinable
== PTHREAD_CREATE_DETACHED
&& thread
->joiner
== NULL
)
1918 thread
->joiner
= thread
;
1919 thread
->mutex
.unlock ();
1921 #ifdef _CYG_THREAD_FAILSAFE
1922 if (_REENT
== _impure_ptr
)
1923 system_printf ("local storage for thread isn't setup correctly");
1926 thread_printf ("started thread %p %p %p %p %p %p", _arg
, &local_clib
,
1927 _impure_ptr
, thread
, thread
->function
, thread
->arg
);
1929 // call the user's thread
1930 void *ret
= thread
->function (thread
->arg
);
1936 pthread::is_good_object (pthread_t
const *thread
)
1938 if (verifyable_object_isvalid (thread
, PTHREAD_MAGIC
) != VALID_OBJECT
)
1944 pthread::getsequence_np ()
1946 return get_thread_id ();
1950 pthread::create (pthread_t
*thread
, const pthread_attr_t
*attr
,
1951 void *(*start_routine
) (void *), void *arg
)
1953 if (attr
&& !pthread_attr::is_good_object (attr
))
1956 *thread
= new pthread ();
1957 (*thread
)->create (start_routine
, attr
? *attr
: NULL
, arg
);
1958 if (!is_good_object (thread
))
1969 pthread::once (pthread_once_t
*once_control
, void (*init_routine
) (void))
1972 if (once_control
->state
)
1975 pthread_mutex_lock (&once_control
->mutex
);
1976 /* Here we must set a cancellation handler to unlock the mutex if needed */
1977 /* but a cancellation handler is not the right thing. We need this in the thread
1978 *cleanup routine. Assumption: a thread can only be in one pthread_once routine
1979 *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
1980 *on pthread_exit ();
1982 if (!once_control
->state
)
1985 once_control
->state
= 1;
1987 /* Here we must remove our cancellation handler */
1988 pthread_mutex_unlock (&once_control
->mutex
);
1993 pthread::cancel (pthread_t thread
)
1995 if (!is_good_object (&thread
))
1998 return thread
->cancel ();
2002 pthread::atforkprepare (void)
2004 MT_INTERFACE
->fixup_before_fork ();
2006 callback
*cb
= MT_INTERFACE
->pthread_prepare
;
2015 pthread::atforkparent (void)
2017 callback
*cb
= MT_INTERFACE
->pthread_parent
;
2026 pthread::atforkchild (void)
2028 MT_INTERFACE
->fixup_after_fork ();
2030 callback
*cb
= MT_INTERFACE
->pthread_child
;
2038 /* Register a set of functions to run before and after fork.
2039 prepare calls are called in LI-FC order.
2040 parent and child calls are called in FI-FC order. */
2042 pthread::atfork (void (*prepare
)(void), void (*parent
)(void), void (*child
)(void))
2044 callback
*prepcb
= NULL
, *parentcb
= NULL
, *childcb
= NULL
;
2047 prepcb
= new callback
;
2053 parentcb
= new callback
;
2063 childcb
= new callback
;
2076 prepcb
->cb
= prepare
;
2077 List_insert (MT_INTERFACE
->pthread_prepare
, prepcb
);
2081 parentcb
->cb
= parent
;
2082 callback
**t
= &MT_INTERFACE
->pthread_parent
;
2085 /* t = pointer to last next in the list */
2086 List_insert (*t
, parentcb
);
2090 childcb
->cb
= child
;
2091 callback
**t
= &MT_INTERFACE
->pthread_child
;
2094 /* t = pointer to last next in the list */
2095 List_insert (*t
, childcb
);
2101 pthread_attr_init (pthread_attr_t
*attr
)
2103 if (pthread_attr::is_good_object (attr
))
2106 *attr
= new pthread_attr
;
2107 if (!pthread_attr::is_good_object (attr
))
2117 pthread_attr_getinheritsched (const pthread_attr_t
*attr
,
2120 if (!pthread_attr::is_good_object (attr
))
2122 *inheritsched
= (*attr
)->inheritsched
;
2127 pthread_attr_getschedparam (const pthread_attr_t
*attr
,
2128 struct sched_param
*param
)
2130 if (!pthread_attr::is_good_object (attr
))
2132 *param
= (*attr
)->schedparam
;
2136 /* From a pure code point of view, this should call a helper in sched.cc,
2137 to allow for someone adding scheduler policy changes to win32 in the future.
2138 However that's extremely unlikely, so short and sweet will do us */
2140 pthread_attr_getschedpolicy (const pthread_attr_t
*attr
, int *policy
)
2142 if (!pthread_attr::is_good_object (attr
))
2144 *policy
= SCHED_FIFO
;
2150 pthread_attr_getscope (const pthread_attr_t
*attr
, int *contentionscope
)
2152 if (!pthread_attr::is_good_object (attr
))
2154 *contentionscope
= (*attr
)->contentionscope
;
2159 pthread_attr_setdetachstate (pthread_attr_t
*attr
, int detachstate
)
2161 if (!pthread_attr::is_good_object (attr
))
2163 if (detachstate
< 0 || detachstate
> 1)
2165 (*attr
)->joinable
= detachstate
;
2170 pthread_attr_getdetachstate (const pthread_attr_t
*attr
, int *detachstate
)
2172 if (!pthread_attr::is_good_object (attr
))
2174 *detachstate
= (*attr
)->joinable
;
2179 pthread_attr_setinheritsched (pthread_attr_t
*attr
, int inheritsched
)
2181 if (!pthread_attr::is_good_object (attr
))
2183 if (inheritsched
!= PTHREAD_INHERIT_SCHED
2184 && inheritsched
!= PTHREAD_EXPLICIT_SCHED
)
2186 (*attr
)->inheritsched
= inheritsched
;
2191 pthread_attr_setschedparam (pthread_attr_t
*attr
,
2192 const struct sched_param
*param
)
2194 if (!pthread_attr::is_good_object (attr
))
2196 if (!valid_sched_parameters (param
))
2198 (*attr
)->schedparam
= *param
;
2202 /* See __pthread_attr_getschedpolicy for some notes */
2204 pthread_attr_setschedpolicy (pthread_attr_t
*attr
, int policy
)
2206 if (!pthread_attr::is_good_object (attr
))
2208 if (policy
!= SCHED_FIFO
)
2214 pthread_attr_setscope (pthread_attr_t
*attr
, int contentionscope
)
2216 if (!pthread_attr::is_good_object (attr
))
2218 if (contentionscope
!= PTHREAD_SCOPE_SYSTEM
2219 && contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2221 /* In future, we may be able to support system scope by escalating the thread
2222 priority to exceed the priority class. For now we only support PROCESS scope. */
2223 if (contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2225 (*attr
)->contentionscope
= contentionscope
;
2230 pthread_attr_setstacksize (pthread_attr_t
*attr
, size_t size
)
2232 if (!pthread_attr::is_good_object (attr
))
2234 (*attr
)->stacksize
= size
;
2239 pthread_attr_getstacksize (const pthread_attr_t
*attr
, size_t *size
)
2241 if (!pthread_attr::is_good_object (attr
))
2243 *size
= (*attr
)->stacksize
;
2248 pthread_attr_destroy (pthread_attr_t
*attr
)
2250 if (!pthread_attr::is_good_object (attr
))
2258 pthread::join (pthread_t
*thread
, void **return_val
)
2260 pthread_t joiner
= self ();
2262 joiner
->testcancel ();
2264 // Initialize return val with NULL
2268 if (!is_good_object (&joiner
))
2271 if (!is_good_object (thread
))
2274 if (equal (*thread
,joiner
))
2277 (*thread
)->mutex
.lock ();
2279 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2281 (*thread
)->mutex
.unlock ();
2286 (*thread
)->joiner
= joiner
;
2287 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2288 (*thread
)->mutex
.unlock ();
2290 switch (cancelable_wait ((*thread
)->win32_obj_id
, INFINITE
, false))
2294 *return_val
= (*thread
)->return_ptr
;
2298 // set joined thread back to joinable since we got canceled
2299 (*thread
)->joiner
= NULL
;
2300 (*thread
)->attr
.joinable
= PTHREAD_CREATE_JOINABLE
;
2301 joiner
->cancel_self ();
2305 // should never happen
2314 pthread::detach (pthread_t
*thread
)
2316 if (!is_good_object (thread
))
2319 (*thread
)->mutex
.lock ();
2320 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2322 (*thread
)->mutex
.unlock ();
2326 // check if thread is still alive
2327 if ((*thread
)->valid
&& WaitForSingleObject ((*thread
)->win32_obj_id
, 0) == WAIT_TIMEOUT
)
2329 // force cleanup on exit
2330 (*thread
)->joiner
= *thread
;
2331 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2332 (*thread
)->mutex
.unlock ();
2336 // thread has already terminated.
2337 (*thread
)->mutex
.unlock ();
2345 pthread::suspend (pthread_t
*thread
)
2347 if (!is_good_object (thread
))
2350 if ((*thread
)->suspended
== false)
2352 (*thread
)->suspended
= true;
2353 SuspendThread ((*thread
)->win32_obj_id
);
2361 pthread::resume (pthread_t
*thread
)
2363 if (!is_good_object (thread
))
2366 if ((*thread
)->suspended
== true)
2367 ResumeThread ((*thread
)->win32_obj_id
);
2368 (*thread
)->suspended
= false;
2373 /* provided for source level compatability.
2374 See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2377 pthread_getconcurrency (void)
2379 return MT_INTERFACE
->concurrency
;
2382 /* keep this in sync with sched.cc */
2384 pthread_getschedparam (pthread_t thread
, int *policy
,
2385 struct sched_param
*param
)
2387 if (!pthread::is_good_object (&thread
))
2389 *policy
= SCHED_FIFO
;
2390 /* we don't return the current effective priority, we return the current
2391 requested priority */
2392 *param
= thread
->attr
.schedparam
;
2396 /* Thread SpecificData */
2398 pthread_key_create (pthread_key_t
*key
, void (*destructor
) (void *))
2400 /* The opengroup docs don't define if we should check this or not,
2401 but creation is relatively rare. */
2402 if (pthread_key::is_good_object (key
))
2405 *key
= new pthread_key (destructor
);
2407 if (!pthread_key::is_good_object (key
))
2417 pthread_key_delete (pthread_key_t key
)
2419 if (!pthread_key::is_good_object (&key
))
2426 /* provided for source level compatability. See
2427 http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2430 pthread_setconcurrency (int new_level
)
2434 MT_INTERFACE
->concurrency
= new_level
;
2438 /* keep syncronised with sched.cc */
2440 pthread_setschedparam (pthread_t thread
, int policy
,
2441 const struct sched_param
*param
)
2443 if (!pthread::is_good_object (&thread
))
2445 if (policy
!= SCHED_FIFO
)
2450 sched_set_thread_priority (thread
->win32_obj_id
, param
->sched_priority
);
2452 thread
->attr
.schedparam
.sched_priority
= param
->sched_priority
;
2458 pthread_setspecific (pthread_key_t key
, const void *value
)
2460 if (!pthread_key::is_good_object (&key
))
2467 pthread_getspecific (pthread_key_t key
)
2469 if (!pthread_key::is_good_object (&key
))
2472 return (key
)->get ();
2476 /* Thread synchronisation */
2478 pthread_cond::is_good_object (pthread_cond_t
const *cond
)
2480 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
) != VALID_OBJECT
)
2486 pthread_cond::is_good_initializer (pthread_cond_t
const *cond
)
2488 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) != VALID_STATIC_OBJECT
)
2494 pthread_cond::is_good_initializer_or_object (pthread_cond_t
const *cond
)
2496 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) == INVALID_OBJECT
)
2502 pthread_cond::is_good_initializer_or_bad_object (pthread_cond_t
const *cond
)
2504 verifyable_object_state objectState
= verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
);
2505 if (objectState
== VALID_OBJECT
)
2511 pthread_cond_destroy (pthread_cond_t
*cond
)
2513 if (pthread_cond::is_good_initializer (cond
))
2515 if (!pthread_cond::is_good_object (cond
))
2518 /* reads are atomic */
2519 if ((*cond
)->waiting
)
2529 pthread_cond::init (pthread_cond_t
*cond
, const pthread_condattr_t
*attr
)
2531 if (attr
&& !pthread_condattr::is_good_object (attr
))
2534 cond_initialization_lock
.lock ();
2536 if (!is_good_initializer_or_bad_object (cond
))
2538 cond_initialization_lock
.unlock ();
2542 *cond
= new pthread_cond (attr
? (*attr
) : NULL
);
2543 if (!is_good_object (cond
))
2547 cond_initialization_lock
.unlock ();
2550 cond_initialization_lock
.unlock ();
2555 pthread_cond_broadcast (pthread_cond_t
*cond
)
2557 if (pthread_cond::is_good_initializer (cond
))
2559 if (!pthread_cond::is_good_object (cond
))
2562 (*cond
)->unblock (true);
2568 pthread_cond_signal (pthread_cond_t
*cond
)
2570 if (pthread_cond::is_good_initializer (cond
))
2572 if (!pthread_cond::is_good_object (cond
))
2575 (*cond
)->unblock (false);
2581 __pthread_cond_dowait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2584 if (!pthread_mutex::is_good_object (mutex
))
2586 if (!pthread_mutex::can_be_unlocked (mutex
))
2589 if (pthread_cond::is_good_initializer (cond
))
2590 pthread_cond::init (cond
, NULL
);
2591 if (!pthread_cond::is_good_object (cond
))
2594 return (*cond
)->wait (*mutex
, waitlength
);
2598 pthread_cond_timedwait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2599 const struct timespec
*abstime
)
2604 pthread_testcancel ();
2606 if (check_valid_pointer (abstime
))
2609 gettimeofday (&tv
, NULL
);
2610 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
2611 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
2614 return __pthread_cond_dowait (cond
, mutex
, waitlength
);
2618 pthread_cond_wait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
2620 pthread_testcancel ();
2622 return __pthread_cond_dowait (cond
, mutex
, INFINITE
);
2626 pthread_condattr_init (pthread_condattr_t
*condattr
)
2628 if (pthread_condattr::is_good_object (condattr
))
2631 *condattr
= new pthread_condattr
;
2632 if (!pthread_condattr::is_good_object (condattr
))
2642 pthread_condattr_getpshared (const pthread_condattr_t
*attr
, int *pshared
)
2644 if (!pthread_condattr::is_good_object (attr
))
2646 *pshared
= (*attr
)->shared
;
2651 pthread_condattr_setpshared (pthread_condattr_t
*attr
, int pshared
)
2653 if (!pthread_condattr::is_good_object (attr
))
2655 if ((pshared
< 0) || (pshared
> 1))
2657 /* shared cond vars not currently supported */
2658 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2660 (*attr
)->shared
= pshared
;
2665 pthread_condattr_destroy (pthread_condattr_t
*condattr
)
2667 if (!pthread_condattr::is_good_object (condattr
))
2676 pthread_rwlock::is_good_object (pthread_rwlock_t
const *rwlock
)
2678 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
) != VALID_OBJECT
)
2684 pthread_rwlock::is_good_initializer (pthread_rwlock_t
const *rwlock
)
2686 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) != VALID_STATIC_OBJECT
)
2692 pthread_rwlock::is_good_initializer_or_object (pthread_rwlock_t
const *rwlock
)
2694 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) == INVALID_OBJECT
)
2700 pthread_rwlock::is_good_initializer_or_bad_object (pthread_rwlock_t
const *rwlock
)
2702 verifyable_object_state objectState
= verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
);
2703 if (objectState
== VALID_OBJECT
)
2709 pthread_rwlock_destroy (pthread_rwlock_t
*rwlock
)
2711 if (pthread_rwlock::is_good_initializer (rwlock
))
2713 if (!pthread_rwlock::is_good_object (rwlock
))
2716 if ((*rwlock
)->writer
|| (*rwlock
)->readers
||
2717 (*rwlock
)->waiting_readers
|| (*rwlock
)->waiting_writers
)
2727 pthread_rwlock::init (pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*attr
)
2729 if (attr
&& !pthread_rwlockattr::is_good_object (attr
))
2732 rwlock_initialization_lock
.lock ();
2734 if (!is_good_initializer_or_bad_object (rwlock
))
2736 rwlock_initialization_lock
.unlock ();
2740 *rwlock
= new pthread_rwlock (attr
? (*attr
) : NULL
);
2741 if (!is_good_object (rwlock
))
2745 rwlock_initialization_lock
.unlock ();
2748 rwlock_initialization_lock
.unlock ();
2753 pthread_rwlock_rdlock (pthread_rwlock_t
*rwlock
)
2755 pthread_testcancel ();
2757 if (pthread_rwlock::is_good_initializer (rwlock
))
2758 pthread_rwlock::init (rwlock
, NULL
);
2759 if (!pthread_rwlock::is_good_object (rwlock
))
2762 return (*rwlock
)->rdlock ();
2766 pthread_rwlock_tryrdlock (pthread_rwlock_t
*rwlock
)
2768 if (pthread_rwlock::is_good_initializer (rwlock
))
2769 pthread_rwlock::init (rwlock
, NULL
);
2770 if (!pthread_rwlock::is_good_object (rwlock
))
2773 return (*rwlock
)->tryrdlock ();
2777 pthread_rwlock_wrlock (pthread_rwlock_t
*rwlock
)
2779 pthread_testcancel ();
2781 if (pthread_rwlock::is_good_initializer (rwlock
))
2782 pthread_rwlock::init (rwlock
, NULL
);
2783 if (!pthread_rwlock::is_good_object (rwlock
))
2786 return (*rwlock
)->wrlock ();
2790 pthread_rwlock_trywrlock (pthread_rwlock_t
*rwlock
)
2792 if (pthread_rwlock::is_good_initializer (rwlock
))
2793 pthread_rwlock::init (rwlock
, NULL
);
2794 if (!pthread_rwlock::is_good_object (rwlock
))
2797 return (*rwlock
)->trywrlock ();
2801 pthread_rwlock_unlock (pthread_rwlock_t
*rwlock
)
2803 if (pthread_rwlock::is_good_initializer (rwlock
))
2805 if (!pthread_rwlock::is_good_object (rwlock
))
2808 return (*rwlock
)->unlock ();
2812 pthread_rwlockattr_init (pthread_rwlockattr_t
*rwlockattr
)
2814 if (pthread_rwlockattr::is_good_object (rwlockattr
))
2817 *rwlockattr
= new pthread_rwlockattr
;
2818 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2820 delete (*rwlockattr
);
2828 pthread_rwlockattr_getpshared (const pthread_rwlockattr_t
*attr
, int *pshared
)
2830 if (!pthread_rwlockattr::is_good_object (attr
))
2832 *pshared
= (*attr
)->shared
;
2837 pthread_rwlockattr_setpshared (pthread_rwlockattr_t
*attr
, int pshared
)
2839 if (!pthread_rwlockattr::is_good_object (attr
))
2841 if ((pshared
< 0) || (pshared
> 1))
2843 /* shared rwlock vars not currently supported */
2844 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2846 (*attr
)->shared
= pshared
;
2851 pthread_rwlockattr_destroy (pthread_rwlockattr_t
*rwlockattr
)
2853 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2855 delete (*rwlockattr
);
2862 pthread_kill (pthread_t thread
, int sig
)
2864 // lock myself, for the use of thread2signal
2865 // two different kills might clash: FIXME
2867 if (!pthread::is_good_object (&thread
))
2870 int rval
= sig
? sig_send (NULL
, sig
, 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
);
2892 /* FIXME: there's a potential race with PTHREAD_MUTEX_INITALIZER:
2893 the mutex is not actually inited until the first use.
2894 So two threads trying to lock/trylock may collide.
2895 Solution: we need a global mutex on mutex creation, or possibly simply
2896 on all constructors that allow INITIALIZER macros.
2897 the lock should be very small: only around the init routine, not
2898 every test, or all mutex access will be synchronised. */
2901 pthread_mutex::init (pthread_mutex_t
*mutex
,
2902 const pthread_mutexattr_t
*attr
)
2904 if (attr
&& !pthread_mutexattr::is_good_object (attr
) || check_valid_pointer (mutex
))
2907 mutex_initialization_lock
.lock ();
2909 if (!is_good_initializer_or_bad_object (mutex
))
2911 mutex_initialization_lock
.unlock ();
2915 *mutex
= new pthread_mutex (attr
? (*attr
) : NULL
);
2916 if (!is_good_object (mutex
))
2920 mutex_initialization_lock
.unlock ();
2923 mutex_initialization_lock
.unlock ();
2928 pthread_mutex_getprioceiling (const pthread_mutex_t
*mutex
,
2931 pthread_mutex_t
*themutex
= (pthread_mutex_t
*) mutex
;
2932 if (pthread_mutex::is_good_initializer (mutex
))
2933 pthread_mutex::init ((pthread_mutex_t
*) mutex
, NULL
);
2934 if (!pthread_mutex::is_good_object (themutex
))
2936 /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
2939 We can support mutex priorities in the future though:
2940 Store a priority with each mutex.
2941 When the mutex is optained, set the thread priority as appropriate
2942 When the mutex is released, reset the thread priority. */
2947 pthread_mutex_lock (pthread_mutex_t
*mutex
)
2949 pthread_mutex_t
*themutex
= mutex
;
2950 /* This could be simplified via is_good_initializer_or_object
2951 and is_good_initializer, but in a performance critical call like this....
2953 switch (verifyable_object_isvalid (themutex
, PTHREAD_MUTEX_MAGIC
, PTHREAD_MUTEX_INITIALIZER
))
2955 case INVALID_OBJECT
:
2958 case VALID_STATIC_OBJECT
:
2959 if (pthread_mutex::is_good_initializer (mutex
))
2961 int rv
= pthread_mutex::init (mutex
, NULL
);
2962 if (rv
&& rv
!= EBUSY
)
2965 /* No else needed. If it's been initialized while we waited,
2966 we can just attempt to lock it */
2971 return (*themutex
)->lock ();
2975 pthread_mutex_trylock (pthread_mutex_t
*mutex
)
2977 pthread_mutex_t
*themutex
= mutex
;
2978 if (pthread_mutex::is_good_initializer (mutex
))
2979 pthread_mutex::init (mutex
, NULL
);
2980 if (!pthread_mutex::is_good_object (themutex
))
2982 return (*themutex
)->trylock ();
2986 pthread_mutex_unlock (pthread_mutex_t
*mutex
)
2988 if (pthread_mutex::is_good_initializer (mutex
))
2989 pthread_mutex::init (mutex
, NULL
);
2990 if (!pthread_mutex::is_good_object (mutex
))
2992 return (*mutex
)->unlock ();
2996 pthread_mutex_destroy (pthread_mutex_t
*mutex
)
3000 if (pthread_mutex::is_good_initializer (mutex
))
3002 if (!pthread_mutex::is_good_object (mutex
))
3005 rv
= (*mutex
)->destroy ();
3014 pthread_mutex_setprioceiling (pthread_mutex_t
*mutex
, int prioceiling
,
3017 pthread_mutex_t
*themutex
= mutex
;
3018 if (pthread_mutex::is_good_initializer (mutex
))
3019 pthread_mutex::init (mutex
, NULL
);
3020 if (!pthread_mutex::is_good_object (themutex
))
3025 /* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
3028 pthread_mutexattr_getprotocol (const pthread_mutexattr_t
*attr
,
3031 if (!pthread_mutexattr::is_good_object (attr
))
3037 pthread_mutexattr_getpshared (const pthread_mutexattr_t
*attr
,
3040 if (!pthread_mutexattr::is_good_object (attr
))
3042 *pshared
= (*attr
)->pshared
;
3047 pthread_mutexattr_gettype (const pthread_mutexattr_t
*attr
, int *type
)
3049 if (!pthread_mutexattr::is_good_object (attr
))
3051 *type
= (*attr
)->mutextype
;
3055 /* FIXME: write and test process shared mutex's. */
3057 pthread_mutexattr_init (pthread_mutexattr_t
*attr
)
3059 if (pthread_mutexattr::is_good_object (attr
))
3062 *attr
= new pthread_mutexattr ();
3063 if (!pthread_mutexattr::is_good_object (attr
))
3073 pthread_mutexattr_destroy (pthread_mutexattr_t
*attr
)
3075 if (!pthread_mutexattr::is_good_object (attr
))
3083 /* Win32 doesn't support mutex priorities */
3085 pthread_mutexattr_setprotocol (pthread_mutexattr_t
*attr
, int protocol
)
3087 if (!pthread_mutexattr::is_good_object (attr
))
3092 /* Win32 doesn't support mutex priorities */
3094 pthread_mutexattr_setprioceiling (pthread_mutexattr_t
*attr
,
3097 if (!pthread_mutexattr::is_good_object (attr
))
3103 pthread_mutexattr_getprioceiling (const pthread_mutexattr_t
*attr
,
3106 if (!pthread_mutexattr::is_good_object (attr
))
3112 pthread_mutexattr_setpshared (pthread_mutexattr_t
*attr
, int pshared
)
3114 if (!pthread_mutexattr::is_good_object (attr
))
3116 /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
3119 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
3121 (*attr
)->pshared
= pshared
;
3125 /* see pthread_mutex_gettype */
3127 pthread_mutexattr_settype (pthread_mutexattr_t
*attr
, int type
)
3129 if (!pthread_mutexattr::is_good_object (attr
))
3134 case PTHREAD_MUTEX_ERRORCHECK
:
3135 case PTHREAD_MUTEX_RECURSIVE
:
3136 case PTHREAD_MUTEX_NORMAL
:
3137 (*attr
)->mutextype
= type
;
3148 /* static members */
3150 semaphore::is_good_object (sem_t
const * sem
)
3152 if (verifyable_object_isvalid (sem
, SEM_MAGIC
) != VALID_OBJECT
)
3158 semaphore::init (sem_t
*sem
, int pshared
, unsigned int value
)
3160 /* opengroup calls this undefined */
3161 if (is_good_object (sem
))
3164 if (value
> SEM_VALUE_MAX
)
3167 *sem
= new semaphore (pshared
, value
);
3169 if (!is_good_object (sem
))
3179 semaphore::destroy (sem_t
*sem
)
3181 if (!is_good_object (sem
))
3184 /* FIXME - new feature - test for busy against threads... */
3192 semaphore::open (const char *name
, int oflag
, mode_t mode
, unsigned int value
)
3194 if (value
> SEM_VALUE_MAX
)
3200 sem_t
*sem
= new sem_t
;
3207 *sem
= new semaphore (name
, oflag
, mode
, value
);
3209 if (!is_good_object (sem
))
3219 semaphore::wait (sem_t
*sem
)
3221 pthread_testcancel ();
3223 if (!is_good_object (sem
))
3234 semaphore::trywait (sem_t
*sem
)
3236 if (!is_good_object (sem
))
3242 return (*sem
)->_trywait ();
3246 semaphore::timedwait (sem_t
*sem
, const struct timespec
*abstime
)
3248 if (!is_good_object (sem
))
3254 return (*sem
)->_timedwait (abstime
);
3258 semaphore::post (sem_t
*sem
)
3260 if (!is_good_object (sem
))
3271 semaphore::getvalue (sem_t
*sem
, int *sval
)
3274 if (!is_good_object (sem
)
3275 || __check_null_invalid_struct (sval
, sizeof (int)))
3281 return (*sem
)->_getvalue (sval
);
3286 pthread_null::get_null_pthread ()
3288 /* because of weird entry points */
3289 _instance
.magic
= 0;
3293 pthread_null::pthread_null ()
3295 attr
.joinable
= PTHREAD_CREATE_DETACHED
;
3296 /* Mark ourselves as invalid */
3300 pthread_null::~pthread_null ()
3305 pthread_null::create (void *(*)(void *), pthread_attr
*, void *)
3310 pthread_null::exit (void *value_ptr
)
3316 pthread_null::cancel ()
3322 pthread_null::testcancel ()
3327 pthread_null::setcancelstate (int state
, int *oldstate
)
3333 pthread_null::setcanceltype (int type
, int *oldtype
)
3339 pthread_null::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
3344 pthread_null::pop_cleanup_handler (int const execute
)
3349 pthread_null::getsequence_np ()
3354 pthread_null
pthread_null::_instance
;