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