1 /* thread.cc: Locking and threading module functions
3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
5 Originally written by Marco Fuykschot <marco@ddi.nl>
6 Substantialy enhanced by Robert Collins <rbtcollins@hotmail.com>
8 This file is part of Cygwin.
10 This software is a copyrighted work licensed under the terms of the
11 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
14 /* Implementation overview and caveats:
16 Win32 puts some contraints on what can and cannot be implemented. Where
17 possible we work around those contrainsts. Where we cannot work around
18 the constraints we either pretend to be conformant, or return an error
21 Some caveats: PROCESS_SHARED objects while they pretend to be process
22 shared, may not actually work. Some test cases are needed to determine
23 win32's behaviour. My suspicion is that the win32 handle needs to be
24 opened with different flags for proper operation.
26 R.Collins, April 2001. */
39 #include "perprocess.h"
42 #include <semaphore.h>
44 #include <sys/timeb.h>
45 #include <exceptions.h>
46 #include <sys/fcntl.h>
49 extern "C" void __fp_lock_all ();
50 extern "C" void __fp_unlock_all ();
51 static inline verifyable_object_state
52 verifyable_object_isvalid (void const * objectptr
, long magic
,
53 void *static_ptr1
= NULL
,
54 void *static_ptr2
= NULL
,
55 void *static_ptr3
= NULL
);
57 extern int threadsafe
;
60 extern "C" struct _reent
*
63 return &_my_tls
.local_clib
;
67 __cygwin_lock_init (_LOCK_T
*lock
)
69 *lock
= _LOCK_T_INITIALIZER
;
73 __cygwin_lock_init_recursive (_LOCK_T
*lock
)
75 *lock
= _LOCK_T_RECURSIVE_INITIALIZER
;
79 __cygwin_lock_fini (_LOCK_T
*lock
)
81 pthread_mutex_destroy ((pthread_mutex_t
*) lock
);
85 __cygwin_lock_lock (_LOCK_T
*lock
)
87 if (MT_INTERFACE
->threadcount
<= 1)
88 paranoid_printf ("threadcount %d. not locking", MT_INTERFACE
->threadcount
);
91 paranoid_printf ("threadcount %d. locking", MT_INTERFACE
->threadcount
);
92 pthread_mutex_lock ((pthread_mutex_t
*) lock
);
97 __cygwin_lock_trylock (_LOCK_T
*lock
)
99 return pthread_mutex_trylock ((pthread_mutex_t
*) lock
);
104 __cygwin_lock_unlock (_LOCK_T
*lock
)
106 if (MT_INTERFACE
->threadcount
<= 1)
107 paranoid_printf ("threadcount %d. not unlocking", MT_INTERFACE
->threadcount
);
110 pthread_mutex_unlock ((pthread_mutex_t
*) lock
);
111 paranoid_printf ("threadcount %d. unlocked", MT_INTERFACE
->threadcount
);
115 static inline verifyable_object_state
116 verifyable_object_isvalid (void const *objectptr
, long magic
, void *static_ptr1
,
117 void *static_ptr2
, void *static_ptr3
)
120 /* Check for NULL pointer specifically since it is a cheap test and avoids the
121 overhead of setting up the fault handler. */
122 if (!objectptr
|| efault
.faulted ())
123 return INVALID_OBJECT
;
125 verifyable_object
**object
= (verifyable_object
**) objectptr
;
127 if ((static_ptr1
&& *object
== static_ptr1
) ||
128 (static_ptr2
&& *object
== static_ptr2
) ||
129 (static_ptr3
&& *object
== static_ptr3
))
130 return VALID_STATIC_OBJECT
;
131 if ((*object
)->magic
!= magic
)
132 return INVALID_OBJECT
;
138 pthread_attr::is_good_object (pthread_attr_t
const *attr
)
140 if (verifyable_object_isvalid (attr
, PTHREAD_ATTR_MAGIC
) != VALID_OBJECT
)
146 pthread_condattr::is_good_object (pthread_condattr_t
const *attr
)
148 if (verifyable_object_isvalid (attr
, PTHREAD_CONDATTR_MAGIC
) != VALID_OBJECT
)
154 pthread_rwlockattr::is_good_object (pthread_rwlockattr_t
const *attr
)
156 if (verifyable_object_isvalid (attr
, PTHREAD_RWLOCKATTR_MAGIC
) != VALID_OBJECT
)
162 pthread_key::is_good_object (pthread_key_t
const *key
)
164 if (verifyable_object_isvalid (key
, PTHREAD_KEY_MAGIC
) != VALID_OBJECT
)
170 pthread_mutex::is_good_object (pthread_mutex_t
const *mutex
)
172 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
) != VALID_OBJECT
)
178 pthread_mutex::is_good_initializer (pthread_mutex_t
const *mutex
)
180 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
181 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
182 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
183 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) != VALID_STATIC_OBJECT
)
189 pthread_mutex::is_good_initializer_or_object (pthread_mutex_t
const *mutex
)
191 if (verifyable_object_isvalid (mutex
, PTHREAD_MUTEX_MAGIC
,
192 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
,
193 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
,
194 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
) == INVALID_OBJECT
)
200 pthread_mutex::can_be_unlocked (pthread_mutex_t
const *mutex
)
202 pthread_t self
= pthread::self ();
204 if (!is_good_object (mutex
))
206 /* Check if the mutex is owned by the current thread and can be unlocked.
207 * Also check for the ANONYMOUS owner to cover NORMAL mutexes as well. */
208 return ((*mutex
)->recursion_counter
== 1
209 && ((*mutex
)->owner
== MUTEX_OWNER_ANONYMOUS
210 || pthread::equal ((*mutex
)->owner
, self
)));
214 pthread_mutexattr::is_good_object (pthread_mutexattr_t
const * attr
)
216 if (verifyable_object_isvalid (attr
, PTHREAD_MUTEXATTR_MAGIC
) != VALID_OBJECT
)
221 inline bool __attribute__ ((used
))
222 pthread::is_good_object (pthread_t
const *thread
)
224 if (verifyable_object_isvalid (thread
, PTHREAD_MAGIC
) != VALID_OBJECT
)
229 /* Thread synchronisation */
231 pthread_cond::is_good_object (pthread_cond_t
const *cond
)
233 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
) != VALID_OBJECT
)
239 pthread_cond::is_good_initializer (pthread_cond_t
const *cond
)
241 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) != VALID_STATIC_OBJECT
)
247 pthread_cond::is_good_initializer_or_object (pthread_cond_t
const *cond
)
249 if (verifyable_object_isvalid (cond
, PTHREAD_COND_MAGIC
, PTHREAD_COND_INITIALIZER
) == INVALID_OBJECT
)
256 pthread_rwlock::is_good_object (pthread_rwlock_t
const *rwlock
)
258 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
) != VALID_OBJECT
)
264 pthread_rwlock::is_good_initializer (pthread_rwlock_t
const *rwlock
)
266 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) != VALID_STATIC_OBJECT
)
272 pthread_rwlock::is_good_initializer_or_object (pthread_rwlock_t
const *rwlock
)
274 if (verifyable_object_isvalid (rwlock
, PTHREAD_RWLOCK_MAGIC
, PTHREAD_RWLOCK_INITIALIZER
) == INVALID_OBJECT
)
280 semaphore::is_good_object (sem_t
const * sem
)
282 if (verifyable_object_isvalid (sem
, SEM_MAGIC
) != VALID_OBJECT
)
288 ResourceLocks::Lock (int _resid
)
294 SetResourceLock (int _res_id
, int _mode
, const char *_function
)
296 EnterCriticalSection (user_data
->resourcelocks
->Lock (_res_id
));
300 ReleaseResourceLock (int _res_id
, int _mode
, const char *_function
)
302 LeaveCriticalSection (user_data
->resourcelocks
->Lock (_res_id
));
306 ResourceLocks::Init ()
308 InitializeCriticalSection (&lock
);
310 thread_printf ("lock %p inited by %p , %d", &lock
, user_data
, myself
->pid
);
314 ResourceLocks::Delete ()
318 thread_printf ("Close Resource Locks %p ", &lock
);
319 DeleteCriticalSection (&lock
);
327 pthread_mutex::init_mutex ();
328 pthread_cond::init_mutex ();
329 pthread_rwlock::init_mutex ();
333 MTinterface::fixup_before_fork ()
335 pthread_key::fixup_before_fork ();
338 /* This function is called from a single threaded process */
340 MTinterface::fixup_after_fork ()
342 pthread_key::fixup_after_fork ();
345 pthread::init_mainthread ();
347 pthread::fixup_after_fork ();
348 pthread_mutex::fixup_after_fork ();
349 pthread_cond::fixup_after_fork ();
350 pthread_rwlock::fixup_after_fork ();
351 semaphore::fixup_after_fork ();
358 pthread::init_mainthread ()
360 pthread
*thread
= get_tls_self_pointer ();
363 thread
= new pthread ();
365 api_fatal ("failed to create mainthread object");
368 set_tls_self_pointer (thread
);
369 thread
->thread_id
= GetCurrentThreadId ();
370 if (!DuplicateHandle (hMainProc
, GetCurrentThread (), hMainProc
,
371 &thread
->win32_obj_id
, 0, FALSE
, DUPLICATE_SAME_ACCESS
))
372 api_fatal ("failed to create mainthread handle");
373 if (!thread
->create_cancel_event ())
374 api_fatal ("couldn't create cancel event for main thread");
375 VerifyHandle (thread
->win32_obj_id
);
376 thread
->postcreate ();
382 pthread
*thread
= get_tls_self_pointer ();
385 thread
= pthread_null::get_null_pthread ();
386 set_tls_self_pointer (thread
);
392 pthread::get_tls_self_pointer ()
398 pthread::set_tls_self_pointer (pthread
*thread
)
400 thread
->cygtls
= &_my_tls
;
401 _my_tls
.tid
= thread
;
404 List
<pthread
> pthread::threads
;
407 pthread::pthread ():verifyable_object (PTHREAD_MAGIC
), win32_obj_id (0),
408 valid (false), suspended (false),
409 cancelstate (0), canceltype (0), cancel_event (0),
410 joiner (NULL
), next (NULL
), cleanup_stack (NULL
)
412 if (this != pthread_null::get_null_pthread ())
413 threads
.insert (this);
419 CloseHandle (win32_obj_id
);
421 CloseHandle (cancel_event
);
423 if (this != pthread_null::get_null_pthread ())
424 threads
.remove (this);
428 pthread::create_cancel_event ()
430 cancel_event
= ::CreateEvent (&sec_none_nih
, TRUE
, FALSE
, NULL
);
433 system_printf ("couldn't create cancel event, %E");
434 /* we need the event for correct behaviour */
441 pthread::precreate (pthread_attr
*newattr
)
443 pthread_mutex
*verifyable_mutex_obj
= &mutex
;
445 /* already running ? */
451 attr
.joinable
= newattr
->joinable
;
452 attr
.contentionscope
= newattr
->contentionscope
;
453 attr
.inheritsched
= newattr
->inheritsched
;
454 attr
.stacksize
= newattr
->stacksize
;
457 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
459 thread_printf ("New thread object access mutex is not valid. this %p",
464 /* Change the mutex type to NORMAL to speed up mutex operations */
465 mutex
.type
= PTHREAD_MUTEX_NORMAL
;
466 if (!create_cancel_event ())
471 pthread::create (void *(*func
) (void *), pthread_attr
*newattr
,
484 win32_obj_id
= ::CreateThread (&sec_none_nih
, attr
.stacksize
,
485 thread_init_wrapper
, this, 0, &thread_id
);
489 thread_printf ("CreateThread failed: this %p, %E", this);
496 low_priority_sleep (0);
504 pthread::postcreate ()
508 InterlockedIncrement (&MT_INTERFACE
->threadcount
);
509 /* FIXME: set the priority appropriately for system contention scope */
510 if (attr
.inheritsched
== PTHREAD_EXPLICIT_SCHED
)
512 /* FIXME: set the scheduling settings for the new thread */
513 /* sched_thread_setparam (win32_obj_id, attr.schedparam); */
518 pthread::exit (void *value_ptr
)
520 class pthread
*thread
= this;
522 // run cleanup handlers
523 pop_all_cleanup_handlers ();
525 pthread_key::run_all_destructors ();
528 // cleanup if thread is in detached state and not joined
529 if (equal (joiner
, thread
))
534 return_ptr
= value_ptr
;
538 if (_my_tls
.local_clib
.__sdidinit
< 0)
539 _my_tls
.local_clib
.__sdidinit
= 0;
540 (_reclaim_reent
) (_REENT
);
543 if (InterlockedDecrement (&MT_INTERFACE
->threadcount
) == 0)
547 _my_tls
.remove (INFINITE
);
555 class pthread
*thread
= this;
556 class pthread
*self
= pthread::self ();
566 if (canceltype
== PTHREAD_CANCEL_DEFERRED
||
567 cancelstate
== PTHREAD_CANCEL_DISABLE
)
571 SetEvent (cancel_event
);
574 else if (equal (thread
, self
))
578 return 0; // Never reached
581 // cancel asynchronous
582 SuspendThread (win32_obj_id
);
583 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
586 context
.ContextFlags
= CONTEXT_CONTROL
;
587 GetThreadContext (win32_obj_id
, &context
);
588 context
.Eip
= (DWORD
) pthread::static_cancel_self
;
589 SetThreadContext (win32_obj_id
, &context
);
592 ResumeThread (win32_obj_id
);
596 TODO: insert pthread_testcancel into the required functions
597 the required function list is: *indicates done, X indicates not present in cygwin.
616 *pthread_cond_timedwait ()
617 *pthread_cond_wait ()
619 *pthread_testcancel ()
643 the optional list is:
763 Note, that for fcntl (), for any value of the cmd argument.
765 And we must not introduce cancellation points anywhere else that's part of the posix or
771 pthread::testcancel ()
773 if (cancelstate
== PTHREAD_CANCEL_DISABLE
)
776 if (WaitForSingleObject (cancel_event
, 0) == WAIT_OBJECT_0
)
781 pthread::static_cancel_self ()
783 pthread::self ()->cancel_self ();
787 cancelable_wait (HANDLE object
, DWORD timeout
, const cw_cancel_action cancel_action
,
788 const enum cw_sig_wait sig_wait
)
792 HANDLE wait_objects
[3];
793 pthread_t thread
= pthread::self ();
795 /* Do not change the wait order.
796 The object must have higher priority than the cancel event,
797 because WaitForMultipleObjects will return the smallest index
798 if both objects are signaled. */
799 wait_objects
[num
++] = object
;
801 if (cancel_action
== cw_no_cancel
|| !pthread::is_good_object (&thread
) ||
802 thread
->cancelstate
== PTHREAD_CANCEL_DISABLE
)
803 cancel_n
= (DWORD
) -1;
806 cancel_n
= WAIT_OBJECT_0
+ num
++;
807 wait_objects
[cancel_n
] = thread
->cancel_event
;
811 if (sig_wait
== cw_sig_nosig
|| &_my_tls
!= _main_tls
)
815 sig_n
= WAIT_OBJECT_0
+ num
++;
816 wait_objects
[sig_n
] = signal_arrived
;
821 res
= WaitForMultipleObjects (num
, wait_objects
, FALSE
, timeout
);
824 if (cancel_action
== cw_cancel_self
)
825 pthread::static_cancel_self ();
828 else if (res
!= sig_n
)
830 else if (sig_wait
== cw_sig_eintr
)
834 _my_tls
.call_signal_handler ();
843 pthread::setcancelstate (int state
, int *oldstate
)
849 if (state
!= PTHREAD_CANCEL_ENABLE
&& state
!= PTHREAD_CANCEL_DISABLE
)
854 *oldstate
= cancelstate
;
864 pthread::setcanceltype (int type
, int *oldtype
)
870 if (type
!= PTHREAD_CANCEL_DEFERRED
&& type
!= PTHREAD_CANCEL_ASYNCHRONOUS
)
875 *oldtype
= canceltype
;
885 pthread::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
889 api_fatal ("Attempt to push a cleanup handler across threads");
890 handler
->next
= cleanup_stack
;
891 cleanup_stack
= handler
;
895 pthread::pop_cleanup_handler (int const execute
)
898 // TODO: send a signal or something to the thread ?
899 api_fatal ("Attempt to execute a cleanup handler across threads");
903 if (cleanup_stack
!= NULL
)
905 __pthread_cleanup_handler
*handler
= cleanup_stack
;
908 (*handler
->function
) (handler
->arg
);
909 cleanup_stack
= handler
->next
;
916 pthread::pop_all_cleanup_handlers ()
918 while (cleanup_stack
!= NULL
)
919 pop_cleanup_handler (1);
923 pthread::cancel_self ()
925 exit (PTHREAD_CANCELED
);
929 pthread::get_thread_id ()
935 pthread::_fixup_after_fork ()
937 /* set thread to not running if it is not the forking thread */
938 if (this != pthread::self ())
948 pthread::suspend_except_self ()
950 if (valid
&& this != pthread::self ())
951 SuspendThread (win32_obj_id
);
958 ResumeThread (win32_obj_id
);
961 /* instance members */
963 pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC
),
964 joinable (PTHREAD_CREATE_JOINABLE
), contentionscope (PTHREAD_SCOPE_PROCESS
),
965 inheritsched (PTHREAD_INHERIT_SCHED
), stacksize (0)
967 schedparam
.sched_priority
= 0;
970 pthread_attr::~pthread_attr ()
974 pthread_condattr::pthread_condattr ():verifyable_object
975 (PTHREAD_CONDATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
979 pthread_condattr::~pthread_condattr ()
983 List
<pthread_cond
> pthread_cond::conds
;
985 /* This is used for cond creation protection within a single process only */
986 fast_mutex NO_COPY
pthread_cond::cond_initialization_lock
;
988 /* We can only be called once.
989 TODO: (no rush) use a non copied memory section to
990 hold an initialization flag. */
992 pthread_cond::init_mutex ()
994 if (!cond_initialization_lock
.init ())
995 api_fatal ("Could not create win32 Mutex for pthread cond static initializer support.");
998 pthread_cond::pthread_cond (pthread_condattr
*attr
) :
999 verifyable_object (PTHREAD_COND_MAGIC
),
1000 shared (0), waiting (0), pending (0), sem_wait (NULL
),
1001 mtx_cond(NULL
), next (NULL
)
1003 pthread_mutex
*verifyable_mutex_obj
;
1006 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
1012 verifyable_mutex_obj
= &mtx_in
;
1013 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1015 thread_printf ("Internal cond mutex is not valid. this %p", this);
1020 * Change the mutex type to NORMAL.
1021 * This mutex MUST be of type normal
1023 mtx_in
.type
= PTHREAD_MUTEX_NORMAL
;
1025 verifyable_mutex_obj
= &mtx_out
;
1026 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1028 thread_printf ("Internal cond mutex is not valid. this %p", this);
1032 /* Change the mutex type to NORMAL to speed up mutex operations */
1033 mtx_out
.type
= PTHREAD_MUTEX_NORMAL
;
1035 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1038 debug_printf ("CreateSemaphore failed. %E");
1043 conds
.insert (this);
1046 pthread_cond::~pthread_cond ()
1049 CloseHandle (sem_wait
);
1051 conds
.remove (this);
1055 pthread_cond::unblock (const bool all
)
1057 unsigned long releaseable
;
1060 * Block outgoing threads (and avoid simultanous unblocks)
1064 releaseable
= waiting
- pending
;
1067 unsigned long released
;
1072 * Block incoming threads until all waiting threads are released.
1077 * Calculate releaseable again because threads can enter until
1078 * the semaphore has been taken, but they can not leave, therefore pending
1079 * is unchanged and releaseable can only get higher
1081 releaseable
= waiting
- pending
;
1084 released
= all
? releaseable
: 1;
1085 pending
+= released
;
1089 ::ReleaseSemaphore (sem_wait
, released
, NULL
);
1093 * And let the threads release.
1099 pthread_cond::wait (pthread_mutex_t mutex
, DWORD dwMilliseconds
)
1104 if (InterlockedIncrement ((long *)&waiting
) == 1)
1106 else if (mtx_cond
!= mutex
)
1108 InterlockedDecrement ((long *)&waiting
);
1115 * Release the mutex and wait on semaphore
1120 rv
= cancelable_wait (sem_wait
, dwMilliseconds
, cw_no_cancel_self
, cw_sig_eintr
);
1124 if (rv
!= WAIT_OBJECT_0
)
1127 * It might happen that a signal is sent while the thread got canceled
1128 * or timed out. Try to take one.
1129 * If the thread gets one than a signal|broadcast is in progress.
1131 if (WaitForSingleObject (sem_wait
, 0) == WAIT_OBJECT_0
)
1133 * thread got cancelled ot timed out while a signalling is in progress.
1134 * Set wait result back to signaled
1139 InterlockedDecrement ((long *)&waiting
);
1141 if (rv
== WAIT_OBJECT_0
&& --pending
== 0)
1143 * All signaled threads are released,
1144 * new threads can enter Wait
1153 if (rv
== WAIT_CANCELED
)
1154 pthread::static_cancel_self ();
1155 else if (rv
== WAIT_SIGNALED
)
1156 /* SUSv3 states: If a signal is delivered to a thread waiting for a
1157 condition variable, upon return from the signal handler the thread
1158 resumes waiting for the condition variable as if it was not
1159 interrupted, or it shall return zero due to spurious wakeup.
1160 We opt for the latter choice here. */
1162 else if (rv
== WAIT_TIMEOUT
)
1169 pthread_cond::_fixup_after_fork ()
1171 waiting
= pending
= 0;
1174 /* Unlock eventually locked mutexes */
1178 sem_wait
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1180 api_fatal ("pthread_cond::_fixup_after_fork () failed to recreate win32 semaphore");
1183 pthread_rwlockattr::pthread_rwlockattr ():verifyable_object
1184 (PTHREAD_RWLOCKATTR_MAGIC
), shared (PTHREAD_PROCESS_PRIVATE
)
1188 pthread_rwlockattr::~pthread_rwlockattr ()
1192 List
<pthread_rwlock
> pthread_rwlock::rwlocks
;
1194 /* This is used for rwlock creation protection within a single process only */
1195 fast_mutex NO_COPY
pthread_rwlock::rwlock_initialization_lock
;
1197 /* We can only be called once.
1198 TODO: (no rush) use a non copied memory section to
1199 hold an initialization flag. */
1201 pthread_rwlock::init_mutex ()
1203 if (!rwlock_initialization_lock
.init ())
1204 api_fatal ("Could not create win32 Mutex for pthread rwlock static initializer support.");
1207 pthread_rwlock::pthread_rwlock (pthread_rwlockattr
*attr
) :
1208 verifyable_object (PTHREAD_RWLOCK_MAGIC
),
1209 shared (0), waiting_readers (0), waiting_writers (0), writer (NULL
),
1210 readers (NULL
), readers_mx (), mtx (NULL
), cond_readers (NULL
), cond_writers (NULL
),
1213 pthread_mutex
*verifyable_mutex_obj
= &mtx
;
1214 pthread_cond
*verifyable_cond_obj
;
1216 if (!readers_mx
.init ())
1218 thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this);
1224 if (attr
->shared
!= PTHREAD_PROCESS_PRIVATE
)
1230 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj
))
1232 thread_printf ("Internal rwlock mutex is not valid. this %p", this);
1236 /* Change the mutex type to NORMAL to speed up mutex operations */
1237 mtx
.type
= PTHREAD_MUTEX_NORMAL
;
1239 verifyable_cond_obj
= &cond_readers
;
1240 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1242 thread_printf ("Internal rwlock readers cond is not valid. this %p", this);
1247 verifyable_cond_obj
= &cond_writers
;
1248 if (!pthread_cond::is_good_object (&verifyable_cond_obj
))
1250 thread_printf ("Internal rwlock writers cond is not valid. this %p", this);
1256 rwlocks
.insert (this);
1259 pthread_rwlock::~pthread_rwlock ()
1261 rwlocks
.remove (this);
1265 pthread_rwlock::rdlock ()
1268 struct RWLOCK_READER
*reader
;
1269 pthread_t self
= pthread::self ();
1273 if (lookup_reader (self
))
1279 reader
= new struct RWLOCK_READER
;
1286 while (writer
|| waiting_writers
)
1288 pthread_cleanup_push (pthread_rwlock::rdlock_cleanup
, this);
1291 cond_readers
.wait (&mtx
);
1294 pthread_cleanup_pop (0);
1297 reader
->thread
= self
;
1298 add_reader (reader
);
1307 pthread_rwlock::tryrdlock ()
1310 pthread_t self
= pthread::self ();
1314 if (writer
|| waiting_writers
|| lookup_reader (self
))
1318 struct RWLOCK_READER
*reader
= new struct RWLOCK_READER
;
1321 reader
->thread
= self
;
1322 add_reader (reader
);
1334 pthread_rwlock::wrlock ()
1337 pthread_t self
= pthread::self ();
1341 if (writer
== self
|| lookup_reader (self
))
1347 while (writer
|| readers
)
1349 pthread_cleanup_push (pthread_rwlock::wrlock_cleanup
, this);
1352 cond_writers
.wait (&mtx
);
1355 pthread_cleanup_pop (0);
1367 pthread_rwlock::trywrlock ()
1370 pthread_t self
= pthread::self ();
1374 if (writer
|| readers
)
1385 pthread_rwlock::unlock ()
1388 pthread_t self
= pthread::self ();
1404 struct RWLOCK_READER
*reader
= lookup_reader (self
);
1412 remove_reader (reader
);
1425 pthread_rwlock::add_reader (struct RWLOCK_READER
*rd
)
1427 List_insert (readers
, rd
);
1431 pthread_rwlock::remove_reader (struct RWLOCK_READER
*rd
)
1433 List_remove (readers_mx
, readers
, rd
);
1436 struct pthread_rwlock::RWLOCK_READER
*
1437 pthread_rwlock::lookup_reader (pthread_t thread
)
1441 struct RWLOCK_READER
*cur
= readers
;
1443 while (cur
&& cur
->thread
!= thread
)
1446 readers_mx
.unlock ();
1452 pthread_rwlock::rdlock_cleanup (void *arg
)
1454 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1456 --(rwlock
->waiting_readers
);
1458 rwlock
->mtx
.unlock ();
1462 pthread_rwlock::wrlock_cleanup (void *arg
)
1464 pthread_rwlock
*rwlock
= (pthread_rwlock
*) arg
;
1466 --(rwlock
->waiting_writers
);
1468 rwlock
->mtx
.unlock ();
1472 pthread_rwlock::_fixup_after_fork ()
1474 pthread_t self
= pthread::self ();
1475 struct RWLOCK_READER
**temp
= &readers
;
1477 waiting_readers
= 0;
1478 waiting_writers
= 0;
1480 if (!readers_mx
.init ())
1481 api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex");
1483 /* Unlock eventually locked mutex */
1486 * Remove all readers except self
1490 if ((*temp
)->thread
== self
)
1491 temp
= &((*temp
)->next
);
1494 struct RWLOCK_READER
*cur
= *temp
;
1495 *temp
= (*temp
)->next
;
1502 /* static members */
1503 /* This stores pthread_key information across fork() boundaries */
1504 List
<pthread_key
> pthread_key::keys
;
1506 /* non-static members */
1508 pthread_key::pthread_key (void (*aDestructor
) (void *)):verifyable_object (PTHREAD_KEY_MAGIC
), destructor (aDestructor
)
1510 tls_index
= TlsAlloc ();
1511 if (tls_index
== TLS_OUT_OF_INDEXES
)
1517 pthread_key::~pthread_key ()
1519 /* We may need to make the list code lock the list during operations
1524 TlsFree (tls_index
);
1529 pthread_key::_fixup_before_fork ()
1535 pthread_key::_fixup_after_fork ()
1537 tls_index
= TlsAlloc ();
1538 if (tls_index
== TLS_OUT_OF_INDEXES
)
1539 api_fatal ("pthread_key::recreate_key_from_buffer () failed to reallocate Tls storage");
1544 pthread_key::run_destructor ()
1548 void *oldValue
= get ();
1552 destructor (oldValue
);
1559 REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
1560 gymnastics can be a lot easier.
1562 the mutex_t (size 4) is not used as a verifyable object because we cannot
1563 guarantee the same address space for all processes.
1564 we use the following:
1565 high bit set (never a valid address).
1566 second byte is reserved for the priority.
1567 third byte is reserved
1568 fourth byte is the mutex id. (max 255 cygwin mutexs system wide).
1569 creating mutex's does get slower and slower, but as creation is a one time
1570 job, it should never become an issue
1572 And if you're looking at this and thinking, why not an array in cygwin for all mutexs,
1573 - you incur a penalty on _every_ mutex call and you have toserialise them all.
1576 option 2? put everything in userspace and update the ABI?
1577 - bad karma as well - the HANDLE, while identical across process's,
1578 Isn't duplicated, it's reopened. */
1580 /* static members */
1582 List
<pthread_mutex
> pthread_mutex::mutexes
;
1584 /* This is used for mutex creation protection within a single process only */
1585 fast_mutex NO_COPY
pthread_mutex::mutex_initialization_lock
;
1587 /* We can only be called once.
1588 TODO: (no rush) use a non copied memory section to
1589 hold an initialization flag. */
1591 pthread_mutex::init_mutex ()
1593 if (!mutex_initialization_lock
.init ())
1594 api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support.");
1597 pthread_mutex::pthread_mutex (pthread_mutexattr
*attr
) :
1598 verifyable_object (PTHREAD_MUTEX_MAGIC
),
1600 win32_obj_id (NULL
), recursion_counter (0),
1601 condwaits (0), owner (NULL
), type (PTHREAD_MUTEX_ERRORCHECK
),
1602 pshared (PTHREAD_PROCESS_PRIVATE
)
1604 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1610 /*attr checked in the C call */
1613 if (attr
->pshared
== PTHREAD_PROCESS_SHARED
)
1620 type
= attr
->mutextype
;
1623 mutexes
.insert (this);
1626 pthread_mutex::~pthread_mutex ()
1629 CloseHandle (win32_obj_id
);
1631 mutexes
.remove (this);
1635 pthread_mutex::_lock (pthread_t self
)
1639 if (InterlockedIncrement ((long *)&lock_counter
) == 1)
1641 else if (type
== PTHREAD_MUTEX_NORMAL
|| !pthread::equal (owner
, self
))
1643 cancelable_wait (win32_obj_id
, INFINITE
, cw_no_cancel
, cw_sig_resume
);
1648 InterlockedDecrement ((long *) &lock_counter
);
1649 if (type
== PTHREAD_MUTEX_RECURSIVE
)
1650 result
= lock_recursive ();
1659 pthread_mutex::_trylock (pthread_t self
)
1663 if (InterlockedCompareExchange ((long *) &lock_counter
, 1, 0) == 0)
1665 else if (type
== PTHREAD_MUTEX_RECURSIVE
&& pthread::equal (owner
, self
))
1666 result
= lock_recursive ();
1674 pthread_mutex::_unlock (pthread_t self
)
1676 if (!pthread::equal (owner
, self
))
1679 if (--recursion_counter
== 0)
1682 if (InterlockedDecrement ((long *)&lock_counter
))
1683 // Another thread is waiting
1684 ::ReleaseSemaphore (win32_obj_id
, 1, NULL
);
1691 pthread_mutex::_destroy (pthread_t self
)
1693 if (condwaits
|| _trylock (self
))
1694 // Do not destroy a condwaited or locked mutex
1696 else if (recursion_counter
!= 1)
1698 // Do not destroy a recursive locked mutex
1699 --recursion_counter
;
1708 pthread_mutex::_fixup_after_fork ()
1710 debug_printf ("mutex %x in _fixup_after_fork", this);
1711 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1712 api_fatal ("pthread_mutex::_fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's");
1715 /* mutex has no owner, reset to initial */
1717 else if (lock_counter
!= 0)
1718 /* All waiting threads are gone after a fork */
1721 win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, 0, LONG_MAX
, NULL
);
1723 api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 semaphore for mutex");
1728 pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC
),
1729 pshared (PTHREAD_PROCESS_PRIVATE
), mutextype (PTHREAD_MUTEX_ERRORCHECK
)
1733 pthread_mutexattr::~pthread_mutexattr ()
1737 List
<semaphore
> semaphore::semaphores
;
1739 semaphore::semaphore (int pshared
, unsigned int value
)
1740 : verifyable_object (SEM_MAGIC
),
1742 currentvalue (value
),
1745 SECURITY_ATTRIBUTES sa
= (pshared
!= PTHREAD_PROCESS_PRIVATE
)
1746 ? sec_all
: sec_none_nih
;
1747 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, NULL
);
1748 if (!this->win32_obj_id
)
1751 semaphores
.insert (this);
1754 semaphore::semaphore (const char *sem_name
, int oflag
, mode_t mode
,
1756 : verifyable_object (SEM_MAGIC
),
1757 shared (PTHREAD_PROCESS_SHARED
),
1758 currentvalue (value
), /* Unused for named semaphores. */
1761 if (oflag
& O_CREAT
)
1763 SECURITY_ATTRIBUTES sa
= sec_all
;
1764 security_descriptor sd
;
1766 set_security_attribute (mode
, &sa
, sd
);
1767 this->win32_obj_id
= ::CreateSemaphore (&sa
, value
, LONG_MAX
, sem_name
);
1768 if (!this->win32_obj_id
)
1770 if (GetLastError () == ERROR_ALREADY_EXISTS
&& (oflag
& O_EXCL
))
1773 CloseHandle (this->win32_obj_id
);
1779 this->win32_obj_id
= ::OpenSemaphore (SEMAPHORE_ALL_ACCESS
, FALSE
,
1781 if (!this->win32_obj_id
)
1789 name
= new char [strlen (sem_name
+ 1)];
1793 CloseHandle (this->win32_obj_id
);
1797 strcpy (name
, sem_name
);
1800 semaphores
.insert (this);
1803 semaphore::~semaphore ()
1806 CloseHandle (win32_obj_id
);
1810 semaphores
.remove (this);
1816 if (ReleaseSemaphore (win32_obj_id
, 1, ¤tvalue
))
1821 semaphore::_getvalue (int *sval
)
1825 switch (WaitForSingleObject (win32_obj_id
, 0))
1828 ReleaseSemaphore (win32_obj_id
, 1, &val
);
1842 semaphore::_trywait ()
1844 /* FIXME: signals should be able to interrupt semaphores...
1845 We probably need WaitForMultipleObjects here. */
1846 if (WaitForSingleObject (win32_obj_id
, 0) == WAIT_TIMEOUT
)
1856 semaphore::_timedwait (const struct timespec
*abstime
)
1862 if (efault
.faulted ())
1864 /* According to SUSv3, abstime need not be checked for validity,
1865 if the semaphore can be locked immediately. */
1872 gettimeofday (&tv
, NULL
);
1873 waitlength
= abstime
->tv_sec
* 1000 + abstime
->tv_nsec
/ (1000 * 1000);
1874 waitlength
-= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
1877 switch (cancelable_wait (win32_obj_id
, waitlength
, cw_cancel_self
, cw_sig_eintr
))
1886 set_errno (ETIMEDOUT
);
1889 debug_printf ("cancelable_wait failed. %E");
1899 switch (cancelable_wait (win32_obj_id
, INFINITE
, cw_cancel_self
, cw_sig_eintr
))
1908 debug_printf ("cancelable_wait failed. %E");
1915 semaphore::_fixup_after_fork ()
1917 if (shared
== PTHREAD_PROCESS_PRIVATE
)
1919 debug_printf ("sem %x in _fixup_after_fork", this);
1920 /* FIXME: duplicate code here and in the constructor. */
1921 this->win32_obj_id
= ::CreateSemaphore (&sec_none_nih
, currentvalue
,
1924 api_fatal ("failed to create new win32 semaphore, error %d");
1928 verifyable_object::verifyable_object (long verifyer
):
1933 verifyable_object::~verifyable_object ()
1939 pthread::thread_init_wrapper (void *arg
)
1941 pthread
*thread
= (pthread
*) arg
;
1942 set_tls_self_pointer (thread
);
1944 thread
->mutex
.lock ();
1946 // if thread is detached force cleanup on exit
1947 if (thread
->attr
.joinable
== PTHREAD_CREATE_DETACHED
&& thread
->joiner
== NULL
)
1948 thread
->joiner
= thread
;
1949 thread
->mutex
.unlock ();
1951 thread_printf ("started thread %p %p %p %p %p %p", arg
, &_my_tls
.local_clib
,
1952 _impure_ptr
, thread
, thread
->function
, thread
->arg
);
1954 // call the user's thread
1955 void *ret
= thread
->function (thread
->arg
);
1959 return 0; // just for show. Never returns.
1963 pthread::getsequence_np ()
1965 return get_thread_id ();
1969 pthread::create (pthread_t
*thread
, const pthread_attr_t
*attr
,
1970 void *(*start_routine
) (void *), void *arg
)
1972 if (attr
&& !pthread_attr::is_good_object (attr
))
1975 *thread
= new pthread ();
1976 if (!(*thread
)->create (start_routine
, attr
? *attr
: NULL
, arg
))
1987 pthread::once (pthread_once_t
*once_control
, void (*init_routine
) (void))
1990 if (once_control
->state
)
1993 pthread_mutex_lock (&once_control
->mutex
);
1994 /* Here we must set a cancellation handler to unlock the mutex if needed */
1995 /* but a cancellation handler is not the right thing. We need this in the thread
1996 *cleanup routine. Assumption: a thread can only be in one pthread_once routine
1997 *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
1998 *on pthread_exit ();
2000 if (!once_control
->state
)
2003 once_control
->state
= 1;
2005 /* Here we must remove our cancellation handler */
2006 pthread_mutex_unlock (&once_control
->mutex
);
2011 pthread::cancel (pthread_t thread
)
2013 if (!is_good_object (&thread
))
2016 return thread
->cancel ();
2020 pthread::atforkprepare ()
2022 callback
*cb
= MT_INTERFACE
->pthread_prepare
;
2031 MT_INTERFACE
->fixup_before_fork ();
2035 pthread::atforkparent ()
2039 callback
*cb
= MT_INTERFACE
->pthread_parent
;
2048 pthread::atforkchild ()
2050 MT_INTERFACE
->fixup_after_fork ();
2054 callback
*cb
= MT_INTERFACE
->pthread_child
;
2062 /* Register a set of functions to run before and after fork.
2063 prepare calls are called in LI-FC order.
2064 parent and child calls are called in FI-FC order. */
2066 pthread::atfork (void (*prepare
)(void), void (*parent
)(void), void (*child
)(void))
2068 callback
*prepcb
= NULL
, *parentcb
= NULL
, *childcb
= NULL
;
2071 prepcb
= new callback
;
2077 parentcb
= new callback
;
2087 childcb
= new callback
;
2100 prepcb
->cb
= prepare
;
2101 List_insert (MT_INTERFACE
->pthread_prepare
, prepcb
);
2105 parentcb
->cb
= parent
;
2106 callback
**t
= &MT_INTERFACE
->pthread_parent
;
2109 /* t = pointer to last next in the list */
2110 List_insert (*t
, parentcb
);
2114 childcb
->cb
= child
;
2115 callback
**t
= &MT_INTERFACE
->pthread_child
;
2118 /* t = pointer to last next in the list */
2119 List_insert (*t
, childcb
);
2125 pthread_attr_init (pthread_attr_t
*attr
)
2127 if (pthread_attr::is_good_object (attr
))
2130 *attr
= new pthread_attr
;
2131 if (!pthread_attr::is_good_object (attr
))
2141 pthread_attr_getinheritsched (const pthread_attr_t
*attr
,
2144 if (!pthread_attr::is_good_object (attr
))
2146 *inheritsched
= (*attr
)->inheritsched
;
2151 pthread_attr_getschedparam (const pthread_attr_t
*attr
,
2152 struct sched_param
*param
)
2154 if (!pthread_attr::is_good_object (attr
))
2156 *param
= (*attr
)->schedparam
;
2160 /* From a pure code point of view, this should call a helper in sched.cc,
2161 to allow for someone adding scheduler policy changes to win32 in the future.
2162 However that's extremely unlikely, so short and sweet will do us */
2164 pthread_attr_getschedpolicy (const pthread_attr_t
*attr
, int *policy
)
2166 if (!pthread_attr::is_good_object (attr
))
2168 *policy
= SCHED_FIFO
;
2174 pthread_attr_getscope (const pthread_attr_t
*attr
, int *contentionscope
)
2176 if (!pthread_attr::is_good_object (attr
))
2178 *contentionscope
= (*attr
)->contentionscope
;
2183 pthread_attr_setdetachstate (pthread_attr_t
*attr
, int detachstate
)
2185 if (!pthread_attr::is_good_object (attr
))
2187 if (detachstate
< 0 || detachstate
> 1)
2189 (*attr
)->joinable
= detachstate
;
2194 pthread_attr_getdetachstate (const pthread_attr_t
*attr
, int *detachstate
)
2196 if (!pthread_attr::is_good_object (attr
))
2198 *detachstate
= (*attr
)->joinable
;
2203 pthread_attr_setinheritsched (pthread_attr_t
*attr
, int inheritsched
)
2205 if (!pthread_attr::is_good_object (attr
))
2207 if (inheritsched
!= PTHREAD_INHERIT_SCHED
2208 && inheritsched
!= PTHREAD_EXPLICIT_SCHED
)
2210 (*attr
)->inheritsched
= inheritsched
;
2215 pthread_attr_setschedparam (pthread_attr_t
*attr
,
2216 const struct sched_param
*param
)
2218 if (!pthread_attr::is_good_object (attr
))
2220 if (!valid_sched_parameters (param
))
2222 (*attr
)->schedparam
= *param
;
2226 /* See __pthread_attr_getschedpolicy for some notes */
2228 pthread_attr_setschedpolicy (pthread_attr_t
*attr
, int policy
)
2230 if (!pthread_attr::is_good_object (attr
))
2232 if (policy
!= SCHED_FIFO
)
2238 pthread_attr_setscope (pthread_attr_t
*attr
, int contentionscope
)
2240 if (!pthread_attr::is_good_object (attr
))
2242 if (contentionscope
!= PTHREAD_SCOPE_SYSTEM
2243 && contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2245 /* In future, we may be able to support system scope by escalating the thread
2246 priority to exceed the priority class. For now we only support PROCESS scope. */
2247 if (contentionscope
!= PTHREAD_SCOPE_PROCESS
)
2249 (*attr
)->contentionscope
= contentionscope
;
2254 pthread_attr_setstacksize (pthread_attr_t
*attr
, size_t size
)
2256 if (!pthread_attr::is_good_object (attr
))
2258 (*attr
)->stacksize
= size
;
2263 pthread_attr_getstacksize (const pthread_attr_t
*attr
, size_t *size
)
2265 if (!pthread_attr::is_good_object (attr
))
2267 *size
= (*attr
)->stacksize
;
2272 pthread_attr_destroy (pthread_attr_t
*attr
)
2274 if (!pthread_attr::is_good_object (attr
))
2282 pthread::join (pthread_t
*thread
, void **return_val
)
2284 pthread_t joiner
= self ();
2286 joiner
->testcancel ();
2288 // Initialize return val with NULL
2292 if (!is_good_object (&joiner
))
2295 if (!is_good_object (thread
))
2298 if (equal (*thread
,joiner
))
2301 (*thread
)->mutex
.lock ();
2303 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2305 (*thread
)->mutex
.unlock ();
2310 (*thread
)->joiner
= joiner
;
2311 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2312 (*thread
)->mutex
.unlock ();
2314 switch (cancelable_wait ((*thread
)->win32_obj_id
, INFINITE
, cw_no_cancel_self
, cw_sig_resume
))
2318 *return_val
= (*thread
)->return_ptr
;
2322 // set joined thread back to joinable since we got canceled
2323 (*thread
)->joiner
= NULL
;
2324 (*thread
)->attr
.joinable
= PTHREAD_CREATE_JOINABLE
;
2325 joiner
->cancel_self ();
2329 // should never happen
2338 pthread::detach (pthread_t
*thread
)
2340 if (!is_good_object (thread
))
2343 (*thread
)->mutex
.lock ();
2344 if ((*thread
)->attr
.joinable
== PTHREAD_CREATE_DETACHED
)
2346 (*thread
)->mutex
.unlock ();
2350 // check if thread is still alive
2351 if ((*thread
)->valid
&& WaitForSingleObject ((*thread
)->win32_obj_id
, 0) == WAIT_TIMEOUT
)
2353 // force cleanup on exit
2354 (*thread
)->joiner
= *thread
;
2355 (*thread
)->attr
.joinable
= PTHREAD_CREATE_DETACHED
;
2356 (*thread
)->mutex
.unlock ();
2360 // thread has already terminated.
2361 (*thread
)->mutex
.unlock ();
2369 pthread::suspend (pthread_t
*thread
)
2371 if (!is_good_object (thread
))
2374 if ((*thread
)->suspended
== false)
2376 (*thread
)->suspended
= true;
2377 SuspendThread ((*thread
)->win32_obj_id
);
2385 pthread::resume (pthread_t
*thread
)
2387 if (!is_good_object (thread
))
2390 if ((*thread
)->suspended
== true)
2391 ResumeThread ((*thread
)->win32_obj_id
);
2392 (*thread
)->suspended
= false;
2397 /* provided for source level compatability.
2398 See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2401 pthread_getconcurrency ()
2403 return MT_INTERFACE
->concurrency
;
2406 /* keep this in sync with sched.cc */
2408 pthread_getschedparam (pthread_t thread
, int *policy
,
2409 struct sched_param
*param
)
2411 if (!pthread::is_good_object (&thread
))
2413 *policy
= SCHED_FIFO
;
2414 /* we don't return the current effective priority, we return the current
2415 requested priority */
2416 *param
= thread
->attr
.schedparam
;
2420 /* Thread Specific Data */
2422 pthread_key_create (pthread_key_t
*key
, void (*destructor
) (void *))
2424 /* The opengroup docs don't define if we should check this or not,
2425 but creation is relatively rare. */
2426 if (pthread_key::is_good_object (key
))
2429 *key
= new pthread_key (destructor
);
2431 if (!pthread_key::is_good_object (key
))
2441 pthread_key_delete (pthread_key_t key
)
2443 if (!pthread_key::is_good_object (&key
))
2450 /* provided for source level compatability. See
2451 http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2454 pthread_setconcurrency (int new_level
)
2458 MT_INTERFACE
->concurrency
= new_level
;
2462 /* keep syncronised with sched.cc */
2464 pthread_setschedparam (pthread_t thread
, int policy
,
2465 const struct sched_param
*param
)
2467 if (!pthread::is_good_object (&thread
))
2469 if (policy
!= SCHED_FIFO
)
2474 sched_set_thread_priority (thread
->win32_obj_id
, param
->sched_priority
);
2476 thread
->attr
.schedparam
.sched_priority
= param
->sched_priority
;
2482 pthread_setspecific (pthread_key_t key
, const void *value
)
2484 if (!pthread_key::is_good_object (&key
))
2491 pthread_getspecific (pthread_key_t key
)
2493 if (!pthread_key::is_good_object (&key
))
2496 return (key
)->get ();
2501 pthread_cond_destroy (pthread_cond_t
*cond
)
2503 if (pthread_cond::is_good_initializer (cond
))
2505 if (!pthread_cond::is_good_object (cond
))
2508 /* reads are atomic */
2509 if ((*cond
)->waiting
)
2519 pthread_cond::init (pthread_cond_t
*cond
, const pthread_condattr_t
*attr
)
2521 pthread_cond_t new_cond
;
2523 if (attr
&& !pthread_condattr::is_good_object (attr
))
2526 cond_initialization_lock
.lock ();
2528 new_cond
= new pthread_cond (attr
? (*attr
) : NULL
);
2529 if (!is_good_object (&new_cond
))
2532 cond_initialization_lock
.unlock ();
2537 if (efault
.faulted ())
2540 cond_initialization_lock
.unlock ();
2545 cond_initialization_lock
.unlock ();
2551 pthread_cond_broadcast (pthread_cond_t
*cond
)
2553 if (pthread_cond::is_good_initializer (cond
))
2555 if (!pthread_cond::is_good_object (cond
))
2558 (*cond
)->unblock (true);
2564 pthread_cond_signal (pthread_cond_t
*cond
)
2566 if (pthread_cond::is_good_initializer (cond
))
2568 if (!pthread_cond::is_good_object (cond
))
2571 (*cond
)->unblock (false);
2577 __pthread_cond_dowait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2580 if (!pthread_mutex::is_good_object (mutex
))
2582 if (!pthread_mutex::can_be_unlocked (mutex
))
2585 if (pthread_cond::is_good_initializer (cond
))
2586 pthread_cond::init (cond
, NULL
);
2587 if (!pthread_cond::is_good_object (cond
))
2590 return (*cond
)->wait (*mutex
, waitlength
);
2594 pthread_cond_timedwait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
2595 const struct timespec
*abstime
)
2601 if (efault
.faulted ())
2604 pthread_testcancel ();
2606 /* According to SUSv3, the abstime value must be checked for validity. */
2607 if (abstime
->tv_sec
< 0
2608 || abstime
->tv_nsec
< 0
2609 || abstime
->tv_nsec
> 999999999)
2612 gettimeofday (&tv
, NULL
);
2613 /* Check for immediate timeout before converting to microseconds, since
2614 the resulting value can easily overflow long. This also allows to
2615 evaluate microseconds directly in DWORD. */
2616 if (tv
.tv_sec
> abstime
->tv_sec
2617 || (tv
.tv_sec
== abstime
->tv_sec
2618 && tv
.tv_usec
> abstime
->tv_nsec
/ 1000))
2621 waitlength
= (abstime
->tv_sec
- tv
.tv_sec
) * 1000;
2622 waitlength
+= (abstime
->tv_nsec
/ 1000 - tv
.tv_usec
) / 1000;
2623 return __pthread_cond_dowait (cond
, mutex
, waitlength
);
2627 pthread_cond_wait (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
2629 pthread_testcancel ();
2631 return __pthread_cond_dowait (cond
, mutex
, INFINITE
);
2635 pthread_condattr_init (pthread_condattr_t
*condattr
)
2637 if (pthread_condattr::is_good_object (condattr
))
2640 *condattr
= new pthread_condattr
;
2641 if (!pthread_condattr::is_good_object (condattr
))
2651 pthread_condattr_getpshared (const pthread_condattr_t
*attr
, int *pshared
)
2653 if (!pthread_condattr::is_good_object (attr
))
2655 *pshared
= (*attr
)->shared
;
2660 pthread_condattr_setpshared (pthread_condattr_t
*attr
, int pshared
)
2662 if (!pthread_condattr::is_good_object (attr
))
2664 if ((pshared
< 0) || (pshared
> 1))
2666 /* shared cond vars not currently supported */
2667 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2669 (*attr
)->shared
= pshared
;
2674 pthread_condattr_destroy (pthread_condattr_t
*condattr
)
2676 if (!pthread_condattr::is_good_object (condattr
))
2684 pthread_rwlock_destroy (pthread_rwlock_t
*rwlock
)
2686 if (pthread_rwlock::is_good_initializer (rwlock
))
2688 if (!pthread_rwlock::is_good_object (rwlock
))
2691 if ((*rwlock
)->writer
|| (*rwlock
)->readers
||
2692 (*rwlock
)->waiting_readers
|| (*rwlock
)->waiting_writers
)
2702 pthread_rwlock::init (pthread_rwlock_t
*rwlock
, const pthread_rwlockattr_t
*attr
)
2704 pthread_rwlock_t new_rwlock
;
2706 if (attr
&& !pthread_rwlockattr::is_good_object (attr
))
2709 rwlock_initialization_lock
.lock ();
2711 new_rwlock
= new pthread_rwlock (attr
? (*attr
) : NULL
);
2712 if (!is_good_object (&new_rwlock
))
2715 rwlock_initialization_lock
.unlock ();
2720 if (efault
.faulted ())
2723 rwlock_initialization_lock
.unlock ();
2727 *rwlock
= new_rwlock
;
2728 rwlock_initialization_lock
.unlock ();
2734 pthread_rwlock_rdlock (pthread_rwlock_t
*rwlock
)
2736 pthread_testcancel ();
2738 if (pthread_rwlock::is_good_initializer (rwlock
))
2739 pthread_rwlock::init (rwlock
, NULL
);
2740 if (!pthread_rwlock::is_good_object (rwlock
))
2743 return (*rwlock
)->rdlock ();
2747 pthread_rwlock_tryrdlock (pthread_rwlock_t
*rwlock
)
2749 if (pthread_rwlock::is_good_initializer (rwlock
))
2750 pthread_rwlock::init (rwlock
, NULL
);
2751 if (!pthread_rwlock::is_good_object (rwlock
))
2754 return (*rwlock
)->tryrdlock ();
2758 pthread_rwlock_wrlock (pthread_rwlock_t
*rwlock
)
2760 pthread_testcancel ();
2762 if (pthread_rwlock::is_good_initializer (rwlock
))
2763 pthread_rwlock::init (rwlock
, NULL
);
2764 if (!pthread_rwlock::is_good_object (rwlock
))
2767 return (*rwlock
)->wrlock ();
2771 pthread_rwlock_trywrlock (pthread_rwlock_t
*rwlock
)
2773 if (pthread_rwlock::is_good_initializer (rwlock
))
2774 pthread_rwlock::init (rwlock
, NULL
);
2775 if (!pthread_rwlock::is_good_object (rwlock
))
2778 return (*rwlock
)->trywrlock ();
2782 pthread_rwlock_unlock (pthread_rwlock_t
*rwlock
)
2784 if (pthread_rwlock::is_good_initializer (rwlock
))
2786 if (!pthread_rwlock::is_good_object (rwlock
))
2789 return (*rwlock
)->unlock ();
2793 pthread_rwlockattr_init (pthread_rwlockattr_t
*rwlockattr
)
2795 if (pthread_rwlockattr::is_good_object (rwlockattr
))
2798 *rwlockattr
= new pthread_rwlockattr
;
2799 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2801 delete (*rwlockattr
);
2809 pthread_rwlockattr_getpshared (const pthread_rwlockattr_t
*attr
, int *pshared
)
2811 if (!pthread_rwlockattr::is_good_object (attr
))
2813 *pshared
= (*attr
)->shared
;
2818 pthread_rwlockattr_setpshared (pthread_rwlockattr_t
*attr
, int pshared
)
2820 if (!pthread_rwlockattr::is_good_object (attr
))
2822 if ((pshared
< 0) || (pshared
> 1))
2824 /* shared rwlock vars not currently supported */
2825 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
2827 (*attr
)->shared
= pshared
;
2832 pthread_rwlockattr_destroy (pthread_rwlockattr_t
*rwlockattr
)
2834 if (!pthread_rwlockattr::is_good_object (rwlockattr
))
2836 delete (*rwlockattr
);
2843 pthread_kill (pthread_t thread
, int sig
)
2845 // lock myself, for the use of thread2signal
2846 // two different kills might clash: FIXME
2848 if (!pthread::is_good_object (&thread
))
2853 si
.si_code
= SI_USER
;
2854 si
.si_pid
= myself
->pid
;
2855 si
.si_uid
= myself
->uid
;
2856 thread
->cygtls
->set_threadkill ();
2857 int rval
= sig
? sig_send (NULL
, si
, thread
->cygtls
) : 0;
2864 pthread_sigmask (int operation
, const sigset_t
*set
, sigset_t
*old_set
)
2866 return handle_sigprocmask (operation
, set
, old_set
, _my_tls
.sigmask
);
2872 pthread_equal (pthread_t t1
, pthread_t t2
)
2874 return pthread::equal (t1
, t2
);
2880 pthread_mutex::init (pthread_mutex_t
*mutex
,
2881 const pthread_mutexattr_t
*attr
,
2882 const pthread_mutex_t initializer
)
2884 pthread_mutex_t new_mutex
;
2886 if (attr
&& !pthread_mutexattr::is_good_object (attr
))
2889 mutex_initialization_lock
.lock ();
2891 new_mutex
= new pthread_mutex (attr
? (*attr
) : NULL
);
2892 if (!is_good_object (&new_mutex
))
2895 mutex_initialization_lock
.unlock ();
2899 if (!attr
&& initializer
)
2901 if (initializer
== PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
)
2902 new_mutex
->type
= PTHREAD_MUTEX_RECURSIVE
;
2903 else if (initializer
== PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
)
2904 new_mutex
->type
= PTHREAD_MUTEX_NORMAL
;
2905 else if (initializer
== PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
)
2906 new_mutex
->type
= PTHREAD_MUTEX_ERRORCHECK
;
2910 if (efault
.faulted ())
2913 mutex_initialization_lock
.unlock ();
2918 mutex_initialization_lock
.unlock ();
2924 pthread_mutex_getprioceiling (const pthread_mutex_t
*mutex
,
2927 /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
2930 We can support mutex priorities in the future though:
2931 Store a priority with each mutex.
2932 When the mutex is optained, set the thread priority as appropriate
2933 When the mutex is released, reset the thread priority. */
2938 pthread_mutex_lock (pthread_mutex_t
*mutex
)
2940 if (pthread_mutex::is_good_initializer (mutex
))
2941 pthread_mutex::init (mutex
, NULL
, *mutex
);
2942 if (!pthread_mutex::is_good_object (mutex
))
2944 return (*mutex
)->lock ();
2948 pthread_mutex_trylock (pthread_mutex_t
*mutex
)
2950 if (pthread_mutex::is_good_initializer (mutex
))
2951 pthread_mutex::init (mutex
, NULL
, *mutex
);
2952 if (!pthread_mutex::is_good_object (mutex
))
2954 return (*mutex
)->trylock ();
2958 pthread_mutex_unlock (pthread_mutex_t
*mutex
)
2960 if (pthread_mutex::is_good_initializer (mutex
))
2962 if (!pthread_mutex::is_good_object (mutex
))
2964 return (*mutex
)->unlock ();
2968 pthread_mutex_destroy (pthread_mutex_t
*mutex
)
2972 if (pthread_mutex::is_good_initializer (mutex
))
2974 if (!pthread_mutex::is_good_object (mutex
))
2977 rv
= (*mutex
)->destroy ();
2986 pthread_mutex_setprioceiling (pthread_mutex_t
*mutex
, int prioceiling
,
2992 /* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
2995 pthread_mutexattr_getprotocol (const pthread_mutexattr_t
*attr
,
2998 if (!pthread_mutexattr::is_good_object (attr
))
3004 pthread_mutexattr_getpshared (const pthread_mutexattr_t
*attr
,
3007 if (!pthread_mutexattr::is_good_object (attr
))
3009 *pshared
= (*attr
)->pshared
;
3014 pthread_mutexattr_gettype (const pthread_mutexattr_t
*attr
, int *type
)
3016 if (!pthread_mutexattr::is_good_object (attr
))
3018 *type
= (*attr
)->mutextype
;
3022 /* FIXME: write and test process shared mutex's. */
3024 pthread_mutexattr_init (pthread_mutexattr_t
*attr
)
3026 if (pthread_mutexattr::is_good_object (attr
))
3029 *attr
= new pthread_mutexattr ();
3030 if (!pthread_mutexattr::is_good_object (attr
))
3040 pthread_mutexattr_destroy (pthread_mutexattr_t
*attr
)
3042 if (!pthread_mutexattr::is_good_object (attr
))
3050 /* Win32 doesn't support mutex priorities */
3052 pthread_mutexattr_setprotocol (pthread_mutexattr_t
*attr
, int protocol
)
3054 if (!pthread_mutexattr::is_good_object (attr
))
3059 /* Win32 doesn't support mutex priorities */
3061 pthread_mutexattr_setprioceiling (pthread_mutexattr_t
*attr
,
3064 if (!pthread_mutexattr::is_good_object (attr
))
3070 pthread_mutexattr_getprioceiling (const pthread_mutexattr_t
*attr
,
3073 if (!pthread_mutexattr::is_good_object (attr
))
3079 pthread_mutexattr_setpshared (pthread_mutexattr_t
*attr
, int pshared
)
3081 if (!pthread_mutexattr::is_good_object (attr
))
3083 /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
3086 if (pshared
!= PTHREAD_PROCESS_PRIVATE
)
3088 (*attr
)->pshared
= pshared
;
3092 /* see pthread_mutex_gettype */
3094 pthread_mutexattr_settype (pthread_mutexattr_t
*attr
, int type
)
3096 if (!pthread_mutexattr::is_good_object (attr
))
3101 case PTHREAD_MUTEX_ERRORCHECK
:
3102 case PTHREAD_MUTEX_RECURSIVE
:
3103 case PTHREAD_MUTEX_NORMAL
:
3104 (*attr
)->mutextype
= type
;
3115 /* static members */
3118 semaphore::init (sem_t
*sem
, int pshared
, unsigned int value
)
3120 /* opengroup calls this undefined */
3121 if (is_good_object (sem
))
3124 if (value
> SEM_VALUE_MAX
)
3127 *sem
= new semaphore (pshared
, value
);
3129 if (!is_good_object (sem
))
3139 semaphore::destroy (sem_t
*sem
)
3141 if (!is_good_object (sem
))
3144 /* FIXME - new feature - test for busy against threads... */
3152 semaphore::open (const char *name
, int oflag
, mode_t mode
, unsigned int value
)
3154 if (value
> SEM_VALUE_MAX
)
3160 sem_t
*sem
= new sem_t
;
3167 *sem
= new semaphore (name
, oflag
, mode
, value
);
3169 if (!is_good_object (sem
))
3179 semaphore::wait (sem_t
*sem
)
3181 pthread_testcancel ();
3183 if (!is_good_object (sem
))
3189 return (*sem
)->_wait ();
3193 semaphore::trywait (sem_t
*sem
)
3195 if (!is_good_object (sem
))
3201 return (*sem
)->_trywait ();
3205 semaphore::timedwait (sem_t
*sem
, const struct timespec
*abstime
)
3207 if (!is_good_object (sem
))
3213 return (*sem
)->_timedwait (abstime
);
3217 semaphore::post (sem_t
*sem
)
3219 if (!is_good_object (sem
))
3230 semaphore::getvalue (sem_t
*sem
, int *sval
)
3233 if (efault
.faulted () || !is_good_object (sem
))
3239 return (*sem
)->_getvalue (sval
);
3244 pthread_null::get_null_pthread ()
3246 /* because of weird entry points */
3247 _instance
.magic
= 0;
3251 pthread_null::pthread_null ()
3253 attr
.joinable
= PTHREAD_CREATE_DETACHED
;
3254 /* Mark ourselves as invalid */
3258 pthread_null::~pthread_null ()
3263 pthread_null::create (void *(*)(void *), pthread_attr
*, void *)
3269 pthread_null::exit (void *value_ptr
)
3271 _my_tls
.remove (INFINITE
);
3276 pthread_null::cancel ()
3282 pthread_null::testcancel ()
3287 pthread_null::setcancelstate (int state
, int *oldstate
)
3293 pthread_null::setcanceltype (int type
, int *oldtype
)
3299 pthread_null::push_cleanup_handler (__pthread_cleanup_handler
*handler
)
3304 pthread_null::pop_cleanup_handler (int const execute
)
3309 pthread_null::getsequence_np ()
3314 pthread_null
pthread_null::_instance
;