]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/thread.cc
* cygpath.cc (do_pathconv): Fix erroneously printing native NT path
[newlib-cygwin.git] / winsup / cygwin / thread.cc
CommitLineData
7b80d68f 1/* thread.cc: Locking and threading module functions
1fd5e000 2
39fc0d36 3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3700578e 4 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
1fd5e000
CF
5
6This file is part of Cygwin.
7
8This software is a copyrighted work licensed under the terms of the
9Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10details. */
11
ff6e295e 12/* Implementation overview and caveats:
5c83f260 13
ff6e295e
CF
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
17 code.
5c83f260 18
ff6e295e
CF
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.
5c83f260 23
ff6e295e 24 R.Collins, April 2001. */
5c83f260 25
1fd5e000 26#ifdef HAVE_CONFIG_H
1fd5e000
CF
27#endif
28
1fd5e000 29#include "winsup.h"
ade47a34 30#include "miscfuncs.h"
e6fbf13e 31#include "path.h"
1fd5e000 32#include <stdlib.h>
e2ebe117 33#include "pinfo.h"
9a4d574b 34#include "sigproc.h"
f0338f54 35#include "perprocess.h"
9a4d574b 36#include "cygtls.h"
e6fbf13e
CV
37#include "fhandler.h"
38#include "dtable.h"
39#include "cygheap.h"
11a9a1cf
CF
40
41extern "C" void __fp_lock_all ();
42extern "C" void __fp_unlock_all ();
4c157aa9 43static inline verifyable_object_state
2b1407d3 44 verifyable_object_isvalid (void const * objectptr, thread_magic_t magic,
4c157aa9
CF
45 void *static_ptr1 = NULL,
46 void *static_ptr2 = NULL,
47 void *static_ptr3 = NULL);
1fd5e000
CF
48
49extern int threadsafe;
50
29d52c8a 51#undef __getreent
c433f461
CF
52extern "C" struct _reent *
53__getreent ()
1fd5e000 54{
29d52c8a 55 return &_my_tls.local_clib;
166b2571 56}
1fd5e000 57
11a9a1cf
CF
58extern "C" void
59__cygwin_lock_init (_LOCK_T *lock)
60{
61 *lock = _LOCK_T_INITIALIZER;
62}
63
64extern "C" void
65__cygwin_lock_init_recursive (_LOCK_T *lock)
66{
67 *lock = _LOCK_T_RECURSIVE_INITIALIZER;
68}
69
70extern "C" void
71__cygwin_lock_fini (_LOCK_T *lock)
72{
73 pthread_mutex_destroy ((pthread_mutex_t*) lock);
74}
75
76extern "C" void
77__cygwin_lock_lock (_LOCK_T *lock)
78{
b650c255
DK
79 paranoid_printf ("threadcount %d. locking", MT_INTERFACE->threadcount);
80 pthread_mutex_lock ((pthread_mutex_t*) lock);
11a9a1cf
CF
81}
82
68509b30 83extern "C" int
11a9a1cf
CF
84__cygwin_lock_trylock (_LOCK_T *lock)
85{
68509b30 86 return pthread_mutex_trylock ((pthread_mutex_t*) lock);
11a9a1cf
CF
87}
88
89
90extern "C" void
91__cygwin_lock_unlock (_LOCK_T *lock)
92{
b650c255
DK
93 pthread_mutex_unlock ((pthread_mutex_t*) lock);
94 paranoid_printf ("threadcount %d. unlocked", MT_INTERFACE->threadcount);
11a9a1cf
CF
95}
96
4c157aa9 97static inline verifyable_object_state
2b1407d3 98verifyable_object_isvalid (void const *objectptr, thread_magic_t magic, void *static_ptr1,
4c157aa9
CF
99 void *static_ptr2, void *static_ptr3)
100{
4c157aa9 101 myfault efault;
17fed6fe
CF
102 /* Check for NULL pointer specifically since it is a cheap test and avoids the
103 overhead of setting up the fault handler. */
104 if (!objectptr || efault.faulted ())
4c157aa9 105 return INVALID_OBJECT;
a64b8b2d 106
17fed6fe
CF
107 verifyable_object **object = (verifyable_object **) objectptr;
108
4c157aa9
CF
109 if ((static_ptr1 && *object == static_ptr1) ||
110 (static_ptr2 && *object == static_ptr2) ||
111 (static_ptr3 && *object == static_ptr3))
112 return VALID_STATIC_OBJECT;
113 if ((*object)->magic != magic)
114 return INVALID_OBJECT;
115 return VALID_OBJECT;
116}
117
118/* static members */
119inline bool
120pthread_attr::is_good_object (pthread_attr_t const *attr)
121{
122 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
123 return false;
124 return true;
125}
126
127inline bool
128pthread_condattr::is_good_object (pthread_condattr_t const *attr)
129{
130 if (verifyable_object_isvalid (attr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
131 return false;
132 return true;
133}
134
135inline bool
136pthread_rwlockattr::is_good_object (pthread_rwlockattr_t const *attr)
137{
138 if (verifyable_object_isvalid (attr, PTHREAD_RWLOCKATTR_MAGIC) != VALID_OBJECT)
139 return false;
140 return true;
141}
142
143inline bool
144pthread_key::is_good_object (pthread_key_t const *key)
145{
146 if (verifyable_object_isvalid (key, PTHREAD_KEY_MAGIC) != VALID_OBJECT)
147 return false;
148 return true;
149}
150
151inline bool
152pthread_mutex::is_good_object (pthread_mutex_t const *mutex)
153{
154 if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
155 return false;
156 return true;
157}
158
159inline bool
160pthread_mutex::is_good_initializer (pthread_mutex_t const *mutex)
161{
162 if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC,
163 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
164 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP,
165 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) != VALID_STATIC_OBJECT)
166 return false;
167 return true;
168}
169
170inline bool
171pthread_mutex::is_good_initializer_or_object (pthread_mutex_t const *mutex)
172{
173 if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC,
174 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
175 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP,
176 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) == INVALID_OBJECT)
177 return false;
178 return true;
179}
180
4c157aa9
CF
181inline bool
182pthread_mutex::can_be_unlocked (pthread_mutex_t const *mutex)
183{
184 pthread_t self = pthread::self ();
185
186 if (!is_good_object (mutex))
187 return false;
75833f08
CV
188 /* Check if the mutex is owned by the current thread and can be unlocked.
189 * Also check for the ANONYMOUS owner to cover NORMAL mutexes as well. */
3700578e
CF
190 return (*mutex)->recursion_counter == 1
191 && pthread::equal ((*mutex)->owner, self);
4c157aa9
CF
192}
193
194inline bool
195pthread_mutexattr::is_good_object (pthread_mutexattr_t const * attr)
196{
197 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
198 return false;
199 return true;
200}
201
202inline bool __attribute__ ((used))
203pthread::is_good_object (pthread_t const *thread)
204{
205 if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT)
206 return false;
207 return true;
208}
209
210/* Thread synchronisation */
211inline bool
212pthread_cond::is_good_object (pthread_cond_t const *cond)
213{
214 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
215 return false;
216 return true;
217}
218
219inline bool
220pthread_cond::is_good_initializer (pthread_cond_t const *cond)
221{
222 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) != VALID_STATIC_OBJECT)
223 return false;
224 return true;
225}
226
227inline bool
228pthread_cond::is_good_initializer_or_object (pthread_cond_t const *cond)
229{
230 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) == INVALID_OBJECT)
231 return false;
232 return true;
233}
234
4c157aa9
CF
235/* RW locks */
236inline bool
237pthread_rwlock::is_good_object (pthread_rwlock_t const *rwlock)
238{
239 if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC) != VALID_OBJECT)
240 return false;
241 return true;
242}
243
244inline bool
245pthread_rwlock::is_good_initializer (pthread_rwlock_t const *rwlock)
246{
247 if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, PTHREAD_RWLOCK_INITIALIZER) != VALID_STATIC_OBJECT)
248 return false;
249 return true;
250}
251
252inline bool
253pthread_rwlock::is_good_initializer_or_object (pthread_rwlock_t const *rwlock)
254{
255 if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, PTHREAD_RWLOCK_INITIALIZER) == INVALID_OBJECT)
256 return false;
257 return true;
258}
259
4c157aa9
CF
260inline bool
261semaphore::is_good_object (sem_t const * sem)
262{
263 if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
264 return false;
265 return true;
266}
267
1fd5e000 268void
c8fa3426 269MTinterface::Init ()
1fd5e000 270{
15648790
TP
271 pthread_mutex::init_mutex ();
272 pthread_cond::init_mutex ();
273 pthread_rwlock::init_mutex ();
166b2571 274}
1fd5e000 275
f1f13795 276void
2f9ae2ed 277MTinterface::fixup_before_fork ()
f1f13795
RC
278{
279 pthread_key::fixup_before_fork ();
280}
281
f9229ef7
RC
282/* This function is called from a single threaded process */
283void
2f9ae2ed 284MTinterface::fixup_after_fork ()
f9229ef7 285{
f1f13795 286 pthread_key::fixup_after_fork ();
88243328 287
9a4d574b 288 threadcount = 0;
56a188d1 289 pthread::init_mainthread ();
88243328 290
e1e196a2 291 pthread::fixup_after_fork ();
9306ba2e
TP
292 pthread_mutex::fixup_after_fork ();
293 pthread_cond::fixup_after_fork ();
294 pthread_rwlock::fixup_after_fork ();
295 semaphore::fixup_after_fork ();
f9229ef7
RC
296}
297
007276b3
RC
298/* pthread calls */
299
300/* static methods */
4e786173 301void
56a188d1 302pthread::init_mainthread ()
4e786173 303{
3700578e 304 pthread *thread = _my_tls.tid;
f8c8e13b
RC
305 if (!thread)
306 {
56a188d1
CF
307 thread = new pthread ();
308 if (!thread)
e3778517 309 api_fatal ("failed to create mainthread object");
f8c8e13b
RC
310 }
311
56a188d1 312 set_tls_self_pointer (thread);
9a4d574b 313 thread->thread_id = GetCurrentThreadId ();
f16706de
CV
314 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
315 GetCurrentProcess (), &thread->win32_obj_id,
316 0, FALSE, DUPLICATE_SAME_ACCESS))
5c07a574 317 api_fatal ("failed to create mainthread handle");
5c07a574
CF
318 if (!thread->create_cancel_event ())
319 api_fatal ("couldn't create cancel event for main thread");
f7239090 320 VerifyHandle (thread->win32_obj_id);
9a4d574b 321 thread->postcreate ();
4e786173 322}
007276b3
RC
323
324pthread *
325pthread::self ()
326{
3700578e 327 pthread *thread = _my_tls.tid;
56a188d1
CF
328 if (!thread)
329 {
330 thread = pthread_null::get_null_pthread ();
331 set_tls_self_pointer (thread);
332 }
333 return thread;
4e786173
RC
334}
335
56a188d1
CF
336void
337pthread::set_tls_self_pointer (pthread *thread)
338{
339 thread->cygtls = &_my_tls;
340 _my_tls.tid = thread;
341}
342
e1e196a2
TP
343List<pthread> pthread::threads;
344
007276b3 345/* member methods */
5c83f260 346pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),
c6e0f665 347 valid (false), suspended (false),
6299349b 348 cancelstate (0), canceltype (0), cancel_event (0),
e1e196a2 349 joiner (NULL), next (NULL), cleanup_stack (NULL)
1fd5e000 350{
e1e196a2
TP
351 if (this != pthread_null::get_null_pthread ())
352 threads.insert (this);
70300fdb 353 parent_tls = &_my_tls;
9a08b2c0 354}
1fd5e000 355
9a08b2c0
CF
356pthread::~pthread ()
357{
358 if (win32_obj_id)
359 CloseHandle (win32_obj_id);
d288c1c7
RC
360 if (cancel_event)
361 CloseHandle (cancel_event);
e1e196a2
TP
362
363 if (this != pthread_null::get_null_pthread ())
364 threads.remove (this);
9a08b2c0 365}
1fd5e000 366
c76d70d7
CF
367bool
368pthread::create_cancel_event ()
369{
370 cancel_event = ::CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
371 if (!cancel_event)
372 {
5c07a574 373 system_printf ("couldn't create cancel event, %E");
c76d70d7
CF
374 /* we need the event for correct behaviour */
375 return false;
376 }
377 return true;
378}
379
9a08b2c0 380void
4e786173 381pthread::precreate (pthread_attr *newattr)
9a08b2c0 382{
f6709c07
RC
383 pthread_mutex *verifyable_mutex_obj = &mutex;
384
79ed4300 385 /* already running ? */
9a08b2c0
CF
386 if (win32_obj_id)
387 return;
1fd5e000 388
9a08b2c0
CF
389 if (newattr)
390 {
391 attr.joinable = newattr->joinable;
5c83f260
RC
392 attr.contentionscope = newattr->contentionscope;
393 attr.inheritsched = newattr->inheritsched;
9a08b2c0
CF
394 attr.stacksize = newattr->stacksize;
395 }
1fd5e000 396
15648790 397 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
43c3c4e3
RC
398 {
399 thread_printf ("New thread object access mutex is not valid. this %p",
400 this);
401 magic = 0;
402 return;
403 }
2ff03dc2
TP
404 /* Change the mutex type to NORMAL to speed up mutex operations */
405 mutex.type = PTHREAD_MUTEX_NORMAL;
c76d70d7
CF
406 if (!create_cancel_event ())
407 magic = 0;
4e786173
RC
408}
409
7d7e7a21 410bool
4e786173
RC
411pthread::create (void *(*func) (void *), pthread_attr *newattr,
412 void *threadarg)
d04cf16c 413{
7d7e7a21
CV
414 bool retval;
415
4e786173
RC
416 precreate (newattr);
417 if (!magic)
7d7e7a21 418 return false;
8861377a
CF
419
420 function = func;
421 arg = threadarg;
d288c1c7 422
3e78b5d7 423 mutex.lock ();
4d029f39 424 win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize,
3e78b5d7 425 thread_init_wrapper, this, 0, &thread_id);
1fd5e000 426
9a08b2c0 427 if (!win32_obj_id)
196cdd45 428 {
9a4d574b 429 thread_printf ("CreateThread failed: this %p, %E", this);
196cdd45
CF
430 magic = 0;
431 }
e2b9eb11
CF
432 else
433 {
d84a4e2e 434 postcreate ();
85564567
CF
435 while (!cygtls)
436 low_priority_sleep (0);
e2b9eb11 437 }
7d7e7a21 438 retval = magic;
3e78b5d7 439 mutex.unlock ();
7d7e7a21 440 return retval;
4e786173
RC
441}
442
443void
444pthread::postcreate ()
445{
c6e0f665 446 valid = true;
e1e196a2
TP
447
448 InterlockedIncrement (&MT_INTERFACE->threadcount);
449 /* FIXME: set the priority appropriately for system contention scope */
450 if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED)
451 {
452 /* FIXME: set the scheduling settings for the new thread */
453 /* sched_thread_setparam (win32_obj_id, attr.schedparam); */
454 }
9a08b2c0 455}
1fd5e000 456
d288c1c7
RC
457void
458pthread::exit (void *value_ptr)
459{
460 class pthread *thread = this;
461
462 // run cleanup handlers
463 pop_all_cleanup_handlers ();
464
15648790 465 pthread_key::run_all_destructors ();
d288c1c7 466
15648790 467 mutex.lock ();
d288c1c7 468 // cleanup if thread is in detached state and not joined
a4cea440 469 if (equal (joiner, thread))
d288c1c7
RC
470 delete this;
471 else
d04cf16c 472 {
c6e0f665 473 valid = false;
d288c1c7 474 return_ptr = value_ptr;
15648790 475 mutex.unlock ();
d288c1c7
RC
476 }
477
6f7a746c
CF
478 if (_my_tls.local_clib.__sdidinit < 0)
479 _my_tls.local_clib.__sdidinit = 0;
068834a1
TP
480 (_reclaim_reent) (_REENT);
481
d288c1c7
RC
482 if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0)
483 ::exit (0);
484 else
161387a7 485 ExitThread (0);
d288c1c7
RC
486}
487
488int
2f9ae2ed 489pthread::cancel ()
d288c1c7
RC
490{
491 class pthread *thread = this;
492 class pthread *self = pthread::self ();
493
15648790 494 mutex.lock ();
d288c1c7 495
c6e0f665 496 if (!valid)
e1e196a2
TP
497 {
498 mutex.unlock ();
499 return 0;
500 }
501
d288c1c7
RC
502 if (canceltype == PTHREAD_CANCEL_DEFERRED ||
503 cancelstate == PTHREAD_CANCEL_DISABLE)
504 {
505 // cancel deferred
15648790 506 mutex.unlock ();
d288c1c7
RC
507 SetEvent (cancel_event);
508 return 0;
509 }
a4cea440 510 else if (equal (thread, self))
d288c1c7 511 {
15648790 512 mutex.unlock ();
d288c1c7
RC
513 cancel_self ();
514 return 0; // Never reached
515 }
516
517 // cancel asynchronous
518 SuspendThread (win32_obj_id);
519 if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)
520 {
521 CONTEXT context;
522 context.ContextFlags = CONTEXT_CONTROL;
523 GetThreadContext (win32_obj_id, &context);
524 context.Eip = (DWORD) pthread::static_cancel_self;
525 SetThreadContext (win32_obj_id, &context);
526 }
15648790 527 mutex.unlock ();
d288c1c7
RC
528 ResumeThread (win32_obj_id);
529
530 return 0;
531/*
532 TODO: insert pthread_testcancel into the required functions
533 the required function list is: *indicates done, X indicates not present in cygwin.
534aio_suspend ()
535*close ()
536*creat ()
537fcntl ()
538fsync ()
539getmsg ()
540getpmsg ()
541lockf ()
542mq_receive ()
543mq_send ()
544msgrcv ()
545msgsnd ()
546msync ()
547nanosleep ()
548open ()
3457ce4d 549*pause ()
d288c1c7
RC
550poll ()
551pread ()
f592b05d
TP
552*pthread_cond_timedwait ()
553*pthread_cond_wait ()
d288c1c7 554*pthread_join ()
e14328f4 555*pthread_testcancel ()
d288c1c7
RC
556putmsg ()
557putpmsg ()
558pwrite ()
559read ()
560readv ()
561select ()
09cbb9d6 562*sem_wait ()
3457ce4d
TP
563*sigpause ()
564*sigsuspend ()
d288c1c7
RC
565sigtimedwait ()
566sigwait ()
567sigwaitinfo ()
568*sleep ()
e14328f4 569*system ()
d288c1c7
RC
570tcdrain ()
571*usleep ()
4a3584c8
TP
572*wait ()
573*wait3()
d288c1c7 574waitid ()
4a3584c8 575*waitpid ()
d288c1c7
RC
576write ()
577writev ()
578
579the optional list is:
580catclose ()
581catgets ()
582catopen ()
583closedir ()
584closelog ()
585ctermid ()
586dbm_close ()
587dbm_delete ()
588dbm_fetch ()
589dbm_nextkey ()
590dbm_open ()
591dbm_store ()
592dlclose ()
593dlopen ()
594endgrent ()
595endpwent ()
596endutxent ()
597fclose ()
598fcntl ()
599fflush ()
600fgetc ()
601fgetpos ()
602fgets ()
603fgetwc ()
604fgetws ()
605fopen ()
606fprintf ()
607fputc ()
608fputs ()
609fputwc ()
610fputws ()
611fread ()
612freopen ()
613fscanf ()
614fseek ()
615fseeko ()
616fsetpos ()
617ftell ()
618ftello ()
619ftw ()
620fwprintf ()
621fwrite ()
622fwscanf ()
623getc ()
624getc_unlocked ()
625getchar ()
626getchar_unlocked ()
627getcwd ()
628getdate ()
629getgrent ()
630getgrgid ()
631getgrgid_r ()
632getgrnam ()
633getgrnam_r ()
634getlogin ()
635getlogin_r ()
636getpwent ()
637*getpwnam ()
638*getpwnam_r ()
639*getpwuid ()
640*getpwuid_r ()
641gets ()
642getutxent ()
643getutxid ()
644getutxline ()
645getw ()
646getwc ()
647getwchar ()
648getwd ()
649glob ()
650iconv_close ()
651iconv_open ()
652ioctl ()
653lseek ()
654mkstemp ()
655nftw ()
656opendir ()
657openlog ()
658pclose ()
659perror ()
660popen ()
661printf ()
662putc ()
663putc_unlocked ()
664putchar ()
665putchar_unlocked ()
666puts ()
667pututxline ()
668putw ()
669putwc ()
670putwchar ()
671readdir ()
672readdir_r ()
673remove ()
674rename ()
675rewind ()
676rewinddir ()
677scanf ()
678seekdir ()
679semop ()
680setgrent ()
681setpwent ()
682setutxent ()
683strerror ()
684syslog ()
685tmpfile ()
686tmpnam ()
687ttyname ()
688ttyname_r ()
689ungetc ()
690ungetwc ()
691unlink ()
692vfprintf ()
693vfwprintf ()
694vprintf ()
695vwprintf ()
696wprintf ()
697wscanf ()
698
699Note, that for fcntl (), for any value of the cmd argument.
700
701And we must not introduce cancellation points anywhere else that's part of the posix or
702opengroup specs.
703 */
704}
705
706void
2f9ae2ed 707pthread::testcancel ()
d288c1c7
RC
708{
709 if (cancelstate == PTHREAD_CANCEL_DISABLE)
710 return;
711
eff6c00e 712 if (WaitForSingleObject (cancel_event, 0) == WAIT_OBJECT_0)
d288c1c7
RC
713 cancel_self ();
714}
715
716void
2f9ae2ed 717pthread::static_cancel_self ()
d288c1c7 718{
f1f13795 719 pthread::self ()->cancel_self ();
d288c1c7
RC
720}
721
9a47ce7f 722DWORD
8fbd574e
CV
723cancelable_wait (HANDLE object, DWORD timeout,
724 const cw_cancel_action cancel_action,
ed364fa9 725 const enum cw_sig_wait sig_wait)
09cbb9d6
TP
726{
727 DWORD res;
c9a76075
CV
728 DWORD num = 0;
729 HANDLE wait_objects[3];
ed364fa9 730 pthread_t thread = pthread::self ();
09cbb9d6 731
c9a76075
CV
732 /* Do not change the wait order.
733 The object must have higher priority than the cancel event,
734 because WaitForMultipleObjects will return the smallest index
735 if both objects are signaled. */
736 wait_objects[num++] = object;
1940656a 737 DWORD cancel_n;
85564567 738 if (cancel_action == cw_no_cancel || !pthread::is_good_object (&thread) ||
1940656a
CF
739 thread->cancelstate == PTHREAD_CANCEL_DISABLE)
740 cancel_n = (DWORD) -1;
741 else
742 {
abf60784 743 cancel_n = WAIT_OBJECT_0 + num++;
1940656a
CF
744 wait_objects[cancel_n] = thread->cancel_event;
745 }
746
747 DWORD sig_n;
ed364fa9 748 if (sig_wait == cw_sig_nosig || &_my_tls != _main_tls)
1940656a
CF
749 sig_n = (DWORD) -1;
750 else
751 {
abf60784 752 sig_n = WAIT_OBJECT_0 + num++;
1940656a
CF
753 wait_objects[sig_n] = signal_arrived;
754 }
c9a76075 755
ed364fa9 756 while (1)
c9a76075 757 {
ed364fa9 758 res = WaitForMultipleObjects (num, wait_objects, FALSE, timeout);
ed364fa9
CF
759 if (res == cancel_n)
760 {
85564567 761 if (cancel_action == cw_cancel_self)
ed364fa9
CF
762 pthread::static_cancel_self ();
763 res = WAIT_CANCELED;
764 }
765 else if (res != sig_n)
766 /* all set */;
767 else if (sig_wait == cw_sig_eintr)
768 res = WAIT_SIGNALED;
769 else
770 {
771 _my_tls.call_signal_handler ();
772 continue;
773 }
774 break;
c9a76075 775 }
09cbb9d6
TP
776 return res;
777}
778
d288c1c7
RC
779int
780pthread::setcancelstate (int state, int *oldstate)
781{
782 int result = 0;
783
15648790 784 mutex.lock ();
d288c1c7
RC
785
786 if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)
787 result = EINVAL;
788 else
789 {
790 if (oldstate)
d04cf16c 791 *oldstate = cancelstate;
d288c1c7
RC
792 cancelstate = state;
793 }
794
15648790 795 mutex.unlock ();
d288c1c7
RC
796
797 return result;
798}
799
800int
801pthread::setcanceltype (int type, int *oldtype)
802{
803 int result = 0;
804
15648790 805 mutex.lock ();
d288c1c7
RC
806
807 if (type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS)
808 result = EINVAL;
809 else
810 {
811 if (oldtype)
d04cf16c 812 *oldtype = canceltype;
d288c1c7
RC
813 canceltype = type;
814 }
815
15648790 816 mutex.unlock ();
d288c1c7
RC
817
818 return result;
819}
820
007276b3
RC
821void
822pthread::push_cleanup_handler (__pthread_cleanup_handler *handler)
823{
824 if (this != self ())
825 // TODO: do it?
d04cf16c 826 api_fatal ("Attempt to push a cleanup handler across threads");
f6709c07 827 handler->next = cleanup_stack;
28194e81 828 cleanup_stack = handler;
007276b3
RC
829}
830
831void
832pthread::pop_cleanup_handler (int const execute)
833{
834 if (this != self ())
835 // TODO: send a signal or something to the thread ?
836 api_fatal ("Attempt to execute a cleanup handler across threads");
d04cf16c 837
15648790 838 mutex.lock ();
d288c1c7 839
f6709c07 840 if (cleanup_stack != NULL)
007276b3 841 {
f6709c07 842 __pthread_cleanup_handler *handler = cleanup_stack;
007276b3
RC
843
844 if (execute)
d04cf16c 845 (*handler->function) (handler->arg);
f6709c07 846 cleanup_stack = handler->next;
007276b3 847 }
d288c1c7 848
15648790 849 mutex.unlock ();
007276b3
RC
850}
851
852void
853pthread::pop_all_cleanup_handlers ()
854{
f6709c07 855 while (cleanup_stack != NULL)
007276b3
RC
856 pop_cleanup_handler (1);
857}
858
4e786173 859void
f1f13795 860pthread::cancel_self ()
4e786173
RC
861{
862 exit (PTHREAD_CANCELED);
863}
864
865DWORD
15648790 866pthread::get_thread_id ()
4e786173
RC
867{
868 return thread_id;
869}
870
e1e196a2
TP
871void
872pthread::_fixup_after_fork ()
873{
874 /* set thread to not running if it is not the forking thread */
875 if (this != pthread::self ())
876 {
877 magic = 0;
c6e0f665 878 valid = false;
e1e196a2
TP
879 win32_obj_id = NULL;
880 cancel_event = NULL;
881 }
882}
883
c6e0f665
TP
884void
885pthread::suspend_except_self ()
886{
887 if (valid && this != pthread::self ())
970ca292 888 SuspendThread (win32_obj_id);
c6e0f665
TP
889}
890
891void
892pthread::resume ()
893{
894 if (valid)
970ca292 895 ResumeThread (win32_obj_id);
c6e0f665
TP
896}
897
4e2822f1
RC
898/* instance members */
899
9a08b2c0 900pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC),
5c83f260
RC
901joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS),
902inheritsched (PTHREAD_INHERIT_SCHED), stacksize (0)
9a08b2c0 903{
5c83f260 904 schedparam.sched_priority = 0;
166b2571 905}
1fd5e000 906
9a08b2c0 907pthread_attr::~pthread_attr ()
1fd5e000 908{
9a08b2c0 909}
1fd5e000 910
5c83f260
RC
911pthread_condattr::pthread_condattr ():verifyable_object
912 (PTHREAD_CONDATTR_MAGIC), shared (PTHREAD_PROCESS_PRIVATE)
9a08b2c0
CF
913{
914}
1fd5e000 915
9a08b2c0
CF
916pthread_condattr::~pthread_condattr ()
917{
918}
1fd5e000 919
9306ba2e
TP
920List<pthread_cond> pthread_cond::conds;
921
ed9fe455 922/* This is used for cond creation protection within a single process only */
28194e81 923fast_mutex NO_COPY pthread_cond::cond_initialization_lock;
ed9fe455
TP
924
925/* We can only be called once.
926 TODO: (no rush) use a non copied memory section to
927 hold an initialization flag. */
928void
15648790 929pthread_cond::init_mutex ()
ed9fe455 930{
15648790 931 if (!cond_initialization_lock.init ())
ed9fe455
TP
932 api_fatal ("Could not create win32 Mutex for pthread cond static initializer support.");
933}
934
f592b05d
TP
935pthread_cond::pthread_cond (pthread_condattr *attr) :
936 verifyable_object (PTHREAD_COND_MAGIC),
15648790
TP
937 shared (0), waiting (0), pending (0), sem_wait (NULL),
938 mtx_cond(NULL), next (NULL)
9a08b2c0 939{
f592b05d 940 pthread_mutex *verifyable_mutex_obj;
1fd5e000 941
f592b05d
TP
942 if (attr)
943 if (attr->shared != PTHREAD_PROCESS_PRIVATE)
944 {
df04ae29
CF
945 magic = 0;
946 return;
f592b05d
TP
947 }
948
15648790
TP
949 verifyable_mutex_obj = &mtx_in;
950 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
68ebd3f6 951 {
f592b05d 952 thread_printf ("Internal cond mutex is not valid. this %p", this);
32c30349 953 magic = 0;
f592b05d
TP
954 return;
955 }
15648790
TP
956 /*
957 * Change the mutex type to NORMAL.
958 * This mutex MUST be of type normal
959 */
960 mtx_in.type = PTHREAD_MUTEX_NORMAL;
f592b05d 961
15648790
TP
962 verifyable_mutex_obj = &mtx_out;
963 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
f592b05d
TP
964 {
965 thread_printf ("Internal cond mutex is not valid. this %p", this);
966 magic = 0;
967 return;
968 }
969 /* Change the mutex type to NORMAL to speed up mutex operations */
15648790 970 mtx_out.type = PTHREAD_MUTEX_NORMAL;
f592b05d 971
15648790
TP
972 sem_wait = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL);
973 if (!sem_wait)
f592b05d
TP
974 {
975 debug_printf ("CreateSemaphore failed. %E");
976 magic = 0;
977 return;
68ebd3f6 978 }
1fd5e000 979
15648790 980 conds.insert (this);
9a08b2c0 981}
1fd5e000 982
9a08b2c0
CF
983pthread_cond::~pthread_cond ()
984{
15648790
TP
985 if (sem_wait)
986 CloseHandle (sem_wait);
f592b05d 987
15648790 988 conds.remove (this);
1fd5e000
CF
989}
990
9a08b2c0 991void
15648790 992pthread_cond::unblock (const bool all)
1fd5e000 993{
f592b05d 994 unsigned long releaseable;
1fd5e000 995
df04ae29 996 /*
f592b05d 997 * Block outgoing threads (and avoid simultanous unblocks)
cbce4980 998 */
15648790 999 mtx_out.lock ();
f592b05d
TP
1000
1001 releaseable = waiting - pending;
1002 if (releaseable)
86336f4f 1003 {
f592b05d
TP
1004 unsigned long released;
1005
1006 if (!pending)
df04ae29
CF
1007 {
1008 /*
1009 * Block incoming threads until all waiting threads are released.
1010 */
1011 mtx_in.lock ();
1012
1013 /*
1014 * Calculate releaseable again because threads can enter until
1015 * the semaphore has been taken, but they can not leave, therefore pending
1016 * is unchanged and releaseable can only get higher
1017 */
1018 releaseable = waiting - pending;
1019 }
f592b05d
TP
1020
1021 released = all ? releaseable : 1;
1022 pending += released;
1023 /*
1024 * Signal threads
1025 */
15648790 1026 ::ReleaseSemaphore (sem_wait, released, NULL);
86336f4f 1027 }
f592b05d
TP
1028
1029 /*
1030 * And let the threads release.
1031 */
15648790 1032 mtx_out.unlock ();
9a08b2c0
CF
1033}
1034
1035int
15648790 1036pthread_cond::wait (pthread_mutex_t mutex, DWORD dwMilliseconds)
1fd5e000 1037{
9450ad0d 1038 DWORD rv;
5d68d1de 1039
15648790 1040 mtx_in.lock ();
eff6c00e 1041 if (InterlockedIncrement ((long *)&waiting) == 1)
15648790
TP
1042 mtx_cond = mutex;
1043 else if (mtx_cond != mutex)
f592b05d
TP
1044 {
1045 InterlockedDecrement ((long *)&waiting);
15648790 1046 mtx_in.unlock ();
f592b05d
TP
1047 return EINVAL;
1048 }
15648790 1049 mtx_in.unlock ();
f592b05d
TP
1050
1051 /*
1052 * Release the mutex and wait on semaphore
5d68d1de 1053 */
f592b05d 1054 ++mutex->condwaits;
15648790 1055 mutex->unlock ();
ff6e295e 1056
85564567 1057 rv = cancelable_wait (sem_wait, dwMilliseconds, cw_no_cancel_self, cw_sig_eintr);
f592b05d 1058
15648790 1059 mtx_out.lock ();
df04ae29 1060
f592b05d 1061 if (rv != WAIT_OBJECT_0)
9a08b2c0 1062 {
f592b05d
TP
1063 /*
1064 * It might happen that a signal is sent while the thread got canceled
1065 * or timed out. Try to take one.
1066 * If the thread gets one than a signal|broadcast is in progress.
df04ae29 1067 */
eff6c00e 1068 if (WaitForSingleObject (sem_wait, 0) == WAIT_OBJECT_0)
df04ae29
CF
1069 /*
1070 * thread got cancelled ot timed out while a signalling is in progress.
1071 * Set wait result back to signaled
1072 */
1073 rv = WAIT_OBJECT_0;
9a08b2c0 1074 }
f592b05d
TP
1075
1076 InterlockedDecrement ((long *)&waiting);
1077
eff6c00e 1078 if (rv == WAIT_OBJECT_0 && --pending == 0)
f592b05d
TP
1079 /*
1080 * All signaled threads are released,
1081 * new threads can enter Wait
1082 */
15648790 1083 mtx_in.unlock ();
f592b05d 1084
15648790 1085 mtx_out.unlock ();
df04ae29 1086
15648790 1087 mutex->lock ();
f592b05d
TP
1088 --mutex->condwaits;
1089
1090 if (rv == WAIT_CANCELED)
1091 pthread::static_cancel_self ();
c9a76075
CV
1092 else if (rv == WAIT_SIGNALED)
1093 /* SUSv3 states: If a signal is delivered to a thread waiting for a
1094 condition variable, upon return from the signal handler the thread
1095 resumes waiting for the condition variable as if it was not
1096 interrupted, or it shall return zero due to spurious wakeup.
1097 We opt for the latter choice here. */
1098 return 0;
f592b05d
TP
1099 else if (rv == WAIT_TIMEOUT)
1100 return ETIMEDOUT;
1101
1102 return 0;
166b2571 1103}
1fd5e000 1104
f9229ef7 1105void
15648790 1106pthread_cond::_fixup_after_fork ()
f9229ef7 1107{
f592b05d 1108 waiting = pending = 0;
15648790 1109 mtx_cond = NULL;
f592b05d
TP
1110
1111 /* Unlock eventually locked mutexes */
15648790
TP
1112 mtx_in.unlock ();
1113 mtx_out.unlock ();
f592b05d 1114
15648790
TP
1115 sem_wait = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL);
1116 if (!sem_wait)
1117 api_fatal ("pthread_cond::_fixup_after_fork () failed to recreate win32 semaphore");
f9229ef7
RC
1118}
1119
00d296a3
TP
1120pthread_rwlockattr::pthread_rwlockattr ():verifyable_object
1121 (PTHREAD_RWLOCKATTR_MAGIC), shared (PTHREAD_PROCESS_PRIVATE)
1122{
1123}
1124
1125pthread_rwlockattr::~pthread_rwlockattr ()
1126{
1127}
1128
9306ba2e
TP
1129List<pthread_rwlock> pthread_rwlock::rwlocks;
1130
00d296a3 1131/* This is used for rwlock creation protection within a single process only */
28194e81 1132fast_mutex NO_COPY pthread_rwlock::rwlock_initialization_lock;
00d296a3
TP
1133
1134/* We can only be called once.
1135 TODO: (no rush) use a non copied memory section to
1136 hold an initialization flag. */
1137void
15648790 1138pthread_rwlock::init_mutex ()
00d296a3 1139{
15648790 1140 if (!rwlock_initialization_lock.init ())
00d296a3
TP
1141 api_fatal ("Could not create win32 Mutex for pthread rwlock static initializer support.");
1142}
1143
1144pthread_rwlock::pthread_rwlock (pthread_rwlockattr *attr) :
1145 verifyable_object (PTHREAD_RWLOCK_MAGIC),
15648790 1146 shared (0), waiting_readers (0), waiting_writers (0), writer (NULL),
28194e81 1147 readers (NULL), readers_mx (), mtx (NULL), cond_readers (NULL), cond_writers (NULL),
00d296a3
TP
1148 next (NULL)
1149{
1150 pthread_mutex *verifyable_mutex_obj = &mtx;
1151 pthread_cond *verifyable_cond_obj;
1152
28194e81
TP
1153 if (!readers_mx.init ())
1154 {
1155 thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this);
1156 magic = 0;
1157 return;
1158 }
1159
00d296a3
TP
1160 if (attr)
1161 if (attr->shared != PTHREAD_PROCESS_PRIVATE)
1162 {
df04ae29
CF
1163 magic = 0;
1164 return;
00d296a3
TP
1165 }
1166
15648790 1167 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
00d296a3
TP
1168 {
1169 thread_printf ("Internal rwlock mutex is not valid. this %p", this);
1170 magic = 0;
1171 return;
1172 }
1173 /* Change the mutex type to NORMAL to speed up mutex operations */
1174 mtx.type = PTHREAD_MUTEX_NORMAL;
1175
15648790
TP
1176 verifyable_cond_obj = &cond_readers;
1177 if (!pthread_cond::is_good_object (&verifyable_cond_obj))
00d296a3
TP
1178 {
1179 thread_printf ("Internal rwlock readers cond is not valid. this %p", this);
1180 magic = 0;
1181 return;
1182 }
1183
15648790
TP
1184 verifyable_cond_obj = &cond_writers;
1185 if (!pthread_cond::is_good_object (&verifyable_cond_obj))
00d296a3
TP
1186 {
1187 thread_printf ("Internal rwlock writers cond is not valid. this %p", this);
1188 magic = 0;
1189 return;
1190 }
1191
1192
15648790 1193 rwlocks.insert (this);
00d296a3
TP
1194}
1195
1196pthread_rwlock::~pthread_rwlock ()
1197{
15648790 1198 rwlocks.remove (this);
00d296a3
TP
1199}
1200
1201int
15648790 1202pthread_rwlock::rdlock ()
00d296a3
TP
1203{
1204 int result = 0;
1205 struct RWLOCK_READER *reader;
1206 pthread_t self = pthread::self ();
1207
15648790 1208 mtx.lock ();
00d296a3 1209
f8190b57
CV
1210 reader = lookup_reader (self);
1211 if (reader)
00d296a3 1212 {
f8190b57
CV
1213 if (reader->n < ULONG_MAX)
1214 ++reader->n;
1215 else
1216 errno = EAGAIN;
00d296a3
TP
1217 goto DONE;
1218 }
1219
1220 reader = new struct RWLOCK_READER;
1221 if (!reader)
1222 {
1223 result = EAGAIN;
1224 goto DONE;
1225 }
1226
15648790 1227 while (writer || waiting_writers)
df04ae29 1228 {
15648790 1229 pthread_cleanup_push (pthread_rwlock::rdlock_cleanup, this);
00d296a3 1230
15648790
TP
1231 ++waiting_readers;
1232 cond_readers.wait (&mtx);
1233 --waiting_readers;
00d296a3
TP
1234
1235 pthread_cleanup_pop (0);
1236 }
1237
1238 reader->thread = self;
f8190b57 1239 reader->n = 1;
15648790 1240 add_reader (reader);
00d296a3
TP
1241
1242 DONE:
15648790 1243 mtx.unlock ();
00d296a3
TP
1244
1245 return result;
1246}
1247
1248int
15648790 1249pthread_rwlock::tryrdlock ()
00d296a3
TP
1250{
1251 int result = 0;
1252 pthread_t self = pthread::self ();
1253
15648790 1254 mtx.lock ();
00d296a3 1255
15648790 1256 if (writer || waiting_writers || lookup_reader (self))
00d296a3
TP
1257 result = EBUSY;
1258 else
1259 {
f8190b57
CV
1260 struct RWLOCK_READER *reader;
1261
1262 reader = lookup_reader (self);
1263 if (reader && reader->n < ULONG_MAX)
1264 ++reader->n;
1265 else if ((reader = new struct RWLOCK_READER))
df04ae29
CF
1266 {
1267 reader->thread = self;
f8190b57 1268 reader->n = 1;
df04ae29
CF
1269 add_reader (reader);
1270 }
00d296a3 1271 else
df04ae29 1272 result = EAGAIN;
00d296a3 1273 }
df04ae29 1274
15648790 1275 mtx.unlock ();
00d296a3
TP
1276
1277 return result;
1278}
1279
1280int
15648790 1281pthread_rwlock::wrlock ()
00d296a3
TP
1282{
1283 int result = 0;
1284 pthread_t self = pthread::self ();
1285
15648790 1286 mtx.lock ();
00d296a3 1287
15648790 1288 if (writer == self || lookup_reader (self))
00d296a3
TP
1289 {
1290 result = EDEADLK;
1291 goto DONE;
1292 }
1293
1294 while (writer || readers)
df04ae29 1295 {
15648790 1296 pthread_cleanup_push (pthread_rwlock::wrlock_cleanup, this);
00d296a3 1297
15648790
TP
1298 ++waiting_writers;
1299 cond_writers.wait (&mtx);
1300 --waiting_writers;
00d296a3
TP
1301
1302 pthread_cleanup_pop (0);
1303 }
1304
1305 writer = self;
1306
1307 DONE:
15648790 1308 mtx.unlock ();
00d296a3
TP
1309
1310 return result;
1311}
1312
1313int
15648790 1314pthread_rwlock::trywrlock ()
00d296a3
TP
1315{
1316 int result = 0;
1317 pthread_t self = pthread::self ();
1318
15648790 1319 mtx.lock ();
00d296a3
TP
1320
1321 if (writer || readers)
1322 result = EBUSY;
1323 else
1324 writer = self;
df04ae29 1325
15648790 1326 mtx.unlock ();
00d296a3
TP
1327
1328 return result;
1329}
1330
1331int
15648790 1332pthread_rwlock::unlock ()
00d296a3
TP
1333{
1334 int result = 0;
1335 pthread_t self = pthread::self ();
1336
15648790 1337 mtx.lock ();
00d296a3
TP
1338
1339 if (writer)
1340 {
1341 if (writer != self)
df04ae29
CF
1342 {
1343 result = EPERM;
1344 goto DONE;
1345 }
00d296a3
TP
1346
1347 writer = NULL;
1348 }
1349 else
1350 {
15648790 1351 struct RWLOCK_READER *reader = lookup_reader (self);
00d296a3
TP
1352
1353 if (!reader)
df04ae29
CF
1354 {
1355 result = EPERM;
1356 goto DONE;
1357 }
f8190b57
CV
1358 if (--reader->n > 0)
1359 goto DONE;
00d296a3 1360
15648790 1361 remove_reader (reader);
00d296a3
TP
1362 delete reader;
1363 }
1364
ffb576fb 1365 release ();
00d296a3
TP
1366
1367 DONE:
15648790 1368 mtx.unlock ();
00d296a3
TP
1369
1370 return result;
1371}
1372
1373void
15648790 1374pthread_rwlock::add_reader (struct RWLOCK_READER *rd)
00d296a3 1375{
94d24160 1376 List_insert (readers, rd);
00d296a3
TP
1377}
1378
1379void
15648790 1380pthread_rwlock::remove_reader (struct RWLOCK_READER *rd)
00d296a3 1381{
28194e81 1382 List_remove (readers_mx, readers, rd);
00d296a3
TP
1383}
1384
1385struct pthread_rwlock::RWLOCK_READER *
15648790 1386pthread_rwlock::lookup_reader (pthread_t thread)
00d296a3 1387{
28194e81
TP
1388 readers_mx.lock ();
1389
1390 struct RWLOCK_READER *cur = readers;
00d296a3 1391
28194e81
TP
1392 while (cur && cur->thread != thread)
1393 cur = cur->next;
00d296a3 1394
28194e81
TP
1395 readers_mx.unlock ();
1396
1397 return cur;
00d296a3
TP
1398}
1399
1400void
15648790 1401pthread_rwlock::rdlock_cleanup (void *arg)
00d296a3
TP
1402{
1403 pthread_rwlock *rwlock = (pthread_rwlock *) arg;
1404
15648790 1405 --(rwlock->waiting_readers);
ffb576fb 1406 rwlock->release ();
15648790 1407 rwlock->mtx.unlock ();
00d296a3
TP
1408}
1409
1410void
15648790 1411pthread_rwlock::wrlock_cleanup (void *arg)
00d296a3
TP
1412{
1413 pthread_rwlock *rwlock = (pthread_rwlock *) arg;
1414
15648790 1415 --(rwlock->waiting_writers);
ffb576fb 1416 rwlock->release ();
15648790 1417 rwlock->mtx.unlock ();
00d296a3
TP
1418}
1419
1420void
15648790 1421pthread_rwlock::_fixup_after_fork ()
00d296a3
TP
1422{
1423 pthread_t self = pthread::self ();
1424 struct RWLOCK_READER **temp = &readers;
1425
15648790
TP
1426 waiting_readers = 0;
1427 waiting_writers = 0;
00d296a3 1428
28194e81
TP
1429 if (!readers_mx.init ())
1430 api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex");
1431
00d296a3 1432 /* Unlock eventually locked mutex */
15648790 1433 mtx.unlock ();
00d296a3
TP
1434 /*
1435 * Remove all readers except self
1436 */
1437 while (*temp)
1438 {
1439 if ((*temp)->thread == self)
df04ae29 1440 temp = &((*temp)->next);
00d296a3 1441 else
df04ae29
CF
1442 {
1443 struct RWLOCK_READER *cur = *temp;
1444 *temp = (*temp)->next;
1445 delete cur;
1446 }
00d296a3
TP
1447 }
1448}
1449
f1f13795
RC
1450/* pthread_key */
1451/* static members */
404f35cb
RC
1452/* This stores pthread_key information across fork() boundaries */
1453List<pthread_key> pthread_key::keys;
af428c1e 1454
f1f13795 1455/* non-static members */
f9229ef7 1456
20b94ee9 1457pthread_key::pthread_key (void (*aDestructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC), destructor (aDestructor)
1fd5e000 1458{
15648790
TP
1459 tls_index = TlsAlloc ();
1460 if (tls_index == TLS_OUT_OF_INDEXES)
9a08b2c0 1461 magic = 0;
af428c1e 1462 else
15648790 1463 keys.insert (this);
1fd5e000
CF
1464}
1465
9a08b2c0
CF
1466pthread_key::~pthread_key ()
1467{
af428c1e
RC
1468 /* We may need to make the list code lock the list during operations
1469 */
6299349b 1470 if (magic != 0)
f1f13795 1471 {
15648790
TP
1472 keys.remove (this);
1473 TlsFree (tls_index);
f1f13795 1474 }
3c76c076 1475}
9a08b2c0 1476
f1f13795 1477void
28194e81 1478pthread_key::_fixup_before_fork ()
f1f13795
RC
1479{
1480 fork_buf = get ();
1481}
1482
1483void
28194e81 1484pthread_key::_fixup_after_fork ()
f1f13795 1485{
15648790
TP
1486 tls_index = TlsAlloc ();
1487 if (tls_index == TLS_OUT_OF_INDEXES)
1488 api_fatal ("pthread_key::recreate_key_from_buffer () failed to reallocate Tls storage");
f1f13795
RC
1489 set (fork_buf);
1490}
1491
20b94ee9 1492void
15648790 1493pthread_key::run_destructor ()
20b94ee9 1494{
79ed4300 1495 if (destructor)
da6a08de 1496 {
79ed4300 1497 void *oldValue = get ();
da6a08de
RC
1498 if (oldValue)
1499 {
9a47ce7f
CF
1500 set (NULL);
1501 destructor (oldValue);
da6a08de
RC
1502 }
1503 }
20b94ee9
RC
1504}
1505
2b1407d3 1506/* pshared mutexs */
9450ad0d 1507
4e2822f1 1508/* static members */
2ff03dc2 1509
9306ba2e
TP
1510List<pthread_mutex> pthread_mutex::mutexes;
1511
404f35cb 1512/* This is used for mutex creation protection within a single process only */
28194e81 1513fast_mutex NO_COPY pthread_mutex::mutex_initialization_lock;
eb208df0 1514
eb208df0 1515void
15648790 1516pthread_mutex::init_mutex ()
eb208df0 1517{
15648790 1518 if (!mutex_initialization_lock.init ())
66dca8bb 1519 api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support.");
eb208df0
RC
1520}
1521
5d68d1de 1522pthread_mutex::pthread_mutex (pthread_mutexattr *attr) :
2b1407d3 1523 verifyable_object (0), /* set magic to zero initially */
2ff03dc2 1524 lock_counter (0),
5d68d1de 1525 win32_obj_id (NULL), recursion_counter (0),
39fc0d36
CF
1526 condwaits (0), owner (NULL),
1527#ifdef DEBUGGING
1528 tid (0),
1529#endif
1530 type (PTHREAD_MUTEX_ERRORCHECK),
9a47ce7f 1531 pshared (PTHREAD_PROCESS_PRIVATE)
1fd5e000 1532{
3700578e 1533 win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL);
5d68d1de 1534 if (!win32_obj_id)
2b1407d3 1535 return;
5d68d1de 1536 /*attr checked in the C call */
2b1407d3
CF
1537 if (!attr)
1538 /* handled in the caller */;
1539 else if (attr->pshared != PTHREAD_PROCESS_SHARED)
1540 type = attr->mutextype;
1541 else
1542 return; /* Not implemented */
5d68d1de 1543
2b1407d3 1544 magic = PTHREAD_MUTEX_MAGIC;
15648790 1545 mutexes.insert (this);
5c83f260 1546}
9a08b2c0
CF
1547
1548pthread_mutex::~pthread_mutex ()
1549{
5d68d1de
TP
1550 if (win32_obj_id)
1551 CloseHandle (win32_obj_id);
1552
15648790 1553 mutexes.remove (this);
166b2571 1554}
1fd5e000
CF
1555
1556int
3700578e 1557pthread_mutex::lock ()
1fd5e000 1558{
3700578e 1559 pthread_t self = ::pthread_self ();
5d68d1de 1560 int result = 0;
9a47ce7f 1561
eff6c00e 1562 if (InterlockedIncrement ((long *)&lock_counter) == 1)
15648790 1563 set_owner (self);
85564567
CF
1564 else if (type == PTHREAD_MUTEX_NORMAL || !pthread::equal (owner, self))
1565 {
0c55f6ed 1566 cancelable_wait (win32_obj_id, INFINITE, cw_no_cancel, cw_sig_resume);
85564567
CF
1567 set_owner (self);
1568 }
1569 else
8e4d9692 1570 {
2ff03dc2 1571 InterlockedDecrement ((long *) &lock_counter);
eff6c00e 1572 if (type == PTHREAD_MUTEX_RECURSIVE)
15648790 1573 result = lock_recursive ();
5d68d1de 1574 else
9a47ce7f 1575 result = EDEADLK;
8e4d9692 1576 }
9a47ce7f 1577
5d68d1de 1578 return result;
166b2571 1579}
1fd5e000
CF
1580
1581int
3700578e 1582pthread_mutex::unlock ()
1fd5e000 1583{
3700578e 1584 pthread_t self = ::pthread_self ();
a4cea440 1585 if (!pthread::equal (owner, self))
5d68d1de 1586 return EPERM;
9a47ce7f 1587
dc74da05
CF
1588 /* Don't try to unlock anything if recursion_counter == 0 initially.
1589 That means that we've forked. */
1590 if (recursion_counter > 0 && --recursion_counter == 0)
8e4d9692 1591 {
5d68d1de 1592 owner = NULL;
39fc0d36
CF
1593#ifdef DEBUGGING
1594 tid = 0;
1595#endif
dc74da05 1596 if (InterlockedDecrement ((long *) &lock_counter))
2b1407d3 1597 ::SetEvent (win32_obj_id); // Another thread is waiting
8e4d9692 1598 }
9a47ce7f 1599
5d68d1de
TP
1600 return 0;
1601}
1602
1603int
3700578e 1604pthread_mutex::trylock ()
5d68d1de 1605{
3700578e
CF
1606 pthread_t self = ::pthread_self ();
1607 int result = 0;
1608
1609 if (InterlockedCompareExchange ((long *) &lock_counter, 1, 0) == 0)
1610 set_owner (self);
1611 else if (type == PTHREAD_MUTEX_RECURSIVE && pthread::equal (owner, self))
1612 result = lock_recursive ();
1613 else
1614 result = EBUSY;
1615
1616 return result;
1617}
1618
1619int
1620pthread_mutex::destroy ()
1621{
1622 if (condwaits || trylock ())
5d68d1de
TP
1623 // Do not destroy a condwaited or locked mutex
1624 return EBUSY;
dc74da05 1625 else if (recursion_counter > 1)
5d68d1de
TP
1626 {
1627 // Do not destroy a recursive locked mutex
dc74da05 1628 recursion_counter--;
5d68d1de
TP
1629 return EBUSY;
1630 }
9a47ce7f 1631
5d68d1de
TP
1632 delete this;
1633 return 0;
1634}
9a47ce7f 1635
f9229ef7 1636void
15648790 1637pthread_mutex::_fixup_after_fork ()
f9229ef7 1638{
dc74da05 1639 debug_printf ("mutex %p in _fixup_after_fork", this);
f9229ef7 1640 if (pshared != PTHREAD_PROCESS_PRIVATE)
18f43099 1641 api_fatal ("pthread_mutex::_fixup_after_fork () doesn't understand PROCESS_SHARED mutex's");
5d68d1de 1642
18f43099 1643 /* All waiting threads are gone after a fork */
dc74da05 1644 recursion_counter = 0;
18f43099 1645 lock_counter = 0;
8e4d9692 1646 condwaits = 0;
36670cc2 1647#ifdef DEBUGGING
dc74da05 1648 tid = 0xffffffff; /* Don't know the tid after a fork */
36670cc2 1649#endif
3700578e 1650 win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL);
dc74da05
CF
1651 if (!win32_obj_id)
1652 api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 semaphore for mutex");
f9229ef7
RC
1653}
1654
5c83f260 1655pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC),
85564567 1656pshared (PTHREAD_PROCESS_PRIVATE), mutextype (PTHREAD_MUTEX_ERRORCHECK)
5c83f260
RC
1657{
1658}
1659
1660pthread_mutexattr::~pthread_mutexattr ()
1661{
3c76c076 1662}
5c83f260 1663
c350feda
CF
1664DWORD WINAPI
1665pthread::thread_init_wrapper (void *arg)
1fd5e000 1666{
d1eb7a46 1667 pthread *thread = (pthread *) arg;
3e78b5d7 1668 set_tls_self_pointer (thread);
1fd5e000 1669
15648790 1670 thread->mutex.lock ();
29d52c8a 1671
e9259cb2 1672 // if thread is detached force cleanup on exit
007276b3 1673 if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL)
f8c8e13b 1674 thread->joiner = thread;
70300fdb 1675 _my_tls.sigmask = thread->parent_tls->sigmask;
15648790 1676 thread->mutex.unlock ();
e9259cb2 1677
29d52c8a 1678 thread_printf ("started thread %p %p %p %p %p %p", arg, &_my_tls.local_clib,
9a08b2c0 1679 _impure_ptr, thread, thread->function, thread->arg);
1fd5e000 1680
94b03f23 1681 // call the user's thread
1fd5e000
CF
1682 void *ret = thread->function (thread->arg);
1683
d288c1c7 1684 thread->exit (ret);
1fd5e000 1685
c350feda 1686 return 0; // just for show. Never returns.
d1eb7a46
CF
1687}
1688
4e786173
RC
1689unsigned long
1690pthread::getsequence_np ()
1691{
15648790 1692 return get_thread_id ();
4e786173
RC
1693}
1694
1fd5e000 1695int
01f58e41 1696pthread::create (pthread_t *thread, const pthread_attr_t *attr,
9a08b2c0 1697 void *(*start_routine) (void *), void *arg)
1fd5e000 1698{
15648790 1699 if (attr && !pthread_attr::is_good_object (attr))
9a08b2c0 1700 return EINVAL;
1fd5e000 1701
9a08b2c0 1702 *thread = new pthread ();
7d7e7a21 1703 if (!(*thread)->create (start_routine, attr ? *attr : NULL, arg))
1fd5e000 1704 {
9a08b2c0
CF
1705 delete (*thread);
1706 *thread = NULL;
1707 return EAGAIN;
91892f50 1708 }
1fd5e000 1709
1fd5e000 1710 return 0;
166b2571 1711}
1fd5e000 1712
5c83f260 1713int
01f58e41 1714pthread::once (pthread_once_t *once_control, void (*init_routine) (void))
5c83f260 1715{
f6709c07
RC
1716 // already done ?
1717 if (once_control->state)
1718 return 0;
1719
5c83f260 1720 pthread_mutex_lock (&once_control->mutex);
79ed4300
CF
1721 /* Here we must set a cancellation handler to unlock the mutex if needed */
1722 /* but a cancellation handler is not the right thing. We need this in the thread
f9f2c119
CF
1723 *cleanup routine. Assumption: a thread can only be in one pthread_once routine
1724 *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
1725 *on pthread_exit ();
5c83f260 1726 */
f6709c07 1727 if (!once_control->state)
5c83f260
RC
1728 {
1729 init_routine ();
1730 once_control->state = 1;
1731 }
79ed4300 1732 /* Here we must remove our cancellation handler */
5c83f260
RC
1733 pthread_mutex_unlock (&once_control->mutex);
1734 return 0;
1735}
1736
5c83f260 1737int
01f58e41 1738pthread::cancel (pthread_t thread)
5c83f260 1739{
15648790 1740 if (!is_good_object (&thread))
5c83f260 1741 return ESRCH;
5c83f260 1742
d288c1c7 1743 return thread->cancel ();
5c83f260
RC
1744}
1745
39b6859a 1746void
2f9ae2ed 1747pthread::atforkprepare ()
39b6859a 1748{
3c76c076 1749 callback *cb = MT_INTERFACE->pthread_prepare;
39b6859a
CF
1750 while (cb)
1751 {
3c76c076
CF
1752 cb->cb ();
1753 cb = cb->next;
39b6859a 1754 }
11a9a1cf
CF
1755
1756 __fp_lock_all ();
c7f060d0
CF
1757
1758 MT_INTERFACE->fixup_before_fork ();
39b6859a
CF
1759}
1760
3c76c076 1761void
2f9ae2ed 1762pthread::atforkparent ()
39b6859a 1763{
11a9a1cf
CF
1764 __fp_unlock_all ();
1765
3c76c076 1766 callback *cb = MT_INTERFACE->pthread_parent;
39b6859a
CF
1767 while (cb)
1768 {
3c76c076
CF
1769 cb->cb ();
1770 cb = cb->next;
39b6859a
CF
1771 }
1772}
1773
1774void
2f9ae2ed 1775pthread::atforkchild ()
39b6859a 1776{
f1f13795
RC
1777 MT_INTERFACE->fixup_after_fork ();
1778
11a9a1cf
CF
1779 __fp_unlock_all ();
1780
3c76c076 1781 callback *cb = MT_INTERFACE->pthread_child;
39b6859a
CF
1782 while (cb)
1783 {
3c76c076
CF
1784 cb->cb ();
1785 cb = cb->next;
39b6859a
CF
1786 }
1787}
1788
79ed4300
CF
1789/* Register a set of functions to run before and after fork.
1790 prepare calls are called in LI-FC order.
1791 parent and child calls are called in FI-FC order. */
39b6859a 1792int
01f58e41 1793pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void))
39b6859a 1794{
f9f2c119 1795 callback *prepcb = NULL, *parentcb = NULL, *childcb = NULL;
39b6859a
CF
1796 if (prepare)
1797 {
1798 prepcb = new callback;
1799 if (!prepcb)
1800 return ENOMEM;
1801 }
1802 if (parent)
1803 {
1804 parentcb = new callback;
1805 if (!parentcb)
1806 {
1807 if (prepcb)
1808 delete prepcb;
1809 return ENOMEM;
1810 }
1811 }
1812 if (child)
1813 {
1814 childcb = new callback;
1815 if (!childcb)
1816 {
1817 if (prepcb)
1818 delete prepcb;
1819 if (parentcb)
1820 delete parentcb;
1821 return ENOMEM;
1822 }
1823 }
1824
1825 if (prepcb)
1826 {
1827 prepcb->cb = prepare;
94d24160 1828 List_insert (MT_INTERFACE->pthread_prepare, prepcb);
39b6859a
CF
1829 }
1830 if (parentcb)
1831 {
1832 parentcb->cb = parent;
f9f2c119 1833 callback **t = &MT_INTERFACE->pthread_parent;
39b6859a
CF
1834 while (*t)
1835 t = &(*t)->next;
79ed4300 1836 /* t = pointer to last next in the list */
94d24160 1837 List_insert (*t, parentcb);
39b6859a
CF
1838 }
1839 if (childcb)
1840 {
1841 childcb->cb = child;
f9f2c119 1842 callback **t = &MT_INTERFACE->pthread_child;
39b6859a
CF
1843 while (*t)
1844 t = &(*t)->next;
79ed4300 1845 /* t = pointer to last next in the list */
94d24160 1846 List_insert (*t, childcb);
39b6859a
CF
1847 }
1848 return 0;
1849}
1850
6a80a133
TP
1851extern "C" int
1852pthread_attr_init (pthread_attr_t *attr)
1fd5e000 1853{
00e6660b 1854 if (pthread_attr::is_good_object (attr))
1c80421c 1855 return EBUSY;
00e6660b 1856
9a08b2c0 1857 *attr = new pthread_attr;
15648790 1858 if (!pthread_attr::is_good_object (attr))
9a08b2c0
CF
1859 {
1860 delete (*attr);
1861 *attr = NULL;
00e6660b 1862 return ENOMEM;
9a08b2c0
CF
1863 }
1864 return 0;
1865}
1866
6a80a133
TP
1867extern "C" int
1868pthread_attr_getinheritsched (const pthread_attr_t *attr,
5c83f260
RC
1869 int *inheritsched)
1870{
15648790 1871 if (!pthread_attr::is_good_object (attr))
5c83f260
RC
1872 return EINVAL;
1873 *inheritsched = (*attr)->inheritsched;
1874 return 0;
1875}
1876
6a80a133
TP
1877extern "C" int
1878pthread_attr_getschedparam (const pthread_attr_t *attr,
5c83f260
RC
1879 struct sched_param *param)
1880{
15648790 1881 if (!pthread_attr::is_good_object (attr))
5c83f260
RC
1882 return EINVAL;
1883 *param = (*attr)->schedparam;
1884 return 0;
1885}
1886
79ed4300
CF
1887/* From a pure code point of view, this should call a helper in sched.cc,
1888 to allow for someone adding scheduler policy changes to win32 in the future.
1889 However that's extremely unlikely, so short and sweet will do us */
6a80a133
TP
1890extern "C" int
1891pthread_attr_getschedpolicy (const pthread_attr_t *attr, int *policy)
5c83f260 1892{
15648790 1893 if (!pthread_attr::is_good_object (attr))
5c83f260
RC
1894 return EINVAL;
1895 *policy = SCHED_FIFO;
1896 return 0;
1897}
1898
1899
6a80a133
TP
1900extern "C" int
1901pthread_attr_getscope (const pthread_attr_t *attr, int *contentionscope)
5c83f260 1902{
15648790 1903 if (!pthread_attr::is_good_object (attr))
5c83f260
RC
1904 return EINVAL;
1905 *contentionscope = (*attr)->contentionscope;
1906 return 0;
1907}
1908
6a80a133
TP
1909extern "C" int
1910pthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate)
9a08b2c0 1911{
15648790 1912 if (!pthread_attr::is_good_object (attr))
9a08b2c0
CF
1913 return EINVAL;
1914 if (detachstate < 0 || detachstate > 1)
1915 return EINVAL;
1916 (*attr)->joinable = detachstate;
1917 return 0;
1918}
1919
6a80a133
TP
1920extern "C" int
1921pthread_attr_getdetachstate (const pthread_attr_t *attr, int *detachstate)
9a08b2c0 1922{
15648790 1923 if (!pthread_attr::is_good_object (attr))
9a08b2c0
CF
1924 return EINVAL;
1925 *detachstate = (*attr)->joinable;
1fd5e000 1926 return 0;
166b2571 1927}
1fd5e000 1928
6a80a133
TP
1929extern "C" int
1930pthread_attr_setinheritsched (pthread_attr_t *attr, int inheritsched)
5c83f260 1931{
15648790 1932 if (!pthread_attr::is_good_object (attr))
5c83f260
RC
1933 return EINVAL;
1934 if (inheritsched != PTHREAD_INHERIT_SCHED
1935 && inheritsched != PTHREAD_EXPLICIT_SCHED)
1936 return ENOTSUP;
1937 (*attr)->inheritsched = inheritsched;
1938 return 0;
1939}
1940
6a80a133
TP
1941extern "C" int
1942pthread_attr_setschedparam (pthread_attr_t *attr,
5c83f260
RC
1943 const struct sched_param *param)
1944{
15648790 1945 if (!pthread_attr::is_good_object (attr))
5c83f260
RC
1946 return EINVAL;
1947 if (!valid_sched_parameters (param))
1948 return ENOTSUP;
1949 (*attr)->schedparam = *param;
1950 return 0;
1951}
1952
79ed4300 1953/* See __pthread_attr_getschedpolicy for some notes */
6a80a133
TP
1954extern "C" int
1955pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy)
5c83f260 1956{
15648790 1957 if (!pthread_attr::is_good_object (attr))
5c83f260
RC
1958 return EINVAL;
1959 if (policy != SCHED_FIFO)
1960 return ENOTSUP;
1961 return 0;
1962}
1963
6a80a133
TP
1964extern "C" int
1965pthread_attr_setscope (pthread_attr_t *attr, int contentionscope)
5c83f260 1966{
15648790 1967 if (!pthread_attr::is_good_object (attr))
5c83f260
RC
1968 return EINVAL;
1969 if (contentionscope != PTHREAD_SCOPE_SYSTEM
1970 && contentionscope != PTHREAD_SCOPE_PROCESS)
1971 return EINVAL;
79ed4300
CF
1972 /* In future, we may be able to support system scope by escalating the thread
1973 priority to exceed the priority class. For now we only support PROCESS scope. */
5c83f260
RC
1974 if (contentionscope != PTHREAD_SCOPE_PROCESS)
1975 return ENOTSUP;
1976 (*attr)->contentionscope = contentionscope;
1977 return 0;
1978}
1979
6a80a133
TP
1980extern "C" int
1981pthread_attr_setstacksize (pthread_attr_t *attr, size_t size)
1fd5e000 1982{
15648790 1983 if (!pthread_attr::is_good_object (attr))
9a08b2c0
CF
1984 return EINVAL;
1985 (*attr)->stacksize = size;
1fd5e000 1986 return 0;
166b2571 1987}
1fd5e000 1988
6a80a133
TP
1989extern "C" int
1990pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *size)
1fd5e000 1991{
15648790 1992 if (!pthread_attr::is_good_object (attr))
9a08b2c0
CF
1993 return EINVAL;
1994 *size = (*attr)->stacksize;
1fd5e000 1995 return 0;
166b2571 1996}
1fd5e000 1997
6a80a133
TP
1998extern "C" int
1999pthread_attr_destroy (pthread_attr_t *attr)
1fd5e000 2000{
15648790 2001 if (!pthread_attr::is_good_object (attr))
9a08b2c0
CF
2002 return EINVAL;
2003 delete (*attr);
2004 *attr = NULL;
1fd5e000 2005 return 0;
166b2571 2006}
1fd5e000 2007
1fd5e000 2008int
01f58e41 2009pthread::join (pthread_t *thread, void **return_val)
1fd5e000 2010{
01f58e41 2011 pthread_t joiner = self ();
e9259cb2 2012
09cbb9d6 2013 joiner->testcancel ();
f8c8e13b 2014
f6709c07
RC
2015 // Initialize return val with NULL
2016 if (return_val)
2017 *return_val = NULL;
2018
15648790 2019 if (!is_good_object (&joiner))
09cbb9d6
TP
2020 return EINVAL;
2021
15648790 2022 if (!is_good_object (thread))
9a08b2c0 2023 return ESRCH;
1fd5e000 2024
a4cea440 2025 if (equal (*thread,joiner))
f6709c07 2026 return EDEADLK;
e9259cb2 2027
15648790 2028 (*thread)->mutex.lock ();
43c3c4e3 2029
f1f13795 2030 if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
e9259cb2 2031 {
15648790 2032 (*thread)->mutex.unlock ();
43c3c4e3 2033 return EINVAL;
e9259cb2 2034 }
1fd5e000 2035 else
9a08b2c0 2036 {
e9259cb2 2037 (*thread)->joiner = joiner;
007276b3 2038 (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
15648790 2039 (*thread)->mutex.unlock ();
9450ad0d 2040
85564567 2041 switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, cw_no_cancel_self, cw_sig_resume))
ed364fa9
CF
2042 {
2043 case WAIT_OBJECT_0:
2044 if (return_val)
2045 *return_val = (*thread)->return_ptr;
2046 delete (*thread);
2047 break;
2048 case WAIT_CANCELED:
2049 // set joined thread back to joinable since we got canceled
2050 (*thread)->joiner = NULL;
2051 (*thread)->attr.joinable = PTHREAD_CREATE_JOINABLE;
2052 joiner->cancel_self ();
2053 // never reached
2054 break;
2055 default:
2056 // should never happen
2057 return EINVAL;
2058 }
09cbb9d6 2059 }
1fd5e000
CF
2060
2061 return 0;
166b2571 2062}
1fd5e000
CF
2063
2064int
01f58e41 2065pthread::detach (pthread_t *thread)
1fd5e000 2066{
15648790 2067 if (!is_good_object (thread))
9a08b2c0 2068 return ESRCH;
1fd5e000 2069
15648790 2070 (*thread)->mutex.lock ();
5c83f260 2071 if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
9a08b2c0 2072 {
15648790 2073 (*thread)->mutex.unlock ();
9a08b2c0
CF
2074 return EINVAL;
2075 }
1fd5e000 2076
43c3c4e3 2077 // check if thread is still alive
c6e0f665 2078 if ((*thread)->valid && WaitForSingleObject ((*thread)->win32_obj_id, 0) == WAIT_TIMEOUT)
43c3c4e3
RC
2079 {
2080 // force cleanup on exit
2081 (*thread)->joiner = *thread;
2082 (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
15648790 2083 (*thread)->mutex.unlock ();
43c3c4e3
RC
2084 }
2085 else
f6709c07
RC
2086 {
2087 // thread has already terminated.
15648790 2088 (*thread)->mutex.unlock ();
43c3c4e3 2089 delete (*thread);
f6709c07 2090 }
e9259cb2 2091
1fd5e000
CF
2092 return 0;
2093}
2094
2095int
01f58e41 2096pthread::suspend (pthread_t *thread)
1fd5e000 2097{
15648790 2098 if (!is_good_object (thread))
9a08b2c0 2099 return ESRCH;
1fd5e000 2100
9a08b2c0
CF
2101 if ((*thread)->suspended == false)
2102 {
2103 (*thread)->suspended = true;
2104 SuspendThread ((*thread)->win32_obj_id);
2105 }
1fd5e000
CF
2106
2107 return 0;
2108}
2109
2110
2111int
01f58e41 2112pthread::resume (pthread_t *thread)
1fd5e000 2113{
15648790 2114 if (!is_good_object (thread))
9a08b2c0 2115 return ESRCH;
1fd5e000 2116
9a08b2c0
CF
2117 if ((*thread)->suspended == true)
2118 ResumeThread ((*thread)->win32_obj_id);
2119 (*thread)->suspended = false;
1fd5e000
CF
2120
2121 return 0;
2122}
2123
79ed4300
CF
2124/* provided for source level compatability.
2125 See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2126*/
6a80a133 2127extern "C" int
2f9ae2ed 2128pthread_getconcurrency ()
5c83f260
RC
2129{
2130 return MT_INTERFACE->concurrency;
2131}
2132
79ed4300 2133/* keep this in sync with sched.cc */
6a80a133
TP
2134extern "C" int
2135pthread_getschedparam (pthread_t thread, int *policy,
5c83f260
RC
2136 struct sched_param *param)
2137{
15648790 2138 if (!pthread::is_good_object (&thread))
5c83f260
RC
2139 return ESRCH;
2140 *policy = SCHED_FIFO;
79ed4300
CF
2141 /* we don't return the current effective priority, we return the current
2142 requested priority */
5c83f260
RC
2143 *param = thread->attr.schedparam;
2144 return 0;
2145}
2146
29d52c8a 2147/* Thread Specific Data */
6a80a133
TP
2148extern "C" int
2149pthread_key_create (pthread_key_t *key, void (*destructor) (void *))
1fd5e000 2150{
5c83f260 2151 *key = new pthread_key (destructor);
9a08b2c0 2152
15648790 2153 if (!pthread_key::is_good_object (key))
9a08b2c0
CF
2154 {
2155 delete (*key);
2156 *key = NULL;
2157 return EAGAIN;
2158 }
2159 return 0;
166b2571 2160}
1fd5e000 2161
6a80a133
TP
2162extern "C" int
2163pthread_key_delete (pthread_key_t key)
1fd5e000 2164{
15648790 2165 if (!pthread_key::is_good_object (&key))
9a08b2c0
CF
2166 return EINVAL;
2167
5c83f260
RC
2168 delete (key);
2169 return 0;
2170}
2171
79ed4300
CF
2172/* provided for source level compatability. See
2173http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2174*/
6a80a133
TP
2175extern "C" int
2176pthread_setconcurrency (int new_level)
5c83f260
RC
2177{
2178 if (new_level < 0)
2179 return EINVAL;
2180 MT_INTERFACE->concurrency = new_level;
9a08b2c0 2181 return 0;
166b2571 2182}
9a08b2c0 2183
79ed4300 2184/* keep syncronised with sched.cc */
6a80a133
TP
2185extern "C" int
2186pthread_setschedparam (pthread_t thread, int policy,
5c83f260
RC
2187 const struct sched_param *param)
2188{
15648790 2189 if (!pthread::is_good_object (&thread))
5c83f260
RC
2190 return ESRCH;
2191 if (policy != SCHED_FIFO)
2192 return ENOTSUP;
2193 if (!param)
2194 return EINVAL;
2195 int rv =
2196 sched_set_thread_priority (thread->win32_obj_id, param->sched_priority);
2197 if (!rv)
2198 thread->attr.schedparam.sched_priority = param->sched_priority;
2199 return rv;
2200}
2201
9a08b2c0 2202
6a80a133
TP
2203extern "C" int
2204pthread_setspecific (pthread_key_t key, const void *value)
1fd5e000 2205{
15648790 2206 if (!pthread_key::is_good_object (&key))
9a08b2c0
CF
2207 return EINVAL;
2208 (key)->set (value);
2209 return 0;
166b2571 2210}
9a08b2c0 2211
6a80a133
TP
2212extern "C" void *
2213pthread_getspecific (pthread_key_t key)
1fd5e000 2214{
15648790 2215 if (!pthread_key::is_good_object (&key))
9a08b2c0
CF
2216 return NULL;
2217
2218 return (key)->get ();
2219
166b2571 2220}
1fd5e000 2221
6a80a133
TP
2222extern "C" int
2223pthread_cond_destroy (pthread_cond_t *cond)
5ccbf4b6 2224{
15648790 2225 if (pthread_cond::is_good_initializer (cond))
f38ac9b7 2226 return 0;
15648790 2227 if (!pthread_cond::is_good_object (cond))
9a08b2c0 2228 return EINVAL;
5ccbf4b6 2229
79ed4300 2230 /* reads are atomic */
9a08b2c0
CF
2231 if ((*cond)->waiting)
2232 return EBUSY;
5ccbf4b6 2233
9a08b2c0
CF
2234 delete (*cond);
2235 *cond = NULL;
5ccbf4b6 2236
5ccbf4b6
CF
2237 return 0;
2238}
2239
2240int
ed9fe455 2241pthread_cond::init (pthread_cond_t *cond, const pthread_condattr_t *attr)
5ccbf4b6 2242{
b95ae504
TP
2243 pthread_cond_t new_cond;
2244
15648790 2245 if (attr && !pthread_condattr::is_good_object (attr))
5ccbf4b6 2246 return EINVAL;
28194e81
TP
2247
2248 cond_initialization_lock.lock ();
f352ebca 2249
b95ae504
TP
2250 new_cond = new pthread_cond (attr ? (*attr) : NULL);
2251 if (!is_good_object (&new_cond))
9a08b2c0 2252 {
b95ae504 2253 delete new_cond;
15648790 2254 cond_initialization_lock.unlock ();
9a08b2c0
CF
2255 return EAGAIN;
2256 }
b95ae504 2257
f352ebca
CV
2258 myfault efault;
2259 if (efault.faulted ())
2260 {
2261 delete new_cond;
2262 cond_initialization_lock.unlock ();
2263 return EINVAL;
2264 }
2265
b95ae504 2266 *cond = new_cond;
15648790 2267 cond_initialization_lock.unlock ();
b95ae504 2268
9a08b2c0 2269 return 0;
5ccbf4b6
CF
2270}
2271
6a80a133
TP
2272extern "C" int
2273pthread_cond_broadcast (pthread_cond_t *cond)
5ccbf4b6 2274{
15648790 2275 if (pthread_cond::is_good_initializer (cond))
f592b05d 2276 return 0;
15648790 2277 if (!pthread_cond::is_good_object (cond))
9a08b2c0 2278 return EINVAL;
94b03f23 2279
15648790 2280 (*cond)->unblock (true);
5ccbf4b6
CF
2281
2282 return 0;
2283}
2284
6a80a133
TP
2285extern "C" int
2286pthread_cond_signal (pthread_cond_t *cond)
5ccbf4b6 2287{
15648790 2288 if (pthread_cond::is_good_initializer (cond))
f592b05d 2289 return 0;
15648790 2290 if (!pthread_cond::is_good_object (cond))
9a08b2c0 2291 return EINVAL;
5ccbf4b6 2292
15648790 2293 (*cond)->unblock (false);
5ccbf4b6
CF
2294
2295 return 0;
2296}
2297
f592b05d 2298static int
86336f4f 2299__pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex,
f592b05d
TP
2300 DWORD waitlength)
2301{
15648790 2302 if (!pthread_mutex::is_good_object (mutex))
f592b05d 2303 return EINVAL;
15648790 2304 if (!pthread_mutex::can_be_unlocked (mutex))
f592b05d
TP
2305 return EPERM;
2306
15648790 2307 if (pthread_cond::is_good_initializer (cond))
ed9fe455 2308 pthread_cond::init (cond, NULL);
15648790 2309 if (!pthread_cond::is_good_object (cond))
5ccbf4b6 2310 return EINVAL;
462f4eff 2311
15648790 2312 return (*cond)->wait (*mutex, waitlength);
5ccbf4b6
CF
2313}
2314
86336f4f
RC
2315extern "C" int
2316pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
2317 const struct timespec *abstime)
94b03f23 2318{
f592b05d 2319 struct timeval tv;
8cba6920 2320 DWORD waitlength;
f592b05d 2321
a64b8b2d 2322 myfault efault;
4c157aa9 2323 if (efault.faulted ())
94b03f23 2324 return EINVAL;
f592b05d 2325
4c157aa9
CF
2326 pthread_testcancel ();
2327
8cba6920
CV
2328 /* According to SUSv3, the abstime value must be checked for validity. */
2329 if (abstime->tv_sec < 0
2330 || abstime->tv_nsec < 0
2331 || abstime->tv_nsec > 999999999)
2332 return EINVAL;
2333
f592b05d 2334 gettimeofday (&tv, NULL);
8cba6920
CV
2335 /* Check for immediate timeout before converting to microseconds, since
2336 the resulting value can easily overflow long. This also allows to
2337 evaluate microseconds directly in DWORD. */
2338 if (tv.tv_sec > abstime->tv_sec
2339 || (tv.tv_sec == abstime->tv_sec
1cd06583 2340 && tv.tv_usec > abstime->tv_nsec / 1000))
86336f4f 2341 return ETIMEDOUT;
8cba6920
CV
2342
2343 waitlength = (abstime->tv_sec - tv.tv_sec) * 1000;
2344 waitlength += (abstime->tv_nsec / 1000 - tv.tv_usec) / 1000;
86336f4f
RC
2345 return __pthread_cond_dowait (cond, mutex, waitlength);
2346}
9a08b2c0 2347
86336f4f
RC
2348extern "C" int
2349pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
2350{
f592b05d
TP
2351 pthread_testcancel ();
2352
86336f4f 2353 return __pthread_cond_dowait (cond, mutex, INFINITE);
5ccbf4b6
CF
2354}
2355
6a80a133
TP
2356extern "C" int
2357pthread_condattr_init (pthread_condattr_t *condattr)
5ccbf4b6 2358{
00e6660b 2359 if (pthread_condattr::is_good_object (condattr))
1c80421c 2360 return EBUSY;
00e6660b 2361
9a08b2c0 2362 *condattr = new pthread_condattr;
15648790 2363 if (!pthread_condattr::is_good_object (condattr))
9a08b2c0
CF
2364 {
2365 delete (*condattr);
2366 *condattr = NULL;
00e6660b 2367 return ENOMEM;
9a08b2c0 2368 }
5ccbf4b6
CF
2369 return 0;
2370}
2371
6a80a133
TP
2372extern "C" int
2373pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
5ccbf4b6 2374{
15648790 2375 if (!pthread_condattr::is_good_object (attr))
5ccbf4b6 2376 return EINVAL;
9a08b2c0 2377 *pshared = (*attr)->shared;
5ccbf4b6
CF
2378 return 0;
2379}
2380
6a80a133
TP
2381extern "C" int
2382pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared)
5ccbf4b6 2383{
15648790 2384 if (!pthread_condattr::is_good_object (attr))
5ccbf4b6 2385 return EINVAL;
9a08b2c0
CF
2386 if ((pshared < 0) || (pshared > 1))
2387 return EINVAL;
79ed4300 2388 /* shared cond vars not currently supported */
9450ad0d
RC
2389 if (pshared != PTHREAD_PROCESS_PRIVATE)
2390 return EINVAL;
9a08b2c0 2391 (*attr)->shared = pshared;
5ccbf4b6
CF
2392 return 0;
2393}
2394
6a80a133
TP
2395extern "C" int
2396pthread_condattr_destroy (pthread_condattr_t *condattr)
5ccbf4b6 2397{
15648790 2398 if (!pthread_condattr::is_good_object (condattr))
9a08b2c0
CF
2399 return EINVAL;
2400 delete (*condattr);
2401 *condattr = NULL;
5ccbf4b6
CF
2402 return 0;
2403}
2404
6a80a133
TP
2405extern "C" int
2406pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
00d296a3 2407{
15648790 2408 if (pthread_rwlock::is_good_initializer (rwlock))
00d296a3 2409 return 0;
15648790 2410 if (!pthread_rwlock::is_good_object (rwlock))
00d296a3
TP
2411 return EINVAL;
2412
2413 if ((*rwlock)->writer || (*rwlock)->readers ||
15648790 2414 (*rwlock)->waiting_readers || (*rwlock)->waiting_writers)
00d296a3
TP
2415 return EBUSY;
2416
2417 delete (*rwlock);
2418 *rwlock = NULL;
2419
2420 return 0;
2421}
2422
2423int
2424pthread_rwlock::init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
2425{
b95ae504
TP
2426 pthread_rwlock_t new_rwlock;
2427
15648790 2428 if (attr && !pthread_rwlockattr::is_good_object (attr))
00d296a3 2429 return EINVAL;
28194e81
TP
2430
2431 rwlock_initialization_lock.lock ();
f352ebca 2432
b95ae504
TP
2433 new_rwlock = new pthread_rwlock (attr ? (*attr) : NULL);
2434 if (!is_good_object (&new_rwlock))
00d296a3 2435 {
b95ae504 2436 delete new_rwlock;
15648790 2437 rwlock_initialization_lock.unlock ();
00d296a3
TP
2438 return EAGAIN;
2439 }
b95ae504 2440
f352ebca
CV
2441 myfault efault;
2442 if (efault.faulted ())
2443 {
2444 delete new_rwlock;
2445 rwlock_initialization_lock.unlock ();
2446 return EINVAL;
2447 }
2448
b95ae504 2449 *rwlock = new_rwlock;
15648790 2450 rwlock_initialization_lock.unlock ();
b95ae504 2451
00d296a3
TP
2452 return 0;
2453}
2454
6a80a133
TP
2455extern "C" int
2456pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
00d296a3
TP
2457{
2458 pthread_testcancel ();
2459
15648790 2460 if (pthread_rwlock::is_good_initializer (rwlock))
00d296a3 2461 pthread_rwlock::init (rwlock, NULL);
15648790 2462 if (!pthread_rwlock::is_good_object (rwlock))
00d296a3
TP
2463 return EINVAL;
2464
15648790 2465 return (*rwlock)->rdlock ();
00d296a3
TP
2466}
2467
6a80a133
TP
2468extern "C" int
2469pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
00d296a3 2470{
15648790 2471 if (pthread_rwlock::is_good_initializer (rwlock))
00d296a3 2472 pthread_rwlock::init (rwlock, NULL);
15648790 2473 if (!pthread_rwlock::is_good_object (rwlock))
00d296a3
TP
2474 return EINVAL;
2475
15648790 2476 return (*rwlock)->tryrdlock ();
00d296a3
TP
2477}
2478
6a80a133
TP
2479extern "C" int
2480pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
00d296a3
TP
2481{
2482 pthread_testcancel ();
2483
15648790 2484 if (pthread_rwlock::is_good_initializer (rwlock))
00d296a3 2485 pthread_rwlock::init (rwlock, NULL);
15648790 2486 if (!pthread_rwlock::is_good_object (rwlock))
00d296a3
TP
2487 return EINVAL;
2488
15648790 2489 return (*rwlock)->wrlock ();
00d296a3
TP
2490}
2491
6a80a133
TP
2492extern "C" int
2493pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
00d296a3 2494{
15648790 2495 if (pthread_rwlock::is_good_initializer (rwlock))
00d296a3 2496 pthread_rwlock::init (rwlock, NULL);
15648790 2497 if (!pthread_rwlock::is_good_object (rwlock))
00d296a3
TP
2498 return EINVAL;
2499
15648790 2500 return (*rwlock)->trywrlock ();
00d296a3
TP
2501}
2502
6a80a133
TP
2503extern "C" int
2504pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
00d296a3 2505{
15648790 2506 if (pthread_rwlock::is_good_initializer (rwlock))
00d296a3 2507 return 0;
15648790 2508 if (!pthread_rwlock::is_good_object (rwlock))
00d296a3
TP
2509 return EINVAL;
2510
15648790 2511 return (*rwlock)->unlock ();
00d296a3
TP
2512}
2513
6a80a133
TP
2514extern "C" int
2515pthread_rwlockattr_init (pthread_rwlockattr_t *rwlockattr)
00d296a3 2516{
00e6660b 2517 if (pthread_rwlockattr::is_good_object (rwlockattr))
1c80421c 2518 return EBUSY;
00e6660b 2519
00d296a3 2520 *rwlockattr = new pthread_rwlockattr;
15648790 2521 if (!pthread_rwlockattr::is_good_object (rwlockattr))
00d296a3
TP
2522 {
2523 delete (*rwlockattr);
2524 *rwlockattr = NULL;
00e6660b 2525 return ENOMEM;
00d296a3
TP
2526 }
2527 return 0;
2528}
2529
6a80a133
TP
2530extern "C" int
2531pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared)
00d296a3 2532{
15648790 2533 if (!pthread_rwlockattr::is_good_object (attr))
00d296a3
TP
2534 return EINVAL;
2535 *pshared = (*attr)->shared;
2536 return 0;
2537}
2538
6a80a133
TP
2539extern "C" int
2540pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
00d296a3 2541{
15648790 2542 if (!pthread_rwlockattr::is_good_object (attr))
00d296a3
TP
2543 return EINVAL;
2544 if ((pshared < 0) || (pshared > 1))
2545 return EINVAL;
2546 /* shared rwlock vars not currently supported */
2547 if (pshared != PTHREAD_PROCESS_PRIVATE)
2548 return EINVAL;
2549 (*attr)->shared = pshared;
2550 return 0;
2551}
2552
6a80a133
TP
2553extern "C" int
2554pthread_rwlockattr_destroy (pthread_rwlockattr_t *rwlockattr)
00d296a3 2555{
15648790 2556 if (!pthread_rwlockattr::is_good_object (rwlockattr))
00d296a3
TP
2557 return EINVAL;
2558 delete (*rwlockattr);
2559 *rwlockattr = NULL;
2560 return 0;
2561}
2562
79ed4300 2563/* Thread signal */
6a80a133
TP
2564extern "C" int
2565pthread_kill (pthread_t thread, int sig)
1fd5e000 2566{
79ed4300 2567 // lock myself, for the use of thread2signal
ac9841a0 2568 // two different kills might clash: FIXME
1fd5e000 2569
15648790 2570 if (!pthread::is_good_object (&thread))
9a08b2c0
CF
2571 return EINVAL;
2572
985d0e68 2573 siginfo_t si = {0};
f6936c48
CF
2574 si.si_signo = sig;
2575 si.si_code = SI_USER;
f153e6b2
CF
2576 si.si_pid = myself->pid;
2577 si.si_uid = myself->uid;
b40597cb
CF
2578 int rval;
2579 if (!thread->valid)
2580 rval = ESRCH;
2581 else if (sig)
2582 {
2583 thread->cygtls->set_threadkill ();
2584 rval = sig_send (NULL, si, thread->cygtls);
2585 }
2586 else
2587 switch (WaitForSingleObject (thread->win32_obj_id, 0))
2588 {
2589 case WAIT_TIMEOUT:
2590 rval = 0;
2591 break;
2592 default:
2593 rval = ESRCH;
2594 break;
2595 }
1fd5e000 2596
94b03f23 2597 // unlock myself
1fd5e000 2598 return rval;
166b2571 2599}
1fd5e000 2600
6a80a133
TP
2601extern "C" int
2602pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set)
1fd5e000 2603{
9a4d574b 2604 return handle_sigprocmask (operation, set, old_set, _my_tls.sigmask);
166b2571 2605}
1fd5e000 2606
f9f2c119 2607/* ID */
1fd5e000 2608
9306ba2e 2609extern "C" int
6a80a133 2610pthread_equal (pthread_t t1, pthread_t t2)
1fd5e000 2611{
a4cea440 2612 return pthread::equal (t1, t2);
166b2571 2613}
1fd5e000 2614
79ed4300 2615/* Mutexes */
1fd5e000
CF
2616
2617int
eb208df0 2618pthread_mutex::init (pthread_mutex_t *mutex,
e3778517
CF
2619 const pthread_mutexattr_t *attr,
2620 const pthread_mutex_t initializer)
1fd5e000 2621{
a64b8b2d 2622 if (attr && !pthread_mutexattr::is_good_object (attr))
9a08b2c0 2623 return EINVAL;
28194e81
TP
2624
2625 mutex_initialization_lock.lock ();
2b1407d3 2626 if (initializer == NULL || pthread_mutex::is_good_initializer (mutex))
9a08b2c0 2627 {
3700578e
CF
2628 pthread_mutex_t new_mutex = new pthread_mutex (attr ? (*attr) : NULL);
2629 if (!is_good_object (&new_mutex))
2630 {
2631 delete new_mutex;
2632 mutex_initialization_lock.unlock ();
2633 return EAGAIN;
2634 }
b95ae504 2635
3700578e
CF
2636 if (!attr && initializer)
2637 {
2638 if (initializer == PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
2639 new_mutex->type = PTHREAD_MUTEX_RECURSIVE;
2640 else if (initializer == PTHREAD_NORMAL_MUTEX_INITIALIZER_NP)
2641 new_mutex->type = PTHREAD_MUTEX_NORMAL;
2642 else if (initializer == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)
2643 new_mutex->type = PTHREAD_MUTEX_ERRORCHECK;
2644 }
b95ae504 2645
3700578e
CF
2646 myfault efault;
2647 if (efault.faulted ())
2648 {
2649 delete new_mutex;
2650 mutex_initialization_lock.unlock ();
2651 return EINVAL;
2652 }
f352ebca 2653
3700578e
CF
2654 *mutex = new_mutex;
2655 }
15648790 2656 mutex_initialization_lock.unlock ();
b95ae504 2657
1fd5e000 2658 return 0;
166b2571 2659}
1fd5e000 2660
6a80a133
TP
2661extern "C" int
2662pthread_mutex_getprioceiling (const pthread_mutex_t *mutex,
5c83f260
RC
2663 int *prioceiling)
2664{
79ed4300
CF
2665 /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
2666 mutex priorities.
2667
2668 We can support mutex priorities in the future though:
2669 Store a priority with each mutex.
2670 When the mutex is optained, set the thread priority as appropriate
2671 When the mutex is released, reset the thread priority. */
5c83f260
RC
2672 return ENOSYS;
2673}
2674
9306ba2e 2675extern "C" int
6a80a133 2676pthread_mutex_lock (pthread_mutex_t *mutex)
1fd5e000 2677{
b95ae504
TP
2678 if (pthread_mutex::is_good_initializer (mutex))
2679 pthread_mutex::init (mutex, NULL, *mutex);
2680 if (!pthread_mutex::is_good_object (mutex))
2681 return EINVAL;
2682 return (*mutex)->lock ();
166b2571 2683}
1fd5e000 2684
6a80a133
TP
2685extern "C" int
2686pthread_mutex_trylock (pthread_mutex_t *mutex)
1fd5e000 2687{
15648790 2688 if (pthread_mutex::is_good_initializer (mutex))
b95ae504
TP
2689 pthread_mutex::init (mutex, NULL, *mutex);
2690 if (!pthread_mutex::is_good_object (mutex))
9a08b2c0 2691 return EINVAL;
b95ae504 2692 return (*mutex)->trylock ();
166b2571 2693}
1fd5e000 2694
6a80a133
TP
2695extern "C" int
2696pthread_mutex_unlock (pthread_mutex_t *mutex)
1fd5e000 2697{
15648790 2698 if (pthread_mutex::is_good_initializer (mutex))
b95ae504 2699 return EPERM;
15648790 2700 if (!pthread_mutex::is_good_object (mutex))
9a08b2c0 2701 return EINVAL;
15648790 2702 return (*mutex)->unlock ();
166b2571 2703}
1fd5e000 2704
6a80a133
TP
2705extern "C" int
2706pthread_mutex_destroy (pthread_mutex_t *mutex)
1fd5e000 2707{
5d68d1de
TP
2708 int rv;
2709
15648790 2710 if (pthread_mutex::is_good_initializer (mutex))
5c83f260 2711 return 0;
15648790 2712 if (!pthread_mutex::is_good_object (mutex))
9a08b2c0 2713 return EINVAL;
1fd5e000 2714
15648790 2715 rv = (*mutex)->destroy ();
5d68d1de
TP
2716 if (rv)
2717 return rv;
1fd5e000 2718
9a08b2c0 2719 *mutex = NULL;
1fd5e000 2720 return 0;
166b2571 2721}
1fd5e000 2722
6a80a133
TP
2723extern "C" int
2724pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling,
5c83f260
RC
2725 int *old_ceiling)
2726{
5c83f260
RC
2727 return ENOSYS;
2728}
2729
79ed4300
CF
2730/* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
2731 for more detail */
6a80a133
TP
2732extern "C" int
2733pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr,
5c83f260
RC
2734 int *protocol)
2735{
15648790 2736 if (!pthread_mutexattr::is_good_object (attr))
5c83f260
RC
2737 return EINVAL;
2738 return ENOSYS;
2739}
2740
6a80a133
TP
2741extern "C" int
2742pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr,
5c83f260
RC
2743 int *pshared)
2744{
15648790 2745 if (!pthread_mutexattr::is_good_object (attr))
5c83f260
RC
2746 return EINVAL;
2747 *pshared = (*attr)->pshared;
2748 return 0;
2749}
2750
6a80a133
TP
2751extern "C" int
2752pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type)
5c83f260 2753{
15648790 2754 if (!pthread_mutexattr::is_good_object (attr))
5c83f260
RC
2755 return EINVAL;
2756 *type = (*attr)->mutextype;
2757 return 0;
2758}
2759
5d68d1de 2760/* FIXME: write and test process shared mutex's. */
6a80a133
TP
2761extern "C" int
2762pthread_mutexattr_init (pthread_mutexattr_t *attr)
5c83f260 2763{
15648790 2764 if (pthread_mutexattr::is_good_object (attr))
1c80421c 2765 return EBUSY;
5c83f260
RC
2766
2767 *attr = new pthread_mutexattr ();
15648790 2768 if (!pthread_mutexattr::is_good_object (attr))
5c83f260
RC
2769 {
2770 delete (*attr);
2771 *attr = NULL;
2772 return ENOMEM;
2773 }
2774 return 0;
2775}
2776
6a80a133
TP
2777extern "C" int
2778pthread_mutexattr_destroy (pthread_mutexattr_t *attr)
5c83f260 2779{
15648790 2780 if (!pthread_mutexattr::is_good_object (attr))
5c83f260
RC
2781 return EINVAL;
2782 delete (*attr);
2783 *attr = NULL;
2784 return 0;
2785}
2786
2787
79ed4300 2788/* Win32 doesn't support mutex priorities */
6a80a133
TP
2789extern "C" int
2790pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, int protocol)
5c83f260 2791{
15648790 2792 if (!pthread_mutexattr::is_good_object (attr))
5c83f260
RC
2793 return EINVAL;
2794 return ENOSYS;
2795}
2796
79ed4300 2797/* Win32 doesn't support mutex priorities */
6a80a133
TP
2798extern "C" int
2799pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr,
5c83f260
RC
2800 int prioceiling)
2801{
15648790 2802 if (!pthread_mutexattr::is_good_object (attr))
5c83f260
RC
2803 return EINVAL;
2804 return ENOSYS;
2805}
2806
6a80a133
TP
2807extern "C" int
2808pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *attr,
5c83f260
RC
2809 int *prioceiling)
2810{
15648790 2811 if (!pthread_mutexattr::is_good_object (attr))
5c83f260
RC
2812 return EINVAL;
2813 return ENOSYS;
2814}
2815
6a80a133
TP
2816extern "C" int
2817pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared)
5c83f260 2818{
15648790 2819 if (!pthread_mutexattr::is_good_object (attr))
5c83f260 2820 return EINVAL;
79ed4300 2821 /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
f9f2c119 2822 *functionality
5c83f260 2823 */
ac9841a0 2824 if (pshared != PTHREAD_PROCESS_PRIVATE)
5c83f260
RC
2825 return EINVAL;
2826 (*attr)->pshared = pshared;
2827 return 0;
2828}
2829
6a80a133
TP
2830/* see pthread_mutex_gettype */
2831extern "C" int
2832pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type)
5c83f260 2833{
15648790 2834 if (!pthread_mutexattr::is_good_object (attr))
5c83f260 2835 return EINVAL;
9a47ce7f 2836
5d68d1de
TP
2837 switch (type)
2838 {
2839 case PTHREAD_MUTEX_ERRORCHECK:
2840 case PTHREAD_MUTEX_RECURSIVE:
2ff03dc2 2841 case PTHREAD_MUTEX_NORMAL:
5d68d1de
TP
2842 (*attr)->mutextype = type;
2843 break;
2844 default:
2845 return EINVAL;
2846 }
2847
5c83f260
RC
2848 return 0;
2849}
2850
79ed4300 2851/* Semaphores */
8b1978c3 2852
8fbd574e
CV
2853List<semaphore> semaphore::semaphores;
2854
2855semaphore::semaphore (int pshared, unsigned int value)
2856: verifyable_object (SEM_MAGIC),
2857 shared (pshared),
2858 currentvalue (value),
2859 fd (-1),
2860 hash (0ULL),
2861 sem (NULL)
2862{
2863 SECURITY_ATTRIBUTES sa = (pshared != PTHREAD_PROCESS_PRIVATE)
2864 ? sec_all : sec_none_nih;
2865 this->win32_obj_id = ::CreateSemaphore (&sa, value, LONG_MAX, NULL);
2866 if (!this->win32_obj_id)
2867 magic = 0;
2868
2869 semaphores.insert (this);
2870}
2871
2872semaphore::semaphore (unsigned long long shash, LUID sluid, int sfd,
2873 sem_t *ssem, int oflag, mode_t mode, unsigned int value)
2874: verifyable_object (SEM_MAGIC),
2875 shared (PTHREAD_PROCESS_SHARED),
2876 currentvalue (value), /* Unused for named semaphores. */
2877 fd (sfd),
2878 hash (shash),
2879 luid (sluid),
2880 sem (ssem)
2881{
5224a7bb 2882 char name[MAX_PATH];
8fbd574e 2883
dc74da05 2884 __small_sprintf (name, "semaphore/%016X%08x%08x",
8fbd574e
CV
2885 hash, luid.HighPart, luid.LowPart);
2886 this->win32_obj_id = ::CreateSemaphore (&sec_all, value, LONG_MAX, name);
2887 if (!this->win32_obj_id)
2888 magic = 0;
2889 if (GetLastError () == ERROR_ALREADY_EXISTS && (oflag & O_EXCL))
2890 {
2891 __seterrno ();
2892 CloseHandle (this->win32_obj_id);
2893 magic = 0;
2894 }
2895
2896 semaphores.insert (this);
2897}
2898
2899semaphore::~semaphore ()
2900{
2901 if (win32_obj_id)
2902 CloseHandle (win32_obj_id);
2903
2904 semaphores.remove (this);
2905}
2906
2907void
2908semaphore::_post ()
2909{
2910 if (ReleaseSemaphore (win32_obj_id, 1, &currentvalue))
2911 currentvalue++;
2912}
2913
2914int
2915semaphore::_getvalue (int *sval)
2916{
2917 long val;
2918
2919 switch (WaitForSingleObject (win32_obj_id, 0))
2920 {
2921 case WAIT_OBJECT_0:
2922 ReleaseSemaphore (win32_obj_id, 1, &val);
2923 *sval = val + 1;
2924 break;
2925 case WAIT_TIMEOUT:
2926 *sval = 0;
2927 break;
2928 default:
2929 set_errno (EAGAIN);
2930 return -1;
2931 }
2932 return 0;
2933}
2934
2935int
2936semaphore::_trywait ()
2937{
2938 /* FIXME: signals should be able to interrupt semaphores...
2939 We probably need WaitForMultipleObjects here. */
2940 if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)
2941 {
2942 set_errno (EAGAIN);
2943 return -1;
2944 }
2945 currentvalue--;
2946 return 0;
2947}
2948
2949int
2950semaphore::_timedwait (const struct timespec *abstime)
2951{
2952 struct timeval tv;
2953 long waitlength;
2954
2955 myfault efault;
2956 if (efault.faulted ())
2957 {
2958 /* According to SUSv3, abstime need not be checked for validity,
2959 if the semaphore can be locked immediately. */
2960 if (!_trywait ())
2961 return 0;
2962 set_errno (EINVAL);
2963 return -1;
2964 }
2965
2966 gettimeofday (&tv, NULL);
2967 waitlength = abstime->tv_sec * 1000 + abstime->tv_nsec / (1000 * 1000);
2968 waitlength -= tv.tv_sec * 1000 + tv.tv_usec / 1000;
2969 if (waitlength < 0)
2970 waitlength = 0;
2971 switch (cancelable_wait (win32_obj_id, waitlength, cw_cancel_self, cw_sig_eintr))
2972 {
2973 case WAIT_OBJECT_0:
2974 currentvalue--;
2975 break;
2976 case WAIT_SIGNALED:
2977 set_errno (EINTR);
2978 return -1;
2979 case WAIT_TIMEOUT:
2980 set_errno (ETIMEDOUT);
2981 return -1;
2982 default:
2983 debug_printf ("cancelable_wait failed. %E");
2984 __seterrno ();
2985 return -1;
2986 }
2987 return 0;
2988}
2989
2990int
2991semaphore::_wait ()
2992{
2993 switch (cancelable_wait (win32_obj_id, INFINITE, cw_cancel_self, cw_sig_eintr))
2994 {
2995 case WAIT_OBJECT_0:
2996 currentvalue--;
2997 break;
2998 case WAIT_SIGNALED:
2999 set_errno (EINTR);
3000 return -1;
3001 default:
3002 debug_printf ("cancelable_wait failed. %E");
3003 break;
3004 }
3005 return 0;
3006}
3007
3008void
3009semaphore::_fixup_after_fork ()
3010{
3011 if (shared == PTHREAD_PROCESS_PRIVATE)
3012 {
3013 debug_printf ("sem %x in _fixup_after_fork", this);
3014 /* FIXME: duplicate code here and in the constructor. */
3015 this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, currentvalue,
3016 LONG_MAX, NULL);
3017 if (!win32_obj_id)
3018 api_fatal ("failed to create new win32 semaphore, error %d");
3019 }
3020}
3021
3022void
3023semaphore::_terminate ()
3024{
3025 int _sem_close (sem_t *, bool);
3026
3027 if (sem)
3028 _sem_close (sem, false);
3029}
3030
8b1978c3 3031/* static members */
8b1978c3 3032
1fd5e000 3033int
01f58e41 3034semaphore::init (sem_t *sem, int pshared, unsigned int value)
1fd5e000 3035{
79ed4300 3036 /* opengroup calls this undefined */
15648790 3037 if (is_good_object (sem))
9a08b2c0 3038 return EBUSY;
1fd5e000 3039
9a08b2c0
CF
3040 if (value > SEM_VALUE_MAX)
3041 return EINVAL;
1fd5e000 3042
9a08b2c0 3043 *sem = new semaphore (pshared, value);
1fd5e000 3044
15648790 3045 if (!is_good_object (sem))
9a08b2c0
CF
3046 {
3047 delete (*sem);
3048 *sem = NULL;
3049 return EAGAIN;
3050 }
1fd5e000 3051 return 0;
166b2571 3052}
1fd5e000
CF
3053
3054int
01f58e41 3055semaphore::destroy (sem_t *sem)
1fd5e000 3056{
15648790 3057 if (!is_good_object (sem))
9a08b2c0 3058 return EINVAL;
1fd5e000 3059
8fbd574e
CV
3060 /* It's invalid to destroy a semaphore not opened with sem_init. */
3061 if ((*sem)->fd != -1)
3062 return EINVAL;
3063
79ed4300 3064 /* FIXME - new feature - test for busy against threads... */
1fd5e000 3065
9a08b2c0
CF
3066 delete (*sem);
3067 *sem = NULL;
1fd5e000 3068 return 0;
166b2571 3069}
1fd5e000 3070
8fbd574e
CV
3071int
3072semaphore::close (sem_t *sem)
3073{
3074 if (!is_good_object (sem))
3075 return EINVAL;
3076
3077 /* It's invalid to close a semaphore not opened with sem_open. */
3078 if ((*sem)->fd == -1)
3079 return EINVAL;
3080
3081 delete (*sem);
3082 delete sem;
3083 return 0;
3084}
3085
07233966 3086sem_t *
8fbd574e
CV
3087semaphore::open (unsigned long long hash, LUID luid, int fd, int oflag,
3088 mode_t mode, unsigned int value, bool &wasopen)
07233966
CV
3089{
3090 if (value > SEM_VALUE_MAX)
3091 {
3092 set_errno (EINVAL);
3093 return NULL;
3094 }
3095
8fbd574e
CV
3096 /* sem_open is supposed to return the same pointer, if the same named
3097 semaphore is opened multiple times in the same process, as long as
3098 the semaphore hasn't been closed or unlinked in the meantime. */
3099 semaphores.mx.lock ();
3100 for (semaphore *sema = semaphores.head; sema; sema = sema->next)
3101 if (sema->fd >= 0 && sema->hash == hash
3102 && sema->luid.HighPart == luid.HighPart
3103 && sema->luid.LowPart == sema->luid.LowPart)
3104 {
3105 wasopen = true;
3106 semaphores.mx.unlock ();
3107 return sema->sem;
3108 }
3109 semaphores.mx.unlock ();
3110
3111 wasopen = false;
07233966
CV
3112 sem_t *sem = new sem_t;
3113 if (!sem)
3114 {
3115 set_errno (ENOMEM);
3116 return NULL;
3117 }
3118
8fbd574e 3119 *sem = new semaphore (hash, luid, fd, sem, oflag, mode, value);
07233966
CV
3120
3121 if (!is_good_object (sem))
3122 {
3123 delete *sem;
3124 delete sem;
3125 return NULL;
3126 }
3127 return sem;
3128}
3129
1fd5e000 3130int
01f58e41 3131semaphore::wait (sem_t *sem)
1fd5e000 3132{
09cbb9d6
TP
3133 pthread_testcancel ();
3134
15648790 3135 if (!is_good_object (sem))
062401c9
RC
3136 {
3137 set_errno (EINVAL);
3138 return -1;
3139 }
1fd5e000 3140
c9a76075 3141 return (*sem)->_wait ();
166b2571 3142}
1fd5e000
CF
3143
3144int
01f58e41 3145semaphore::trywait (sem_t *sem)
1fd5e000 3146{
15648790 3147 if (!is_good_object (sem))
062401c9
RC
3148 {
3149 set_errno (EINVAL);
3150 return -1;
3151 }
1fd5e000 3152
15648790 3153 return (*sem)->_trywait ();
166b2571 3154}
1fd5e000 3155
07233966
CV
3156int
3157semaphore::timedwait (sem_t *sem, const struct timespec *abstime)
3158{
3159 if (!is_good_object (sem))
3160 {
3161 set_errno (EINVAL);
3162 return -1;
3163 }
3164
3165 return (*sem)->_timedwait (abstime);
3166}
3167
1fd5e000 3168int
01f58e41 3169semaphore::post (sem_t *sem)
1fd5e000 3170{
15648790 3171 if (!is_good_object (sem))
07233966
CV
3172 {
3173 set_errno (EINVAL);
3174 return -1;
3175 }
1fd5e000 3176
15648790 3177 (*sem)->_post ();
1fd5e000 3178 return 0;
166b2571 3179}
1fd5e000 3180
07233966
CV
3181int
3182semaphore::getvalue (sem_t *sem, int *sval)
3183{
893ac8e0
CF
3184 myfault efault;
3185 if (efault.faulted () || !is_good_object (sem))
07233966
CV
3186 {
3187 set_errno (EINVAL);
3188 return -1;
3189 }
3190
3191 return (*sem)->_getvalue (sval);
3192}
3193
8fbd574e
CV
3194int
3195semaphore::getinternal (sem_t *sem, int *sfd, unsigned long long *shash,
3196 LUID *sluid, unsigned int *sval)
3197{
3198 myfault efault;
3199 if (efault.faulted () || !is_good_object (sem))
3200 {
3201 set_errno (EINVAL);
3202 return -1;
3203 }
3204 if ((*sfd = (*sem)->fd) < 0)
3205 {
3206 set_errno (EINVAL);
3207 return -1;
3208 }
3209 *shash = (*sem)->hash;
3210 *sluid = (*sem)->luid;
3211 /* POSIX defines the value in calls to sem_init/sem_open as unsigned, but
3212 the sem_getvalue gets a pointer to int to return the value. Go figure! */
3213 return (*sem)->_getvalue ((int *)sval);
3214}
3215
15648790 3216/* pthread_null */
4e786173 3217pthread *
15648790 3218pthread_null::get_null_pthread ()
4e786173
RC
3219{
3220 /* because of weird entry points */
3221 _instance.magic = 0;
3222 return &_instance;
3223}
3224
15648790 3225pthread_null::pthread_null ()
4e786173 3226{
f8c8e13b 3227 attr.joinable = PTHREAD_CREATE_DETACHED;
4e786173
RC
3228 /* Mark ourselves as invalid */
3229 magic = 0;
3230}
3231
15648790 3232pthread_null::~pthread_null ()
4e786173
RC
3233{
3234}
3235
7d7e7a21 3236bool
15648790 3237pthread_null::create (void *(*)(void *), pthread_attr *, void *)
4e786173 3238{
7d7e7a21 3239 return true;
4e786173
RC
3240}
3241
3242void
15648790 3243pthread_null::exit (void *value_ptr)
4e786173 3244{
2eeb0e70 3245 _my_tls.remove (INFINITE);
f8c8e13b 3246 ExitThread (0);
4e786173
RC
3247}
3248
3249int
15648790 3250pthread_null::cancel ()
4e786173
RC
3251{
3252 return 0;
3253}
3254
3255void
15648790 3256pthread_null::testcancel ()
4e786173
RC
3257{
3258}
3259
3260int
15648790 3261pthread_null::setcancelstate (int state, int *oldstate)
4e786173
RC
3262{
3263 return EINVAL;
3264}
3265
3266int
15648790 3267pthread_null::setcanceltype (int type, int *oldtype)
4e786173
RC
3268{
3269 return EINVAL;
3270}
3271
3272void
15648790 3273pthread_null::push_cleanup_handler (__pthread_cleanup_handler *handler)
4e786173
RC
3274{
3275}
3276
3277void
15648790 3278pthread_null::pop_cleanup_handler (int const execute)
4e786173
RC
3279{
3280}
9a47ce7f 3281
4e786173 3282unsigned long
15648790 3283pthread_null::getsequence_np ()
4e786173
RC
3284{
3285 return 0;
3286}
3287
15648790 3288pthread_null pthread_null::_instance;
This page took 0.846683 seconds and 5 git commands to generate.