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