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