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), canceled (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
)
542 SetEvent (cancel_event
);
545 else if (equal (thread
, self
))
549 return 0; // Never reached
552 // cancel asynchronous
553 SuspendThread (win32_obj_id
);
554 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
557 context
.ContextFlags
= CONTEXT_CONTROL
;
558 GetThreadContext (win32_obj_id
, &context
);
559 context
.Eip
= (DWORD
) pthread::static_cancel_self
;
560 SetThreadContext (win32_obj_id
, &context
);
563 ResumeThread (win32_obj_id
);
568 /* TODO: Insert pthread_testcancel into the required functions.
570 Here are the lists of required and optional functions per POSIX.1-2001
571 and POSIX.1-2008. A start (*) indicates that the Cygwin function already
572 is a cancellation point (aka "calls pthread_testcancel").
574 Required cancellation points:
602 * pthread_cond_timedwait ()
603 * pthread_cond_wait ()
605 * pthread_testcancel ()
636 Optional cancellation points:
728 getopt () (if opterr is nonzero)
783 posix_trace_create ()
784 posix_trace_create_withlog ()
785 posix_trace_eventtypelist_getnext_id ()
786 posix_trace_eventtypelist_rewind ()
788 posix_trace_get_attr ()
789 posix_trace_get_filter ()
790 posix_trace_get_status ()
791 posix_trace_getnext_event ()
793 posix_trace_rewind ()
794 posix_trace_set_filter ()
795 posix_trace_shutdown ()
796 posix_trace_timedgetnext_event ()
797 posix_typed_mem_open ()
801 pthread_rwlock_rdlock ()
802 pthread_rwlock_timedrdlock ()
803 pthread_rwlock_timedwrlock ()
804 pthread_rwlock_wrlock ()
864 An implementation may also mark other functions not specified in the
865 standard as cancellation points. In particular, an implementation is
866 likely to mark any nonstandard function that may block as a
867 cancellation point. */
870 pthread::testcancel ()
872 if (cancelstate
== PTHREAD_CANCEL_DISABLE
)
875 /* We check for the canceled flag first. This allows to use the
876 pthread_testcancel function a lot without adding the overhead of
877 an OS call. Only if the thread is marked as canceled, we wait for
878 cancel_event being really set, on the off-chance that pthread_cancel
879 gets interrupted before calling SetEvent. */
882 WaitForSingleObject (cancel_event
, INFINITE
);
888 pthread::static_cancel_self ()
890 pthread::self ()->cancel_self ();
894 cancelable_wait (HANDLE object
, DWORD timeout
,
895 const cw_cancel_action cancel_action
,
896 const enum cw_sig_wait sig_wait
)
900 HANDLE wait_objects
[3];
901 pthread_t thread
= pthread::self ();
903 /* Do not change the wait order.
904 The object must have higher priority than the cancel event,
905 because WaitForMultipleObjects will return the smallest index
906 if both objects are signaled. */
907 wait_objects
[num
++] = object
;
909 if (cancel_action
== cw_no_cancel
|| !pthread::is_good_object (&thread
) ||
910 thread
->cancelstate
== PTHREAD_CANCEL_DISABLE
)
911 cancel_n
= (DWORD
) -1;
914 cancel_n
= WAIT_OBJECT_0
+ num
++;
915 wait_objects
[cancel_n
] = thread
->cancel_event
;
919 if (sig_wait
== cw_sig_nosig
|| &_my_tls
!= _main_tls
)
923 sig_n
= WAIT_OBJECT_0
+ num
++;
924 wait_objects
[sig_n
] = signal_arrived
;
929 res
= WaitForMultipleObjects (num
, wait_objects
, FALSE
, timeout
);
932 if (cancel_action
== cw_cancel_self
)
933 pthread::static_cancel_self ();
936 else if (res
!= sig_n
)
938 else if (sig_wait
== cw_sig_eintr
)
942 _my_tls
.call_signal_handler ();
951 pthread::setcancelstate (int state
, int *oldstate
)
957 if (state
!= PTHREAD_CANCEL_ENABLE
&& state
!= PTHREAD_CANCEL_DISABLE
)
962 *oldstate
= cancelstate
;
972 pthread::setcanceltype (int type
, int *oldtype
)
978 if (type
!= PTHREAD_CANCEL_DEFERRED
&& type
!= PTHREAD_CANCEL_ASYNCHRONOUS
)
983 *oldtype
= canceltype
;
993 pthread::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
997 api_fatal ("Attempt to push a cleanup handler across threads");
998 handler
->next
= cleanup_stack
;
999 cleanup_stack
= handler
;
1003 pthread::pop_cleanup_handler (int const execute
)
1005 if (this != self ())
1006 // TODO: send a signal or something to the thread ?
1007 api_fatal ("Attempt to execute a cleanup handler across threads");
1011 if (cleanup_stack
!= NULL
)
1013 __pthread_cleanup_handler
*handler
= cleanup_stack
;
1016 (*handler
->function
) (handler
->arg
);
1017 cleanup_stack
= handler
->next
;
1024 pthread::pop_all_cleanup_handlers ()
1026 while (cleanup_stack
!= NULL
)
1027 pop_cleanup_handler (1);
1031 pthread::cancel_self ()
1033 exit (PTHREAD_CANCELED
);
1037 pthread::get_thread_id ()
1043 pthread::_fixup_after_fork ()
1045 /* set thread to not running if it is not the forking thread */
1046 if (this != pthread::self ())
1050 win32_obj_id
= NULL
;
1052 cancel_event
= NULL
;
1057 pthread::suspend_except_self ()
1059 if (valid
&& this != pthread::self ())
1060 SuspendThread (win32_obj_id
);
1067 ResumeThread (win32_obj_id
);
1070 /* instance members */
1072 pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC
),
1073 joinable (PTHREAD_CREATE_JOINABLE
), contentionscope (PTHREAD_SCOPE_PROCESS
),
1074 inheritsched (PTHREAD_INHERIT_SCHED
), stacksize (0)
1076 schedparam
.sched_priority
= 0;
1079 pthread_attr::~pthread_attr ()
1083 pthread_condattr::pthread_condattr ():verifyable_object
1084 (PTHREAD_CONDATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
1088 pthread_condattr::~pthread_condattr ()
1092 List
<pthread_cond
> pthread_cond::conds
;
1094 /* This is used for cond creation protection within a single process only */
1095 fast_mutex NO_COPY
pthread_cond::cond_initialization_lock
;
1097 /* We can only be called once.
1098 TODO: (no rush) use a non copied memory section to
1099 hold an initialization flag. */
1101 pthread_cond::init_mutex ()
1103 if (!cond_initialization_lock
.init ())
1104 api_fatal ("Could not create win32 Mutex for pthread cond static initializer support.");
1107 pthread_cond::pthread_cond (pthread_condattr
*attr
) :
1108 verifyable_object (PTHREAD_COND_MAGIC
),
1109 shared (0), waiting (0), pending (0), sem_wait (NULL
),
1110 mtx_cond(NULL
), next (NULL
)
1112 pthread_mutex
*verifyable_mutex_obj
;
1115 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
1121 verifyable_mutex_obj
= &mtx_in
;
1122 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1124 thread_printf ("Internal cond mutex is not valid. this %p", this);
1129 * Change the mutex type to NORMAL.
1130 * This mutex MUST be of type normal
1132 mtx_in
.set_type (PTHREAD_MUTEX_NORMAL
);
1134 verifyable_mutex_obj
= &mtx_out
;
1135 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1137 thread_printf ("Internal cond mutex is not valid. this %p", this);
1141 /* Change the mutex type to NORMAL to speed up mutex operations */
1142 mtx_out
.set_type (PTHREAD_MUTEX_NORMAL
);
1144 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1147 pthread_printf ("CreateSemaphore failed. %E");
1152 conds
.insert (this);
1155 pthread_cond::~pthread_cond ()
1158 CloseHandle (sem_wait
);
1160 conds
.remove (this);
1164 pthread_cond::unblock (const bool all
)
1166 unsigned long releaseable
;
1169 * Block outgoing threads (and avoid simultanous unblocks)
1173 releaseable
= waiting
- pending
;
1176 unsigned long released
;
1181 * Block incoming threads until all waiting threads are released.
1186 * Calculate releaseable again because threads can enter until
1187 * the semaphore has been taken, but they can not leave, therefore pending
1188 * is unchanged and releaseable can only get higher
1190 releaseable
= waiting
- pending
;
1193 released
= all
? releaseable
: 1;
1194 pending
+= released
;
1198 ::ReleaseSemaphore (sem_wait
, released
, NULL
);
1202 * And let the threads release.
1208 pthread_cond::wait (pthread_mutex_t mutex
, DWORD dwMilliseconds
)
1213 if (InterlockedIncrement ((long *)&waiting
) == 1)
1215 else if (mtx_cond
!= mutex
)
1217 InterlockedDecrement ((long *)&waiting
);
1224 * Release the mutex and wait on semaphore
1229 rv
= cancelable_wait (sem_wait
, dwMilliseconds
, cw_no_cancel_self
, cw_sig_eintr
);
1233 if (rv
!= WAIT_OBJECT_0
)
1236 * It might happen that a signal is sent while the thread got canceled
1237 * or timed out. Try to take one.
1238 * If the thread gets one than a signal|broadcast is in progress.
1240 if (WaitForSingleObject (sem_wait
, 0) == WAIT_OBJECT_0
)
1242 * thread got cancelled ot timed out while a signalling is in progress.
1243 * Set wait result back to signaled
1248 InterlockedDecrement ((long *)&waiting
);
1250 if (rv
== WAIT_OBJECT_0
&& --pending
== 0)
1252 * All signaled threads are released,
1253 * new threads can enter Wait
1262 if (rv
== WAIT_CANCELED
)
1263 pthread::static_cancel_self ();
1264 else if (rv
== WAIT_SIGNALED
)
1265 /* SUSv3 states: If a signal is delivered to a thread waiting for a
1266 condition variable, upon return from the signal handler the thread
1267 resumes waiting for the condition variable as if it was not
1268 interrupted, or it shall return zero due to spurious wakeup.
1269 We opt for the latter choice here. */
1271 else if (rv
== WAIT_TIMEOUT
)
1278 pthread_cond::_fixup_after_fork ()
1280 waiting
= pending
= 0;
1283 /* Unlock eventually locked mutexes */
1287 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1289 api_fatal ("pthread_cond::_fixup_after_fork () failed to recreate win32 semaphore");
1292 pthread_rwlockattr::pthread_rwlockattr ():verifyable_object
1293 (PTHREAD_RWLOCKATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
1297 pthread_rwlockattr::~pthread_rwlockattr ()
1301 List
<pthread_rwlock
> pthread_rwlock::rwlocks
;
1303 /* This is used for rwlock creation protection within a single process only */
1304 fast_mutex NO_COPY
pthread_rwlock::rwlock_initialization_lock
;
1306 /* We can only be called once.
1307 TODO: (no rush) use a non copied memory section to
1308 hold an initialization flag. */
1310 pthread_rwlock::init_mutex ()
1312 if (!rwlock_initialization_lock
.init ())
1313 api_fatal ("Could not create win32 Mutex for pthread rwlock static initializer support.");
1316 pthread_rwlock::pthread_rwlock (pthread_rwlockattr
*attr
) :
1317 verifyable_object (PTHREAD_RWLOCK_MAGIC
),
1318 shared (0), waiting_readers (0), waiting_writers (0), writer (NULL
),
1319 readers (NULL
), readers_mx (), mtx (NULL
), cond_readers (NULL
), cond_writers (NULL
),
1322 pthread_mutex
*verifyable_mutex_obj
= &mtx
;
1323 pthread_cond
*verifyable_cond_obj
;
1325 if (!readers_mx
.init ())
1327 thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this);
1333 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
1339 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1341 thread_printf ("Internal rwlock mutex is not valid. this %p", this);
1345 /* Change the mutex type to NORMAL to speed up mutex operations */
1346 mtx
.set_type (PTHREAD_MUTEX_NORMAL
);
1348 verifyable_cond_obj
= &cond_readers
;
1349 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1351 thread_printf ("Internal rwlock readers cond is not valid. this %p", this);
1356 verifyable_cond_obj
= &cond_writers
;
1357 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1359 thread_printf ("Internal rwlock writers cond is not valid. this %p", this);
1365 rwlocks
.insert (this);
1368 pthread_rwlock::~pthread_rwlock ()
1370 rwlocks
.remove (this);
1374 pthread_rwlock::rdlock ()
1377 struct RWLOCK_READER
*reader
;
1378 pthread_t self
= pthread::self ();
1382 reader
= lookup_reader (self
);
1385 if (reader
->n
< ULONG_MAX
)
1392 reader
= new struct RWLOCK_READER
;
1399 while (writer
|| waiting_writers
)
1401 pthread_cleanup_push (pthread_rwlock::rdlock_cleanup
, this);
1404 cond_readers
.wait (&mtx
);
1407 pthread_cleanup_pop (0);
1410 reader
->thread
= self
;
1412 add_reader (reader
);
1421 pthread_rwlock::tryrdlock ()
1424 pthread_t self
= pthread::self ();
1428 if (writer
|| waiting_writers
|| lookup_reader (self
))
1432 struct RWLOCK_READER
*reader
;
1434 reader
= lookup_reader (self
);
1435 if (reader
&& reader
->n
< ULONG_MAX
)
1437 else if ((reader
= new struct RWLOCK_READER
))
1439 reader
->thread
= self
;
1441 add_reader (reader
);
1453 pthread_rwlock::wrlock ()
1456 pthread_t self
= pthread::self ();
1460 if (writer
== self
|| lookup_reader (self
))
1466 while (writer
|| readers
)
1468 pthread_cleanup_push (pthread_rwlock::wrlock_cleanup
, this);
1471 cond_writers
.wait (&mtx
);
1474 pthread_cleanup_pop (0);
1486 pthread_rwlock::trywrlock ()
1489 pthread_t self
= pthread::self ();
1493 if (writer
|| readers
)
1504 pthread_rwlock::unlock ()
1507 pthread_t self
= pthread::self ();
1523 struct RWLOCK_READER
*reader
= lookup_reader (self
);
1530 if (--reader
->n
> 0)
1533 remove_reader (reader
);
1546 pthread_rwlock::add_reader (struct RWLOCK_READER
*rd
)
1548 List_insert (readers
, rd
);
1552 pthread_rwlock::remove_reader (struct RWLOCK_READER
*rd
)
1554 List_remove (readers_mx
, readers
, rd
);
1557 struct pthread_rwlock::RWLOCK_READER
*
1558 pthread_rwlock::lookup_reader (pthread_t thread
)
1562 struct RWLOCK_READER
*cur
= readers
;
1564 while (cur
&& cur
->thread
!= thread
)
1567 readers_mx
.unlock ();
1573 pthread_rwlock::rdlock_cleanup (void *arg
)
1575 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1577 --(rwlock
->waiting_readers
);
1579 rwlock
->mtx
.unlock ();
1583 pthread_rwlock::wrlock_cleanup (void *arg
)
1585 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1587 --(rwlock
->waiting_writers
);
1589 rwlock
->mtx
.unlock ();
1593 pthread_rwlock::_fixup_after_fork ()
1595 pthread_t self
= pthread::self ();
1596 struct RWLOCK_READER
**temp
= &readers
;
1598 waiting_readers
= 0;
1599 waiting_writers
= 0;
1601 if (!readers_mx
.init ())
1602 api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex");
1604 /* Unlock eventually locked mutex */
1607 * Remove all readers except self
1611 if ((*temp
)->thread
== self
)
1612 temp
= &((*temp
)->next
);
1615 struct RWLOCK_READER
*cur
= *temp
;
1616 *temp
= (*temp
)->next
;
1623 /* static members */
1624 /* This stores pthread_key information across fork() boundaries */
1625 List
<pthread_key
> pthread_key::keys
;
1627 /* non-static members */
1629 pthread_key::pthread_key (void (*aDestructor
) (void *)):verifyable_object (PTHREAD_KEY_MAGIC
), destructor (aDestructor
)
1631 tls_index
= TlsAlloc ();
1632 if (tls_index
== TLS_OUT_OF_INDEXES
)
1638 pthread_key::~pthread_key ()
1640 /* We may need to make the list code lock the list during operations
1645 TlsFree (tls_index
);
1650 pthread_key::_fixup_before_fork ()
1656 pthread_key::_fixup_after_fork ()
1658 tls_index
= TlsAlloc ();
1659 if (tls_index
== TLS_OUT_OF_INDEXES
)
1660 api_fatal ("pthread_key::recreate_key_from_buffer () failed to reallocate Tls storage");
1665 pthread_key::run_destructor ()
1669 void *oldValue
= get ();
1673 destructor (oldValue
);
1678 /* pshared mutexs */
1680 /* static members */
1682 List
<pthread_mutex
> pthread_mutex::mutexes
;
1684 /* This is used for mutex creation protection within a single process only */
1685 fast_mutex NO_COPY
pthread_mutex::mutex_initialization_lock
;
1688 pthread_mutex::init_mutex ()
1690 if (!mutex_initialization_lock
.init ())
1691 api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support.");
1694 pthread_mutex::pthread_mutex (pthread_mutexattr
*attr
) :
1695 verifyable_object (0), /* set magic to zero initially */
1697 win32_obj_id (NULL
), owner (_new_mutex
),
1701 recursion_counter (0), condwaits (0),
1702 type (PTHREAD_MUTEX_ERRORCHECK
),
1703 pshared (PTHREAD_PROCESS_PRIVATE
)
1705 win32_obj_id
= ::CreateEvent (&sec_none_nih
, false, false, NULL
);
1708 /*attr checked in the C call */
1710 /* handled in the caller */;
1711 else if (attr
->pshared
!= PTHREAD_PROCESS_SHARED
)
1712 type
= attr
->mutextype
;
1714 return; /* Not implemented */
1716 magic
= PTHREAD_MUTEX_MAGIC
;
1717 mutexes
.insert (this);
1720 pthread_mutex::~pthread_mutex ()
1724 CloseHandle (win32_obj_id
);
1725 win32_obj_id
= NULL
;
1728 mutexes
.remove (this);
1729 owner
= _destroyed_mutex
;
1734 pthread_mutex::lock ()
1736 pthread_t self
= ::pthread_self ();
1739 if (InterlockedIncrement ((long *) &lock_counter
) == 1)
1741 else if (type
== PTHREAD_MUTEX_NORMAL
/* potentially causes deadlock */
1742 || !pthread::equal (owner
, self
))
1744 cancelable_wait (win32_obj_id
, INFINITE
, cw_no_cancel
, cw_sig_resume
);
1749 InterlockedDecrement ((long *) &lock_counter
);
1750 if (type
== PTHREAD_MUTEX_RECURSIVE
)
1751 result
= lock_recursive ();
1756 pthread_printf ("mutex %p, self %p, owner %p, lock_counter %d, recursion_counter %d",
1757 this, self
, owner
, lock_counter
, recursion_counter
);
1762 pthread_mutex::unlock ()
1765 pthread_t self
= ::pthread_self ();
1766 if (type
== PTHREAD_MUTEX_NORMAL
)
1767 /* no error checking */;
1768 else if (no_owner ())
1769 res
= type
== PTHREAD_MUTEX_ERRORCHECK
? EINVAL
: 0;
1770 else if (!pthread::equal (owner
, self
))
1772 if (!res
&& recursion_counter
> 0 && --recursion_counter
== 0)
1773 /* Don't try to unlock anything if recursion_counter == 0.
1774 This means the mutex was never locked or that we've forked. */
1776 owner
= (pthread_t
) _unlocked_mutex
;
1780 if (InterlockedDecrement ((long *) &lock_counter
))
1781 ::SetEvent (win32_obj_id
); // Another thread is waiting
1785 pthread_printf ("mutex %p, owner %p, self %p, lock_counter %d, recursion_counter %d, type %d, res %d",
1786 this, owner
, self
, lock_counter
, recursion_counter
, type
, res
);
1791 pthread_mutex::trylock ()
1793 pthread_t self
= ::pthread_self ();
1796 if (InterlockedCompareExchange ((long *) &lock_counter
, 1, 0) == 0)
1798 else if (type
== PTHREAD_MUTEX_RECURSIVE
&& pthread::equal (owner
, self
))
1799 result
= lock_recursive ();
1807 pthread_mutex::destroy ()
1809 if (condwaits
|| trylock ())
1810 // Do not destroy a condwaited or locked mutex
1812 else if (recursion_counter
> 1)
1814 // Do not destroy a recursive locked mutex
1815 recursion_counter
--;
1824 pthread_mutex::_fixup_after_fork ()
1826 pthread_printf ("mutex %p", this);
1827 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1828 api_fatal ("pthread_mutex::_fixup_after_fork () doesn't understand PROCESS_SHARED mutex's");
1830 /* All waiting threads are gone after a fork */
1831 recursion_counter
= 0;
1835 tid
= 0xffffffff; /* Don't know the tid after a fork */
1837 win32_obj_id
= ::CreateEvent (&sec_none_nih
, false, false, NULL
);
1839 api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 event for mutex");
1842 pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC
),
1843 pshared (PTHREAD_PROCESS_PRIVATE
), mutextype (PTHREAD_MUTEX_ERRORCHECK
)
1847 pthread_mutexattr::~pthread_mutexattr ()
1851 /* pshared spinlocks
1853 The infrastructure is provided by the underlying pthread_mutex class.
1854 The rest is a simplification implementing spin locking. */
1856 pthread_spinlock::pthread_spinlock (int pshared
) :
1857 pthread_mutex (NULL
)
1859 magic
= PTHREAD_SPINLOCK_MAGIC
;
1860 set_type (PTHREAD_MUTEX_NORMAL
);
1861 set_shared (pshared
);
1865 pthread_spinlock::lock ()
1867 pthread_t self
= ::pthread_self ();
1872 if (InterlockedExchange ((long *) &lock_counter
, 1) == 0)
1877 else if (pthread::equal (owner
, self
))
1879 else /* Minimal timeout to minimize CPU usage while still spinning. */
1880 cancelable_wait (win32_obj_id
, 1L, cw_no_cancel
, cw_sig_resume
);
1882 while (result
== -1);
1883 pthread_printf ("spinlock %p, self %p, owner %p", this, self
, owner
);
1888 pthread_spinlock::unlock ()
1890 pthread_t self
= ::pthread_self ();
1893 if (!pthread::equal (owner
, self
))
1897 owner
= (pthread_t
) _unlocked_mutex
;
1901 InterlockedExchange ((long *) &lock_counter
, 0);
1902 ::SetEvent (win32_obj_id
);
1905 pthread_printf ("spinlock %p, owner %p, self %p, res %d",
1906 this, owner
, self
, result
);
1911 pthread::thread_init_wrapper (void *arg
)
1913 pthread
*thread
= (pthread
*) arg
;
1914 set_tls_self_pointer (thread
);
1916 thread
->mutex
.lock ();
1918 // if thread is detached force cleanup on exit
1919 if (thread
->attr
.joinable
== PTHREAD_CREATE_DETACHED
&& thread
->joiner
== NULL
)
1920 thread
->joiner
= thread
;
1921 _my_tls
.sigmask
= thread
->parent_tls
->sigmask
;
1922 thread
->mutex
.unlock ();
1924 thread_printf ("started thread %p %p %p %p %p %p", arg
, &_my_tls
.local_clib
,
1925 _impure_ptr
, thread
, thread
->function
, thread
->arg
);
1927 // call the user's thread
1928 void *ret
= thread
->function (thread
->arg
);
1932 return 0; // just for show. Never returns.
1936 pthread::getsequence_np ()
1938 return get_thread_id ();
1942 pthread::create (pthread_t
*thread
, const pthread_attr_t
*attr
,
1943 void *(*start_routine
) (void *), void *arg
)
1945 if (attr
&& !pthread_attr::is_good_object (attr
))
1948 *thread
= new pthread ();
1949 if (!(*thread
)->create (start_routine
, attr
? *attr
: NULL
, arg
))
1960 pthread::once (pthread_once_t
*once_control
, void (*init_routine
) (void))
1963 if (once_control
->state
)
1966 pthread_mutex_lock (&once_control
->mutex
);
1967 /* Here we must set a cancellation handler to unlock the mutex if needed */
1968 /* but a cancellation handler is not the right thing. We need this in the thread
1969 *cleanup routine. Assumption: a thread can only be in one pthread_once routine
1970 *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
1971 *on pthread_exit ();
1973 if (!once_control
->state
)
1976 once_control
->state
= 1;
1978 /* Here we must remove our cancellation handler */
1979 pthread_mutex_unlock (&once_control
->mutex
);
1984 pthread::cancel (pthread_t thread
)
1986 if (!is_good_object (&thread
))
1989 return thread
->cancel ();
1993 pthread::atforkprepare ()
1995 callback
*cb
= MT_INTERFACE
->pthread_prepare
;
2004 MT_INTERFACE
->fixup_before_fork ();
2008 pthread::atforkparent ()
2012 callback
*cb
= MT_INTERFACE
->pthread_parent
;
2021 pthread::atforkchild ()
2023 MT_INTERFACE
->fixup_after_fork ();
2027 callback
*cb
= MT_INTERFACE
->pthread_child
;
2035 /* Register a set of functions to run before and after fork.
2036 prepare calls are called in LI-FC order.
2037 parent and child calls are called in FI-FC order. */
2039 pthread::atfork (void (*prepare
)(void), void (*parent
)(void), void (*child
)(void))
2041 callback
*prepcb
= NULL
, *parentcb
= NULL
, *childcb
= NULL
;
2044 prepcb
= new callback
;
2050 parentcb
= new callback
;
2060 childcb
= new callback
;
2073 prepcb
->cb
= prepare
;
2074 List_insert (MT_INTERFACE
->pthread_prepare
, prepcb
);
2078 parentcb
->cb
= parent
;
2079 callback
**t
= &MT_INTERFACE
->pthread_parent
;
2082 /* t = pointer to last next in the list */
2083 List_insert (*t
, parentcb
);
2087 childcb
->cb
= child
;
2088 callback
**t
= &MT_INTERFACE
->pthread_child
;
2091 /* t = pointer to last next in the list */
2092 List_insert (*t
, childcb
);
2098 pthread_attr_init (pthread_attr_t
*attr
)
2100 if (pthread_attr::is_good_object (attr
))
2103 *attr
= new pthread_attr
;
2104 if (!pthread_attr::is_good_object (attr
))
2114 pthread_attr_getinheritsched (const pthread_attr_t
*attr
,
2117 if (!pthread_attr::is_good_object (attr
))
2119 *inheritsched
= (*attr
)->inheritsched
;
2124 pthread_attr_getschedparam (const pthread_attr_t
*attr
,
2125 struct sched_param
*param
)
2127 if (!pthread_attr::is_good_object (attr
))
2129 *param
= (*attr
)->schedparam
;
2133 /* From a pure code point of view, this should call a helper in sched.cc,
2134 to allow for someone adding scheduler policy changes to win32 in the future.
2135 However that's extremely unlikely, so short and sweet will do us */
2137 pthread_attr_getschedpolicy (const pthread_attr_t
*attr
, int *policy
)
2139 if (!pthread_attr::is_good_object (attr
))
2141 *policy
= SCHED_FIFO
;
2147 pthread_attr_getscope (const pthread_attr_t
*attr
, int *contentionscope
)
2149 if (!pthread_attr::is_good_object (attr
))
2151 *contentionscope
= (*attr
)->contentionscope
;
2156 pthread_attr_setdetachstate (pthread_attr_t
*attr
, int detachstate
)
2158 if (!pthread_attr::is_good_object (attr
))
2160 if (detachstate
< 0 || detachstate
> 1)
2162 (*attr
)->joinable
= detachstate
;
2167 pthread_attr_getdetachstate (const pthread_attr_t
*attr
, int *detachstate
)
2169 if (!pthread_attr::is_good_object (attr
))
2171 *detachstate
= (*attr
)->joinable
;
2176 pthread_attr_setinheritsched (pthread_attr_t
*attr
, int inheritsched
)
2178 if (!pthread_attr::is_good_object (attr
))
2180 if (inheritsched
!= PTHREAD_INHERIT_SCHED
2181 && inheritsched
!= PTHREAD_EXPLICIT_SCHED
)
2183 (*attr
)->inheritsched
= inheritsched
;
2188 pthread_attr_setschedparam (pthread_attr_t
*attr
,
2189 const struct sched_param
*param
)
2191 if (!pthread_attr::is_good_object (attr
))
2193 if (!valid_sched_parameters (param
))
2195 (*attr
)->schedparam
= *param
;
2199 /* See __pthread_attr_getschedpolicy for some notes */
2201 pthread_attr_setschedpolicy (pthread_attr_t
*attr
, int policy
)
2203 if (!pthread_attr::is_good_object (attr
))
2205 if (policy
!= SCHED_FIFO
)
2211 pthread_attr_setscope (pthread_attr_t
*attr
, int contentionscope
)
2213 if (!pthread_attr::is_good_object (attr
))
2215 if (contentionscope
!= PTHREAD_SCOPE_SYSTEM
2216 && contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2218 /* In future, we may be able to support system scope by escalating the thread
2219 priority to exceed the priority class. For now we only support PROCESS scope. */
2220 if (contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2222 (*attr
)->contentionscope
= contentionscope
;
2227 pthread_attr_setstacksize (pthread_attr_t
*attr
, size_t size
)
2229 if (!pthread_attr::is_good_object (attr
))
2231 (*attr
)->stacksize
= size
;
2236 pthread_attr_getstacksize (const pthread_attr_t
*attr
, size_t *size
)
2238 if (!pthread_attr::is_good_object (attr
))
2240 *size
= (*attr
)->stacksize
;
2245 pthread_attr_destroy (pthread_attr_t
*attr
)
2247 if (!pthread_attr::is_good_object (attr
))
2255 pthread::join (pthread_t
*thread
, void **return_val
)
2257 pthread_t joiner
= self ();
2259 joiner
->testcancel ();
2261 // Initialize return val with NULL
2265 if (!is_good_object (&joiner
))
2268 if (!is_good_object (thread
))
2271 if (equal (*thread
,joiner
))
2274 (*thread
)->mutex
.lock ();
2276 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2278 (*thread
)->mutex
.unlock ();
2283 (*thread
)->joiner
= joiner
;
2284 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2285 (*thread
)->mutex
.unlock ();
2287 switch (cancelable_wait ((*thread
)->win32_obj_id
, INFINITE
, cw_no_cancel_self
, cw_sig_resume
))
2291 *return_val
= (*thread
)->return_ptr
;
2295 // set joined thread back to joinable since we got canceled
2296 (*thread
)->joiner
= NULL
;
2297 (*thread
)->attr
.joinable
= PTHREAD_CREATE_JOINABLE
;
2298 joiner
->cancel_self ();
2302 // should never happen
2311 pthread::detach (pthread_t
*thread
)
2313 if (!is_good_object (thread
))
2316 (*thread
)->mutex
.lock ();
2317 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2319 (*thread
)->mutex
.unlock ();
2323 // check if thread is still alive
2324 if ((*thread
)->valid
&& WaitForSingleObject ((*thread
)->win32_obj_id
, 0) == WAIT_TIMEOUT
)
2326 // force cleanup on exit
2327 (*thread
)->joiner
= *thread
;
2328 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2329 (*thread
)->mutex
.unlock ();
2333 // thread has already terminated.
2334 (*thread
)->mutex
.unlock ();
2342 pthread::suspend (pthread_t
*thread
)
2344 if (!is_good_object (thread
))
2347 if ((*thread
)->suspended
== false)
2349 (*thread
)->suspended
= true;
2350 SuspendThread ((*thread
)->win32_obj_id
);
2358 pthread::resume (pthread_t
*thread
)
2360 if (!is_good_object (thread
))
2363 if ((*thread
)->suspended
== true)
2364 ResumeThread ((*thread
)->win32_obj_id
);
2365 (*thread
)->suspended
= false;
2370 /* provided for source level compatability.
2371 See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2374 pthread_getconcurrency ()
2376 return MT_INTERFACE
->concurrency
;
2379 /* keep this in sync with sched.cc */
2381 pthread_getschedparam (pthread_t thread
, int *policy
,
2382 struct sched_param
*param
)
2384 if (!pthread::is_good_object (&thread
))
2386 *policy
= SCHED_FIFO
;
2387 /* we don't return the current effective priority, we return the current
2388 requested priority */
2389 *param
= thread
->attr
.schedparam
;
2393 /* Thread Specific Data */
2395 pthread_key_create (pthread_key_t
*key
, void (*destructor
) (void *))
2397 *key
= new pthread_key (destructor
);
2399 if (!pthread_key::is_good_object (key
))
2409 pthread_key_delete (pthread_key_t key
)
2411 if (!pthread_key::is_good_object (&key
))
2418 /* provided for source level compatability. See
2419 http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2422 pthread_setconcurrency (int new_level
)
2426 MT_INTERFACE
->concurrency
= new_level
;
2430 /* keep syncronised with sched.cc */
2432 pthread_setschedparam (pthread_t thread
, int policy
,
2433 const struct sched_param
*param
)
2435 if (!pthread::is_good_object (&thread
))
2437 if (policy
!= SCHED_FIFO
)
2442 sched_set_thread_priority (thread
->win32_obj_id
, param
->sched_priority
);
2444 thread
->attr
.schedparam
.sched_priority
= param
->sched_priority
;
2449 pthread_setschedprio (pthread_t thread
, int priority
)
2451 if (!pthread::is_good_object (&thread
))
2454 sched_set_thread_priority (thread
->win32_obj_id
, priority
);
2456 thread
->attr
.schedparam
.sched_priority
= priority
;
2461 pthread_setspecific (pthread_key_t key
, const void *value
)
2463 if (!pthread_key::is_good_object (&key
))
2470 pthread_getspecific (pthread_key_t key
)
2472 if (!pthread_key::is_good_object (&key
))
2475 return (key
)->get ();
2480 pthread_cond_destroy (pthread_cond_t
*cond
)
2482 if (pthread_cond::is_initializer (cond
))
2484 if (!pthread_cond::is_good_object (cond
))
2487 /* reads are atomic */
2488 if ((*cond
)->waiting
)
2498 pthread_cond::init (pthread_cond_t
*cond
, const pthread_condattr_t
*attr
)
2500 pthread_cond_t new_cond
;
2502 if (attr
&& !pthread_condattr::is_good_object (attr
))
2505 cond_initialization_lock
.lock ();
2507 new_cond
= new pthread_cond (attr
? (*attr
) : NULL
);
2508 if (!is_good_object (&new_cond
))
2511 cond_initialization_lock
.unlock ();
2516 if (efault
.faulted ())
2519 cond_initialization_lock
.unlock ();
2524 cond_initialization_lock
.unlock ();
2530 pthread_cond_broadcast (pthread_cond_t
*cond
)
2532 if (pthread_cond::is_initializer (cond
))
2534 if (!pthread_cond::is_good_object (cond
))
2537 (*cond
)->unblock (true);
2543 pthread_cond_signal (pthread_cond_t
*cond
)
2545 if (pthread_cond::is_initializer (cond
))
2547 if (!pthread_cond::is_good_object (cond
))
2550 (*cond
)->unblock (false);
2556 __pthread_cond_dowait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2559 if (!pthread_mutex::is_good_object (mutex
))
2561 if (!(*mutex
)->can_be_unlocked ())
2564 if (pthread_cond::is_initializer (cond
))
2565 pthread_cond::init (cond
, NULL
);
2566 if (!pthread_cond::is_good_object (cond
))
2569 return (*cond
)->wait (*mutex
, waitlength
);
2573 pthread_cond_timedwait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2574 const struct timespec
*abstime
)
2580 if (efault
.faulted ())
2583 pthread_testcancel ();
2585 /* According to SUSv3, the abstime value must be checked for validity. */
2586 if (abstime
->tv_sec
< 0
2587 || abstime
->tv_nsec
< 0
2588 || abstime
->tv_nsec
> 999999999)
2591 gettimeofday (&tv
, NULL
);
2592 /* Check for immediate timeout before converting to microseconds, since
2593 the resulting value can easily overflow long. This also allows to
2594 evaluate microseconds directly in DWORD. */
2595 if (tv
.tv_sec
> abstime
->tv_sec
2596 || (tv
.tv_sec
== abstime
->tv_sec
2597 && tv
.tv_usec
> abstime
->tv_nsec
/ 1000))
2600 waitlength
= (abstime
->tv_sec
- tv
.tv_sec
) * 1000;
2601 waitlength
+= (abstime
->tv_nsec
/ 1000 - tv
.tv_usec
) / 1000;
2602 return __pthread_cond_dowait (cond
, mutex
, waitlength
);
2606 pthread_cond_wait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
2608 pthread_testcancel ();
2610 return __pthread_cond_dowait (cond
, mutex
, INFINITE
);
2614 pthread_condattr_init (pthread_condattr_t
*condattr
)
2616 if (pthread_condattr::is_good_object (condattr
))
2619 *condattr
= new pthread_condattr
;
2620 if (!pthread_condattr::is_good_object (condattr
))
2630 pthread_condattr_getpshared (const pthread_condattr_t
*attr
, int *pshared
)
2632 if (!pthread_condattr::is_good_object (attr
))
2634 *pshared
= (*attr
)->shared
;
2639 pthread_condattr_setpshared (pthread_condattr_t
*attr
, int pshared
)
2641 if (!pthread_condattr::is_good_object (attr
))
2643 if ((pshared
< 0) || (pshared
> 1))
2645 /* shared cond vars not currently supported */
2646 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2648 (*attr
)->shared
= pshared
;
2653 pthread_condattr_destroy (pthread_condattr_t
*condattr
)
2655 if (!pthread_condattr::is_good_object (condattr
))
2663 pthread_rwlock_destroy (pthread_rwlock_t
*rwlock
)
2665 if (pthread_rwlock::is_initializer (rwlock
))
2667 if (!pthread_rwlock::is_good_object (rwlock
))
2670 if ((*rwlock
)->writer
|| (*rwlock
)->readers
||
2671 (*rwlock
)->waiting_readers
|| (*rwlock
)->waiting_writers
)
2681 pthread_rwlock::init (pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*attr
)
2683 pthread_rwlock_t new_rwlock
;
2685 if (attr
&& !pthread_rwlockattr::is_good_object (attr
))
2688 rwlock_initialization_lock
.lock ();
2690 new_rwlock
= new pthread_rwlock (attr
? (*attr
) : NULL
);
2691 if (!is_good_object (&new_rwlock
))
2694 rwlock_initialization_lock
.unlock ();
2699 if (efault
.faulted ())
2702 rwlock_initialization_lock
.unlock ();
2706 *rwlock
= new_rwlock
;
2707 rwlock_initialization_lock
.unlock ();
2713 pthread_rwlock_rdlock (pthread_rwlock_t
*rwlock
)
2715 pthread_testcancel ();
2717 if (pthread_rwlock::is_initializer (rwlock
))
2718 pthread_rwlock::init (rwlock
, NULL
);
2719 if (!pthread_rwlock::is_good_object (rwlock
))
2722 return (*rwlock
)->rdlock ();
2726 pthread_rwlock_tryrdlock (pthread_rwlock_t
*rwlock
)
2728 if (pthread_rwlock::is_initializer (rwlock
))
2729 pthread_rwlock::init (rwlock
, NULL
);
2730 if (!pthread_rwlock::is_good_object (rwlock
))
2733 return (*rwlock
)->tryrdlock ();
2737 pthread_rwlock_wrlock (pthread_rwlock_t
*rwlock
)
2739 pthread_testcancel ();
2741 if (pthread_rwlock::is_initializer (rwlock
))
2742 pthread_rwlock::init (rwlock
, NULL
);
2743 if (!pthread_rwlock::is_good_object (rwlock
))
2746 return (*rwlock
)->wrlock ();
2750 pthread_rwlock_trywrlock (pthread_rwlock_t
*rwlock
)
2752 if (pthread_rwlock::is_initializer (rwlock
))
2753 pthread_rwlock::init (rwlock
, NULL
);
2754 if (!pthread_rwlock::is_good_object (rwlock
))
2757 return (*rwlock
)->trywrlock ();
2761 pthread_rwlock_unlock (pthread_rwlock_t
*rwlock
)
2763 if (pthread_rwlock::is_initializer (rwlock
))
2765 if (!pthread_rwlock::is_good_object (rwlock
))
2768 return (*rwlock
)->unlock ();
2772 pthread_rwlockattr_init (pthread_rwlockattr_t
*rwlockattr
)
2774 if (pthread_rwlockattr::is_good_object (rwlockattr
))
2777 *rwlockattr
= new pthread_rwlockattr
;
2778 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2780 delete (*rwlockattr
);
2788 pthread_rwlockattr_getpshared (const pthread_rwlockattr_t
*attr
, int *pshared
)
2790 if (!pthread_rwlockattr::is_good_object (attr
))
2792 *pshared
= (*attr
)->shared
;
2797 pthread_rwlockattr_setpshared (pthread_rwlockattr_t
*attr
, int pshared
)
2799 if (!pthread_rwlockattr::is_good_object (attr
))
2801 if ((pshared
< 0) || (pshared
> 1))
2803 /* shared rwlock vars not currently supported */
2804 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2806 (*attr
)->shared
= pshared
;
2811 pthread_rwlockattr_destroy (pthread_rwlockattr_t
*rwlockattr
)
2813 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2815 delete (*rwlockattr
);
2822 pthread_kill (pthread_t thread
, int sig
)
2824 // lock myself, for the use of thread2signal
2825 // two different kills might clash: FIXME
2827 if (!pthread::is_good_object (&thread
))
2832 si
.si_code
= SI_USER
;
2833 si
.si_pid
= myself
->pid
;
2834 si
.si_uid
= myself
->uid
;
2840 thread
->cygtls
->set_threadkill ();
2841 rval
= sig_send (NULL
, si
, thread
->cygtls
);
2844 switch (WaitForSingleObject (thread
->win32_obj_id
, 0))
2859 pthread_sigmask (int operation
, const sigset_t
*set
, sigset_t
*old_set
)
2861 return handle_sigprocmask (operation
, set
, old_set
, _my_tls
.sigmask
);
2867 pthread_equal (pthread_t t1
, pthread_t t2
)
2869 return pthread::equal (t1
, t2
);
2875 pthread_mutex::init (pthread_mutex_t
*mutex
,
2876 const pthread_mutexattr_t
*attr
,
2877 const pthread_mutex_t initializer
)
2879 if (attr
&& !pthread_mutexattr::is_good_object (attr
))
2882 mutex_initialization_lock
.lock ();
2883 if (initializer
== NULL
|| pthread_mutex::is_initializer (mutex
))
2885 pthread_mutex_t new_mutex
= new pthread_mutex (attr
? (*attr
) : NULL
);
2886 if (!is_good_object (&new_mutex
))
2889 mutex_initialization_lock
.unlock ();
2893 if (!attr
&& initializer
)
2895 if (initializer
== PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
)
2896 new_mutex
->type
= PTHREAD_MUTEX_RECURSIVE
;
2897 else if (initializer
== PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
)
2898 new_mutex
->type
= PTHREAD_MUTEX_NORMAL
;
2899 else if (initializer
== PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
)
2900 new_mutex
->type
= PTHREAD_MUTEX_ERRORCHECK
;
2904 if (efault
.faulted ())
2907 mutex_initialization_lock
.unlock ();
2913 mutex_initialization_lock
.unlock ();
2914 pthread_printf ("*mutex %p, attr %p, initializer %p", *mutex
, attr
, initializer
);
2920 pthread_mutex_getprioceiling (const pthread_mutex_t
*mutex
,
2923 /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
2926 We can support mutex priorities in the future though:
2927 Store a priority with each mutex.
2928 When the mutex is optained, set the thread priority as appropriate
2929 When the mutex is released, reset the thread priority. */
2934 pthread_mutex_lock (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
)->lock ();
2944 pthread_mutex_trylock (pthread_mutex_t
*mutex
)
2946 if (pthread_mutex::is_initializer (mutex
))
2947 pthread_mutex::init (mutex
, NULL
, *mutex
);
2948 if (!pthread_mutex::is_good_object (mutex
))
2950 return (*mutex
)->trylock ();
2954 pthread_mutex_unlock (pthread_mutex_t
*mutex
)
2956 if (pthread_mutex::is_initializer (mutex
))
2958 if (!pthread_mutex::is_good_object (mutex
))
2960 return (*mutex
)->unlock ();
2964 pthread_mutex_destroy (pthread_mutex_t
*mutex
)
2968 if (pthread_mutex::is_initializer (mutex
))
2970 if (!pthread_mutex::is_good_object (mutex
))
2973 rv
= (*mutex
)->destroy ();
2982 pthread_mutex_setprioceiling (pthread_mutex_t
*mutex
, int prioceiling
,
2991 pthread_spinlock::init (pthread_spinlock_t
*spinlock
, int pshared
)
2993 pthread_spinlock_t new_spinlock
= new pthread_spinlock (pshared
);
2994 if (!is_good_object (&new_spinlock
))
2996 delete new_spinlock
;
3001 if (efault
.faulted ())
3003 delete new_spinlock
;
3007 *spinlock
= new_spinlock
;
3008 pthread_printf ("*spinlock %p, pshared %d", *spinlock
, pshared
);
3014 pthread_spin_lock (pthread_spinlock_t
*spinlock
)
3016 if (!pthread_spinlock::is_good_object (spinlock
))
3018 return (*spinlock
)->lock ();
3022 pthread_spin_trylock (pthread_spinlock_t
*spinlock
)
3024 if (!pthread_spinlock::is_good_object (spinlock
))
3026 return (*spinlock
)->trylock ();
3030 pthread_spin_unlock (pthread_spinlock_t
*spinlock
)
3032 if (!pthread_spinlock::is_good_object (spinlock
))
3034 return (*spinlock
)->unlock ();
3038 pthread_spin_destroy (pthread_spinlock_t
*spinlock
)
3040 if (!pthread_spinlock::is_good_object (spinlock
))
3042 return (*spinlock
)->destroy ();
3045 /* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
3048 pthread_mutexattr_getprotocol (const pthread_mutexattr_t
*attr
,
3051 if (!pthread_mutexattr::is_good_object (attr
))
3057 pthread_mutexattr_getpshared (const pthread_mutexattr_t
*attr
,
3060 if (!pthread_mutexattr::is_good_object (attr
))
3062 *pshared
= (*attr
)->pshared
;
3067 pthread_mutexattr_gettype (const pthread_mutexattr_t
*attr
, int *type
)
3069 if (!pthread_mutexattr::is_good_object (attr
))
3071 *type
= (*attr
)->mutextype
;
3075 /* FIXME: write and test process shared mutex's. */
3077 pthread_mutexattr_init (pthread_mutexattr_t
*attr
)
3079 if (pthread_mutexattr::is_good_object (attr
))
3082 *attr
= new pthread_mutexattr ();
3083 if (!pthread_mutexattr::is_good_object (attr
))
3093 pthread_mutexattr_destroy (pthread_mutexattr_t
*attr
)
3095 if (!pthread_mutexattr::is_good_object (attr
))
3103 /* Win32 doesn't support mutex priorities */
3105 pthread_mutexattr_setprotocol (pthread_mutexattr_t
*attr
, int protocol
)
3107 if (!pthread_mutexattr::is_good_object (attr
))
3112 /* Win32 doesn't support mutex priorities */
3114 pthread_mutexattr_setprioceiling (pthread_mutexattr_t
*attr
,
3117 if (!pthread_mutexattr::is_good_object (attr
))
3123 pthread_mutexattr_getprioceiling (const pthread_mutexattr_t
*attr
,
3126 if (!pthread_mutexattr::is_good_object (attr
))
3132 pthread_mutexattr_setpshared (pthread_mutexattr_t
*attr
, int pshared
)
3134 if (!pthread_mutexattr::is_good_object (attr
))
3136 /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
3139 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
3141 (*attr
)->pshared
= pshared
;
3145 /* see pthread_mutex_gettype */
3147 pthread_mutexattr_settype (pthread_mutexattr_t
*attr
, int type
)
3149 if (!pthread_mutexattr::is_good_object (attr
))
3154 case PTHREAD_MUTEX_ERRORCHECK
:
3155 case PTHREAD_MUTEX_RECURSIVE
:
3156 case PTHREAD_MUTEX_NORMAL
:
3157 (*attr
)->mutextype
= type
;
3168 List
<semaphore
> semaphore::semaphores
;
3170 semaphore::semaphore (int pshared
, unsigned int value
)
3171 : verifyable_object (SEM_MAGIC
),
3173 currentvalue (value
),
3178 SECURITY_ATTRIBUTES sa
= (pshared
!= PTHREAD_PROCESS_PRIVATE
)
3179 ? sec_all
: sec_none_nih
;
3180 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, NULL
);
3181 if (!this->win32_obj_id
)
3184 semaphores
.insert (this);
3187 semaphore::semaphore (unsigned long long shash
, LUID sluid
, int sfd
,
3188 sem_t
*ssem
, int oflag
, mode_t mode
, unsigned int value
)
3189 : verifyable_object (SEM_MAGIC
),
3190 shared (PTHREAD_PROCESS_SHARED
),
3191 currentvalue (value
), /* Unused for named semaphores. */
3197 char name
[MAX_PATH
];
3199 __small_sprintf (name
, "semaphore/%016X%08x%08x",
3200 hash
, luid
.HighPart
, luid
.LowPart
);
3201 this->win32_obj_id
= ::CreateSemaphore (&sec_all
, value
, LONG_MAX
, name
);
3202 if (!this->win32_obj_id
)
3204 if (GetLastError () == ERROR_ALREADY_EXISTS
&& (oflag
& O_EXCL
))
3207 CloseHandle (this->win32_obj_id
);
3211 semaphores
.insert (this);
3214 semaphore::~semaphore ()
3217 CloseHandle (win32_obj_id
);
3219 semaphores
.remove (this);
3225 if (ReleaseSemaphore (win32_obj_id
, 1, ¤tvalue
))
3230 semaphore::_getvalue (int *sval
)
3234 switch (WaitForSingleObject (win32_obj_id
, 0))
3237 ReleaseSemaphore (win32_obj_id
, 1, &val
);
3251 semaphore::_trywait ()
3253 /* FIXME: signals should be able to interrupt semaphores...
3254 We probably need WaitForMultipleObjects here. */
3255 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
3265 semaphore::_timedwait (const struct timespec
*abstime
)
3271 if (efault
.faulted ())
3273 /* According to SUSv3, abstime need not be checked for validity,
3274 if the semaphore can be locked immediately. */
3281 gettimeofday (&tv
, NULL
);
3282 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
3283 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3286 switch (cancelable_wait (win32_obj_id
, waitlength
, cw_cancel_self
, cw_sig_eintr
))
3295 set_errno (ETIMEDOUT
);
3298 pthread_printf ("cancelable_wait failed. %E");
3308 switch (cancelable_wait (win32_obj_id
, INFINITE
, cw_cancel_self
, cw_sig_eintr
))
3317 pthread_printf ("cancelable_wait failed. %E");
3324 semaphore::_fixup_after_fork ()
3326 if (shared
== PTHREAD_PROCESS_PRIVATE
)
3328 pthread_printf ("sem %x", this);
3329 /* FIXME: duplicate code here and in the constructor. */
3330 this->win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, currentvalue
,
3333 api_fatal ("failed to create new win32 semaphore, error %d");
3338 semaphore::_terminate ()
3340 int _sem_close (sem_t
*, bool);
3343 _sem_close (sem
, false);
3346 /* static members */
3349 semaphore::init (sem_t
*sem
, int pshared
, unsigned int value
)
3352 We can't tell the difference between reinitialising an
3353 existing semaphore and initialising a semaphore who's
3354 contents happen to be a valid pointer
3356 if (is_good_object (sem
))
3358 paranoid_printf ("potential attempt to reinitialise a semaphore");
3361 if (value
> SEM_VALUE_MAX
)
3367 *sem
= new semaphore (pshared
, value
);
3369 if (!is_good_object (sem
))
3380 semaphore::destroy (sem_t
*sem
)
3382 if (!is_good_object (sem
))
3388 /* It's invalid to destroy a semaphore not opened with sem_init. */
3389 if ((*sem
)->fd
!= -1)
3395 /* FIXME - new feature - test for busy against threads... */
3403 semaphore::close (sem_t
*sem
)
3405 if (!is_good_object (sem
))
3411 /* It's invalid to close a semaphore not opened with sem_open. */
3412 if ((*sem
)->fd
== -1)
3424 semaphore::open (unsigned long long hash
, LUID luid
, int fd
, int oflag
,
3425 mode_t mode
, unsigned int value
, bool &wasopen
)
3427 if (value
> SEM_VALUE_MAX
)
3433 /* sem_open is supposed to return the same pointer, if the same named
3434 semaphore is opened multiple times in the same process, as long as
3435 the semaphore hasn't been closed or unlinked in the meantime. */
3436 semaphores
.mx
.lock ();
3437 for (semaphore
*sema
= semaphores
.head
; sema
; sema
= sema
->next
)
3438 if (sema
->fd
>= 0 && sema
->hash
== hash
3439 && sema
->luid
.HighPart
== luid
.HighPart
3440 && sema
->luid
.LowPart
== sema
->luid
.LowPart
)
3443 semaphores
.mx
.unlock ();
3446 semaphores
.mx
.unlock ();
3449 sem_t
*sem
= new sem_t
;
3456 *sem
= new semaphore (hash
, luid
, fd
, sem
, oflag
, mode
, value
);
3458 if (!is_good_object (sem
))
3468 semaphore::wait (sem_t
*sem
)
3470 pthread_testcancel ();
3472 if (!is_good_object (sem
))
3478 return (*sem
)->_wait ();
3482 semaphore::trywait (sem_t
*sem
)
3484 if (!is_good_object (sem
))
3490 return (*sem
)->_trywait ();
3494 semaphore::timedwait (sem_t
*sem
, const struct timespec
*abstime
)
3496 if (!is_good_object (sem
))
3502 return (*sem
)->_timedwait (abstime
);
3506 semaphore::post (sem_t
*sem
)
3508 if (!is_good_object (sem
))
3519 semaphore::getvalue (sem_t
*sem
, int *sval
)
3522 if (efault
.faulted () || !is_good_object (sem
))
3528 return (*sem
)->_getvalue (sval
);
3532 semaphore::getinternal (sem_t
*sem
, int *sfd
, unsigned long long *shash
,
3533 LUID
*sluid
, unsigned int *sval
)
3536 if (efault
.faulted () || !is_good_object (sem
))
3541 if ((*sfd
= (*sem
)->fd
) < 0)
3546 *shash
= (*sem
)->hash
;
3547 *sluid
= (*sem
)->luid
;
3548 /* POSIX defines the value in calls to sem_init/sem_open as unsigned, but
3549 the sem_getvalue gets a pointer to int to return the value. Go figure! */
3550 return (*sem
)->_getvalue ((int *)sval
);
3555 pthread_null::get_null_pthread ()
3557 /* because of weird entry points */
3558 _instance
.magic
= 0;
3562 pthread_null::pthread_null ()
3564 attr
.joinable
= PTHREAD_CREATE_DETACHED
;
3565 /* Mark ourselves as invalid */
3569 pthread_null::~pthread_null ()
3574 pthread_null::create (void *(*)(void *), pthread_attr
*, void *)
3580 pthread_null::exit (void *value_ptr
)
3582 _my_tls
.remove (INFINITE
);
3587 pthread_null::cancel ()
3593 pthread_null::testcancel ()
3598 pthread_null::setcancelstate (int state
, int *oldstate
)
3604 pthread_null::setcanceltype (int type
, int *oldtype
)
3610 pthread_null::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
3615 pthread_null::pop_cleanup_handler (int const execute
)
3620 pthread_null::getsequence_np ()
3625 pthread_null
pthread_null::_instance
;