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. */
39 #include "perprocess.h"
42 #include <semaphore.h>
44 #include <sys/timeb.h>
45 #include <exceptions.h>
46 #include <sys/fcntl.h>
48 extern int threadsafe
;
51 extern "C" struct _reent
*
54 return &_my_tls
.local_clib
;
57 inline LPCRITICAL_SECTION
58 ResourceLocks::Lock (int _resid
)
64 SetResourceLock (int _res_id
, int _mode
, const char *_function
)
66 EnterCriticalSection (user_data
->resourcelocks
->Lock (_res_id
));
70 ReleaseResourceLock (int _res_id
, int _mode
, const char *_function
)
72 LeaveCriticalSection (user_data
->resourcelocks
->Lock (_res_id
));
76 ResourceLocks::Init ()
78 InitializeCriticalSection (&lock
);
80 thread_printf ("lock %p inited by %p , %d", &lock
, user_data
, myself
->pid
);
84 ResourceLocks::Delete ()
88 thread_printf ("Close Resource Locks %p ", &lock
);
89 DeleteCriticalSection (&lock
);
97 pthread_mutex::init_mutex ();
98 pthread_cond::init_mutex ();
99 pthread_rwlock::init_mutex ();
103 MTinterface::fixup_before_fork (void)
105 pthread_key::fixup_before_fork ();
108 /* This function is called from a single threaded process */
110 MTinterface::fixup_after_fork (void)
112 pthread_key::fixup_after_fork ();
115 pthread::init_mainthread ();
117 pthread::fixup_after_fork ();
118 pthread_mutex::fixup_after_fork ();
119 pthread_cond::fixup_after_fork ();
120 pthread_rwlock::fixup_after_fork ();
121 semaphore::fixup_after_fork ();
128 pthread::init_mainthread ()
130 pthread
*thread
= get_tls_self_pointer ();
133 thread
= new pthread ();
135 api_fatal ("failed to create mainthread object");
138 thread
->cygtls
= &_my_tls
;
139 _my_tls
.tid
= thread
;
140 thread
->thread_id
= GetCurrentThreadId ();
141 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
142 GetCurrentProcess (), &thread
->win32_obj_id
,
143 0, FALSE
, DUPLICATE_SAME_ACCESS
))
144 api_fatal ("failed to create mainthread handle");
145 if (!thread
->create_cancel_event ())
146 api_fatal ("couldn't create cancel event for main thread");
147 thread
->postcreate ();
153 pthread
*thread
= get_tls_self_pointer ();
156 return pthread_null::get_null_pthread ();
160 pthread::get_tls_self_pointer ()
165 List
<pthread
> pthread::threads
;
168 pthread::pthread ():verifyable_object (PTHREAD_MAGIC
), win32_obj_id (0),
169 valid (false), suspended (false),
170 cancelstate (0), canceltype (0), cancel_event (0),
171 joiner (NULL
), next (NULL
), cleanup_stack (NULL
)
173 if (this != pthread_null::get_null_pthread ())
174 threads
.insert (this);
180 CloseHandle (win32_obj_id
);
182 CloseHandle (cancel_event
);
184 if (this != pthread_null::get_null_pthread ())
185 threads
.remove (this);
189 pthread::create_cancel_event ()
191 cancel_event
= ::CreateEvent (&sec_none_nih
, TRUE
, FALSE
, NULL
);
194 system_printf ("couldn't create cancel event, %E");
195 /* we need the event for correct behaviour */
202 pthread::precreate (pthread_attr
*newattr
)
204 pthread_mutex
*verifyable_mutex_obj
= &mutex
;
206 /* already running ? */
212 attr
.joinable
= newattr
->joinable
;
213 attr
.contentionscope
= newattr
->contentionscope
;
214 attr
.inheritsched
= newattr
->inheritsched
;
215 attr
.stacksize
= newattr
->stacksize
;
218 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
220 thread_printf ("New thread object access mutex is not valid. this %p",
225 /* Change the mutex type to NORMAL to speed up mutex operations */
226 mutex
.type
= PTHREAD_MUTEX_NORMAL
;
227 if (!create_cancel_event ())
232 pthread::create (void *(*func
) (void *), pthread_attr
*newattr
,
242 win32_obj_id
= ::CreateThread (&sec_none_nih
, attr
.stacksize
,
243 thread_init_wrapper
, this, CREATE_SUSPENDED
,
248 thread_printf ("CreateThread failed: this %p, %E", this);
254 ResumeThread (win32_obj_id
);
259 pthread::postcreate ()
263 InterlockedIncrement (&MT_INTERFACE
->threadcount
);
264 /* FIXME: set the priority appropriately for system contention scope */
265 if (attr
.inheritsched
== PTHREAD_EXPLICIT_SCHED
)
267 /* FIXME: set the scheduling settings for the new thread */
268 /* sched_thread_setparam (win32_obj_id, attr.schedparam); */
273 pthread::exit (void *value_ptr
)
275 class pthread
*thread
= this;
277 // run cleanup handlers
278 pop_all_cleanup_handlers ();
280 pthread_key::run_all_destructors ();
283 // cleanup if thread is in detached state and not joined
284 if (equal (joiner
, thread
))
289 return_ptr
= value_ptr
;
293 (_reclaim_reent
) (_REENT
);
296 if (InterlockedDecrement (&MT_INTERFACE
->threadcount
) == 0)
300 _my_tls
.remove (INFINITE
);
306 pthread::cancel (void)
308 class pthread
*thread
= this;
309 class pthread
*self
= pthread::self ();
319 if (canceltype
== PTHREAD_CANCEL_DEFERRED
||
320 cancelstate
== PTHREAD_CANCEL_DISABLE
)
324 SetEvent (cancel_event
);
327 else if (equal (thread
, self
))
331 return 0; // Never reached
334 // cancel asynchronous
335 SuspendThread (win32_obj_id
);
336 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
339 context
.ContextFlags
= CONTEXT_CONTROL
;
340 GetThreadContext (win32_obj_id
, &context
);
341 context
.Eip
= (DWORD
) pthread::static_cancel_self
;
342 SetThreadContext (win32_obj_id
, &context
);
345 ResumeThread (win32_obj_id
);
349 TODO: insert pthread_testcancel into the required functions
350 the required function list is: *indicates done, X indicates not present in cygwin.
369 *pthread_cond_timedwait ()
370 *pthread_cond_wait ()
372 *pthread_testcancel ()
396 the optional list is:
516 Note, that for fcntl (), for any value of the cmd argument.
518 And we must not introduce cancellation points anywhere else that's part of the posix or
524 pthread::testcancel (void)
526 if (cancelstate
== PTHREAD_CANCEL_DISABLE
)
529 if (WaitForSingleObject (cancel_event
, 0) == WAIT_OBJECT_0
)
534 pthread::static_cancel_self (void)
536 pthread::self ()->cancel_self ();
541 pthread::cancelable_wait (HANDLE object
, DWORD timeout
, const bool do_cancel
)
544 HANDLE wait_objects
[2];
545 pthread_t thread
= self ();
547 if (!is_good_object (&thread
) || thread
->cancelstate
== PTHREAD_CANCEL_DISABLE
)
548 return WaitForSingleObject (object
, timeout
);
550 // Do not change the wait order
551 // The object must have higher priority than the cancel event,
552 // because WaitForMultipleObjects will return the smallest index
553 // if both objects are signaled
554 wait_objects
[0] = object
;
555 wait_objects
[1] = thread
->cancel_event
;
557 res
= WaitForMultipleObjects (2, wait_objects
, FALSE
, timeout
);
558 if (do_cancel
&& res
== WAIT_CANCELED
)
559 pthread::static_cancel_self ();
564 pthread::setcancelstate (int state
, int *oldstate
)
570 if (state
!= PTHREAD_CANCEL_ENABLE
&& state
!= PTHREAD_CANCEL_DISABLE
)
575 *oldstate
= cancelstate
;
585 pthread::setcanceltype (int type
, int *oldtype
)
591 if (type
!= PTHREAD_CANCEL_DEFERRED
&& type
!= PTHREAD_CANCEL_ASYNCHRONOUS
)
596 *oldtype
= canceltype
;
606 pthread::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
610 api_fatal ("Attempt to push a cleanup handler across threads");
611 handler
->next
= cleanup_stack
;
612 cleanup_stack
= handler
;
616 pthread::pop_cleanup_handler (int const execute
)
619 // TODO: send a signal or something to the thread ?
620 api_fatal ("Attempt to execute a cleanup handler across threads");
624 if (cleanup_stack
!= NULL
)
626 __pthread_cleanup_handler
*handler
= cleanup_stack
;
629 (*handler
->function
) (handler
->arg
);
630 cleanup_stack
= handler
->next
;
637 pthread::pop_all_cleanup_handlers ()
639 while (cleanup_stack
!= NULL
)
640 pop_cleanup_handler (1);
644 pthread::cancel_self ()
646 exit (PTHREAD_CANCELED
);
650 pthread::get_thread_id ()
656 pthread::_fixup_after_fork ()
658 /* set thread to not running if it is not the forking thread */
659 if (this != pthread::self ())
669 pthread::suspend_except_self ()
671 if (valid
&& this != pthread::self ())
672 SuspendThread (win32_obj_id
);
679 ResumeThread (win32_obj_id
);
684 pthread_attr::is_good_object (pthread_attr_t
const *attr
)
686 if (verifyable_object_isvalid (attr
, PTHREAD_ATTR_MAGIC
) != VALID_OBJECT
)
691 /* instance members */
693 pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC
),
694 joinable (PTHREAD_CREATE_JOINABLE
), contentionscope (PTHREAD_SCOPE_PROCESS
),
695 inheritsched (PTHREAD_INHERIT_SCHED
), stacksize (0)
697 schedparam
.sched_priority
= 0;
700 pthread_attr::~pthread_attr ()
705 pthread_condattr::is_good_object (pthread_condattr_t
const *attr
)
707 if (verifyable_object_isvalid (attr
, PTHREAD_CONDATTR_MAGIC
) != VALID_OBJECT
)
712 pthread_condattr::pthread_condattr ():verifyable_object
713 (PTHREAD_CONDATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
717 pthread_condattr::~pthread_condattr ()
721 List
<pthread_cond
> pthread_cond::conds
;
723 /* This is used for cond creation protection within a single process only */
724 fast_mutex NO_COPY
pthread_cond::cond_initialization_lock
;
726 /* We can only be called once.
727 TODO: (no rush) use a non copied memory section to
728 hold an initialization flag. */
730 pthread_cond::init_mutex ()
732 if (!cond_initialization_lock
.init ())
733 api_fatal ("Could not create win32 Mutex for pthread cond static initializer support.");
736 pthread_cond::pthread_cond (pthread_condattr
*attr
) :
737 verifyable_object (PTHREAD_COND_MAGIC
),
738 shared (0), waiting (0), pending (0), sem_wait (NULL
),
739 mtx_cond(NULL
), next (NULL
)
741 pthread_mutex
*verifyable_mutex_obj
;
744 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
750 verifyable_mutex_obj
= &mtx_in
;
751 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
753 thread_printf ("Internal cond mutex is not valid. this %p", this);
758 * Change the mutex type to NORMAL.
759 * This mutex MUST be of type normal
761 mtx_in
.type
= PTHREAD_MUTEX_NORMAL
;
763 verifyable_mutex_obj
= &mtx_out
;
764 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
766 thread_printf ("Internal cond mutex is not valid. this %p", this);
770 /* Change the mutex type to NORMAL to speed up mutex operations */
771 mtx_out
.type
= PTHREAD_MUTEX_NORMAL
;
773 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
776 debug_printf ("CreateSemaphore failed. %E");
784 pthread_cond::~pthread_cond ()
787 CloseHandle (sem_wait
);
793 pthread_cond::unblock (const bool all
)
795 unsigned long releaseable
;
798 * Block outgoing threads (and avoid simultanous unblocks)
802 releaseable
= waiting
- pending
;
805 unsigned long released
;
810 * Block incoming threads until all waiting threads are released.
815 * Calculate releaseable again because threads can enter until
816 * the semaphore has been taken, but they can not leave, therefore pending
817 * is unchanged and releaseable can only get higher
819 releaseable
= waiting
- pending
;
822 released
= all
? releaseable
: 1;
827 ::ReleaseSemaphore (sem_wait
, released
, NULL
);
831 * And let the threads release.
837 pthread_cond::wait (pthread_mutex_t mutex
, DWORD dwMilliseconds
)
842 if (InterlockedIncrement ((long *)&waiting
) == 1)
844 else if (mtx_cond
!= mutex
)
846 InterlockedDecrement ((long *)&waiting
);
853 * Release the mutex and wait on semaphore
858 rv
= pthread::cancelable_wait (sem_wait
, dwMilliseconds
, false);
862 if (rv
!= WAIT_OBJECT_0
)
865 * It might happen that a signal is sent while the thread got canceled
866 * or timed out. Try to take one.
867 * If the thread gets one than a signal|broadcast is in progress.
869 if (WaitForSingleObject (sem_wait
, 0) == WAIT_OBJECT_0
)
871 * thread got cancelled ot timed out while a signalling is in progress.
872 * Set wait result back to signaled
877 InterlockedDecrement ((long *)&waiting
);
879 if (rv
== WAIT_OBJECT_0
&& --pending
== 0)
881 * All signaled threads are released,
882 * new threads can enter Wait
891 if (rv
== WAIT_CANCELED
)
892 pthread::static_cancel_self ();
893 else if (rv
== WAIT_TIMEOUT
)
900 pthread_cond::_fixup_after_fork ()
902 waiting
= pending
= 0;
905 /* Unlock eventually locked mutexes */
909 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
911 api_fatal ("pthread_cond::_fixup_after_fork () failed to recreate win32 semaphore");
915 pthread_rwlockattr::is_good_object (pthread_rwlockattr_t
const *attr
)
917 if (verifyable_object_isvalid (attr
, PTHREAD_RWLOCKATTR_MAGIC
) != VALID_OBJECT
)
922 pthread_rwlockattr::pthread_rwlockattr ():verifyable_object
923 (PTHREAD_RWLOCKATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
927 pthread_rwlockattr::~pthread_rwlockattr ()
931 List
<pthread_rwlock
> pthread_rwlock::rwlocks
;
933 /* This is used for rwlock creation protection within a single process only */
934 fast_mutex NO_COPY
pthread_rwlock::rwlock_initialization_lock
;
936 /* We can only be called once.
937 TODO: (no rush) use a non copied memory section to
938 hold an initialization flag. */
940 pthread_rwlock::init_mutex ()
942 if (!rwlock_initialization_lock
.init ())
943 api_fatal ("Could not create win32 Mutex for pthread rwlock static initializer support.");
946 pthread_rwlock::pthread_rwlock (pthread_rwlockattr
*attr
) :
947 verifyable_object (PTHREAD_RWLOCK_MAGIC
),
948 shared (0), waiting_readers (0), waiting_writers (0), writer (NULL
),
949 readers (NULL
), readers_mx (), mtx (NULL
), cond_readers (NULL
), cond_writers (NULL
),
952 pthread_mutex
*verifyable_mutex_obj
= &mtx
;
953 pthread_cond
*verifyable_cond_obj
;
955 if (!readers_mx
.init ())
957 thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this);
963 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
969 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
971 thread_printf ("Internal rwlock mutex is not valid. this %p", this);
975 /* Change the mutex type to NORMAL to speed up mutex operations */
976 mtx
.type
= PTHREAD_MUTEX_NORMAL
;
978 verifyable_cond_obj
= &cond_readers
;
979 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
981 thread_printf ("Internal rwlock readers cond is not valid. this %p", this);
986 verifyable_cond_obj
= &cond_writers
;
987 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
989 thread_printf ("Internal rwlock writers cond is not valid. this %p", this);
995 rwlocks
.insert (this);
998 pthread_rwlock::~pthread_rwlock ()
1000 rwlocks
.remove (this);
1004 pthread_rwlock::rdlock ()
1007 struct RWLOCK_READER
*reader
;
1008 pthread_t self
= pthread::self ();
1012 if (lookup_reader (self
))
1018 reader
= new struct RWLOCK_READER
;
1025 while (writer
|| waiting_writers
)
1027 pthread_cleanup_push (pthread_rwlock::rdlock_cleanup
, this);
1030 cond_readers
.wait (&mtx
);
1033 pthread_cleanup_pop (0);
1036 reader
->thread
= self
;
1037 add_reader (reader
);
1046 pthread_rwlock::tryrdlock ()
1049 pthread_t self
= pthread::self ();
1053 if (writer
|| waiting_writers
|| lookup_reader (self
))
1057 struct RWLOCK_READER
*reader
= new struct RWLOCK_READER
;
1060 reader
->thread
= self
;
1061 add_reader (reader
);
1073 pthread_rwlock::wrlock ()
1076 pthread_t self
= pthread::self ();
1080 if (writer
== self
|| lookup_reader (self
))
1086 while (writer
|| readers
)
1088 pthread_cleanup_push (pthread_rwlock::wrlock_cleanup
, this);
1091 cond_writers
.wait (&mtx
);
1094 pthread_cleanup_pop (0);
1106 pthread_rwlock::trywrlock ()
1109 pthread_t self
= pthread::self ();
1113 if (writer
|| readers
)
1124 pthread_rwlock::unlock ()
1127 pthread_t self
= pthread::self ();
1143 struct RWLOCK_READER
*reader
= lookup_reader (self
);
1151 remove_reader (reader
);
1164 pthread_rwlock::add_reader (struct RWLOCK_READER
*rd
)
1166 List_insert (readers
, rd
);
1170 pthread_rwlock::remove_reader (struct RWLOCK_READER
*rd
)
1172 List_remove (readers_mx
, readers
, rd
);
1175 struct pthread_rwlock::RWLOCK_READER
*
1176 pthread_rwlock::lookup_reader (pthread_t thread
)
1180 struct RWLOCK_READER
*cur
= readers
;
1182 while (cur
&& cur
->thread
!= thread
)
1185 readers_mx
.unlock ();
1191 pthread_rwlock::rdlock_cleanup (void *arg
)
1193 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1195 --(rwlock
->waiting_readers
);
1197 rwlock
->mtx
.unlock ();
1201 pthread_rwlock::wrlock_cleanup (void *arg
)
1203 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1205 --(rwlock
->waiting_writers
);
1207 rwlock
->mtx
.unlock ();
1211 pthread_rwlock::_fixup_after_fork ()
1213 pthread_t self
= pthread::self ();
1214 struct RWLOCK_READER
**temp
= &readers
;
1216 waiting_readers
= 0;
1217 waiting_writers
= 0;
1219 if (!readers_mx
.init ())
1220 api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex");
1222 /* Unlock eventually locked mutex */
1225 * Remove all readers except self
1229 if ((*temp
)->thread
== self
)
1230 temp
= &((*temp
)->next
);
1233 struct RWLOCK_READER
*cur
= *temp
;
1234 *temp
= (*temp
)->next
;
1241 /* static members */
1242 /* This stores pthread_key information across fork() boundaries */
1243 List
<pthread_key
> pthread_key::keys
;
1246 pthread_key::is_good_object (pthread_key_t
const *key
)
1248 if (verifyable_object_isvalid (key
, PTHREAD_KEY_MAGIC
) != VALID_OBJECT
)
1253 /* non-static members */
1255 pthread_key::pthread_key (void (*aDestructor
) (void *)):verifyable_object (PTHREAD_KEY_MAGIC
), destructor (aDestructor
)
1257 tls_index
= TlsAlloc ();
1258 if (tls_index
== TLS_OUT_OF_INDEXES
)
1264 pthread_key::~pthread_key ()
1266 /* We may need to make the list code lock the list during operations
1271 TlsFree (tls_index
);
1276 pthread_key::set (const void *value
)
1278 /* the OS function doesn't perform error checking */
1279 TlsSetValue (tls_index
, (void *) value
);
1284 pthread_key::get () const
1286 int saved_error
= ::GetLastError ();
1287 void *result
= TlsGetValue (tls_index
);
1288 ::SetLastError (saved_error
);
1293 pthread_key::_fixup_before_fork ()
1299 pthread_key::_fixup_after_fork ()
1301 tls_index
= TlsAlloc ();
1302 if (tls_index
== TLS_OUT_OF_INDEXES
)
1303 api_fatal ("pthread_key::recreate_key_from_buffer () failed to reallocate Tls storage");
1308 pthread_key::run_destructor ()
1312 void *oldValue
= get ();
1316 destructor (oldValue
);
1323 REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
1324 gymnastics can be a lot easier.
1326 the mutex_t (size 4) is not used as a verifyable object because we cannot
1327 guarantee the same address space for all processes.
1328 we use the following:
1329 high bit set (never a valid address).
1330 second byte is reserved for the priority.
1331 third byte is reserved
1332 fourth byte is the mutex id. (max 255 cygwin mutexs system wide).
1333 creating mutex's does get slower and slower, but as creation is a one time
1334 job, it should never become an issue
1336 And if you're looking at this and thinking, why not an array in cygwin for all mutexs,
1337 - you incur a penalty on _every_ mutex call and you have toserialise them all.
1340 option 2? put everything in userspace and update the ABI?
1341 - bad karma as well - the HANDLE, while identical across process's,
1342 Isn't duplicated, it's reopened. */
1344 /* static members */
1346 pthread_mutex::is_good_object (pthread_mutex_t
const *mutex
)
1348 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
) != VALID_OBJECT
)
1354 pthread_mutex::is_good_initializer (pthread_mutex_t
const *mutex
)
1356 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
, PTHREAD_MUTEX_INITIALIZER
) != VALID_STATIC_OBJECT
)
1362 pthread_mutex::is_good_initializer_or_object (pthread_mutex_t
const *mutex
)
1364 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
, PTHREAD_MUTEX_INITIALIZER
) == INVALID_OBJECT
)
1370 pthread_mutex::is_good_initializer_or_bad_object (pthread_mutex_t
const *mutex
)
1372 verifyable_object_state objectState
= verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
, PTHREAD_MUTEX_INITIALIZER
);
1373 if (objectState
== VALID_OBJECT
)
1379 pthread_mutex::can_be_unlocked (pthread_mutex_t
const *mutex
)
1381 pthread_t self
= pthread::self ();
1383 if (!is_good_object (mutex
))
1386 * Check if the mutex is owned by the current thread and can be unlocked
1388 return ((*mutex
)->recursion_counter
== 1 && pthread::equal ((*mutex
)->owner
, self
));
1391 List
<pthread_mutex
> pthread_mutex::mutexes
;
1393 /* This is used for mutex creation protection within a single process only */
1394 fast_mutex NO_COPY
pthread_mutex::mutex_initialization_lock
;
1396 /* We can only be called once.
1397 TODO: (no rush) use a non copied memory section to
1398 hold an initialization flag. */
1400 pthread_mutex::init_mutex ()
1402 if (!mutex_initialization_lock
.init ())
1403 api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support.");
1406 pthread_mutex::pthread_mutex (pthread_mutexattr
*attr
) :
1407 verifyable_object (PTHREAD_MUTEX_MAGIC
),
1409 win32_obj_id (NULL
), recursion_counter (0),
1410 condwaits (0), owner (NULL
), type (PTHREAD_MUTEX_DEFAULT
),
1411 pshared (PTHREAD_PROCESS_PRIVATE
)
1413 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1419 /*attr checked in the C call */
1422 if (attr
->pshared
== PTHREAD_PROCESS_SHARED
)
1429 type
= attr
->mutextype
;
1432 mutexes
.insert (this);
1435 pthread_mutex::~pthread_mutex ()
1438 CloseHandle (win32_obj_id
);
1440 mutexes
.remove (this);
1444 pthread_mutex::_lock (pthread_t self
)
1448 if (InterlockedIncrement ((long *)&lock_counter
) == 1)
1450 else if (type
!= PTHREAD_MUTEX_NORMAL
&& pthread::equal (owner
, self
))
1452 InterlockedDecrement ((long *) &lock_counter
);
1453 if (type
== PTHREAD_MUTEX_RECURSIVE
)
1454 result
= lock_recursive ();
1460 WaitForSingleObject (win32_obj_id
, INFINITE
);
1468 pthread_mutex::_trylock (pthread_t self
)
1472 if (InterlockedCompareExchange ((long *) &lock_counter
, 1, 0) == 0)
1474 else if (type
== PTHREAD_MUTEX_RECURSIVE
&& pthread::equal (owner
, self
))
1475 result
= lock_recursive ();
1483 pthread_mutex::_unlock (pthread_t self
)
1485 if (!pthread::equal (owner
, self
))
1488 if (--recursion_counter
== 0)
1491 if (InterlockedDecrement ((long *)&lock_counter
))
1492 // Another thread is waiting
1493 ::ReleaseSemaphore (win32_obj_id
, 1, NULL
);
1500 pthread_mutex::_destroy (pthread_t self
)
1502 if (condwaits
|| _trylock (self
))
1503 // Do not destroy a condwaited or locked mutex
1505 else if (recursion_counter
!= 1)
1507 // Do not destroy a recursive locked mutex
1508 --recursion_counter
;
1517 pthread_mutex::_fixup_after_fork ()
1519 debug_printf ("mutex %x in _fixup_after_fork", this);
1520 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1521 api_fatal ("pthread_mutex::_fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's");
1524 /* mutex has no owner, reset to initial */
1526 else if (lock_counter
!= 0)
1527 /* All waiting threads are gone after a fork */
1530 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1532 api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 semaphore for mutex");
1538 pthread_mutexattr::is_good_object (pthread_mutexattr_t
const * attr
)
1540 if (verifyable_object_isvalid (attr
, PTHREAD_MUTEXATTR_MAGIC
) != VALID_OBJECT
)
1545 pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC
),
1546 pshared (PTHREAD_PROCESS_PRIVATE
), mutextype (PTHREAD_MUTEX_DEFAULT
)
1550 pthread_mutexattr::~pthread_mutexattr ()
1554 List
<semaphore
> semaphore::semaphores
;
1556 semaphore::semaphore (int pshared
, unsigned int value
)
1557 : verifyable_object (SEM_MAGIC
),
1559 currentvalue (value
),
1562 SECURITY_ATTRIBUTES sa
= (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1563 ? sec_all
: sec_none_nih
;
1564 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, NULL
);
1565 if (!this->win32_obj_id
)
1568 semaphores
.insert (this);
1571 semaphore::semaphore (const char *sem_name
, int oflag
, mode_t mode
,
1573 : verifyable_object (SEM_MAGIC
),
1574 shared (PTHREAD_PROCESS_SHARED
),
1575 currentvalue (value
), /* Unused for named semaphores. */
1578 if (oflag
& O_CREAT
)
1580 SECURITY_ATTRIBUTES sa
= sec_all
;
1581 security_descriptor sd
;
1583 set_security_attribute (mode
, &sa
, sd
);
1584 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, sem_name
);
1585 if (!this->win32_obj_id
)
1587 if (GetLastError () == ERROR_ALREADY_EXISTS
&& (oflag
& O_EXCL
))
1590 CloseHandle (this->win32_obj_id
);
1596 this->win32_obj_id
= ::OpenSemaphore (SEMAPHORE_ALL_ACCESS
, FALSE
,
1598 if (!this->win32_obj_id
)
1606 name
= new char [strlen (sem_name
+ 1)];
1610 CloseHandle (this->win32_obj_id
);
1614 strcpy (name
, sem_name
);
1617 semaphores
.insert (this);
1620 semaphore::~semaphore ()
1623 CloseHandle (win32_obj_id
);
1627 semaphores
.remove (this);
1633 if (ReleaseSemaphore (win32_obj_id
, 1, ¤tvalue
))
1638 semaphore::_getvalue (int *sval
)
1642 switch (WaitForSingleObject (win32_obj_id
, 0))
1645 ReleaseSemaphore (win32_obj_id
, 1, &val
);
1659 semaphore::_trywait ()
1661 /* FIXME: signals should be able to interrupt semaphores...
1662 *We probably need WaitForMultipleObjects here.
1664 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
1674 semaphore::_timedwait (const struct timespec
*abstime
)
1679 if (__check_invalid_read_ptr (abstime
, sizeof *abstime
))
1681 /* According to SUSv3, abstime need not be checked for validity,
1682 if the semaphore can be locked immediately. */
1689 gettimeofday (&tv
, NULL
);
1690 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
1691 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
1694 switch (pthread::cancelable_wait (win32_obj_id
, waitlength
))
1700 set_errno (ETIMEDOUT
);
1703 debug_printf ("cancelable_wait failed. %E");
1713 switch (pthread::cancelable_wait (win32_obj_id
, INFINITE
))
1719 debug_printf ("cancelable_wait failed. %E");
1725 semaphore::_fixup_after_fork ()
1727 if (shared
== PTHREAD_PROCESS_PRIVATE
)
1729 debug_printf ("sem %x in _fixup_after_fork", this);
1730 /* FIXME: duplicate code here and in the constructor. */
1731 this->win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, currentvalue
,
1734 api_fatal ("failed to create new win32 semaphore, error %d");
1738 verifyable_object::verifyable_object (long verifyer
):
1743 verifyable_object::~verifyable_object ()
1748 /* Generic memory acccess routine - where should it live ? */
1750 check_valid_pointer (void const *pointer
)
1752 if (!pointer
|| IsBadWritePtr ((void *) pointer
, sizeof (verifyable_object
)))
1757 verifyable_object_state
1758 verifyable_object_isvalid (void const * objectptr
, long magic
, void *static_ptr
)
1760 verifyable_object
**object
= (verifyable_object
**)objectptr
;
1761 if (check_valid_pointer (object
))
1762 return INVALID_OBJECT
;
1763 if (static_ptr
&& *object
== static_ptr
)
1764 return VALID_STATIC_OBJECT
;
1766 return INVALID_OBJECT
;
1767 if (check_valid_pointer (*object
))
1768 return INVALID_OBJECT
;
1769 if ((*object
)->magic
!= magic
)
1770 return INVALID_OBJECT
;
1771 return VALID_OBJECT
;
1774 verifyable_object_state
1775 verifyable_object_isvalid (void const * objectptr
, long magic
)
1777 return verifyable_object_isvalid (objectptr
, magic
, NULL
);
1781 pthread::thread_init_wrapper (void *arg
)
1783 pthread
*thread
= (pthread
*) arg
;
1784 _my_tls
.tid
= thread
;
1786 thread
->mutex
.lock ();
1788 // if thread is detached force cleanup on exit
1789 if (thread
->attr
.joinable
== PTHREAD_CREATE_DETACHED
&& thread
->joiner
== NULL
)
1790 thread
->joiner
= thread
;
1791 thread
->mutex
.unlock ();
1793 thread_printf ("started thread %p %p %p %p %p %p", arg
, &_my_tls
.local_clib
,
1794 _impure_ptr
, thread
, thread
->function
, thread
->arg
);
1796 // call the user's thread
1797 void *ret
= thread
->function (thread
->arg
);
1801 return 0; // just for show. Never returns.
1805 pthread::is_good_object (pthread_t
const *thread
)
1807 if (verifyable_object_isvalid (thread
, PTHREAD_MAGIC
) != VALID_OBJECT
)
1813 pthread::getsequence_np ()
1815 return get_thread_id ();
1819 pthread::create (pthread_t
*thread
, const pthread_attr_t
*attr
,
1820 void *(*start_routine
) (void *), void *arg
)
1822 if (attr
&& !pthread_attr::is_good_object (attr
))
1825 *thread
= new pthread ();
1826 (*thread
)->create (start_routine
, attr
? *attr
: NULL
, arg
);
1827 if (!is_good_object (thread
))
1838 pthread::once (pthread_once_t
*once_control
, void (*init_routine
) (void))
1841 if (once_control
->state
)
1844 pthread_mutex_lock (&once_control
->mutex
);
1845 /* Here we must set a cancellation handler to unlock the mutex if needed */
1846 /* but a cancellation handler is not the right thing. We need this in the thread
1847 *cleanup routine. Assumption: a thread can only be in one pthread_once routine
1848 *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
1849 *on pthread_exit ();
1851 if (!once_control
->state
)
1854 once_control
->state
= 1;
1856 /* Here we must remove our cancellation handler */
1857 pthread_mutex_unlock (&once_control
->mutex
);
1862 pthread::cancel (pthread_t thread
)
1864 if (!is_good_object (&thread
))
1867 return thread
->cancel ();
1871 pthread::atforkprepare (void)
1873 MT_INTERFACE
->fixup_before_fork ();
1875 callback
*cb
= MT_INTERFACE
->pthread_prepare
;
1884 pthread::atforkparent (void)
1886 callback
*cb
= MT_INTERFACE
->pthread_parent
;
1895 pthread::atforkchild (void)
1897 MT_INTERFACE
->fixup_after_fork ();
1899 callback
*cb
= MT_INTERFACE
->pthread_child
;
1907 /* Register a set of functions to run before and after fork.
1908 prepare calls are called in LI-FC order.
1909 parent and child calls are called in FI-FC order. */
1911 pthread::atfork (void (*prepare
)(void), void (*parent
)(void), void (*child
)(void))
1913 callback
*prepcb
= NULL
, *parentcb
= NULL
, *childcb
= NULL
;
1916 prepcb
= new callback
;
1922 parentcb
= new callback
;
1932 childcb
= new callback
;
1945 prepcb
->cb
= prepare
;
1946 List_insert (MT_INTERFACE
->pthread_prepare
, prepcb
);
1950 parentcb
->cb
= parent
;
1951 callback
**t
= &MT_INTERFACE
->pthread_parent
;
1954 /* t = pointer to last next in the list */
1955 List_insert (*t
, parentcb
);
1959 childcb
->cb
= child
;
1960 callback
**t
= &MT_INTERFACE
->pthread_child
;
1963 /* t = pointer to last next in the list */
1964 List_insert (*t
, childcb
);
1970 pthread_attr_init (pthread_attr_t
*attr
)
1972 if (pthread_attr::is_good_object (attr
))
1975 *attr
= new pthread_attr
;
1976 if (!pthread_attr::is_good_object (attr
))
1986 pthread_attr_getinheritsched (const pthread_attr_t
*attr
,
1989 if (!pthread_attr::is_good_object (attr
))
1991 *inheritsched
= (*attr
)->inheritsched
;
1996 pthread_attr_getschedparam (const pthread_attr_t
*attr
,
1997 struct sched_param
*param
)
1999 if (!pthread_attr::is_good_object (attr
))
2001 *param
= (*attr
)->schedparam
;
2005 /* From a pure code point of view, this should call a helper in sched.cc,
2006 to allow for someone adding scheduler policy changes to win32 in the future.
2007 However that's extremely unlikely, so short and sweet will do us */
2009 pthread_attr_getschedpolicy (const pthread_attr_t
*attr
, int *policy
)
2011 if (!pthread_attr::is_good_object (attr
))
2013 *policy
= SCHED_FIFO
;
2019 pthread_attr_getscope (const pthread_attr_t
*attr
, int *contentionscope
)
2021 if (!pthread_attr::is_good_object (attr
))
2023 *contentionscope
= (*attr
)->contentionscope
;
2028 pthread_attr_setdetachstate (pthread_attr_t
*attr
, int detachstate
)
2030 if (!pthread_attr::is_good_object (attr
))
2032 if (detachstate
< 0 || detachstate
> 1)
2034 (*attr
)->joinable
= detachstate
;
2039 pthread_attr_getdetachstate (const pthread_attr_t
*attr
, int *detachstate
)
2041 if (!pthread_attr::is_good_object (attr
))
2043 *detachstate
= (*attr
)->joinable
;
2048 pthread_attr_setinheritsched (pthread_attr_t
*attr
, int inheritsched
)
2050 if (!pthread_attr::is_good_object (attr
))
2052 if (inheritsched
!= PTHREAD_INHERIT_SCHED
2053 && inheritsched
!= PTHREAD_EXPLICIT_SCHED
)
2055 (*attr
)->inheritsched
= inheritsched
;
2060 pthread_attr_setschedparam (pthread_attr_t
*attr
,
2061 const struct sched_param
*param
)
2063 if (!pthread_attr::is_good_object (attr
))
2065 if (!valid_sched_parameters (param
))
2067 (*attr
)->schedparam
= *param
;
2071 /* See __pthread_attr_getschedpolicy for some notes */
2073 pthread_attr_setschedpolicy (pthread_attr_t
*attr
, int policy
)
2075 if (!pthread_attr::is_good_object (attr
))
2077 if (policy
!= SCHED_FIFO
)
2083 pthread_attr_setscope (pthread_attr_t
*attr
, int contentionscope
)
2085 if (!pthread_attr::is_good_object (attr
))
2087 if (contentionscope
!= PTHREAD_SCOPE_SYSTEM
2088 && contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2090 /* In future, we may be able to support system scope by escalating the thread
2091 priority to exceed the priority class. For now we only support PROCESS scope. */
2092 if (contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2094 (*attr
)->contentionscope
= contentionscope
;
2099 pthread_attr_setstacksize (pthread_attr_t
*attr
, size_t size
)
2101 if (!pthread_attr::is_good_object (attr
))
2103 (*attr
)->stacksize
= size
;
2108 pthread_attr_getstacksize (const pthread_attr_t
*attr
, size_t *size
)
2110 if (!pthread_attr::is_good_object (attr
))
2112 *size
= (*attr
)->stacksize
;
2117 pthread_attr_destroy (pthread_attr_t
*attr
)
2119 if (!pthread_attr::is_good_object (attr
))
2127 pthread::join (pthread_t
*thread
, void **return_val
)
2129 pthread_t joiner
= self ();
2131 joiner
->testcancel ();
2133 // Initialize return val with NULL
2137 if (!is_good_object (&joiner
))
2140 if (!is_good_object (thread
))
2143 if (equal (*thread
,joiner
))
2146 (*thread
)->mutex
.lock ();
2148 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2150 (*thread
)->mutex
.unlock ();
2155 (*thread
)->joiner
= joiner
;
2156 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2157 (*thread
)->mutex
.unlock ();
2159 switch (cancelable_wait ((*thread
)->win32_obj_id
, INFINITE
, false))
2163 *return_val
= (*thread
)->return_ptr
;
2167 // set joined thread back to joinable since we got canceled
2168 (*thread
)->joiner
= NULL
;
2169 (*thread
)->attr
.joinable
= PTHREAD_CREATE_JOINABLE
;
2170 joiner
->cancel_self ();
2174 // should never happen
2183 pthread::detach (pthread_t
*thread
)
2185 if (!is_good_object (thread
))
2188 (*thread
)->mutex
.lock ();
2189 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2191 (*thread
)->mutex
.unlock ();
2195 // check if thread is still alive
2196 if ((*thread
)->valid
&& WaitForSingleObject ((*thread
)->win32_obj_id
, 0) == WAIT_TIMEOUT
)
2198 // force cleanup on exit
2199 (*thread
)->joiner
= *thread
;
2200 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2201 (*thread
)->mutex
.unlock ();
2205 // thread has already terminated.
2206 (*thread
)->mutex
.unlock ();
2214 pthread::suspend (pthread_t
*thread
)
2216 if (!is_good_object (thread
))
2219 if ((*thread
)->suspended
== false)
2221 (*thread
)->suspended
= true;
2222 SuspendThread ((*thread
)->win32_obj_id
);
2230 pthread::resume (pthread_t
*thread
)
2232 if (!is_good_object (thread
))
2235 if ((*thread
)->suspended
== true)
2236 ResumeThread ((*thread
)->win32_obj_id
);
2237 (*thread
)->suspended
= false;
2242 /* provided for source level compatability.
2243 See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2246 pthread_getconcurrency (void)
2248 return MT_INTERFACE
->concurrency
;
2251 /* keep this in sync with sched.cc */
2253 pthread_getschedparam (pthread_t thread
, int *policy
,
2254 struct sched_param
*param
)
2256 if (!pthread::is_good_object (&thread
))
2258 *policy
= SCHED_FIFO
;
2259 /* we don't return the current effective priority, we return the current
2260 requested priority */
2261 *param
= thread
->attr
.schedparam
;
2265 /* Thread Specific Data */
2267 pthread_key_create (pthread_key_t
*key
, void (*destructor
) (void *))
2269 /* The opengroup docs don't define if we should check this or not,
2270 but creation is relatively rare. */
2271 if (pthread_key::is_good_object (key
))
2274 *key
= new pthread_key (destructor
);
2276 if (!pthread_key::is_good_object (key
))
2286 pthread_key_delete (pthread_key_t key
)
2288 if (!pthread_key::is_good_object (&key
))
2295 /* provided for source level compatability. See
2296 http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2299 pthread_setconcurrency (int new_level
)
2303 MT_INTERFACE
->concurrency
= new_level
;
2307 /* keep syncronised with sched.cc */
2309 pthread_setschedparam (pthread_t thread
, int policy
,
2310 const struct sched_param
*param
)
2312 if (!pthread::is_good_object (&thread
))
2314 if (policy
!= SCHED_FIFO
)
2319 sched_set_thread_priority (thread
->win32_obj_id
, param
->sched_priority
);
2321 thread
->attr
.schedparam
.sched_priority
= param
->sched_priority
;
2327 pthread_setspecific (pthread_key_t key
, const void *value
)
2329 if (!pthread_key::is_good_object (&key
))
2336 pthread_getspecific (pthread_key_t key
)
2338 if (!pthread_key::is_good_object (&key
))
2341 return (key
)->get ();
2345 /* Thread synchronisation */
2347 pthread_cond::is_good_object (pthread_cond_t
const *cond
)
2349 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
) != VALID_OBJECT
)
2355 pthread_cond::is_good_initializer (pthread_cond_t
const *cond
)
2357 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) != VALID_STATIC_OBJECT
)
2363 pthread_cond::is_good_initializer_or_object (pthread_cond_t
const *cond
)
2365 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) == INVALID_OBJECT
)
2371 pthread_cond::is_good_initializer_or_bad_object (pthread_cond_t
const *cond
)
2373 verifyable_object_state objectState
= verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
);
2374 if (objectState
== VALID_OBJECT
)
2380 pthread_cond_destroy (pthread_cond_t
*cond
)
2382 if (pthread_cond::is_good_initializer (cond
))
2384 if (!pthread_cond::is_good_object (cond
))
2387 /* reads are atomic */
2388 if ((*cond
)->waiting
)
2398 pthread_cond::init (pthread_cond_t
*cond
, const pthread_condattr_t
*attr
)
2400 if (attr
&& !pthread_condattr::is_good_object (attr
))
2403 cond_initialization_lock
.lock ();
2405 if (!is_good_initializer_or_bad_object (cond
))
2407 cond_initialization_lock
.unlock ();
2411 *cond
= new pthread_cond (attr
? (*attr
) : NULL
);
2412 if (!is_good_object (cond
))
2416 cond_initialization_lock
.unlock ();
2419 cond_initialization_lock
.unlock ();
2424 pthread_cond_broadcast (pthread_cond_t
*cond
)
2426 if (pthread_cond::is_good_initializer (cond
))
2428 if (!pthread_cond::is_good_object (cond
))
2431 (*cond
)->unblock (true);
2437 pthread_cond_signal (pthread_cond_t
*cond
)
2439 if (pthread_cond::is_good_initializer (cond
))
2441 if (!pthread_cond::is_good_object (cond
))
2444 (*cond
)->unblock (false);
2450 __pthread_cond_dowait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2453 if (!pthread_mutex::is_good_object (mutex
))
2455 if (!pthread_mutex::can_be_unlocked (mutex
))
2458 if (pthread_cond::is_good_initializer (cond
))
2459 pthread_cond::init (cond
, NULL
);
2460 if (!pthread_cond::is_good_object (cond
))
2463 return (*cond
)->wait (*mutex
, waitlength
);
2467 pthread_cond_timedwait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2468 const struct timespec
*abstime
)
2473 pthread_testcancel ();
2475 if (check_valid_pointer (abstime
))
2478 gettimeofday (&tv
, NULL
);
2479 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
2480 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
2483 return __pthread_cond_dowait (cond
, mutex
, waitlength
);
2487 pthread_cond_wait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
2489 pthread_testcancel ();
2491 return __pthread_cond_dowait (cond
, mutex
, INFINITE
);
2495 pthread_condattr_init (pthread_condattr_t
*condattr
)
2497 if (pthread_condattr::is_good_object (condattr
))
2500 *condattr
= new pthread_condattr
;
2501 if (!pthread_condattr::is_good_object (condattr
))
2511 pthread_condattr_getpshared (const pthread_condattr_t
*attr
, int *pshared
)
2513 if (!pthread_condattr::is_good_object (attr
))
2515 *pshared
= (*attr
)->shared
;
2520 pthread_condattr_setpshared (pthread_condattr_t
*attr
, int pshared
)
2522 if (!pthread_condattr::is_good_object (attr
))
2524 if ((pshared
< 0) || (pshared
> 1))
2526 /* shared cond vars not currently supported */
2527 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2529 (*attr
)->shared
= pshared
;
2534 pthread_condattr_destroy (pthread_condattr_t
*condattr
)
2536 if (!pthread_condattr::is_good_object (condattr
))
2545 pthread_rwlock::is_good_object (pthread_rwlock_t
const *rwlock
)
2547 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
) != VALID_OBJECT
)
2553 pthread_rwlock::is_good_initializer (pthread_rwlock_t
const *rwlock
)
2555 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) != VALID_STATIC_OBJECT
)
2561 pthread_rwlock::is_good_initializer_or_object (pthread_rwlock_t
const *rwlock
)
2563 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) == INVALID_OBJECT
)
2569 pthread_rwlock::is_good_initializer_or_bad_object (pthread_rwlock_t
const *rwlock
)
2571 verifyable_object_state objectState
= verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
);
2572 if (objectState
== VALID_OBJECT
)
2578 pthread_rwlock_destroy (pthread_rwlock_t
*rwlock
)
2580 if (pthread_rwlock::is_good_initializer (rwlock
))
2582 if (!pthread_rwlock::is_good_object (rwlock
))
2585 if ((*rwlock
)->writer
|| (*rwlock
)->readers
||
2586 (*rwlock
)->waiting_readers
|| (*rwlock
)->waiting_writers
)
2596 pthread_rwlock::init (pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*attr
)
2598 if (attr
&& !pthread_rwlockattr::is_good_object (attr
))
2601 rwlock_initialization_lock
.lock ();
2603 if (!is_good_initializer_or_bad_object (rwlock
))
2605 rwlock_initialization_lock
.unlock ();
2609 *rwlock
= new pthread_rwlock (attr
? (*attr
) : NULL
);
2610 if (!is_good_object (rwlock
))
2614 rwlock_initialization_lock
.unlock ();
2617 rwlock_initialization_lock
.unlock ();
2622 pthread_rwlock_rdlock (pthread_rwlock_t
*rwlock
)
2624 pthread_testcancel ();
2626 if (pthread_rwlock::is_good_initializer (rwlock
))
2627 pthread_rwlock::init (rwlock
, NULL
);
2628 if (!pthread_rwlock::is_good_object (rwlock
))
2631 return (*rwlock
)->rdlock ();
2635 pthread_rwlock_tryrdlock (pthread_rwlock_t
*rwlock
)
2637 if (pthread_rwlock::is_good_initializer (rwlock
))
2638 pthread_rwlock::init (rwlock
, NULL
);
2639 if (!pthread_rwlock::is_good_object (rwlock
))
2642 return (*rwlock
)->tryrdlock ();
2646 pthread_rwlock_wrlock (pthread_rwlock_t
*rwlock
)
2648 pthread_testcancel ();
2650 if (pthread_rwlock::is_good_initializer (rwlock
))
2651 pthread_rwlock::init (rwlock
, NULL
);
2652 if (!pthread_rwlock::is_good_object (rwlock
))
2655 return (*rwlock
)->wrlock ();
2659 pthread_rwlock_trywrlock (pthread_rwlock_t
*rwlock
)
2661 if (pthread_rwlock::is_good_initializer (rwlock
))
2662 pthread_rwlock::init (rwlock
, NULL
);
2663 if (!pthread_rwlock::is_good_object (rwlock
))
2666 return (*rwlock
)->trywrlock ();
2670 pthread_rwlock_unlock (pthread_rwlock_t
*rwlock
)
2672 if (pthread_rwlock::is_good_initializer (rwlock
))
2674 if (!pthread_rwlock::is_good_object (rwlock
))
2677 return (*rwlock
)->unlock ();
2681 pthread_rwlockattr_init (pthread_rwlockattr_t
*rwlockattr
)
2683 if (pthread_rwlockattr::is_good_object (rwlockattr
))
2686 *rwlockattr
= new pthread_rwlockattr
;
2687 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2689 delete (*rwlockattr
);
2697 pthread_rwlockattr_getpshared (const pthread_rwlockattr_t
*attr
, int *pshared
)
2699 if (!pthread_rwlockattr::is_good_object (attr
))
2701 *pshared
= (*attr
)->shared
;
2706 pthread_rwlockattr_setpshared (pthread_rwlockattr_t
*attr
, int pshared
)
2708 if (!pthread_rwlockattr::is_good_object (attr
))
2710 if ((pshared
< 0) || (pshared
> 1))
2712 /* shared rwlock vars not currently supported */
2713 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2715 (*attr
)->shared
= pshared
;
2720 pthread_rwlockattr_destroy (pthread_rwlockattr_t
*rwlockattr
)
2722 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2724 delete (*rwlockattr
);
2731 pthread_kill (pthread_t thread
, int sig
)
2733 // lock myself, for the use of thread2signal
2734 // two different kills might clash: FIXME
2736 if (!pthread::is_good_object (&thread
))
2741 si
.si_code
= SI_USER
;
2742 si
.si_pid
= si
.si_uid
= si
.si_errno
= 0;
2743 thread
->cygtls
->set_threadkill ();
2744 int rval
= sig
? sig_send (NULL
, si
, thread
->cygtls
) : 0;
2751 pthread_sigmask (int operation
, const sigset_t
*set
, sigset_t
*old_set
)
2753 return handle_sigprocmask (operation
, set
, old_set
, _my_tls
.sigmask
);
2759 pthread_equal (pthread_t t1
, pthread_t t2
)
2761 return pthread::equal (t1
, t2
);
2766 /* FIXME: there's a potential race with PTHREAD_MUTEX_INITALIZER:
2767 the mutex is not actually inited until the first use.
2768 So two threads trying to lock/trylock may collide.
2769 Solution: we need a global mutex on mutex creation, or possibly simply
2770 on all constructors that allow INITIALIZER macros.
2771 the lock should be very small: only around the init routine, not
2772 every test, or all mutex access will be synchronised. */
2775 pthread_mutex::init (pthread_mutex_t
*mutex
,
2776 const pthread_mutexattr_t
*attr
)
2778 if (attr
&& !pthread_mutexattr::is_good_object (attr
) || check_valid_pointer (mutex
))
2781 mutex_initialization_lock
.lock ();
2783 if (!is_good_initializer_or_bad_object (mutex
))
2785 mutex_initialization_lock
.unlock ();
2789 *mutex
= new pthread_mutex (attr
? (*attr
) : NULL
);
2790 if (!is_good_object (mutex
))
2794 mutex_initialization_lock
.unlock ();
2797 mutex_initialization_lock
.unlock ();
2802 pthread_mutex_getprioceiling (const pthread_mutex_t
*mutex
,
2805 pthread_mutex_t
*themutex
= (pthread_mutex_t
*) mutex
;
2806 if (pthread_mutex::is_good_initializer (mutex
))
2807 pthread_mutex::init ((pthread_mutex_t
*) mutex
, NULL
);
2808 if (!pthread_mutex::is_good_object (themutex
))
2810 /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
2813 We can support mutex priorities in the future though:
2814 Store a priority with each mutex.
2815 When the mutex is optained, set the thread priority as appropriate
2816 When the mutex is released, reset the thread priority. */
2821 pthread_mutex_lock (pthread_mutex_t
*mutex
)
2823 pthread_mutex_t
*themutex
= mutex
;
2824 /* This could be simplified via is_good_initializer_or_object
2825 and is_good_initializer, but in a performance critical call like this....
2827 switch (verifyable_object_isvalid (themutex
, PTHREAD_MUTEX_MAGIC
, PTHREAD_MUTEX_INITIALIZER
))
2829 case INVALID_OBJECT
:
2832 case VALID_STATIC_OBJECT
:
2833 if (pthread_mutex::is_good_initializer (mutex
))
2835 int rv
= pthread_mutex::init (mutex
, NULL
);
2836 if (rv
&& rv
!= EBUSY
)
2839 /* No else needed. If it's been initialized while we waited,
2840 we can just attempt to lock it */
2845 return (*themutex
)->lock ();
2849 pthread_mutex_trylock (pthread_mutex_t
*mutex
)
2851 pthread_mutex_t
*themutex
= mutex
;
2852 if (pthread_mutex::is_good_initializer (mutex
))
2853 pthread_mutex::init (mutex
, NULL
);
2854 if (!pthread_mutex::is_good_object (themutex
))
2856 return (*themutex
)->trylock ();
2860 pthread_mutex_unlock (pthread_mutex_t
*mutex
)
2862 if (pthread_mutex::is_good_initializer (mutex
))
2863 pthread_mutex::init (mutex
, NULL
);
2864 if (!pthread_mutex::is_good_object (mutex
))
2866 return (*mutex
)->unlock ();
2870 pthread_mutex_destroy (pthread_mutex_t
*mutex
)
2874 if (pthread_mutex::is_good_initializer (mutex
))
2876 if (!pthread_mutex::is_good_object (mutex
))
2879 rv
= (*mutex
)->destroy ();
2888 pthread_mutex_setprioceiling (pthread_mutex_t
*mutex
, int prioceiling
,
2891 pthread_mutex_t
*themutex
= mutex
;
2892 if (pthread_mutex::is_good_initializer (mutex
))
2893 pthread_mutex::init (mutex
, NULL
);
2894 if (!pthread_mutex::is_good_object (themutex
))
2899 /* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
2902 pthread_mutexattr_getprotocol (const pthread_mutexattr_t
*attr
,
2905 if (!pthread_mutexattr::is_good_object (attr
))
2911 pthread_mutexattr_getpshared (const pthread_mutexattr_t
*attr
,
2914 if (!pthread_mutexattr::is_good_object (attr
))
2916 *pshared
= (*attr
)->pshared
;
2921 pthread_mutexattr_gettype (const pthread_mutexattr_t
*attr
, int *type
)
2923 if (!pthread_mutexattr::is_good_object (attr
))
2925 *type
= (*attr
)->mutextype
;
2929 /* FIXME: write and test process shared mutex's. */
2931 pthread_mutexattr_init (pthread_mutexattr_t
*attr
)
2933 if (pthread_mutexattr::is_good_object (attr
))
2936 *attr
= new pthread_mutexattr ();
2937 if (!pthread_mutexattr::is_good_object (attr
))
2947 pthread_mutexattr_destroy (pthread_mutexattr_t
*attr
)
2949 if (!pthread_mutexattr::is_good_object (attr
))
2957 /* Win32 doesn't support mutex priorities */
2959 pthread_mutexattr_setprotocol (pthread_mutexattr_t
*attr
, int protocol
)
2961 if (!pthread_mutexattr::is_good_object (attr
))
2966 /* Win32 doesn't support mutex priorities */
2968 pthread_mutexattr_setprioceiling (pthread_mutexattr_t
*attr
,
2971 if (!pthread_mutexattr::is_good_object (attr
))
2977 pthread_mutexattr_getprioceiling (const pthread_mutexattr_t
*attr
,
2980 if (!pthread_mutexattr::is_good_object (attr
))
2986 pthread_mutexattr_setpshared (pthread_mutexattr_t
*attr
, int pshared
)
2988 if (!pthread_mutexattr::is_good_object (attr
))
2990 /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
2993 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2995 (*attr
)->pshared
= pshared
;
2999 /* see pthread_mutex_gettype */
3001 pthread_mutexattr_settype (pthread_mutexattr_t
*attr
, int type
)
3003 if (!pthread_mutexattr::is_good_object (attr
))
3008 case PTHREAD_MUTEX_ERRORCHECK
:
3009 case PTHREAD_MUTEX_RECURSIVE
:
3010 case PTHREAD_MUTEX_NORMAL
:
3011 (*attr
)->mutextype
= type
;
3022 /* static members */
3024 semaphore::is_good_object (sem_t
const * sem
)
3026 if (verifyable_object_isvalid (sem
, SEM_MAGIC
) != VALID_OBJECT
)
3032 semaphore::init (sem_t
*sem
, int pshared
, unsigned int value
)
3034 /* opengroup calls this undefined */
3035 if (is_good_object (sem
))
3038 if (value
> SEM_VALUE_MAX
)
3041 *sem
= new semaphore (pshared
, value
);
3043 if (!is_good_object (sem
))
3053 semaphore::destroy (sem_t
*sem
)
3055 if (!is_good_object (sem
))
3058 /* FIXME - new feature - test for busy against threads... */
3066 semaphore::open (const char *name
, int oflag
, mode_t mode
, unsigned int value
)
3068 if (value
> SEM_VALUE_MAX
)
3074 sem_t
*sem
= new sem_t
;
3081 *sem
= new semaphore (name
, oflag
, mode
, value
);
3083 if (!is_good_object (sem
))
3093 semaphore::wait (sem_t
*sem
)
3095 pthread_testcancel ();
3097 if (!is_good_object (sem
))
3108 semaphore::trywait (sem_t
*sem
)
3110 if (!is_good_object (sem
))
3116 return (*sem
)->_trywait ();
3120 semaphore::timedwait (sem_t
*sem
, const struct timespec
*abstime
)
3122 if (!is_good_object (sem
))
3128 return (*sem
)->_timedwait (abstime
);
3132 semaphore::post (sem_t
*sem
)
3134 if (!is_good_object (sem
))
3145 semaphore::getvalue (sem_t
*sem
, int *sval
)
3148 if (!is_good_object (sem
)
3149 || __check_null_invalid_struct (sval
, sizeof (int)))
3155 return (*sem
)->_getvalue (sval
);
3160 pthread_null::get_null_pthread ()
3162 /* because of weird entry points */
3163 _instance
.magic
= 0;
3167 pthread_null::pthread_null ()
3169 attr
.joinable
= PTHREAD_CREATE_DETACHED
;
3170 /* Mark ourselves as invalid */
3174 pthread_null::~pthread_null ()
3179 pthread_null::create (void *(*)(void *), pthread_attr
*, void *)
3184 pthread_null::exit (void *value_ptr
)
3190 pthread_null::cancel ()
3196 pthread_null::testcancel ()
3201 pthread_null::setcancelstate (int state
, int *oldstate
)
3207 pthread_null::setcanceltype (int type
, int *oldtype
)
3213 pthread_null::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
3218 pthread_null::pop_cleanup_handler (int const execute
)
3223 pthread_null::getsequence_np ()
3228 pthread_null
pthread_null::_instance
;