1 /* thread.cc: Locking and threading module functions
3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12 /* Implementation overview and caveats:
14 Win32 puts some contraints on what can and cannot be implemented. Where
15 possible we work around those contrainsts. Where we cannot work around
16 the constraints we either pretend to be conformant, or return an error
19 Some caveats: PROCESS_SHARED objects, while they pretend to be process
20 shared, may not actually work. Some test cases are needed to determine
21 win32's behaviour. My suspicion is that the win32 handle needs to be
22 opened with different flags for proper operation.
24 R.Collins, April 2001. */
30 #include "miscfuncs.h"
35 #include "perprocess.h"
42 extern "C" void __fp_lock_all ();
43 extern "C" void __fp_unlock_all ();
44 extern "C" int valid_sched_parameters(const struct sched_param
*);
45 extern "C" int sched_set_thread_priority(HANDLE thread
, int priority
);
46 static inline verifyable_object_state
47 verifyable_object_isvalid (void const * objectptr
, thread_magic_t magic
,
48 void *static_ptr1
= NULL
,
49 void *static_ptr2
= NULL
,
50 void *static_ptr3
= NULL
);
52 extern int threadsafe
;
54 const pthread_t
pthread_mutex::_new_mutex
= (pthread_t
) 1;
55 const pthread_t
pthread_mutex::_unlocked_mutex
= (pthread_t
) 2;
56 const pthread_t
pthread_mutex::_destroyed_mutex
= (pthread_t
) 3;
59 pthread_mutex::no_owner()
64 debug_printf ("NULL owner value");
67 else if (owner
== _destroyed_mutex
)
69 paranoid_printf ("attempt to use destroyed mutex");
72 else if (owner
== _new_mutex
|| owner
== _unlocked_mutex
)
80 extern "C" struct _reent
*
83 return &_my_tls
.local_clib
;
87 __cygwin_lock_init (_LOCK_T
*lock
)
89 *lock
= _LOCK_T_INITIALIZER
;
93 __cygwin_lock_init_recursive (_LOCK_T
*lock
)
95 *lock
= _LOCK_T_RECURSIVE_INITIALIZER
;
99 __cygwin_lock_fini (_LOCK_T
*lock
)
101 pthread_mutex_destroy ((pthread_mutex_t
*) lock
);
105 __cygwin_lock_lock (_LOCK_T
*lock
)
107 paranoid_printf ("threadcount %d. locking", MT_INTERFACE
->threadcount
);
108 pthread_mutex_lock ((pthread_mutex_t
*) lock
);
112 __cygwin_lock_trylock (_LOCK_T
*lock
)
114 return pthread_mutex_trylock ((pthread_mutex_t
*) lock
);
119 __cygwin_lock_unlock (_LOCK_T
*lock
)
121 pthread_mutex_unlock ((pthread_mutex_t
*) lock
);
122 paranoid_printf ("threadcount %d. unlocked", MT_INTERFACE
->threadcount
);
125 static inline verifyable_object_state
126 verifyable_object_isvalid (void const *objectptr
, thread_magic_t magic
, void *static_ptr1
,
127 void *static_ptr2
, void *static_ptr3
)
130 if (efault
.faulted (objectptr
))
131 return INVALID_OBJECT
;
133 verifyable_object
**object
= (verifyable_object
**) objectptr
;
135 if ((static_ptr1
&& *object
== static_ptr1
) ||
136 (static_ptr2
&& *object
== static_ptr2
) ||
137 (static_ptr3
&& *object
== static_ptr3
))
138 return VALID_STATIC_OBJECT
;
139 if ((*object
)->magic
!= magic
)
140 return INVALID_OBJECT
;
146 pthread_attr::is_good_object (pthread_attr_t
const *attr
)
148 if (verifyable_object_isvalid (attr
, PTHREAD_ATTR_MAGIC
) != VALID_OBJECT
)
154 pthread_condattr::is_good_object (pthread_condattr_t
const *attr
)
156 if (verifyable_object_isvalid (attr
, PTHREAD_CONDATTR_MAGIC
) != VALID_OBJECT
)
162 pthread_rwlockattr::is_good_object (pthread_rwlockattr_t
const *attr
)
164 if (verifyable_object_isvalid (attr
, PTHREAD_RWLOCKATTR_MAGIC
) != VALID_OBJECT
)
170 pthread_key::is_good_object (pthread_key_t
const *key
)
172 if (verifyable_object_isvalid (key
, PTHREAD_KEY_MAGIC
) != VALID_OBJECT
)
178 pthread_spinlock::is_good_object (pthread_spinlock_t
const *mutex
)
180 if (verifyable_object_isvalid (mutex
, PTHREAD_SPINLOCK_MAGIC
) != VALID_OBJECT
)
186 pthread_mutex::is_good_object (pthread_mutex_t
const *mutex
)
188 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
) != VALID_OBJECT
)
194 pthread_mutex::is_initializer (pthread_mutex_t
const *mutex
)
196 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
197 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
198 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
199 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) != VALID_STATIC_OBJECT
)
205 pthread_mutex::is_initializer_or_object (pthread_mutex_t
const *mutex
)
207 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
208 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
209 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
210 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) == INVALID_OBJECT
)
215 /* FIXME: Accommodate PTHREAD_MUTEX_ERRORCHECK */
217 pthread_mutex::can_be_unlocked ()
219 pthread_t self
= pthread::self ();
220 /* Check if the mutex is owned by the current thread and can be unlocked.
221 * Also check for the ANONYMOUS owner to cover NORMAL mutexes as well. */
222 bool res
= type
== PTHREAD_MUTEX_NORMAL
|| no_owner ()
223 || (recursion_counter
== 1 && pthread::equal (owner
, self
));
224 pthread_printf ("recursion_counter %d res %d", recursion_counter
, res
);
229 pthread_mutexattr::is_good_object (pthread_mutexattr_t
const * attr
)
231 if (verifyable_object_isvalid (attr
, PTHREAD_MUTEXATTR_MAGIC
) != VALID_OBJECT
)
236 inline bool __attribute__ ((used
))
237 pthread::is_good_object (pthread_t
const *thread
)
239 if (verifyable_object_isvalid (thread
, PTHREAD_MAGIC
) != VALID_OBJECT
)
244 /* Thread synchronisation */
246 pthread_cond::is_good_object (pthread_cond_t
const *cond
)
248 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
) != VALID_OBJECT
)
254 pthread_cond::is_initializer (pthread_cond_t
const *cond
)
256 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) != VALID_STATIC_OBJECT
)
262 pthread_cond::is_initializer_or_object (pthread_cond_t
const *cond
)
264 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) == INVALID_OBJECT
)
271 pthread_rwlock::is_good_object (pthread_rwlock_t
const *rwlock
)
273 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
) != VALID_OBJECT
)
279 pthread_rwlock::is_initializer (pthread_rwlock_t
const *rwlock
)
281 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) != VALID_STATIC_OBJECT
)
287 pthread_rwlock::is_initializer_or_object (pthread_rwlock_t
const *rwlock
)
289 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) == INVALID_OBJECT
)
295 semaphore::is_good_object (sem_t
const * sem
)
297 if (verifyable_object_isvalid (sem
, SEM_MAGIC
) != VALID_OBJECT
)
305 pthread_mutex::init_mutex ();
306 pthread_cond::init_mutex ();
307 pthread_rwlock::init_mutex ();
311 MTinterface::fixup_before_fork ()
313 pthread_key::fixup_before_fork ();
316 /* This function is called from a single threaded process */
318 MTinterface::fixup_after_fork ()
320 pthread_key::fixup_after_fork ();
323 pthread::init_mainthread ();
325 pthread::fixup_after_fork ();
326 pthread_mutex::fixup_after_fork ();
327 pthread_cond::fixup_after_fork ();
328 pthread_rwlock::fixup_after_fork ();
329 semaphore::fixup_after_fork ();
336 pthread::init_mainthread ()
338 pthread
*thread
= _my_tls
.tid
;
341 thread
= new pthread ();
343 api_fatal ("failed to create mainthread object");
346 set_tls_self_pointer (thread
);
347 thread
->thread_id
= GetCurrentThreadId ();
348 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
349 GetCurrentProcess (), &thread
->win32_obj_id
,
350 0, FALSE
, DUPLICATE_SAME_ACCESS
))
351 api_fatal ("failed to create mainthread handle");
352 if (!thread
->create_cancel_event ())
353 api_fatal ("couldn't create cancel event for main thread");
354 VerifyHandle (thread
->win32_obj_id
);
355 thread
->postcreate ();
361 pthread
*thread
= _my_tls
.tid
;
364 thread
= pthread_null::get_null_pthread ();
365 set_tls_self_pointer (thread
);
371 pthread::set_tls_self_pointer (pthread
*thread
)
373 thread
->cygtls
= &_my_tls
;
374 _my_tls
.tid
= thread
;
377 List
<pthread
> pthread::threads
;
380 pthread::pthread ():verifyable_object (PTHREAD_MAGIC
), win32_obj_id (0),
381 valid (false), suspended (false),
382 cancelstate (0), canceltype (0), cancel_event (0),
383 joiner (NULL
), next (NULL
), cleanup_stack (NULL
)
385 if (this != pthread_null::get_null_pthread ())
386 threads
.insert (this);
387 parent_tls
= &_my_tls
;
393 CloseHandle (win32_obj_id
);
395 CloseHandle (cancel_event
);
397 if (this != pthread_null::get_null_pthread ())
398 threads
.remove (this);
402 pthread::create_cancel_event ()
404 cancel_event
= ::CreateEvent (&sec_none_nih
, true, false, NULL
);
407 system_printf ("couldn't create cancel event, %E");
408 /* we need the event for correct behaviour */
415 pthread::precreate (pthread_attr
*newattr
)
417 pthread_mutex
*verifyable_mutex_obj
= &mutex
;
419 /* already running ? */
425 attr
.joinable
= newattr
->joinable
;
426 attr
.contentionscope
= newattr
->contentionscope
;
427 attr
.inheritsched
= newattr
->inheritsched
;
428 attr
.stacksize
= newattr
->stacksize
;
431 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
433 thread_printf ("New thread object access mutex is not valid. this %p",
438 /* Change the mutex type to NORMAL to speed up mutex operations */
439 mutex
.set_type (PTHREAD_MUTEX_NORMAL
);
440 if (!create_cancel_event ())
445 pthread::create (void *(*func
) (void *), pthread_attr
*newattr
,
458 win32_obj_id
= ::CreateThread (&sec_none_nih
, attr
.stacksize
,
459 thread_init_wrapper
, this, 0, &thread_id
);
463 thread_printf ("CreateThread failed: this %p, %E", this);
478 pthread::postcreate ()
482 InterlockedIncrement (&MT_INTERFACE
->threadcount
);
483 /* FIXME: set the priority appropriately for system contention scope */
484 if (attr
.inheritsched
== PTHREAD_EXPLICIT_SCHED
)
486 /* FIXME: set the scheduling settings for the new thread */
487 /* sched_thread_setparam (win32_obj_id, attr.schedparam); */
492 pthread::exit (void *value_ptr
)
494 class pthread
*thread
= this;
496 // run cleanup handlers
497 pop_all_cleanup_handlers ();
499 pthread_key::run_all_destructors ();
502 // cleanup if thread is in detached state and not joined
503 if (equal (joiner
, thread
))
508 return_ptr
= value_ptr
;
512 if (_my_tls
.local_clib
.__sdidinit
< 0)
513 _my_tls
.local_clib
.__sdidinit
= 0;
514 (_reclaim_reent
) (_REENT
);
516 if (InterlockedDecrement (&MT_INTERFACE
->threadcount
) == 0)
525 class pthread
*thread
= this;
526 class pthread
*self
= pthread::self ();
536 if (canceltype
== PTHREAD_CANCEL_DEFERRED
||
537 cancelstate
== PTHREAD_CANCEL_DISABLE
)
541 SetEvent (cancel_event
);
544 else if (equal (thread
, self
))
548 return 0; // Never reached
551 // cancel asynchronous
552 SuspendThread (win32_obj_id
);
553 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
556 context
.ContextFlags
= CONTEXT_CONTROL
;
557 GetThreadContext (win32_obj_id
, &context
);
558 context
.Eip
= (DWORD
) pthread::static_cancel_self
;
559 SetThreadContext (win32_obj_id
, &context
);
562 ResumeThread (win32_obj_id
);
567 /* TODO: Insert pthread_testcancel into the required functions.
569 Here are the lists of required and optional functions per POSIX.1-2001
570 and POSIX.1-2008. A start (*) indicates that the Cygwin function already
571 is a cancellation point (aka "calls pthread_testcancel").
573 Required cancellation points:
601 * pthread_cond_timedwait ()
602 * pthread_cond_wait ()
604 * pthread_testcancel ()
635 Optional cancellation points:
727 getopt () (if opterr is nonzero)
782 posix_trace_create ()
783 posix_trace_create_withlog ()
784 posix_trace_eventtypelist_getnext_id ()
785 posix_trace_eventtypelist_rewind ()
787 posix_trace_get_attr ()
788 posix_trace_get_filter ()
789 posix_trace_get_status ()
790 posix_trace_getnext_event ()
792 posix_trace_rewind ()
793 posix_trace_set_filter ()
794 posix_trace_shutdown ()
795 posix_trace_timedgetnext_event ()
796 posix_typed_mem_open ()
800 pthread_rwlock_rdlock ()
801 pthread_rwlock_timedrdlock ()
802 pthread_rwlock_timedwrlock ()
803 pthread_rwlock_wrlock ()
863 An implementation may also mark other functions not specified in the
864 standard as cancellation points. In particular, an implementation is
865 likely to mark any nonstandard function that may block as a
866 cancellation point. */
869 pthread::testcancel ()
871 if (cancelstate
== PTHREAD_CANCEL_DISABLE
)
874 if (IsEventSignalled (cancel_event
))
879 pthread::static_cancel_self ()
881 pthread::self ()->cancel_self ();
885 cancelable_wait (HANDLE object
, DWORD timeout
,
886 const cw_cancel_action cancel_action
,
887 const enum cw_sig_wait sig_wait
)
891 HANDLE wait_objects
[3];
892 pthread_t thread
= pthread::self ();
894 /* Do not change the wait order.
895 The object must have higher priority than the cancel event,
896 because WaitForMultipleObjects will return the smallest index
897 if both objects are signaled. */
898 wait_objects
[num
++] = object
;
900 if (cancel_action
== cw_no_cancel
|| !pthread::is_good_object (&thread
) ||
901 thread
->cancelstate
== PTHREAD_CANCEL_DISABLE
)
902 cancel_n
= (DWORD
) -1;
905 cancel_n
= WAIT_OBJECT_0
+ num
++;
906 wait_objects
[cancel_n
] = thread
->cancel_event
;
910 if (sig_wait
== cw_sig_nosig
|| &_my_tls
!= _main_tls
)
914 sig_n
= WAIT_OBJECT_0
+ num
++;
915 wait_objects
[sig_n
] = signal_arrived
;
920 res
= WaitForMultipleObjects (num
, wait_objects
, FALSE
, timeout
);
923 if (cancel_action
== cw_cancel_self
)
924 pthread::static_cancel_self ();
927 else if (res
!= sig_n
)
929 else if (sig_wait
== cw_sig_eintr
)
933 _my_tls
.call_signal_handler ();
942 pthread::setcancelstate (int state
, int *oldstate
)
948 if (state
!= PTHREAD_CANCEL_ENABLE
&& state
!= PTHREAD_CANCEL_DISABLE
)
953 *oldstate
= cancelstate
;
963 pthread::setcanceltype (int type
, int *oldtype
)
969 if (type
!= PTHREAD_CANCEL_DEFERRED
&& type
!= PTHREAD_CANCEL_ASYNCHRONOUS
)
974 *oldtype
= canceltype
;
984 pthread::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
988 api_fatal ("Attempt to push a cleanup handler across threads");
989 handler
->next
= cleanup_stack
;
990 cleanup_stack
= handler
;
994 pthread::pop_cleanup_handler (int const execute
)
997 // TODO: send a signal or something to the thread ?
998 api_fatal ("Attempt to execute a cleanup handler across threads");
1002 if (cleanup_stack
!= NULL
)
1004 __pthread_cleanup_handler
*handler
= cleanup_stack
;
1007 (*handler
->function
) (handler
->arg
);
1008 cleanup_stack
= handler
->next
;
1015 pthread::pop_all_cleanup_handlers ()
1017 while (cleanup_stack
!= NULL
)
1018 pop_cleanup_handler (1);
1022 pthread::cancel_self ()
1024 exit (PTHREAD_CANCELED
);
1028 pthread::get_thread_id ()
1034 pthread::_fixup_after_fork ()
1036 /* set thread to not running if it is not the forking thread */
1037 if (this != pthread::self ())
1041 win32_obj_id
= NULL
;
1042 cancel_event
= NULL
;
1047 pthread::suspend_except_self ()
1049 if (valid
&& this != pthread::self ())
1050 SuspendThread (win32_obj_id
);
1057 ResumeThread (win32_obj_id
);
1060 /* instance members */
1062 pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC
),
1063 joinable (PTHREAD_CREATE_JOINABLE
), contentionscope (PTHREAD_SCOPE_PROCESS
),
1064 inheritsched (PTHREAD_INHERIT_SCHED
), stacksize (0)
1066 schedparam
.sched_priority
= 0;
1069 pthread_attr::~pthread_attr ()
1073 pthread_condattr::pthread_condattr ():verifyable_object
1074 (PTHREAD_CONDATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
1078 pthread_condattr::~pthread_condattr ()
1082 List
<pthread_cond
> pthread_cond::conds
;
1084 /* This is used for cond creation protection within a single process only */
1085 fast_mutex NO_COPY
pthread_cond::cond_initialization_lock
;
1087 /* We can only be called once.
1088 TODO: (no rush) use a non copied memory section to
1089 hold an initialization flag. */
1091 pthread_cond::init_mutex ()
1093 if (!cond_initialization_lock
.init ())
1094 api_fatal ("Could not create win32 Mutex for pthread cond static initializer support.");
1097 pthread_cond::pthread_cond (pthread_condattr
*attr
) :
1098 verifyable_object (PTHREAD_COND_MAGIC
),
1099 shared (0), waiting (0), pending (0), sem_wait (NULL
),
1100 mtx_cond(NULL
), next (NULL
)
1102 pthread_mutex
*verifyable_mutex_obj
;
1105 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
1111 verifyable_mutex_obj
= &mtx_in
;
1112 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1114 thread_printf ("Internal cond mutex is not valid. this %p", this);
1119 * Change the mutex type to NORMAL.
1120 * This mutex MUST be of type normal
1122 mtx_in
.set_type (PTHREAD_MUTEX_NORMAL
);
1124 verifyable_mutex_obj
= &mtx_out
;
1125 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1127 thread_printf ("Internal cond mutex is not valid. this %p", this);
1131 /* Change the mutex type to NORMAL to speed up mutex operations */
1132 mtx_out
.set_type (PTHREAD_MUTEX_NORMAL
);
1134 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1137 pthread_printf ("CreateSemaphore failed. %E");
1142 conds
.insert (this);
1145 pthread_cond::~pthread_cond ()
1148 CloseHandle (sem_wait
);
1150 conds
.remove (this);
1154 pthread_cond::unblock (const bool all
)
1156 unsigned long releaseable
;
1159 * Block outgoing threads (and avoid simultanous unblocks)
1163 releaseable
= waiting
- pending
;
1166 unsigned long released
;
1171 * Block incoming threads until all waiting threads are released.
1176 * Calculate releaseable again because threads can enter until
1177 * the semaphore has been taken, but they can not leave, therefore pending
1178 * is unchanged and releaseable can only get higher
1180 releaseable
= waiting
- pending
;
1183 released
= all
? releaseable
: 1;
1184 pending
+= released
;
1188 ::ReleaseSemaphore (sem_wait
, released
, NULL
);
1192 * And let the threads release.
1198 pthread_cond::wait (pthread_mutex_t mutex
, DWORD dwMilliseconds
)
1203 if (InterlockedIncrement ((long *)&waiting
) == 1)
1205 else if (mtx_cond
!= mutex
)
1207 InterlockedDecrement ((long *)&waiting
);
1214 * Release the mutex and wait on semaphore
1219 rv
= cancelable_wait (sem_wait
, dwMilliseconds
, cw_no_cancel_self
, cw_sig_eintr
);
1223 if (rv
!= WAIT_OBJECT_0
)
1226 * It might happen that a signal is sent while the thread got canceled
1227 * or timed out. Try to take one.
1228 * If the thread gets one than a signal|broadcast is in progress.
1230 if (WaitForSingleObject (sem_wait
, 0) == WAIT_OBJECT_0
)
1232 * thread got cancelled ot timed out while a signalling is in progress.
1233 * Set wait result back to signaled
1238 InterlockedDecrement ((long *)&waiting
);
1240 if (rv
== WAIT_OBJECT_0
&& --pending
== 0)
1242 * All signaled threads are released,
1243 * new threads can enter Wait
1252 if (rv
== WAIT_CANCELED
)
1253 pthread::static_cancel_self ();
1254 else if (rv
== WAIT_SIGNALED
)
1255 /* SUSv3 states: If a signal is delivered to a thread waiting for a
1256 condition variable, upon return from the signal handler the thread
1257 resumes waiting for the condition variable as if it was not
1258 interrupted, or it shall return zero due to spurious wakeup.
1259 We opt for the latter choice here. */
1261 else if (rv
== WAIT_TIMEOUT
)
1268 pthread_cond::_fixup_after_fork ()
1270 waiting
= pending
= 0;
1273 /* Unlock eventually locked mutexes */
1277 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1279 api_fatal ("pthread_cond::_fixup_after_fork () failed to recreate win32 semaphore");
1282 pthread_rwlockattr::pthread_rwlockattr ():verifyable_object
1283 (PTHREAD_RWLOCKATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
1287 pthread_rwlockattr::~pthread_rwlockattr ()
1291 List
<pthread_rwlock
> pthread_rwlock::rwlocks
;
1293 /* This is used for rwlock creation protection within a single process only */
1294 fast_mutex NO_COPY
pthread_rwlock::rwlock_initialization_lock
;
1296 /* We can only be called once.
1297 TODO: (no rush) use a non copied memory section to
1298 hold an initialization flag. */
1300 pthread_rwlock::init_mutex ()
1302 if (!rwlock_initialization_lock
.init ())
1303 api_fatal ("Could not create win32 Mutex for pthread rwlock static initializer support.");
1306 pthread_rwlock::pthread_rwlock (pthread_rwlockattr
*attr
) :
1307 verifyable_object (PTHREAD_RWLOCK_MAGIC
),
1308 shared (0), waiting_readers (0), waiting_writers (0), writer (NULL
),
1309 readers (NULL
), readers_mx (), mtx (NULL
), cond_readers (NULL
), cond_writers (NULL
),
1312 pthread_mutex
*verifyable_mutex_obj
= &mtx
;
1313 pthread_cond
*verifyable_cond_obj
;
1315 if (!readers_mx
.init ())
1317 thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this);
1323 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
1329 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1331 thread_printf ("Internal rwlock mutex is not valid. this %p", this);
1335 /* Change the mutex type to NORMAL to speed up mutex operations */
1336 mtx
.set_type (PTHREAD_MUTEX_NORMAL
);
1338 verifyable_cond_obj
= &cond_readers
;
1339 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1341 thread_printf ("Internal rwlock readers cond is not valid. this %p", this);
1346 verifyable_cond_obj
= &cond_writers
;
1347 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1349 thread_printf ("Internal rwlock writers cond is not valid. this %p", this);
1355 rwlocks
.insert (this);
1358 pthread_rwlock::~pthread_rwlock ()
1360 rwlocks
.remove (this);
1364 pthread_rwlock::rdlock ()
1367 struct RWLOCK_READER
*reader
;
1368 pthread_t self
= pthread::self ();
1372 reader
= lookup_reader (self
);
1375 if (reader
->n
< ULONG_MAX
)
1382 reader
= new struct RWLOCK_READER
;
1389 while (writer
|| waiting_writers
)
1391 pthread_cleanup_push (pthread_rwlock::rdlock_cleanup
, this);
1394 cond_readers
.wait (&mtx
);
1397 pthread_cleanup_pop (0);
1400 reader
->thread
= self
;
1402 add_reader (reader
);
1411 pthread_rwlock::tryrdlock ()
1414 pthread_t self
= pthread::self ();
1418 if (writer
|| waiting_writers
|| lookup_reader (self
))
1422 struct RWLOCK_READER
*reader
;
1424 reader
= lookup_reader (self
);
1425 if (reader
&& reader
->n
< ULONG_MAX
)
1427 else if ((reader
= new struct RWLOCK_READER
))
1429 reader
->thread
= self
;
1431 add_reader (reader
);
1443 pthread_rwlock::wrlock ()
1446 pthread_t self
= pthread::self ();
1450 if (writer
== self
|| lookup_reader (self
))
1456 while (writer
|| readers
)
1458 pthread_cleanup_push (pthread_rwlock::wrlock_cleanup
, this);
1461 cond_writers
.wait (&mtx
);
1464 pthread_cleanup_pop (0);
1476 pthread_rwlock::trywrlock ()
1479 pthread_t self
= pthread::self ();
1483 if (writer
|| readers
)
1494 pthread_rwlock::unlock ()
1497 pthread_t self
= pthread::self ();
1513 struct RWLOCK_READER
*reader
= lookup_reader (self
);
1520 if (--reader
->n
> 0)
1523 remove_reader (reader
);
1536 pthread_rwlock::add_reader (struct RWLOCK_READER
*rd
)
1538 List_insert (readers
, rd
);
1542 pthread_rwlock::remove_reader (struct RWLOCK_READER
*rd
)
1544 List_remove (readers_mx
, readers
, rd
);
1547 struct pthread_rwlock::RWLOCK_READER
*
1548 pthread_rwlock::lookup_reader (pthread_t thread
)
1552 struct RWLOCK_READER
*cur
= readers
;
1554 while (cur
&& cur
->thread
!= thread
)
1557 readers_mx
.unlock ();
1563 pthread_rwlock::rdlock_cleanup (void *arg
)
1565 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1567 --(rwlock
->waiting_readers
);
1569 rwlock
->mtx
.unlock ();
1573 pthread_rwlock::wrlock_cleanup (void *arg
)
1575 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1577 --(rwlock
->waiting_writers
);
1579 rwlock
->mtx
.unlock ();
1583 pthread_rwlock::_fixup_after_fork ()
1585 pthread_t self
= pthread::self ();
1586 struct RWLOCK_READER
**temp
= &readers
;
1588 waiting_readers
= 0;
1589 waiting_writers
= 0;
1591 if (!readers_mx
.init ())
1592 api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex");
1594 /* Unlock eventually locked mutex */
1597 * Remove all readers except self
1601 if ((*temp
)->thread
== self
)
1602 temp
= &((*temp
)->next
);
1605 struct RWLOCK_READER
*cur
= *temp
;
1606 *temp
= (*temp
)->next
;
1613 /* static members */
1614 /* This stores pthread_key information across fork() boundaries */
1615 List
<pthread_key
> pthread_key::keys
;
1617 /* non-static members */
1619 pthread_key::pthread_key (void (*aDestructor
) (void *)):verifyable_object (PTHREAD_KEY_MAGIC
), destructor (aDestructor
)
1621 tls_index
= TlsAlloc ();
1622 if (tls_index
== TLS_OUT_OF_INDEXES
)
1628 pthread_key::~pthread_key ()
1630 /* We may need to make the list code lock the list during operations
1635 TlsFree (tls_index
);
1640 pthread_key::_fixup_before_fork ()
1646 pthread_key::_fixup_after_fork ()
1648 tls_index
= TlsAlloc ();
1649 if (tls_index
== TLS_OUT_OF_INDEXES
)
1650 api_fatal ("pthread_key::recreate_key_from_buffer () failed to reallocate Tls storage");
1655 pthread_key::run_destructor ()
1659 void *oldValue
= get ();
1663 destructor (oldValue
);
1668 /* pshared mutexs */
1670 /* static members */
1672 List
<pthread_mutex
> pthread_mutex::mutexes
;
1674 /* This is used for mutex creation protection within a single process only */
1675 fast_mutex NO_COPY
pthread_mutex::mutex_initialization_lock
;
1678 pthread_mutex::init_mutex ()
1680 if (!mutex_initialization_lock
.init ())
1681 api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support.");
1684 pthread_mutex::pthread_mutex (pthread_mutexattr
*attr
) :
1685 verifyable_object (0), /* set magic to zero initially */
1687 win32_obj_id (NULL
), owner (_new_mutex
),
1691 recursion_counter (0), condwaits (0),
1692 type (PTHREAD_MUTEX_ERRORCHECK
),
1693 pshared (PTHREAD_PROCESS_PRIVATE
)
1695 win32_obj_id
= ::CreateEvent (&sec_none_nih
, false, false, NULL
);
1698 /*attr checked in the C call */
1700 /* handled in the caller */;
1701 else if (attr
->pshared
!= PTHREAD_PROCESS_SHARED
)
1702 type
= attr
->mutextype
;
1704 return; /* Not implemented */
1706 magic
= PTHREAD_MUTEX_MAGIC
;
1707 mutexes
.insert (this);
1710 pthread_mutex::~pthread_mutex ()
1714 CloseHandle (win32_obj_id
);
1715 win32_obj_id
= NULL
;
1718 mutexes
.remove (this);
1719 owner
= _destroyed_mutex
;
1724 pthread_mutex::lock ()
1726 pthread_t self
= ::pthread_self ();
1729 if (InterlockedIncrement ((long *) &lock_counter
) == 1)
1731 else if (type
== PTHREAD_MUTEX_NORMAL
/* potentially causes deadlock */
1732 || !pthread::equal (owner
, self
))
1734 cancelable_wait (win32_obj_id
, INFINITE
, cw_no_cancel
, cw_sig_resume
);
1739 InterlockedDecrement ((long *) &lock_counter
);
1740 if (type
== PTHREAD_MUTEX_RECURSIVE
)
1741 result
= lock_recursive ();
1746 pthread_printf ("mutex %p, self %p, owner %p, lock_counter %d, recursion_counter %d",
1747 this, self
, owner
, lock_counter
, recursion_counter
);
1752 pthread_mutex::unlock ()
1755 pthread_t self
= ::pthread_self ();
1756 if (type
== PTHREAD_MUTEX_NORMAL
)
1757 /* no error checking */;
1758 else if (no_owner ())
1759 res
= type
== PTHREAD_MUTEX_ERRORCHECK
? EINVAL
: 0;
1760 else if (!pthread::equal (owner
, self
))
1762 if (!res
&& recursion_counter
> 0 && --recursion_counter
== 0)
1763 /* Don't try to unlock anything if recursion_counter == 0.
1764 This means the mutex was never locked or that we've forked. */
1766 owner
= (pthread_t
) _unlocked_mutex
;
1770 if (InterlockedDecrement ((long *) &lock_counter
))
1771 ::SetEvent (win32_obj_id
); // Another thread is waiting
1775 pthread_printf ("mutex %p, owner %p, self %p, lock_counter %d, recursion_counter %d, type %d, res %d",
1776 this, owner
, self
, lock_counter
, recursion_counter
, type
, res
);
1781 pthread_mutex::trylock ()
1783 pthread_t self
= ::pthread_self ();
1786 if (InterlockedCompareExchange ((long *) &lock_counter
, 1, 0) == 0)
1788 else if (type
== PTHREAD_MUTEX_RECURSIVE
&& pthread::equal (owner
, self
))
1789 result
= lock_recursive ();
1797 pthread_mutex::destroy ()
1799 if (condwaits
|| trylock ())
1800 // Do not destroy a condwaited or locked mutex
1802 else if (recursion_counter
> 1)
1804 // Do not destroy a recursive locked mutex
1805 recursion_counter
--;
1814 pthread_mutex::_fixup_after_fork ()
1816 pthread_printf ("mutex %p", this);
1817 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1818 api_fatal ("pthread_mutex::_fixup_after_fork () doesn't understand PROCESS_SHARED mutex's");
1820 /* All waiting threads are gone after a fork */
1821 recursion_counter
= 0;
1825 tid
= 0xffffffff; /* Don't know the tid after a fork */
1827 win32_obj_id
= ::CreateEvent (&sec_none_nih
, false, false, NULL
);
1829 api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 event for mutex");
1832 pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC
),
1833 pshared (PTHREAD_PROCESS_PRIVATE
), mutextype (PTHREAD_MUTEX_ERRORCHECK
)
1837 pthread_mutexattr::~pthread_mutexattr ()
1841 /* pshared spinlocks
1843 The infrastructure is provided by the underlying pthread_mutex class.
1844 The rest is a simplification implementing spin locking. */
1846 pthread_spinlock::pthread_spinlock (int pshared
) :
1847 pthread_mutex (NULL
)
1849 magic
= PTHREAD_SPINLOCK_MAGIC
;
1850 set_type (PTHREAD_MUTEX_NORMAL
);
1851 set_shared (pshared
);
1855 pthread_spinlock::lock ()
1857 pthread_t self
= ::pthread_self ();
1862 if (InterlockedExchange ((long *) &lock_counter
, 1) == 0)
1867 else if (pthread::equal (owner
, self
))
1869 else /* Minimal timeout to minimize CPU usage while still spinning. */
1870 cancelable_wait (win32_obj_id
, 1L, cw_no_cancel
, cw_sig_resume
);
1872 while (result
== -1);
1873 pthread_printf ("spinlock %p, self %p, owner %p", this, self
, owner
);
1878 pthread_spinlock::unlock ()
1880 pthread_t self
= ::pthread_self ();
1883 if (!pthread::equal (owner
, self
))
1887 owner
= (pthread_t
) _unlocked_mutex
;
1891 InterlockedExchange ((long *) &lock_counter
, 0);
1892 ::SetEvent (win32_obj_id
);
1895 pthread_printf ("spinlock %p, owner %p, self %p, res %d",
1896 this, owner
, self
, result
);
1901 pthread::thread_init_wrapper (void *arg
)
1903 pthread
*thread
= (pthread
*) arg
;
1904 set_tls_self_pointer (thread
);
1906 thread
->mutex
.lock ();
1908 // if thread is detached force cleanup on exit
1909 if (thread
->attr
.joinable
== PTHREAD_CREATE_DETACHED
&& thread
->joiner
== NULL
)
1910 thread
->joiner
= thread
;
1911 _my_tls
.sigmask
= thread
->parent_tls
->sigmask
;
1912 thread
->mutex
.unlock ();
1914 thread_printf ("started thread %p %p %p %p %p %p", arg
, &_my_tls
.local_clib
,
1915 _impure_ptr
, thread
, thread
->function
, thread
->arg
);
1917 // call the user's thread
1918 void *ret
= thread
->function (thread
->arg
);
1922 return 0; // just for show. Never returns.
1926 pthread::getsequence_np ()
1928 return get_thread_id ();
1932 pthread::create (pthread_t
*thread
, const pthread_attr_t
*attr
,
1933 void *(*start_routine
) (void *), void *arg
)
1935 if (attr
&& !pthread_attr::is_good_object (attr
))
1938 *thread
= new pthread ();
1939 if (!(*thread
)->create (start_routine
, attr
? *attr
: NULL
, arg
))
1950 pthread::once (pthread_once_t
*once_control
, void (*init_routine
) (void))
1953 if (once_control
->state
)
1956 pthread_mutex_lock (&once_control
->mutex
);
1957 /* Here we must set a cancellation handler to unlock the mutex if needed */
1958 /* but a cancellation handler is not the right thing. We need this in the thread
1959 *cleanup routine. Assumption: a thread can only be in one pthread_once routine
1960 *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
1961 *on pthread_exit ();
1963 if (!once_control
->state
)
1966 once_control
->state
= 1;
1968 /* Here we must remove our cancellation handler */
1969 pthread_mutex_unlock (&once_control
->mutex
);
1974 pthread::cancel (pthread_t thread
)
1976 if (!is_good_object (&thread
))
1979 return thread
->cancel ();
1983 pthread::atforkprepare ()
1985 callback
*cb
= MT_INTERFACE
->pthread_prepare
;
1994 MT_INTERFACE
->fixup_before_fork ();
1998 pthread::atforkparent ()
2002 callback
*cb
= MT_INTERFACE
->pthread_parent
;
2011 pthread::atforkchild ()
2013 MT_INTERFACE
->fixup_after_fork ();
2017 callback
*cb
= MT_INTERFACE
->pthread_child
;
2025 /* Register a set of functions to run before and after fork.
2026 prepare calls are called in LI-FC order.
2027 parent and child calls are called in FI-FC order. */
2029 pthread::atfork (void (*prepare
)(void), void (*parent
)(void), void (*child
)(void))
2031 callback
*prepcb
= NULL
, *parentcb
= NULL
, *childcb
= NULL
;
2034 prepcb
= new callback
;
2040 parentcb
= new callback
;
2050 childcb
= new callback
;
2063 prepcb
->cb
= prepare
;
2064 List_insert (MT_INTERFACE
->pthread_prepare
, prepcb
);
2068 parentcb
->cb
= parent
;
2069 callback
**t
= &MT_INTERFACE
->pthread_parent
;
2072 /* t = pointer to last next in the list */
2073 List_insert (*t
, parentcb
);
2077 childcb
->cb
= child
;
2078 callback
**t
= &MT_INTERFACE
->pthread_child
;
2081 /* t = pointer to last next in the list */
2082 List_insert (*t
, childcb
);
2088 pthread_attr_init (pthread_attr_t
*attr
)
2090 if (pthread_attr::is_good_object (attr
))
2093 *attr
= new pthread_attr
;
2094 if (!pthread_attr::is_good_object (attr
))
2104 pthread_attr_getinheritsched (const pthread_attr_t
*attr
,
2107 if (!pthread_attr::is_good_object (attr
))
2109 *inheritsched
= (*attr
)->inheritsched
;
2114 pthread_attr_getschedparam (const pthread_attr_t
*attr
,
2115 struct sched_param
*param
)
2117 if (!pthread_attr::is_good_object (attr
))
2119 *param
= (*attr
)->schedparam
;
2123 /* From a pure code point of view, this should call a helper in sched.cc,
2124 to allow for someone adding scheduler policy changes to win32 in the future.
2125 However that's extremely unlikely, so short and sweet will do us */
2127 pthread_attr_getschedpolicy (const pthread_attr_t
*attr
, int *policy
)
2129 if (!pthread_attr::is_good_object (attr
))
2131 *policy
= SCHED_FIFO
;
2137 pthread_attr_getscope (const pthread_attr_t
*attr
, int *contentionscope
)
2139 if (!pthread_attr::is_good_object (attr
))
2141 *contentionscope
= (*attr
)->contentionscope
;
2146 pthread_attr_setdetachstate (pthread_attr_t
*attr
, int detachstate
)
2148 if (!pthread_attr::is_good_object (attr
))
2150 if (detachstate
< 0 || detachstate
> 1)
2152 (*attr
)->joinable
= detachstate
;
2157 pthread_attr_getdetachstate (const pthread_attr_t
*attr
, int *detachstate
)
2159 if (!pthread_attr::is_good_object (attr
))
2161 *detachstate
= (*attr
)->joinable
;
2166 pthread_attr_setinheritsched (pthread_attr_t
*attr
, int inheritsched
)
2168 if (!pthread_attr::is_good_object (attr
))
2170 if (inheritsched
!= PTHREAD_INHERIT_SCHED
2171 && inheritsched
!= PTHREAD_EXPLICIT_SCHED
)
2173 (*attr
)->inheritsched
= inheritsched
;
2178 pthread_attr_setschedparam (pthread_attr_t
*attr
,
2179 const struct sched_param
*param
)
2181 if (!pthread_attr::is_good_object (attr
))
2183 if (!valid_sched_parameters (param
))
2185 (*attr
)->schedparam
= *param
;
2189 /* See __pthread_attr_getschedpolicy for some notes */
2191 pthread_attr_setschedpolicy (pthread_attr_t
*attr
, int policy
)
2193 if (!pthread_attr::is_good_object (attr
))
2195 if (policy
!= SCHED_FIFO
)
2201 pthread_attr_setscope (pthread_attr_t
*attr
, int contentionscope
)
2203 if (!pthread_attr::is_good_object (attr
))
2205 if (contentionscope
!= PTHREAD_SCOPE_SYSTEM
2206 && contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2208 /* In future, we may be able to support system scope by escalating the thread
2209 priority to exceed the priority class. For now we only support PROCESS scope. */
2210 if (contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2212 (*attr
)->contentionscope
= contentionscope
;
2217 pthread_attr_setstacksize (pthread_attr_t
*attr
, size_t size
)
2219 if (!pthread_attr::is_good_object (attr
))
2221 (*attr
)->stacksize
= size
;
2226 pthread_attr_getstacksize (const pthread_attr_t
*attr
, size_t *size
)
2228 if (!pthread_attr::is_good_object (attr
))
2230 *size
= (*attr
)->stacksize
;
2235 pthread_attr_destroy (pthread_attr_t
*attr
)
2237 if (!pthread_attr::is_good_object (attr
))
2245 pthread::join (pthread_t
*thread
, void **return_val
)
2247 pthread_t joiner
= self ();
2249 joiner
->testcancel ();
2251 // Initialize return val with NULL
2255 if (!is_good_object (&joiner
))
2258 if (!is_good_object (thread
))
2261 if (equal (*thread
,joiner
))
2264 (*thread
)->mutex
.lock ();
2266 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2268 (*thread
)->mutex
.unlock ();
2273 (*thread
)->joiner
= joiner
;
2274 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2275 (*thread
)->mutex
.unlock ();
2277 switch (cancelable_wait ((*thread
)->win32_obj_id
, INFINITE
, cw_no_cancel_self
, cw_sig_resume
))
2281 *return_val
= (*thread
)->return_ptr
;
2285 // set joined thread back to joinable since we got canceled
2286 (*thread
)->joiner
= NULL
;
2287 (*thread
)->attr
.joinable
= PTHREAD_CREATE_JOINABLE
;
2288 joiner
->cancel_self ();
2292 // should never happen
2301 pthread::detach (pthread_t
*thread
)
2303 if (!is_good_object (thread
))
2306 (*thread
)->mutex
.lock ();
2307 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2309 (*thread
)->mutex
.unlock ();
2313 // check if thread is still alive
2314 if ((*thread
)->valid
&& WaitForSingleObject ((*thread
)->win32_obj_id
, 0) == WAIT_TIMEOUT
)
2316 // force cleanup on exit
2317 (*thread
)->joiner
= *thread
;
2318 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2319 (*thread
)->mutex
.unlock ();
2323 // thread has already terminated.
2324 (*thread
)->mutex
.unlock ();
2332 pthread::suspend (pthread_t
*thread
)
2334 if (!is_good_object (thread
))
2337 if ((*thread
)->suspended
== false)
2339 (*thread
)->suspended
= true;
2340 SuspendThread ((*thread
)->win32_obj_id
);
2348 pthread::resume (pthread_t
*thread
)
2350 if (!is_good_object (thread
))
2353 if ((*thread
)->suspended
== true)
2354 ResumeThread ((*thread
)->win32_obj_id
);
2355 (*thread
)->suspended
= false;
2360 /* provided for source level compatability.
2361 See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2364 pthread_getconcurrency ()
2366 return MT_INTERFACE
->concurrency
;
2369 /* keep this in sync with sched.cc */
2371 pthread_getschedparam (pthread_t thread
, int *policy
,
2372 struct sched_param
*param
)
2374 if (!pthread::is_good_object (&thread
))
2376 *policy
= SCHED_FIFO
;
2377 /* we don't return the current effective priority, we return the current
2378 requested priority */
2379 *param
= thread
->attr
.schedparam
;
2383 /* Thread Specific Data */
2385 pthread_key_create (pthread_key_t
*key
, void (*destructor
) (void *))
2387 *key
= new pthread_key (destructor
);
2389 if (!pthread_key::is_good_object (key
))
2399 pthread_key_delete (pthread_key_t key
)
2401 if (!pthread_key::is_good_object (&key
))
2408 /* provided for source level compatability. See
2409 http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2412 pthread_setconcurrency (int new_level
)
2416 MT_INTERFACE
->concurrency
= new_level
;
2420 /* keep syncronised with sched.cc */
2422 pthread_setschedparam (pthread_t thread
, int policy
,
2423 const struct sched_param
*param
)
2425 if (!pthread::is_good_object (&thread
))
2427 if (policy
!= SCHED_FIFO
)
2432 sched_set_thread_priority (thread
->win32_obj_id
, param
->sched_priority
);
2434 thread
->attr
.schedparam
.sched_priority
= param
->sched_priority
;
2439 pthread_setschedprio (pthread_t thread
, int priority
)
2441 if (!pthread::is_good_object (&thread
))
2444 sched_set_thread_priority (thread
->win32_obj_id
, priority
);
2446 thread
->attr
.schedparam
.sched_priority
= priority
;
2451 pthread_setspecific (pthread_key_t key
, const void *value
)
2453 if (!pthread_key::is_good_object (&key
))
2460 pthread_getspecific (pthread_key_t key
)
2462 if (!pthread_key::is_good_object (&key
))
2465 return (key
)->get ();
2470 pthread_cond_destroy (pthread_cond_t
*cond
)
2472 if (pthread_cond::is_initializer (cond
))
2474 if (!pthread_cond::is_good_object (cond
))
2477 /* reads are atomic */
2478 if ((*cond
)->waiting
)
2488 pthread_cond::init (pthread_cond_t
*cond
, const pthread_condattr_t
*attr
)
2490 pthread_cond_t new_cond
;
2492 if (attr
&& !pthread_condattr::is_good_object (attr
))
2495 cond_initialization_lock
.lock ();
2497 new_cond
= new pthread_cond (attr
? (*attr
) : NULL
);
2498 if (!is_good_object (&new_cond
))
2501 cond_initialization_lock
.unlock ();
2506 if (efault
.faulted ())
2509 cond_initialization_lock
.unlock ();
2514 cond_initialization_lock
.unlock ();
2520 pthread_cond_broadcast (pthread_cond_t
*cond
)
2522 if (pthread_cond::is_initializer (cond
))
2524 if (!pthread_cond::is_good_object (cond
))
2527 (*cond
)->unblock (true);
2533 pthread_cond_signal (pthread_cond_t
*cond
)
2535 if (pthread_cond::is_initializer (cond
))
2537 if (!pthread_cond::is_good_object (cond
))
2540 (*cond
)->unblock (false);
2546 __pthread_cond_dowait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2549 if (!pthread_mutex::is_good_object (mutex
))
2551 if (!(*mutex
)->can_be_unlocked ())
2554 if (pthread_cond::is_initializer (cond
))
2555 pthread_cond::init (cond
, NULL
);
2556 if (!pthread_cond::is_good_object (cond
))
2559 return (*cond
)->wait (*mutex
, waitlength
);
2563 pthread_cond_timedwait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2564 const struct timespec
*abstime
)
2570 if (efault
.faulted ())
2573 pthread_testcancel ();
2575 /* According to SUSv3, the abstime value must be checked for validity. */
2576 if (abstime
->tv_sec
< 0
2577 || abstime
->tv_nsec
< 0
2578 || abstime
->tv_nsec
> 999999999)
2581 gettimeofday (&tv
, NULL
);
2582 /* Check for immediate timeout before converting to microseconds, since
2583 the resulting value can easily overflow long. This also allows to
2584 evaluate microseconds directly in DWORD. */
2585 if (tv
.tv_sec
> abstime
->tv_sec
2586 || (tv
.tv_sec
== abstime
->tv_sec
2587 && tv
.tv_usec
> abstime
->tv_nsec
/ 1000))
2590 waitlength
= (abstime
->tv_sec
- tv
.tv_sec
) * 1000;
2591 waitlength
+= (abstime
->tv_nsec
/ 1000 - tv
.tv_usec
) / 1000;
2592 return __pthread_cond_dowait (cond
, mutex
, waitlength
);
2596 pthread_cond_wait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
2598 pthread_testcancel ();
2600 return __pthread_cond_dowait (cond
, mutex
, INFINITE
);
2604 pthread_condattr_init (pthread_condattr_t
*condattr
)
2606 if (pthread_condattr::is_good_object (condattr
))
2609 *condattr
= new pthread_condattr
;
2610 if (!pthread_condattr::is_good_object (condattr
))
2620 pthread_condattr_getpshared (const pthread_condattr_t
*attr
, int *pshared
)
2622 if (!pthread_condattr::is_good_object (attr
))
2624 *pshared
= (*attr
)->shared
;
2629 pthread_condattr_setpshared (pthread_condattr_t
*attr
, int pshared
)
2631 if (!pthread_condattr::is_good_object (attr
))
2633 if ((pshared
< 0) || (pshared
> 1))
2635 /* shared cond vars not currently supported */
2636 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2638 (*attr
)->shared
= pshared
;
2643 pthread_condattr_destroy (pthread_condattr_t
*condattr
)
2645 if (!pthread_condattr::is_good_object (condattr
))
2653 pthread_rwlock_destroy (pthread_rwlock_t
*rwlock
)
2655 if (pthread_rwlock::is_initializer (rwlock
))
2657 if (!pthread_rwlock::is_good_object (rwlock
))
2660 if ((*rwlock
)->writer
|| (*rwlock
)->readers
||
2661 (*rwlock
)->waiting_readers
|| (*rwlock
)->waiting_writers
)
2671 pthread_rwlock::init (pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*attr
)
2673 pthread_rwlock_t new_rwlock
;
2675 if (attr
&& !pthread_rwlockattr::is_good_object (attr
))
2678 rwlock_initialization_lock
.lock ();
2680 new_rwlock
= new pthread_rwlock (attr
? (*attr
) : NULL
);
2681 if (!is_good_object (&new_rwlock
))
2684 rwlock_initialization_lock
.unlock ();
2689 if (efault
.faulted ())
2692 rwlock_initialization_lock
.unlock ();
2696 *rwlock
= new_rwlock
;
2697 rwlock_initialization_lock
.unlock ();
2703 pthread_rwlock_rdlock (pthread_rwlock_t
*rwlock
)
2705 pthread_testcancel ();
2707 if (pthread_rwlock::is_initializer (rwlock
))
2708 pthread_rwlock::init (rwlock
, NULL
);
2709 if (!pthread_rwlock::is_good_object (rwlock
))
2712 return (*rwlock
)->rdlock ();
2716 pthread_rwlock_tryrdlock (pthread_rwlock_t
*rwlock
)
2718 if (pthread_rwlock::is_initializer (rwlock
))
2719 pthread_rwlock::init (rwlock
, NULL
);
2720 if (!pthread_rwlock::is_good_object (rwlock
))
2723 return (*rwlock
)->tryrdlock ();
2727 pthread_rwlock_wrlock (pthread_rwlock_t
*rwlock
)
2729 pthread_testcancel ();
2731 if (pthread_rwlock::is_initializer (rwlock
))
2732 pthread_rwlock::init (rwlock
, NULL
);
2733 if (!pthread_rwlock::is_good_object (rwlock
))
2736 return (*rwlock
)->wrlock ();
2740 pthread_rwlock_trywrlock (pthread_rwlock_t
*rwlock
)
2742 if (pthread_rwlock::is_initializer (rwlock
))
2743 pthread_rwlock::init (rwlock
, NULL
);
2744 if (!pthread_rwlock::is_good_object (rwlock
))
2747 return (*rwlock
)->trywrlock ();
2751 pthread_rwlock_unlock (pthread_rwlock_t
*rwlock
)
2753 if (pthread_rwlock::is_initializer (rwlock
))
2755 if (!pthread_rwlock::is_good_object (rwlock
))
2758 return (*rwlock
)->unlock ();
2762 pthread_rwlockattr_init (pthread_rwlockattr_t
*rwlockattr
)
2764 if (pthread_rwlockattr::is_good_object (rwlockattr
))
2767 *rwlockattr
= new pthread_rwlockattr
;
2768 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2770 delete (*rwlockattr
);
2778 pthread_rwlockattr_getpshared (const pthread_rwlockattr_t
*attr
, int *pshared
)
2780 if (!pthread_rwlockattr::is_good_object (attr
))
2782 *pshared
= (*attr
)->shared
;
2787 pthread_rwlockattr_setpshared (pthread_rwlockattr_t
*attr
, int pshared
)
2789 if (!pthread_rwlockattr::is_good_object (attr
))
2791 if ((pshared
< 0) || (pshared
> 1))
2793 /* shared rwlock vars not currently supported */
2794 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2796 (*attr
)->shared
= pshared
;
2801 pthread_rwlockattr_destroy (pthread_rwlockattr_t
*rwlockattr
)
2803 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2805 delete (*rwlockattr
);
2812 pthread_kill (pthread_t thread
, int sig
)
2814 // lock myself, for the use of thread2signal
2815 // two different kills might clash: FIXME
2817 if (!pthread::is_good_object (&thread
))
2822 si
.si_code
= SI_USER
;
2823 si
.si_pid
= myself
->pid
;
2824 si
.si_uid
= myself
->uid
;
2830 thread
->cygtls
->set_threadkill ();
2831 rval
= sig_send (NULL
, si
, thread
->cygtls
);
2834 switch (WaitForSingleObject (thread
->win32_obj_id
, 0))
2849 pthread_sigmask (int operation
, const sigset_t
*set
, sigset_t
*old_set
)
2851 return handle_sigprocmask (operation
, set
, old_set
, _my_tls
.sigmask
);
2857 pthread_equal (pthread_t t1
, pthread_t t2
)
2859 return pthread::equal (t1
, t2
);
2865 pthread_mutex::init (pthread_mutex_t
*mutex
,
2866 const pthread_mutexattr_t
*attr
,
2867 const pthread_mutex_t initializer
)
2869 if (attr
&& !pthread_mutexattr::is_good_object (attr
))
2872 mutex_initialization_lock
.lock ();
2873 if (initializer
== NULL
|| pthread_mutex::is_initializer (mutex
))
2875 pthread_mutex_t new_mutex
= new pthread_mutex (attr
? (*attr
) : NULL
);
2876 if (!is_good_object (&new_mutex
))
2879 mutex_initialization_lock
.unlock ();
2883 if (!attr
&& initializer
)
2885 if (initializer
== PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
)
2886 new_mutex
->type
= PTHREAD_MUTEX_RECURSIVE
;
2887 else if (initializer
== PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
)
2888 new_mutex
->type
= PTHREAD_MUTEX_NORMAL
;
2889 else if (initializer
== PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
)
2890 new_mutex
->type
= PTHREAD_MUTEX_ERRORCHECK
;
2894 if (efault
.faulted ())
2897 mutex_initialization_lock
.unlock ();
2903 mutex_initialization_lock
.unlock ();
2904 pthread_printf ("*mutex %p, attr %p, initializer %p", *mutex
, attr
, initializer
);
2910 pthread_mutex_getprioceiling (const pthread_mutex_t
*mutex
,
2913 /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
2916 We can support mutex priorities in the future though:
2917 Store a priority with each mutex.
2918 When the mutex is optained, set the thread priority as appropriate
2919 When the mutex is released, reset the thread priority. */
2924 pthread_mutex_lock (pthread_mutex_t
*mutex
)
2926 if (pthread_mutex::is_initializer (mutex
))
2927 pthread_mutex::init (mutex
, NULL
, *mutex
);
2928 if (!pthread_mutex::is_good_object (mutex
))
2930 return (*mutex
)->lock ();
2934 pthread_mutex_trylock (pthread_mutex_t
*mutex
)
2936 if (pthread_mutex::is_initializer (mutex
))
2937 pthread_mutex::init (mutex
, NULL
, *mutex
);
2938 if (!pthread_mutex::is_good_object (mutex
))
2940 return (*mutex
)->trylock ();
2944 pthread_mutex_unlock (pthread_mutex_t
*mutex
)
2946 if (pthread_mutex::is_initializer (mutex
))
2948 if (!pthread_mutex::is_good_object (mutex
))
2950 return (*mutex
)->unlock ();
2954 pthread_mutex_destroy (pthread_mutex_t
*mutex
)
2958 if (pthread_mutex::is_initializer (mutex
))
2960 if (!pthread_mutex::is_good_object (mutex
))
2963 rv
= (*mutex
)->destroy ();
2972 pthread_mutex_setprioceiling (pthread_mutex_t
*mutex
, int prioceiling
,
2981 pthread_spinlock::init (pthread_spinlock_t
*spinlock
, int pshared
)
2983 pthread_spinlock_t new_spinlock
= new pthread_spinlock (pshared
);
2984 if (!is_good_object (&new_spinlock
))
2986 delete new_spinlock
;
2991 if (efault
.faulted ())
2993 delete new_spinlock
;
2997 *spinlock
= new_spinlock
;
2998 pthread_printf ("*spinlock %p, pshared %d", *spinlock
, pshared
);
3004 pthread_spin_lock (pthread_spinlock_t
*spinlock
)
3006 if (!pthread_spinlock::is_good_object (spinlock
))
3008 return (*spinlock
)->lock ();
3012 pthread_spin_trylock (pthread_spinlock_t
*spinlock
)
3014 if (!pthread_spinlock::is_good_object (spinlock
))
3016 return (*spinlock
)->trylock ();
3020 pthread_spin_unlock (pthread_spinlock_t
*spinlock
)
3022 if (!pthread_spinlock::is_good_object (spinlock
))
3024 return (*spinlock
)->unlock ();
3028 pthread_spin_destroy (pthread_spinlock_t
*spinlock
)
3030 if (!pthread_spinlock::is_good_object (spinlock
))
3032 return (*spinlock
)->destroy ();
3035 /* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
3038 pthread_mutexattr_getprotocol (const pthread_mutexattr_t
*attr
,
3041 if (!pthread_mutexattr::is_good_object (attr
))
3047 pthread_mutexattr_getpshared (const pthread_mutexattr_t
*attr
,
3050 if (!pthread_mutexattr::is_good_object (attr
))
3052 *pshared
= (*attr
)->pshared
;
3057 pthread_mutexattr_gettype (const pthread_mutexattr_t
*attr
, int *type
)
3059 if (!pthread_mutexattr::is_good_object (attr
))
3061 *type
= (*attr
)->mutextype
;
3065 /* FIXME: write and test process shared mutex's. */
3067 pthread_mutexattr_init (pthread_mutexattr_t
*attr
)
3069 if (pthread_mutexattr::is_good_object (attr
))
3072 *attr
= new pthread_mutexattr ();
3073 if (!pthread_mutexattr::is_good_object (attr
))
3083 pthread_mutexattr_destroy (pthread_mutexattr_t
*attr
)
3085 if (!pthread_mutexattr::is_good_object (attr
))
3093 /* Win32 doesn't support mutex priorities */
3095 pthread_mutexattr_setprotocol (pthread_mutexattr_t
*attr
, int protocol
)
3097 if (!pthread_mutexattr::is_good_object (attr
))
3102 /* Win32 doesn't support mutex priorities */
3104 pthread_mutexattr_setprioceiling (pthread_mutexattr_t
*attr
,
3107 if (!pthread_mutexattr::is_good_object (attr
))
3113 pthread_mutexattr_getprioceiling (const pthread_mutexattr_t
*attr
,
3116 if (!pthread_mutexattr::is_good_object (attr
))
3122 pthread_mutexattr_setpshared (pthread_mutexattr_t
*attr
, int pshared
)
3124 if (!pthread_mutexattr::is_good_object (attr
))
3126 /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
3129 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
3131 (*attr
)->pshared
= pshared
;
3135 /* see pthread_mutex_gettype */
3137 pthread_mutexattr_settype (pthread_mutexattr_t
*attr
, int type
)
3139 if (!pthread_mutexattr::is_good_object (attr
))
3144 case PTHREAD_MUTEX_ERRORCHECK
:
3145 case PTHREAD_MUTEX_RECURSIVE
:
3146 case PTHREAD_MUTEX_NORMAL
:
3147 (*attr
)->mutextype
= type
;
3158 List
<semaphore
> semaphore::semaphores
;
3160 semaphore::semaphore (int pshared
, unsigned int value
)
3161 : verifyable_object (SEM_MAGIC
),
3163 currentvalue (value
),
3168 SECURITY_ATTRIBUTES sa
= (pshared
!= PTHREAD_PROCESS_PRIVATE
)
3169 ? sec_all
: sec_none_nih
;
3170 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, NULL
);
3171 if (!this->win32_obj_id
)
3174 semaphores
.insert (this);
3177 semaphore::semaphore (unsigned long long shash
, LUID sluid
, int sfd
,
3178 sem_t
*ssem
, int oflag
, mode_t mode
, unsigned int value
)
3179 : verifyable_object (SEM_MAGIC
),
3180 shared (PTHREAD_PROCESS_SHARED
),
3181 currentvalue (value
), /* Unused for named semaphores. */
3187 char name
[MAX_PATH
];
3189 __small_sprintf (name
, "semaphore/%016X%08x%08x",
3190 hash
, luid
.HighPart
, luid
.LowPart
);
3191 this->win32_obj_id
= ::CreateSemaphore (&sec_all
, value
, LONG_MAX
, name
);
3192 if (!this->win32_obj_id
)
3194 if (GetLastError () == ERROR_ALREADY_EXISTS
&& (oflag
& O_EXCL
))
3197 CloseHandle (this->win32_obj_id
);
3201 semaphores
.insert (this);
3204 semaphore::~semaphore ()
3207 CloseHandle (win32_obj_id
);
3209 semaphores
.remove (this);
3215 if (ReleaseSemaphore (win32_obj_id
, 1, ¤tvalue
))
3220 semaphore::_getvalue (int *sval
)
3224 switch (WaitForSingleObject (win32_obj_id
, 0))
3227 ReleaseSemaphore (win32_obj_id
, 1, &val
);
3241 semaphore::_trywait ()
3243 /* FIXME: signals should be able to interrupt semaphores...
3244 We probably need WaitForMultipleObjects here. */
3245 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
3255 semaphore::_timedwait (const struct timespec
*abstime
)
3261 if (efault
.faulted ())
3263 /* According to SUSv3, abstime need not be checked for validity,
3264 if the semaphore can be locked immediately. */
3271 gettimeofday (&tv
, NULL
);
3272 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
3273 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3276 switch (cancelable_wait (win32_obj_id
, waitlength
, cw_cancel_self
, cw_sig_eintr
))
3285 set_errno (ETIMEDOUT
);
3288 pthread_printf ("cancelable_wait failed. %E");
3298 switch (cancelable_wait (win32_obj_id
, INFINITE
, cw_cancel_self
, cw_sig_eintr
))
3307 pthread_printf ("cancelable_wait failed. %E");
3314 semaphore::_fixup_after_fork ()
3316 if (shared
== PTHREAD_PROCESS_PRIVATE
)
3318 pthread_printf ("sem %x", this);
3319 /* FIXME: duplicate code here and in the constructor. */
3320 this->win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, currentvalue
,
3323 api_fatal ("failed to create new win32 semaphore, error %d");
3328 semaphore::_terminate ()
3330 int _sem_close (sem_t
*, bool);
3333 _sem_close (sem
, false);
3336 /* static members */
3339 semaphore::init (sem_t
*sem
, int pshared
, unsigned int value
)
3342 We can't tell the difference between reinitialising an
3343 existing semaphore and initialising a semaphore who's
3344 contents happen to be a valid pointer
3346 if (is_good_object (sem
))
3348 paranoid_printf ("potential attempt to reinitialise a semaphore");
3351 if (value
> SEM_VALUE_MAX
)
3357 *sem
= new semaphore (pshared
, value
);
3359 if (!is_good_object (sem
))
3370 semaphore::destroy (sem_t
*sem
)
3372 if (!is_good_object (sem
))
3378 /* It's invalid to destroy a semaphore not opened with sem_init. */
3379 if ((*sem
)->fd
!= -1)
3385 /* FIXME - new feature - test for busy against threads... */
3393 semaphore::close (sem_t
*sem
)
3395 if (!is_good_object (sem
))
3401 /* It's invalid to close a semaphore not opened with sem_open. */
3402 if ((*sem
)->fd
== -1)
3414 semaphore::open (unsigned long long hash
, LUID luid
, int fd
, int oflag
,
3415 mode_t mode
, unsigned int value
, bool &wasopen
)
3417 if (value
> SEM_VALUE_MAX
)
3423 /* sem_open is supposed to return the same pointer, if the same named
3424 semaphore is opened multiple times in the same process, as long as
3425 the semaphore hasn't been closed or unlinked in the meantime. */
3426 semaphores
.mx
.lock ();
3427 for (semaphore
*sema
= semaphores
.head
; sema
; sema
= sema
->next
)
3428 if (sema
->fd
>= 0 && sema
->hash
== hash
3429 && sema
->luid
.HighPart
== luid
.HighPart
3430 && sema
->luid
.LowPart
== sema
->luid
.LowPart
)
3433 semaphores
.mx
.unlock ();
3436 semaphores
.mx
.unlock ();
3439 sem_t
*sem
= new sem_t
;
3446 *sem
= new semaphore (hash
, luid
, fd
, sem
, oflag
, mode
, value
);
3448 if (!is_good_object (sem
))
3458 semaphore::wait (sem_t
*sem
)
3460 pthread_testcancel ();
3462 if (!is_good_object (sem
))
3468 return (*sem
)->_wait ();
3472 semaphore::trywait (sem_t
*sem
)
3474 if (!is_good_object (sem
))
3480 return (*sem
)->_trywait ();
3484 semaphore::timedwait (sem_t
*sem
, const struct timespec
*abstime
)
3486 if (!is_good_object (sem
))
3492 return (*sem
)->_timedwait (abstime
);
3496 semaphore::post (sem_t
*sem
)
3498 if (!is_good_object (sem
))
3509 semaphore::getvalue (sem_t
*sem
, int *sval
)
3512 if (efault
.faulted () || !is_good_object (sem
))
3518 return (*sem
)->_getvalue (sval
);
3522 semaphore::getinternal (sem_t
*sem
, int *sfd
, unsigned long long *shash
,
3523 LUID
*sluid
, unsigned int *sval
)
3526 if (efault
.faulted () || !is_good_object (sem
))
3531 if ((*sfd
= (*sem
)->fd
) < 0)
3536 *shash
= (*sem
)->hash
;
3537 *sluid
= (*sem
)->luid
;
3538 /* POSIX defines the value in calls to sem_init/sem_open as unsigned, but
3539 the sem_getvalue gets a pointer to int to return the value. Go figure! */
3540 return (*sem
)->_getvalue ((int *)sval
);
3545 pthread_null::get_null_pthread ()
3547 /* because of weird entry points */
3548 _instance
.magic
= 0;
3552 pthread_null::pthread_null ()
3554 attr
.joinable
= PTHREAD_CREATE_DETACHED
;
3555 /* Mark ourselves as invalid */
3559 pthread_null::~pthread_null ()
3564 pthread_null::create (void *(*)(void *), pthread_attr
*, void *)
3570 pthread_null::exit (void *value_ptr
)
3572 _my_tls
.remove (INFINITE
);
3577 pthread_null::cancel ()
3583 pthread_null::testcancel ()
3588 pthread_null::setcancelstate (int state
, int *oldstate
)
3594 pthread_null::setcanceltype (int type
, int *oldtype
)
3600 pthread_null::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
3605 pthread_null::pop_cleanup_handler (int const execute
)
3610 pthread_null::getsequence_np ()
3615 pthread_null
pthread_null::_instance
;