Cygwin: (mostly) drop NT4 and Samba < 3.0 support
[newlib-cygwin.git] / winsup / cygwin / thread.cc
blob0f8327831d6a865e991c23a650284cac0dee4134
1 /* thread.cc: Locking and threading module functions
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 details. */
9 /* Implementation overview and caveats:
11 Win32 puts some contraints on what can and cannot be implemented. Where
12 possible we work around those contrainsts. Where we cannot work around
13 the constraints we either pretend to be conformant, or return an error
14 code.
16 Some caveats: PROCESS_SHARED objects, while they pretend to be process
17 shared, may not actually work. Some test cases are needed to determine
18 win32's behaviour. My suspicion is that the win32 handle needs to be
19 opened with different flags for proper operation.
21 R.Collins, April 2001. */
23 #include "winsup.h"
24 #include "create_posix_thread.h"
25 #include "path.h"
26 #include <sched.h>
27 #include <stdlib.h>
28 #include "sigproc.h"
29 #include "fhandler.h"
30 #include "dtable.h"
31 #include "cygheap.h"
32 #include "ntdll.h"
33 #include "cygwait.h"
34 #include "exception.h"
36 /* For Linux compatibility, the length of a thread name is 16 characters. */
37 #define THRNAMELEN 16
39 extern "C" void __fp_lock_all ();
40 extern "C" void __fp_unlock_all ();
41 extern "C" bool valid_sched_parameters(const struct sched_param *);
42 extern "C" int sched_get_thread_priority(HANDLE thread);
43 extern "C" int sched_set_thread_priority(HANDLE thread, int priority);
45 extern int threadsafe;
47 const pthread_t pthread_mutex::_new_mutex = (pthread_t) 1;
48 const pthread_t pthread_mutex::_unlocked_mutex = (pthread_t) 2;
49 const pthread_t pthread_mutex::_destroyed_mutex = (pthread_t) 3;
51 template <typename T>
52 static inline
53 void
54 delete_and_clear (T * * const ptr)
56 delete *ptr;
57 *ptr = 0;
60 inline bool
61 pthread_mutex::no_owner()
63 int res;
64 if (!owner)
66 debug_printf ("NULL owner value");
67 res = 1;
69 else if (owner == _destroyed_mutex)
71 paranoid_printf ("attempt to use destroyed mutex");
72 res = 1;
74 else if (owner == _new_mutex || owner == _unlocked_mutex)
75 res = 1;
76 else
77 res = 0;
78 return res;
81 #undef __getreent
82 extern "C" struct _reent *
83 __getreent ()
85 return &_my_tls.local_clib;
88 extern "C" void
89 __cygwin_lock_init (_LOCK_T *lock)
91 *lock = _LOCK_T_INITIALIZER;
94 extern "C" void
95 __cygwin_lock_init_recursive (_LOCK_T *lock)
97 *lock = _LOCK_T_RECURSIVE_INITIALIZER;
100 extern "C" void
101 __cygwin_lock_fini (_LOCK_T *lock)
103 pthread_mutex_destroy ((pthread_mutex_t*) lock);
106 extern "C" void
107 __cygwin_lock_lock (_LOCK_T *lock)
109 paranoid_printf ("threadcount %d. locking", MT_INTERFACE->threadcount);
110 pthread_mutex_lock ((pthread_mutex_t*) lock);
113 extern "C" int
114 __cygwin_lock_trylock (_LOCK_T *lock)
116 return pthread_mutex_trylock ((pthread_mutex_t*) lock);
120 extern "C" void
121 __cygwin_lock_unlock (_LOCK_T *lock)
123 pthread_mutex_unlock ((pthread_mutex_t*) lock);
124 paranoid_printf ("threadcount %d. unlocked", MT_INTERFACE->threadcount);
127 static inline verifyable_object_state
128 verifyable_object_isvalid (void const *objectptr, thread_magic_t magic,
129 void *static_ptr1 = NULL,
130 void *static_ptr2 = NULL,
131 void *static_ptr3 = NULL)
133 verifyable_object_state state = INVALID_OBJECT;
135 __try
137 if (!objectptr || !(*(const char **) objectptr))
138 __leave;
140 verifyable_object **object = (verifyable_object **) objectptr;
142 if ((static_ptr1 && *object == static_ptr1) ||
143 (static_ptr2 && *object == static_ptr2) ||
144 (static_ptr3 && *object == static_ptr3))
145 state = VALID_STATIC_OBJECT;
146 else if ((*object)->magic == magic)
147 state = VALID_OBJECT;
149 __except (NO_ERROR) {}
150 __endtry
151 return state;
154 /* static members */
155 inline bool
156 pthread_attr::is_good_object (pthread_attr_t const *attr)
158 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
159 return false;
160 return true;
163 inline bool
164 pthread_condattr::is_good_object (pthread_condattr_t const *attr)
166 if (verifyable_object_isvalid (attr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
167 return false;
168 return true;
171 inline bool
172 pthread_rwlockattr::is_good_object (pthread_rwlockattr_t const *attr)
174 if (verifyable_object_isvalid (attr, PTHREAD_RWLOCKATTR_MAGIC) != VALID_OBJECT)
175 return false;
176 return true;
179 inline bool
180 pthread_key::is_good_object (pthread_key_t const *key)
182 if (verifyable_object_isvalid (key, PTHREAD_KEY_MAGIC) != VALID_OBJECT)
183 return false;
184 return true;
187 inline bool
188 pthread_spinlock::is_good_object (pthread_spinlock_t const *mutex)
190 if (verifyable_object_isvalid (mutex, PTHREAD_SPINLOCK_MAGIC) != VALID_OBJECT)
191 return false;
192 return true;
195 inline bool
196 pthread_mutex::is_good_object (pthread_mutex_t const *mutex)
198 if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
199 return false;
200 return true;
203 inline bool
204 pthread_mutex::is_initializer (pthread_mutex_t const *mutex)
206 if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC,
207 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
208 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP,
209 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) != VALID_STATIC_OBJECT)
210 return false;
211 return true;
214 inline bool
215 pthread_mutex::is_initializer_or_object (pthread_mutex_t const *mutex)
217 if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC,
218 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
219 PTHREAD_NORMAL_MUTEX_INITIALIZER_NP,
220 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) == INVALID_OBJECT)
221 return false;
222 return true;
225 /* FIXME: Accommodate PTHREAD_MUTEX_ERRORCHECK */
226 inline bool
227 pthread_mutex::can_be_unlocked ()
229 pthread_t self = pthread::self ();
230 /* Check if the mutex is owned by the current thread and can be unlocked.
231 * Also check for the ANONYMOUS owner to cover NORMAL mutexes as well. */
232 bool res = type == PTHREAD_MUTEX_NORMAL || no_owner ()
233 || (recursion_counter == 1 && pthread::equal (owner, self));
234 pthread_printf ("recursion_counter %u res %d", recursion_counter, res);
235 return res;
238 inline bool
239 pthread_mutexattr::is_good_object (pthread_mutexattr_t const * attr)
241 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
242 return false;
243 return true;
246 inline bool __attribute__ ((used))
247 pthread::is_good_object (pthread_t const *thread)
249 if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT)
250 return false;
251 return true;
254 /* Thread synchronisation */
255 inline bool
256 pthread_cond::is_good_object (pthread_cond_t const *cond)
258 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
259 return false;
260 return true;
263 inline bool
264 pthread_cond::is_initializer (pthread_cond_t const *cond)
266 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) != VALID_STATIC_OBJECT)
267 return false;
268 return true;
271 inline bool
272 pthread_cond::is_initializer_or_object (pthread_cond_t const *cond)
274 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) == INVALID_OBJECT)
275 return false;
276 return true;
279 inline bool
280 pthread_barrierattr::is_good_object (pthread_barrierattr_t const *cond)
282 if (verifyable_object_isvalid (cond, PTHREAD_BARRIERATTR_MAGIC)
283 != VALID_OBJECT)
284 return false;
285 return true;
288 inline bool
289 pthread_barrier::is_good_object (pthread_barrier_t const *cond)
291 if (verifyable_object_isvalid (cond, PTHREAD_BARRIER_MAGIC) != VALID_OBJECT)
292 return false;
293 return true;
296 /* RW locks */
297 inline bool
298 pthread_rwlock::is_good_object (pthread_rwlock_t const *rwlock)
300 if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC) != VALID_OBJECT)
301 return false;
302 return true;
305 inline bool
306 pthread_rwlock::is_initializer (pthread_rwlock_t const *rwlock)
308 if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, PTHREAD_RWLOCK_INITIALIZER) != VALID_STATIC_OBJECT)
309 return false;
310 return true;
313 inline bool
314 pthread_rwlock::is_initializer_or_object (pthread_rwlock_t const *rwlock)
316 if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, PTHREAD_RWLOCK_INITIALIZER) == INVALID_OBJECT)
317 return false;
318 return true;
321 inline bool
322 semaphore::is_good_object (sem_t const * sem)
324 if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
325 return false;
326 return true;
329 void
330 MTinterface::Init ()
332 pthread_mutex::init_mutex ();
333 pthread_cond::init_mutex ();
334 pthread_rwlock::init_mutex ();
337 void
338 MTinterface::fixup_before_fork ()
340 pthread_key::fixup_before_fork ();
341 semaphore::fixup_before_fork ();
344 /* This function is called from a single threaded process */
345 void
346 MTinterface::fixup_after_fork ()
348 pthread_key::fixup_after_fork ();
350 threadcount = 0;
351 pthread::init_mainthread ();
353 pthread::fixup_after_fork ();
354 pthread_mutex::fixup_after_fork ();
355 pthread_cond::fixup_after_fork ();
356 pthread_rwlock::fixup_after_fork ();
357 semaphore::fixup_after_fork ();
360 /* pthread calls */
362 /* static methods */
363 void
364 pthread::init_mainthread ()
366 pthread *thread = _my_tls.tid;
367 if (!thread || thread == pthread_null::get_null_pthread ())
369 thread = new pthread ();
370 if (!thread)
371 api_fatal ("failed to create mainthread object");
374 thread->set_tls_self_pointer ();
375 thread->thread_id = GetCurrentThreadId ();
376 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
377 GetCurrentProcess (), &thread->win32_obj_id,
378 0, FALSE, DUPLICATE_SAME_ACCESS))
379 api_fatal ("failed to create mainthread handle");
380 if (!thread->create_cancel_event ())
381 api_fatal ("couldn't create cancel event for main thread");
382 VerifyHandle (thread->win32_obj_id);
383 /* Make sure the pthread mutex is recursive. See comment in
384 pthread::precreate (called only for subsequent pthreads)
385 for a description. */
386 thread->mutex.set_type (PTHREAD_MUTEX_RECURSIVE);
387 thread->postcreate ();
390 pthread *
391 pthread::self ()
393 pthread *thread = _my_tls.tid;
394 if (!thread)
396 thread = pthread_null::get_null_pthread ();
397 thread->set_tls_self_pointer ();
399 return thread;
402 void
403 pthread::set_tls_self_pointer ()
405 cygtls = &_my_tls;
406 _my_tls.tid = this;
409 List<pthread> pthread::threads;
411 /* member methods */
412 pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),
413 valid (false), suspended (false), canceled (false),
414 cancelstate (0), canceltype (0), cancel_event (0),
415 joiner (NULL), next (NULL), cleanup_stack (NULL)
417 if (this != pthread_null::get_null_pthread ())
418 threads.insert (this);
419 sigprocmask (SIG_SETMASK, NULL, &parent_sigmask);
422 pthread::~pthread ()
424 if (win32_obj_id)
425 CloseHandle (win32_obj_id);
426 if (cancel_event)
427 CloseHandle (cancel_event);
429 if (this != pthread_null::get_null_pthread ())
430 threads.remove (this);
433 bool
434 pthread::create_cancel_event ()
436 cancel_event = ::CreateEvent (&sec_none_nih, true, false, NULL);
437 if (!cancel_event)
439 system_printf ("couldn't create cancel event, %E");
440 /* we need the event for correct behaviour */
441 return false;
443 return true;
446 void
447 pthread::precreate (pthread_attr *newattr)
449 pthread_mutex *verifyable_mutex_obj = &mutex;
451 /* already running ? */
452 if (win32_obj_id)
453 return;
455 if (newattr)
457 attr.joinable = newattr->joinable;
458 attr.contentionscope = newattr->contentionscope;
459 attr.inheritsched = newattr->inheritsched;
460 attr.schedparam = newattr->schedparam;
461 attr.stackaddr = newattr->stackaddr;
462 attr.stacksize = newattr->stacksize;
463 attr.guardsize = newattr->guardsize;
466 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
468 thread_printf ("New thread object access mutex is not valid. this %p",
469 this);
470 magic = 0;
471 return;
473 /* This mutex MUST be recursive. Consider the following scenario:
474 - The thread installs a cleanup handler.
475 - The cleanup handler calls a function which itself installs a
476 cleanup handler.
477 - pthread_cancel is called for this thread.
478 - The thread's cleanup handler is called under mutex lock condition.
479 - The cleanup handler calls the subsequent function with cleanup handler.
480 - The function runs to completion, so it calls pthread_cleanup_pop.
481 - pthread_cleanup_pop calls pthread::pop_cleanup_handler which will again
482 try to lock the mutex.
483 - Deadlock. */
484 mutex.set_type (PTHREAD_MUTEX_RECURSIVE);
485 if (!create_cancel_event ())
486 magic = 0;
489 bool
490 pthread::create (void *(*func) (void *), pthread_attr *newattr,
491 void *threadarg)
493 bool retval;
495 precreate (newattr);
496 if (!magic)
497 return false;
499 function = func;
500 arg = threadarg;
502 mutex.lock ();
503 /* stackaddr holds the uppermost stack address. See the comments in
504 pthread_attr_setstack and pthread_attr_setstackaddr for a description. */
505 ULONG stacksize = attr.stacksize ?: get_rlimit_stack ();
506 PVOID stackaddr = attr.stackaddr ? ((caddr_t) attr.stackaddr - stacksize)
507 : NULL;
508 win32_obj_id = create_posix_thread (thread_init_wrapper, this, stackaddr,
509 stacksize, attr.guardsize, 0, &thread_id);
511 if (!win32_obj_id)
513 thread_printf ("CreateThread failed: this %p, %E", this);
514 magic = 0;
516 else
518 postcreate ();
519 while (!cygtls)
520 yield ();
522 retval = magic;
523 mutex.unlock ();
524 return retval;
527 void
528 pthread::postcreate ()
530 valid = true;
532 InterlockedIncrement (&MT_INTERFACE->threadcount);
534 /* Per POSIX the new thread inherits the sched priority from its caller
535 thread if PTHREAD_INHERIT_SCHED is set.
536 FIXME: set the priority appropriately for system contention scope */
537 if (attr.inheritsched == PTHREAD_INHERIT_SCHED)
538 attr.schedparam.sched_priority
539 = sched_get_thread_priority (GetCurrentThread ());
540 if (attr.schedparam.sched_priority)
541 sched_set_thread_priority (win32_obj_id, attr.schedparam.sched_priority);
544 void
545 pthread::exit (void *value_ptr)
547 class pthread *thread = this;
548 _cygtls *tls = cygtls; /* Save cygtls before deleting this. */
550 // run cleanup handlers
551 pop_all_cleanup_handlers ();
553 pthread_key::run_all_destructors ();
555 mutex.lock ();
556 // cleanup if thread is in detached state and not joined
557 if (equal (joiner, thread))
558 delete this;
559 else
561 valid = false;
562 return_ptr = value_ptr;
563 mutex.unlock ();
566 if (_my_tls.local_clib.__cleanup == _cygtls::cleanup_early)
567 _my_tls.local_clib.__cleanup = NULL;
568 _reclaim_reent (_REENT);
570 if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0)
571 ::exit (0);
572 else
574 if (tls == _main_tls)
576 cygheap->find_tls (tls); /* Lock _main_tls mutex. */
577 _cygtls *dummy = (_cygtls *) malloc (sizeof (_cygtls));
578 *dummy = *_main_tls;
579 _main_tls = dummy;
580 _main_tls->initialized = 0;
582 /* This also unlocks and closes the _main_tls mutex. */
583 tls->remove (INFINITE);
584 ExitThread (0);
589 pthread::cancel ()
591 class pthread *thread = this;
592 class pthread *self = pthread::self ();
594 mutex.lock ();
596 if (!valid)
598 mutex.unlock ();
599 return 0;
602 if (canceltype == PTHREAD_CANCEL_DEFERRED ||
603 cancelstate == PTHREAD_CANCEL_DISABLE)
605 // cancel deferred
606 mutex.unlock ();
607 canceled = true;
608 SetEvent (cancel_event);
609 return 0;
611 else if (equal (thread, self))
613 mutex.unlock ();
614 cancel_self ();
615 return 0; // Never reached
618 // cancel asynchronous
619 SuspendThread (win32_obj_id);
620 if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)
622 CONTEXT context;
623 context.ContextFlags = CONTEXT_CONTROL;
624 GetThreadContext (win32_obj_id, &context);
625 /* The OS is not foolproof in terms of asynchronous thread cancellation
626 and tends to hang infinitely if we change the instruction pointer.
627 So just don't cancel asynchronously if the thread is currently
628 executing Windows code. Rely on deferred cancellation in this case. */
629 threadlist_t *tl_entry = cygheap->find_tls (cygtls);
630 if (!cygtls->inside_kernel (&context))
632 context.Rip = (ULONG_PTR) pthread::static_cancel_self;
633 SetThreadContext (win32_obj_id, &context);
635 cygheap->unlock_tls (tl_entry);
637 mutex.unlock ();
638 /* See above. For instance, a thread which waits for a semaphore in sem_wait
639 will call cygwait which in turn calls WFMO. While this WFMO call
640 is cancelable by setting the thread's cancel_event object, the OS
641 apparently refuses to set the thread's context and continues to wait for
642 the WFMO conditions. This is *not* reflected in the return value of
643 SetThreadContext or ResumeThread, btw.
644 So, what we do here is to set the cancel_event as well to allow at least
645 a deferred cancel. */
646 canceled = true;
647 SetEvent (cancel_event);
648 ResumeThread (win32_obj_id);
650 return 0;
653 /* TODO: Insert pthread_testcancel into the required functions.
655 Here are the lists of required and optional functions per POSIX.1-2001
656 and POSIX.1-2008. A star (*) indicates that the Cygwin function already
657 is a cancellation point (aka "calls pthread_testcancel"), an o (o)
658 indicates that the function is not implemented in Cygwin.
660 Required cancellation points:
662 * accept ()
663 * aio_suspend ()
664 * clock_nanosleep ()
665 * close ()
666 * connect ()
667 * creat ()
668 * fcntl () F_SETLKW
669 * fdatasync ()
670 * fsync ()
671 o getmsg ()
672 o getpmsg ()
673 * lockf () F_LOCK
674 * mq_receive ()
675 * mq_send ()
676 * mq_timedreceive ()
677 * mq_timedsend ()
678 msgrcv ()
679 msgsnd ()
680 * msync ()
681 * nanosleep ()
682 * open ()
683 * openat ()
684 * pause ()
685 * poll ()
686 * pread ()
687 * pselect ()
688 * pthread_cond_timedwait ()
689 * pthread_cond_wait ()
690 * pthread_join ()
691 * pthread_testcancel ()
692 o putmsg ()
693 o putpmsg ()
694 * pwrite ()
695 * read ()
696 * readv ()
697 * recv ()
698 * recvfrom ()
699 * recvmsg ()
700 * select ()
701 * sem_timedwait ()
702 * sem_wait ()
703 * send ()
704 * sendmsg ()
705 * sendto ()
706 * sigpause ()
707 * sigsuspend ()
708 * sigtimedwait ()
709 * sigwait ()
710 * sigwaitinfo ()
711 * sleep ()
712 * system ()
713 * tcdrain ()
714 * usleep ()
715 * wait ()
716 * wait3()
717 o waitid ()
718 * waitpid ()
719 * write ()
720 * writev ()
722 Optional cancellation points:
724 access ()
725 asctime ()
726 asctime_r ()
727 catclose () Implemented externally: libcatgets
728 catgets () Implemented externally: libcatgets
729 catopen () Implemented externally: libcatgets
730 chmod ()
731 chown ()
732 closedir ()
733 closelog ()
734 ctermid ()
735 ctime ()
736 ctime_r ()
737 dbm_close () Implemented externally: libgdbm
738 dbm_delete () Implemented externally: libgdbm
739 dbm_fetch () Implemented externally: libgdbm
740 dbm_nextkey () Implemented externally: libgdbm
741 dbm_open () Implemented externally: libgdbm
742 dbm_store () Implemented externally: libgdbm
743 dlclose ()
744 dlopen ()
745 dprintf ()
746 endgrent ()
747 endhostent ()
748 o endnetent ()
749 endprotoent ()
750 endpwent ()
751 endservent ()
752 endutxent ()
753 faccessat ()
754 fchmod ()
755 fchmodat ()
756 fchown ()
757 fchownat ()
758 * fclose ()
759 * fcntl () (any value)
760 fflush ()
761 fgetc ()
762 fgetpos ()
763 fgets ()
764 fgetwc ()
765 fgetws ()
766 o fmtmsg ()
767 fopen ()
768 fpathconf ()
769 fprintf ()
770 fputc ()
771 fputs ()
772 fputwc ()
773 fputws ()
774 fread ()
775 freopen ()
776 fscanf ()
777 fseek ()
778 fseeko ()
779 fsetpos ()
780 fstat ()
781 fstatat ()
782 ftell ()
783 ftello ()
784 ftw ()
785 futimens ()
786 fwprintf ()
787 fwrite ()
788 fwscanf ()
789 getaddrinfo ()
790 getc ()
791 getc_unlocked ()
792 getchar ()
793 getchar_unlocked ()
794 getcwd ()
795 o getdate ()
796 getdelim ()
797 getgrent ()
798 getgrgid ()
799 getgrgid_r ()
800 getgrnam ()
801 getgrnam_r ()
802 gethostbyaddr ()
803 gethostbyname ()
804 gethostent ()
805 gethostid ()
806 gethostname ()
807 getline ()
808 getlogin ()
809 getlogin_r ()
810 getnameinfo ()
811 o getnetbyaddr ()
812 o getnetbyname ()
813 o getnetent ()
814 getopt () (if opterr is nonzero)
815 getprotobyname ()
816 getprotobynumber ()
817 getprotoent ()
818 getpwent ()
819 * getpwnam ()
820 * getpwnam_r ()
821 * getpwuid ()
822 * getpwuid_r ()
823 gets ()
824 getservbyname ()
825 getservbyport ()
826 getservent ()
827 getutxent ()
828 getutxid ()
829 getutxline ()
830 getwc ()
831 getwchar ()
832 getwd ()
833 glob ()
834 iconv_close () Implemented externally: libiconv
835 iconv_open () Implemented externally: libiconv
836 ioctl ()
837 link ()
838 linkat ()
839 * lio_listio ()
840 localtime ()
841 localtime_r ()
842 * lockf ()
843 lseek ()
844 lstat ()
845 mkdir ()
846 mkdirat ()
847 mkdtemp ()
848 mkfifo ()
849 mkfifoat ()
850 mknod ()
851 mknodat ()
852 mkstemp ()
853 mktime ()
854 nftw ()
855 opendir ()
856 openlog ()
857 pathconf ()
858 pclose ()
859 perror ()
860 popen ()
861 posix_fadvise ()
862 posix_fallocate ()
863 posix_madvise ()
864 posix_openpt ()
865 posix_spawn ()
866 posix_spawnp ()
867 o posix_trace_clear ()
868 o posix_trace_close ()
869 o posix_trace_create ()
870 o posix_trace_create_withlog ()
871 o posix_trace_eventtypelist_getnext_id ()
872 o posix_trace_eventtypelist_rewind ()
873 o posix_trace_flush ()
874 o posix_trace_get_attr ()
875 o posix_trace_get_filter ()
876 o posix_trace_get_status ()
877 o posix_trace_getnext_event ()
878 o posix_trace_open ()
879 o posix_trace_rewind ()
880 o posix_trace_set_filter ()
881 o posix_trace_shutdown ()
882 o posix_trace_timedgetnext_event ()
883 o posix_typed_mem_open ()
884 printf ()
885 psiginfo ()
886 psignal ()
887 pthread_rwlock_rdlock ()
888 o pthread_rwlock_timedrdlock ()
889 o pthread_rwlock_timedwrlock ()
890 pthread_rwlock_wrlock ()
891 putc ()
892 putc_unlocked ()
893 putchar ()
894 putchar_unlocked ()
895 puts ()
896 pututxline ()
897 putwc ()
898 putwchar ()
899 readdir ()
900 readdir_r ()
901 readlink ()
902 readlinkat ()
903 remove ()
904 rename ()
905 renameat ()
906 rewind ()
907 rewinddir ()
908 scandir ()
909 scanf ()
910 seekdir ()
911 semop ()
912 setgrent ()
913 sethostent ()
914 o setnetent ()
915 setprotoent ()
916 setpwent ()
917 setservent ()
918 setutxent ()
919 sigpause ()
920 stat ()
921 strerror ()
922 strerror_r ()
923 strftime ()
924 symlink ()
925 symlinkat ()
926 sync ()
927 syslog ()
928 tmpfile ()
929 tmpnam ()
930 ttyname ()
931 ttyname_r ()
932 tzset ()
933 ungetc ()
934 ungetwc ()
935 unlink ()
936 unlinkat ()
937 utime ()
938 utimensat ()
939 utimes ()
940 vdprintf ()
941 vfprintf ()
942 vfwprintf ()
943 vprintf ()
944 vwprintf ()
945 wcsftime ()
946 wordexp ()
947 wprintf ()
948 wscanf ()
950 An implementation may also mark other functions not specified in the
951 standard as cancellation points. In particular, an implementation is
952 likely to mark any nonstandard function that may block as a
953 cancellation point. */
955 void
956 pthread::testcancel ()
958 if (cancelstate == PTHREAD_CANCEL_DISABLE)
959 return;
961 /* We check for the canceled flag first. This allows to use the
962 pthread_testcancel function a lot without adding the overhead of
963 an OS call. Only if the thread is marked as canceled, we wait for
964 cancel_event being really set, on the off-chance that pthread_cancel
965 gets interrupted or terminated before calling SetEvent. */
966 if (canceled && IsEventSignalled (cancel_event))
967 cancel_self ();
970 /* Return cancel event handle if it exists *and* cancel is not disabled.
971 This function is supposed to be used from other functions which are
972 cancelable and need the cancel event in a WFMO call. */
973 HANDLE
974 pthread::get_cancel_event ()
976 pthread_t thread = pthread::self ();
978 return (thread && thread->cancel_event
979 && thread->cancelstate != PTHREAD_CANCEL_DISABLE)
980 ? thread->cancel_event : NULL;
983 void
984 pthread::static_cancel_self ()
986 pthread::self ()->cancel_self ();
990 pthread::setcancelstate (int state, int *oldstate)
992 if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)
993 return EINVAL;
995 if (oldstate)
996 *oldstate = cancelstate;
997 cancelstate = state;
999 return 0;
1003 pthread::setcanceltype (int type, int *oldtype)
1005 if (type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS)
1006 return EINVAL;
1008 if (oldtype)
1009 *oldtype = canceltype;
1010 canceltype = type;
1012 return 0;
1015 void
1016 pthread::push_cleanup_handler (__pthread_cleanup_handler *handler)
1018 if (this != self ())
1019 // TODO: do it?
1020 api_fatal ("Attempt to push a cleanup handler across threads");
1021 handler->next = cleanup_stack;
1022 cleanup_stack = handler;
1025 void
1026 pthread::pop_cleanup_handler (int const execute)
1028 if (this != self ())
1029 // TODO: send a signal or something to the thread ?
1030 api_fatal ("Attempt to execute a cleanup handler across threads");
1032 mutex.lock ();
1034 if (cleanup_stack != NULL)
1036 __pthread_cleanup_handler *handler = cleanup_stack;
1038 if (execute)
1039 (*handler->function) (handler->arg);
1040 cleanup_stack = handler->next;
1043 mutex.unlock ();
1046 void
1047 pthread::pop_all_cleanup_handlers ()
1049 /* We will no honor cancels since the thread is exiting. */
1050 cancelstate = PTHREAD_CANCEL_DISABLE;
1052 while (cleanup_stack != NULL)
1053 pop_cleanup_handler (1);
1056 void
1057 pthread::cancel_self ()
1059 /* Can someone explain why the pthread:: is needed here? g++ complains
1060 without it. */
1061 pthread::exit (PTHREAD_CANCELED);
1064 DWORD
1065 pthread::get_thread_id ()
1067 return thread_id;
1070 void
1071 pthread::_fixup_after_fork ()
1073 /* set thread to not running if it is not the forking thread */
1074 if (this != pthread::self ())
1076 magic = 0;
1077 valid = false;
1078 win32_obj_id = NULL;
1079 canceled = false;
1080 cancel_event = NULL;
1084 void
1085 pthread::suspend_except_self ()
1087 if (valid && this != pthread::self ())
1088 SuspendThread (win32_obj_id);
1091 void
1092 pthread::resume ()
1094 if (valid)
1095 ResumeThread (win32_obj_id);
1098 /* instance members */
1100 pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC),
1101 joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS),
1102 inheritsched (PTHREAD_INHERIT_SCHED), stackaddr (NULL), stacksize (0),
1103 guardsize (wincap.def_guard_page_size ()), name (NULL)
1105 schedparam.sched_priority = 0;
1108 pthread_attr::~pthread_attr ()
1112 pthread_condattr::pthread_condattr ():verifyable_object
1113 (PTHREAD_CONDATTR_MAGIC), shared (PTHREAD_PROCESS_PRIVATE),
1114 clock_id (CLOCK_REALTIME)
1118 pthread_condattr::~pthread_condattr ()
1122 List<pthread_cond> pthread_cond::conds;
1124 /* This is used for cond creation protection within a single process only */
1125 fast_mutex NO_COPY pthread_cond::cond_initialization_lock;
1127 /* We can only be called once.
1128 TODO: (no rush) use a non copied memory section to
1129 hold an initialization flag. */
1130 void
1131 pthread_cond::init_mutex ()
1133 if (!cond_initialization_lock.init ())
1134 api_fatal ("Could not create win32 Mutex for pthread cond static initializer support.");
1137 pthread_cond::pthread_cond (pthread_condattr *attr) :
1138 verifyable_object (PTHREAD_COND_MAGIC),
1139 shared (0), clock_id (CLOCK_REALTIME), waiting (0), pending (0),
1140 sem_wait (NULL), mtx_cond(NULL), next (NULL)
1142 pthread_mutex *verifyable_mutex_obj;
1144 if (attr)
1146 clock_id = attr->clock_id;
1148 if (attr->shared != PTHREAD_PROCESS_PRIVATE)
1150 magic = 0;
1151 return;
1155 verifyable_mutex_obj = &mtx_in;
1156 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
1158 thread_printf ("Internal cond mutex is not valid. this %p", this);
1159 magic = 0;
1160 return;
1163 * Change the mutex type to NORMAL.
1164 * This mutex MUST be of type normal
1166 mtx_in.set_type (PTHREAD_MUTEX_NORMAL);
1168 verifyable_mutex_obj = &mtx_out;
1169 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
1171 thread_printf ("Internal cond mutex is not valid. this %p", this);
1172 magic = 0;
1173 return;
1175 /* Change the mutex type to NORMAL to speed up mutex operations */
1176 mtx_out.set_type (PTHREAD_MUTEX_NORMAL);
1178 sem_wait = ::CreateSemaphore (&sec_none_nih, 0, INT32_MAX, NULL);
1179 if (!sem_wait)
1181 pthread_printf ("CreateSemaphore failed. %E");
1182 magic = 0;
1183 return;
1186 conds.insert (this);
1189 pthread_cond::~pthread_cond ()
1191 if (sem_wait)
1192 CloseHandle (sem_wait);
1194 conds.remove (this);
1197 void
1198 pthread_cond::unblock (const bool all)
1200 LONG releaseable;
1203 * Block outgoing threads (and avoid simultanous unblocks)
1205 mtx_out.lock ();
1207 releaseable = waiting - pending;
1208 if (releaseable)
1210 LONG released;
1212 if (!pending)
1215 * Block incoming threads until all waiting threads are released.
1217 mtx_in.lock ();
1220 * Calculate releaseable again because threads can enter until
1221 * the semaphore has been taken, but they can not leave, therefore pending
1222 * is unchanged and releaseable can only get higher
1224 releaseable = waiting - pending;
1227 released = all ? releaseable : 1;
1228 pending += released;
1230 * Signal threads
1232 ::ReleaseSemaphore (sem_wait, released, NULL);
1236 * And let the threads release.
1238 mtx_out.unlock ();
1242 pthread_cond::wait (pthread_mutex_t mutex, PLARGE_INTEGER timeout)
1244 DWORD rv;
1246 mtx_in.lock ();
1247 if (InterlockedIncrement (&waiting) == 1)
1248 mtx_cond = mutex;
1249 else if (mtx_cond != mutex)
1251 InterlockedDecrement (&waiting);
1252 mtx_in.unlock ();
1253 return EINVAL;
1255 mtx_in.unlock ();
1258 * Release the mutex and wait on semaphore
1260 ++mutex->condwaits;
1261 mutex->unlock ();
1263 rv = cygwait (sem_wait, timeout, cw_cancel | cw_sig_restart);
1265 mtx_out.lock ();
1267 if (rv != WAIT_OBJECT_0 && WaitForSingleObject (sem_wait, 0) == WAIT_OBJECT_0)
1268 /* Thread got cancelled ot timed out while a signalling is in progress.
1269 Set wait result back to signaled */
1270 rv = WAIT_OBJECT_0;
1272 InterlockedDecrement (&waiting);
1274 if (rv == WAIT_OBJECT_0 && --pending == 0)
1276 * All signaled threads are released,
1277 * new threads can enter Wait
1279 mtx_in.unlock ();
1281 mtx_out.unlock ();
1283 mutex->lock ();
1284 --mutex->condwaits;
1286 if (rv == WAIT_CANCELED)
1287 pthread::static_cancel_self ();
1288 else if (rv == WAIT_TIMEOUT)
1289 return ETIMEDOUT;
1291 return 0;
1294 void
1295 pthread_cond::_fixup_after_fork ()
1297 waiting = pending = 0;
1298 mtx_cond = NULL;
1300 /* Unlock eventually locked mutexes */
1301 mtx_in.unlock ();
1302 mtx_out.unlock ();
1304 sem_wait = ::CreateSemaphore (&sec_none_nih, 0, INT32_MAX, NULL);
1305 if (!sem_wait)
1306 api_fatal ("pthread_cond::_fixup_after_fork () failed to recreate win32 semaphore");
1309 pthread_barrierattr::pthread_barrierattr ()
1310 : verifyable_object (PTHREAD_BARRIERATTR_MAGIC)
1311 , shared (PTHREAD_PROCESS_PRIVATE)
1315 pthread_barrierattr::~pthread_barrierattr ()
1319 pthread_barrier::pthread_barrier ()
1320 : verifyable_object (PTHREAD_BARRIER_MAGIC)
1324 pthread_barrier::~pthread_barrier ()
1328 pthread_rwlockattr::pthread_rwlockattr ():verifyable_object
1329 (PTHREAD_RWLOCKATTR_MAGIC), shared (PTHREAD_PROCESS_PRIVATE)
1333 pthread_rwlockattr::~pthread_rwlockattr ()
1337 List<pthread_rwlock> pthread_rwlock::rwlocks;
1339 /* This is used for rwlock creation protection within a single process only */
1340 fast_mutex NO_COPY pthread_rwlock::rwlock_initialization_lock;
1342 /* We can only be called once.
1343 TODO: (no rush) use a non copied memory section to
1344 hold an initialization flag. */
1345 void
1346 pthread_rwlock::init_mutex ()
1348 if (!rwlock_initialization_lock.init ())
1349 api_fatal ("Could not create win32 Mutex for pthread rwlock static initializer support.");
1352 pthread_rwlock::pthread_rwlock (pthread_rwlockattr *attr) :
1353 verifyable_object (PTHREAD_RWLOCK_MAGIC),
1354 shared (0), waiting_readers (0), waiting_writers (0), writer (NULL),
1355 readers (NULL), readers_mx (), mtx (NULL), cond_readers (NULL), cond_writers (NULL),
1356 next (NULL)
1358 pthread_mutex *verifyable_mutex_obj = &mtx;
1359 pthread_cond *verifyable_cond_obj;
1361 if (!readers_mx.init ())
1363 thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this);
1364 magic = 0;
1365 return;
1368 if (attr)
1369 if (attr->shared != PTHREAD_PROCESS_PRIVATE)
1371 magic = 0;
1372 return;
1375 if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
1377 thread_printf ("Internal rwlock mutex is not valid. this %p", this);
1378 magic = 0;
1379 return;
1381 /* Change the mutex type to NORMAL to speed up mutex operations */
1382 mtx.set_type (PTHREAD_MUTEX_NORMAL);
1384 verifyable_cond_obj = &cond_readers;
1385 if (!pthread_cond::is_good_object (&verifyable_cond_obj))
1387 thread_printf ("Internal rwlock readers cond is not valid. this %p", this);
1388 magic = 0;
1389 return;
1392 verifyable_cond_obj = &cond_writers;
1393 if (!pthread_cond::is_good_object (&verifyable_cond_obj))
1395 thread_printf ("Internal rwlock writers cond is not valid. this %p", this);
1396 magic = 0;
1397 return;
1401 rwlocks.insert (this);
1404 pthread_rwlock::~pthread_rwlock ()
1406 rwlocks.remove (this);
1410 pthread_rwlock::rdlock (PLARGE_INTEGER timeout)
1412 int result = 0;
1413 struct RWLOCK_READER *reader;
1415 mtx.lock ();
1417 reader = lookup_reader ();
1418 if (reader)
1420 if (reader->n < UINT32_MAX)
1421 ++reader->n;
1422 else
1423 result = EAGAIN;
1424 goto DONE;
1427 while (writer || waiting_writers)
1429 int ret;
1431 pthread_cleanup_push (pthread_rwlock::rdlock_cleanup, this);
1433 ++waiting_readers;
1434 ret = cond_readers.wait (&mtx, timeout);
1435 --waiting_readers;
1437 pthread_cleanup_pop (0);
1439 if (ret == ETIMEDOUT)
1441 result = ETIMEDOUT;
1442 goto DONE;
1446 if ((reader = add_reader ()))
1447 ++reader->n;
1448 else
1450 result = EAGAIN;
1451 goto DONE;
1454 DONE:
1455 mtx.unlock ();
1457 return result;
1461 pthread_rwlock::tryrdlock ()
1463 int result = 0;
1465 mtx.lock ();
1467 if (writer || waiting_writers)
1468 result = EBUSY;
1469 else
1471 RWLOCK_READER *reader = lookup_reader ();
1472 if (!reader)
1473 reader = add_reader ();
1474 if (reader && reader->n < UINT32_MAX)
1475 ++reader->n;
1476 else
1477 result = EAGAIN;
1480 mtx.unlock ();
1482 return result;
1486 pthread_rwlock::wrlock (PLARGE_INTEGER timeout)
1488 int result = 0;
1489 pthread_t self = pthread::self ();
1491 mtx.lock ();
1493 if (writer == self || lookup_reader ())
1495 result = EDEADLK;
1496 goto DONE;
1499 while (writer || readers)
1501 int ret;
1503 pthread_cleanup_push (pthread_rwlock::wrlock_cleanup, this);
1505 ++waiting_writers;
1506 ret = cond_writers.wait (&mtx, timeout);
1507 --waiting_writers;
1509 pthread_cleanup_pop (0);
1511 if (ret == ETIMEDOUT)
1513 result = ETIMEDOUT;
1514 goto DONE;
1518 writer = self;
1520 DONE:
1521 mtx.unlock ();
1523 return result;
1527 pthread_rwlock::trywrlock ()
1529 int result = 0;
1530 pthread_t self = pthread::self ();
1532 mtx.lock ();
1534 if (writer || readers)
1535 result = EBUSY;
1536 else
1537 writer = self;
1539 mtx.unlock ();
1541 return result;
1545 pthread_rwlock::unlock ()
1547 int result = 0;
1549 mtx.lock ();
1551 if (writer)
1553 if (writer != pthread::self ())
1555 result = EPERM;
1556 goto DONE;
1559 writer = NULL;
1561 else
1563 struct RWLOCK_READER *reader = lookup_reader ();
1565 if (!reader)
1567 result = EPERM;
1568 goto DONE;
1570 if (--reader->n > 0)
1571 goto DONE;
1573 remove_reader (reader);
1574 delete reader;
1577 release ();
1579 DONE:
1580 mtx.unlock ();
1582 return result;
1585 pthread_rwlock::RWLOCK_READER *
1586 pthread_rwlock::add_reader ()
1588 RWLOCK_READER *rd = new RWLOCK_READER;
1589 if (rd)
1590 List_insert_nolock (readers, rd);
1591 return rd;
1594 void
1595 pthread_rwlock::remove_reader (struct RWLOCK_READER *rd)
1597 List_remove (readers_mx, readers, rd);
1600 struct pthread_rwlock::RWLOCK_READER *
1601 pthread_rwlock::lookup_reader ()
1603 readers_mx.lock ();
1604 pthread_t thread = pthread::self ();
1606 struct RWLOCK_READER *cur = readers;
1608 while (cur && cur->thread != thread)
1609 cur = cur->next;
1611 readers_mx.unlock ();
1613 return cur;
1616 void
1617 pthread_rwlock::rdlock_cleanup (void *arg)
1619 pthread_rwlock *rwlock = (pthread_rwlock *) arg;
1621 --(rwlock->waiting_readers);
1622 rwlock->release ();
1623 rwlock->mtx.unlock ();
1626 void
1627 pthread_rwlock::wrlock_cleanup (void *arg)
1629 pthread_rwlock *rwlock = (pthread_rwlock *) arg;
1631 --(rwlock->waiting_writers);
1632 rwlock->release ();
1633 rwlock->mtx.unlock ();
1636 void
1637 pthread_rwlock::_fixup_after_fork ()
1639 pthread_t self = pthread::self ();
1640 struct RWLOCK_READER **temp = &readers;
1642 waiting_readers = 0;
1643 waiting_writers = 0;
1645 if (!readers_mx.init ())
1646 api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex");
1648 /* Unlock eventually locked mutex */
1649 mtx.unlock ();
1651 * Remove all readers except self
1653 while (*temp)
1655 if ((*temp)->thread == self)
1656 temp = &((*temp)->next);
1657 else
1659 struct RWLOCK_READER *cur = *temp;
1660 *temp = (*temp)->next;
1661 delete cur;
1666 /* pthread_key */
1667 /* static members */
1668 /* This stores pthread_key information across fork() boundaries */
1669 List<pthread_key> pthread_key::keys;
1671 /* non-static members */
1673 pthread_key::pthread_key (void (*aDestructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC), destructor (aDestructor)
1675 tls_index = TlsAlloc ();
1676 if (tls_index == TLS_OUT_OF_INDEXES)
1677 magic = 0;
1678 else
1679 keys.insert (this);
1682 pthread_key::~pthread_key ()
1684 /* We may need to make the list code lock the list during operations
1686 if (magic != 0)
1688 keys.remove (this);
1689 TlsFree (tls_index);
1693 void
1694 pthread_key::_fixup_before_fork ()
1696 fork_buf = get ();
1699 void
1700 pthread_key::_fixup_after_fork ()
1702 tls_index = TlsAlloc ();
1703 if (tls_index == TLS_OUT_OF_INDEXES)
1704 api_fatal ("pthread_key::recreate_key_from_buffer () failed to reallocate Tls storage");
1705 set (fork_buf);
1708 bool pthread_key::iterate_dtors_once_more;
1710 void
1711 pthread_key::run_destructor ()
1713 if (destructor)
1715 void *oldValue = get ();
1716 if (oldValue)
1718 set (NULL);
1719 destructor (oldValue);
1720 if (get ())
1721 iterate_dtors_once_more = true;
1726 /* pshared mutexs */
1728 /* static members */
1730 List<pthread_mutex> pthread_mutex::mutexes;
1732 /* This is used for mutex creation protection within a single process only */
1733 fast_mutex NO_COPY pthread_mutex::mutex_initialization_lock;
1735 void
1736 pthread_mutex::init_mutex ()
1738 if (!mutex_initialization_lock.init ())
1739 api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support.");
1742 pthread_mutex::pthread_mutex (pthread_mutexattr *attr) :
1743 verifyable_object (0), /* set magic to zero initially */
1744 lock_counter (0),
1745 win32_obj_id (NULL), owner (_new_mutex),
1746 #ifdef DEBUGGING
1747 tid (0),
1748 #endif
1749 recursion_counter (0), condwaits (0),
1750 type (PTHREAD_MUTEX_NORMAL),
1751 pshared (PTHREAD_PROCESS_PRIVATE)
1753 win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL);
1754 if (!win32_obj_id)
1755 return;
1756 /*attr checked in the C call */
1757 if (!attr)
1758 /* handled in the caller */;
1759 else if (attr->pshared != PTHREAD_PROCESS_SHARED)
1760 type = attr->mutextype;
1761 else
1762 return; /* Not implemented */
1764 magic = PTHREAD_MUTEX_MAGIC;
1765 mutexes.insert (this);
1768 pthread_mutex::~pthread_mutex ()
1770 if (win32_obj_id)
1772 CloseHandle (win32_obj_id);
1773 win32_obj_id = NULL;
1776 mutexes.remove (this);
1777 owner = _destroyed_mutex;
1778 magic = 0;
1782 pthread_mutex::lock (PLARGE_INTEGER timeout)
1784 pthread_t self = ::pthread_self ();
1785 int result = 0;
1787 if (InterlockedIncrement (&lock_counter) == 1)
1788 set_owner (self);
1789 else if (type == PTHREAD_MUTEX_NORMAL /* potentially causes deadlock */
1790 || !pthread::equal (owner, self))
1792 if (cygwait (win32_obj_id, timeout, cw_sig | cw_sig_restart)
1793 != WAIT_TIMEOUT)
1794 set_owner (self);
1795 else
1797 InterlockedDecrement (&lock_counter);
1798 result = ETIMEDOUT;
1801 else
1803 InterlockedDecrement (&lock_counter);
1804 if (type == PTHREAD_MUTEX_RECURSIVE)
1805 result = lock_recursive ();
1806 else
1807 result = EDEADLK;
1810 pthread_printf ("mutex %p, self %p, owner %p, lock_counter %d, recursion_counter %u",
1811 this, self, owner, lock_counter, recursion_counter);
1812 return result;
1816 pthread_mutex::unlock ()
1818 int res = 0;
1819 pthread_t self = ::pthread_self ();
1820 if (type == PTHREAD_MUTEX_NORMAL)
1821 /* no error checking */;
1822 else if (no_owner ())
1823 res = type == PTHREAD_MUTEX_ERRORCHECK ? EPERM : 0;
1824 else if (!pthread::equal (owner, self))
1825 res = EPERM;
1826 if (!res && recursion_counter > 0 && --recursion_counter == 0)
1827 /* Don't try to unlock anything if recursion_counter == 0.
1828 This means the mutex was never locked or that we've forked. */
1830 owner = (pthread_t) _unlocked_mutex;
1831 #ifdef DEBUGGING
1832 tid = 0; // thread-id
1833 #endif
1834 if (InterlockedDecrement (&lock_counter))
1835 ::SetEvent (win32_obj_id); // Another thread is waiting
1836 res = 0;
1839 pthread_printf ("mutex %p, owner %p, self %p, lock_counter %d, recursion_counter %u, type %d, res %d",
1840 this, owner, self, lock_counter, recursion_counter, type, res);
1841 return res;
1845 pthread_mutex::trylock ()
1847 pthread_t self = ::pthread_self ();
1848 int result = 0;
1850 if (InterlockedCompareExchange (&lock_counter, 1, 0) == 0)
1851 set_owner (self);
1852 else if (type == PTHREAD_MUTEX_RECURSIVE && pthread::equal (owner, self))
1853 result = lock_recursive ();
1854 else
1855 result = EBUSY;
1857 return result;
1861 pthread_mutex::destroy ()
1863 if (condwaits || trylock ())
1864 // Do not destroy a condwaited or locked mutex
1865 return EBUSY;
1866 else if (recursion_counter > 1)
1868 // Do not destroy a recursive locked mutex
1869 recursion_counter--;
1870 return EBUSY;
1873 delete this;
1874 return 0;
1877 void
1878 pthread_mutex::_fixup_after_fork ()
1880 pthread_printf ("mutex %p", this);
1881 if (pshared != PTHREAD_PROCESS_PRIVATE)
1882 api_fatal ("pthread_mutex::_fixup_after_fork () doesn't understand PROCESS_SHARED mutex's");
1884 /* All waiting threads are gone after a fork */
1885 recursion_counter = 0;
1886 lock_counter = 0;
1887 condwaits = 0;
1888 #ifdef DEBUGGING
1889 tid = 0xffffffff; /* Don't know the tid after a fork */
1890 #endif
1891 win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL);
1892 if (!win32_obj_id)
1893 api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 event for mutex");
1896 pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC),
1897 pshared (PTHREAD_PROCESS_PRIVATE), mutextype (PTHREAD_MUTEX_NORMAL)
1901 pthread_mutexattr::~pthread_mutexattr ()
1905 /* pshared spinlocks
1907 The infrastructure is provided by the underlying pthread_mutex class.
1908 The rest is a simplification implementing spin locking. */
1910 pthread_spinlock::pthread_spinlock (int pshared) :
1911 pthread_mutex (NULL)
1913 magic = PTHREAD_SPINLOCK_MAGIC;
1914 set_type (PTHREAD_MUTEX_NORMAL);
1915 set_shared (pshared);
1919 pthread_spinlock::lock ()
1921 pthread_t self = ::pthread_self ();
1922 int result = -1;
1923 unsigned spins = 0;
1926 We want to spin using 'pause' instruction on multi-core system but we
1927 want to avoid this on single-core systems.
1929 The limit of 1000 spins is semi-arbitrary. Microsoft suggests (in their
1930 InitializeCriticalSectionAndSpinCount documentation on MSDN) they are
1931 using spin count limit 4000 for their heap manager critical
1932 sections. Other source suggest spin count as small as 200 for fast path
1933 of mutex locking.
1935 unsigned const FAST_SPINS_LIMIT = wincap.cpu_count () != 1 ? 1000 : 0;
1939 if (InterlockedExchange (&lock_counter, 1) == 0)
1941 set_owner (self);
1942 result = 0;
1944 else if (unlikely(pthread::equal (owner, self)))
1945 result = EDEADLK;
1946 else if (spins < FAST_SPINS_LIMIT)
1948 ++spins;
1949 __asm__ volatile ("pause":::);
1951 else
1953 /* Minimal timeout to minimize CPU usage while still spinning. */
1954 LARGE_INTEGER timeout;
1955 timeout.QuadPart = -10000LL;
1956 /* FIXME: no cancel? */
1957 cygwait (win32_obj_id, &timeout, cw_sig);
1960 while (result == -1);
1961 pthread_printf ("spinlock %p, self %p, owner %p", this, self, owner);
1962 return result;
1966 pthread_spinlock::unlock ()
1968 pthread_t self = ::pthread_self ();
1969 int result = 0;
1971 if (!pthread::equal (owner, self))
1972 result = EPERM;
1973 else
1975 owner = (pthread_t) _unlocked_mutex;
1976 #ifdef DEBUGGING
1977 tid = 0; // thread-id
1978 #endif
1979 InterlockedExchange (&lock_counter, 0);
1980 ::SetEvent (win32_obj_id);
1981 result = 0;
1983 pthread_printf ("spinlock %p, owner %p, self %p, res %d",
1984 this, owner, self, result);
1985 return result;
1988 DWORD
1989 pthread::thread_init_wrapper (void *arg)
1991 exception protect;
1992 pthread *thread = (pthread *) arg;
1993 /* This *must* be set prior to calling set_tls_self_pointer or there is
1994 a race with the signal processing code which may miss the signal mask
1995 settings. */
1996 _my_tls.sigmask = thread->parent_sigmask;
1997 thread->set_tls_self_pointer ();
1999 // Give thread default name
2000 SetThreadName (GetCurrentThreadId (), program_invocation_short_name);
2002 thread->mutex.lock ();
2004 // if thread is detached force cleanup on exit
2005 if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL)
2006 thread->joiner = thread;
2007 thread->mutex.unlock ();
2009 debug_printf ("tid %p", &_my_tls);
2010 thread_printf ("started thread %p %p %p %p %p %p", arg, &_my_tls.local_clib,
2011 _impure_ptr, thread, thread->function, thread->arg);
2013 // call the user's thread
2014 void *ret = thread->function (thread->arg);
2016 thread->exit (ret);
2018 return 0; // just for show. Never returns.
2021 unsigned long
2022 pthread::getsequence_np ()
2024 return get_thread_id ();
2028 pthread::create (pthread_t *thread, const pthread_attr_t *attr,
2029 void *(*start_routine) (void *), void *arg)
2031 if (attr && !pthread_attr::is_good_object (attr))
2032 return EINVAL;
2034 *thread = new pthread ();
2035 if (!(*thread)->create (start_routine, attr ? *attr : NULL, arg))
2037 delete (*thread);
2038 *thread = NULL;
2039 return EAGAIN;
2042 return 0;
2046 pthread::once (pthread_once_t *once_control, void (*init_routine) (void))
2048 // already done ?
2049 if (once_control->state)
2050 return 0;
2052 pthread_mutex_lock (&once_control->mutex);
2053 /* Here we must set a cancellation handler to unlock the mutex if needed */
2054 /* but a cancellation handler is not the right thing. We need this in the thread
2055 *cleanup routine. Assumption: a thread can only be in one pthread_once routine
2056 *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
2057 *on pthread_exit ();
2059 if (!once_control->state)
2061 init_routine ();
2062 once_control->state = 1;
2063 pthread_mutex_unlock (&once_control->mutex);
2064 while (pthread_mutex_destroy (&once_control->mutex) == EBUSY);
2065 return 0;
2067 /* Here we must remove our cancellation handler */
2068 pthread_mutex_unlock (&once_control->mutex);
2069 return 0;
2073 pthread::cancel (pthread_t thread)
2075 if (!is_good_object (&thread))
2076 return ESRCH;
2078 return thread->cancel ();
2081 void
2082 pthread::atforkprepare ()
2084 callback *cb = MT_INTERFACE->pthread_prepare;
2085 while (cb)
2087 cb->cb ();
2088 cb = cb->next;
2091 __fp_lock_all ();
2093 MT_INTERFACE->fixup_before_fork ();
2096 void
2097 pthread::atforkparent ()
2099 __fp_unlock_all ();
2101 callback *cb = MT_INTERFACE->pthread_parent;
2102 while (cb)
2104 cb->cb ();
2105 cb = cb->next;
2109 void
2110 pthread::atforkchild ()
2112 MT_INTERFACE->fixup_after_fork ();
2114 __fp_unlock_all ();
2116 callback *cb = MT_INTERFACE->pthread_child;
2117 while (cb)
2119 cb->cb ();
2120 cb = cb->next;
2124 /* Register a set of functions to run before and after fork.
2125 prepare calls are called in LI-FC order.
2126 parent and child calls are called in FI-FC order. */
2128 pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void))
2130 callback *prepcb = NULL, *parentcb = NULL, *childcb = NULL;
2131 if (prepare)
2133 prepcb = new callback;
2134 if (!prepcb)
2135 return ENOMEM;
2137 if (parent)
2139 parentcb = new callback;
2140 if (!parentcb)
2142 if (prepcb)
2143 delete prepcb;
2144 return ENOMEM;
2147 if (child)
2149 childcb = new callback;
2150 if (!childcb)
2152 if (prepcb)
2153 delete prepcb;
2154 if (parentcb)
2155 delete parentcb;
2156 return ENOMEM;
2160 if (prepcb)
2162 prepcb->cb = prepare;
2163 List_insert_nolock (MT_INTERFACE->pthread_prepare, prepcb);
2165 if (parentcb)
2167 parentcb->cb = parent;
2168 callback **t = &MT_INTERFACE->pthread_parent;
2169 while (*t)
2170 t = &(*t)->next;
2171 /* t = pointer to last next in the list */
2172 List_insert_nolock (*t, parentcb);
2174 if (childcb)
2176 childcb->cb = child;
2177 callback **t = &MT_INTERFACE->pthread_child;
2178 while (*t)
2179 t = &(*t)->next;
2180 /* t = pointer to last next in the list */
2181 List_insert_nolock (*t, childcb);
2183 return 0;
2187 pthread::join (pthread_t *thread, void **return_val, PLARGE_INTEGER timeout)
2189 pthread_t joiner = self ();
2191 joiner->testcancel ();
2193 // Initialize return val with NULL
2194 if (return_val)
2195 *return_val = NULL;
2197 if (!is_good_object (&joiner))
2198 return EINVAL;
2200 if (!is_good_object (thread))
2201 return ESRCH;
2203 if (equal (*thread,joiner))
2204 return EDEADLK;
2206 (*thread)->mutex.lock ();
2208 if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
2210 (*thread)->mutex.unlock ();
2211 return EINVAL;
2213 else
2215 (*thread)->joiner = joiner;
2216 (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
2217 (*thread)->mutex.unlock ();
2219 switch (cygwait ((*thread)->win32_obj_id, timeout,
2220 cw_sig | cw_sig_restart | cw_cancel))
2222 case WAIT_OBJECT_0:
2223 if (return_val)
2224 *return_val = (*thread)->return_ptr;
2225 delete (*thread);
2226 break;
2227 case WAIT_CANCELED:
2228 // set joined thread back to joinable since we got canceled
2229 (*thread)->joiner = NULL;
2230 (*thread)->attr.joinable = PTHREAD_CREATE_JOINABLE;
2231 joiner->cancel_self ();
2232 // never reached
2233 break;
2234 case WAIT_TIMEOUT:
2235 // set joined thread back to joinable since we got canceled
2236 (*thread)->joiner = NULL;
2237 (*thread)->attr.joinable = PTHREAD_CREATE_JOINABLE;
2238 return (timeout && timeout->QuadPart == 0LL) ? EBUSY : ETIMEDOUT;
2239 default:
2240 // should never happen
2241 return EINVAL;
2245 return 0;
2249 pthread::detach (pthread_t *thread)
2251 if (!is_good_object (thread))
2252 return ESRCH;
2254 (*thread)->mutex.lock ();
2255 if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
2257 (*thread)->mutex.unlock ();
2258 return EINVAL;
2261 // check if thread is still alive
2262 if ((*thread)->valid && WaitForSingleObject ((*thread)->win32_obj_id, 0) == WAIT_TIMEOUT)
2264 // force cleanup on exit
2265 (*thread)->joiner = *thread;
2266 (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
2267 (*thread)->mutex.unlock ();
2269 else
2271 // thread has already terminated.
2272 (*thread)->mutex.unlock ();
2273 delete (*thread);
2276 return 0;
2280 pthread::suspend (pthread_t *thread)
2282 if (!is_good_object (thread))
2283 return ESRCH;
2285 if ((*thread)->suspended == false)
2287 (*thread)->suspended = true;
2288 SuspendThread ((*thread)->win32_obj_id);
2291 return 0;
2296 pthread::resume (pthread_t *thread)
2298 if (!is_good_object (thread))
2299 return ESRCH;
2301 if ((*thread)->suspended == true)
2302 ResumeThread ((*thread)->win32_obj_id);
2303 (*thread)->suspended = false;
2305 return 0;
2308 static inline int
2309 pthread_convert_abstime (clockid_t clock_id, const struct timespec *abstime,
2310 PLARGE_INTEGER timeout)
2312 struct timespec tp;
2314 /* According to SUSv3, the abstime value must be checked for validity. */
2315 if (!valid_timespec (*abstime))
2316 return EINVAL;
2318 /* Check for immediate timeout before converting */
2319 clock_gettime (clock_id, &tp);
2320 if (tp.tv_sec > abstime->tv_sec
2321 || (tp.tv_sec == abstime->tv_sec
2322 && tp.tv_nsec > abstime->tv_nsec))
2323 return ETIMEDOUT;
2325 timeout->QuadPart = abstime->tv_sec * NS100PERSEC
2326 + (abstime->tv_nsec + (NSPERSEC/NS100PERSEC) - 1)
2327 / (NSPERSEC/NS100PERSEC);
2328 switch (clock_id)
2330 case CLOCK_REALTIME_COARSE:
2331 case CLOCK_REALTIME:
2332 timeout->QuadPart += FACTOR;
2333 break;
2334 default:
2335 /* other clocks must be handled as relative timeout */
2336 timeout->QuadPart -= tp.tv_sec * NS100PERSEC + tp.tv_nsec
2337 / (NSPERSEC/NS100PERSEC);
2338 timeout->QuadPart *= -1LL;
2339 break;
2341 return 0;
2345 pthread_cond::init (pthread_cond_t *cond, const pthread_condattr_t *attr)
2347 pthread_cond_t new_cond;
2349 if (attr && !pthread_condattr::is_good_object (attr))
2350 return EINVAL;
2352 cond_initialization_lock.lock ();
2354 new_cond = new pthread_cond (attr ? (*attr) : NULL);
2355 if (!is_good_object (&new_cond))
2357 delete new_cond;
2358 cond_initialization_lock.unlock ();
2359 return EAGAIN;
2362 int ret = 0;
2364 __try
2366 *cond = new_cond;
2368 __except (NO_ERROR)
2370 delete new_cond;
2371 ret = EINVAL;
2373 __endtry
2374 cond_initialization_lock.unlock ();
2375 return ret;
2379 pthread_rwlock::init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
2381 pthread_rwlock_t new_rwlock;
2383 if (attr && !pthread_rwlockattr::is_good_object (attr))
2384 return EINVAL;
2386 rwlock_initialization_lock.lock ();
2388 new_rwlock = new pthread_rwlock (attr ? (*attr) : NULL);
2389 if (!is_good_object (&new_rwlock))
2391 delete new_rwlock;
2392 rwlock_initialization_lock.unlock ();
2393 return EAGAIN;
2396 int ret = 0;
2398 __try
2400 *rwlock = new_rwlock;
2402 __except (NO_ERROR)
2404 delete new_rwlock;
2405 ret = EINVAL;
2407 __endtry
2408 rwlock_initialization_lock.unlock ();
2409 return ret;
2412 /* Mutexes */
2415 pthread_mutex::init (pthread_mutex_t *mutex,
2416 const pthread_mutexattr_t *attr,
2417 const pthread_mutex_t initializer)
2419 if (attr && !pthread_mutexattr::is_good_object (attr))
2420 return EINVAL;
2422 mutex_initialization_lock.lock ();
2423 if (initializer == NULL || pthread_mutex::is_initializer (mutex))
2425 pthread_mutex_t new_mutex = new pthread_mutex (attr ? (*attr) : NULL);
2426 if (!is_good_object (&new_mutex))
2428 delete new_mutex;
2429 mutex_initialization_lock.unlock ();
2430 return EAGAIN;
2433 if (!attr && initializer)
2435 if (initializer == PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
2436 new_mutex->type = PTHREAD_MUTEX_RECURSIVE;
2437 else if (initializer == PTHREAD_NORMAL_MUTEX_INITIALIZER_NP)
2438 new_mutex->type = PTHREAD_MUTEX_NORMAL;
2439 else if (initializer == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)
2440 new_mutex->type = PTHREAD_MUTEX_ERRORCHECK;
2443 __try
2445 *mutex = new_mutex;
2447 __except (NO_ERROR)
2449 delete new_mutex;
2450 mutex_initialization_lock.unlock ();
2451 return EINVAL;
2453 __endtry
2455 mutex_initialization_lock.unlock ();
2456 pthread_printf ("*mutex %p, attr %p, initializer %p", *mutex, attr, initializer);
2458 return 0;
2461 /* Spinlocks */
2464 pthread_spinlock::init (pthread_spinlock_t *spinlock, int pshared)
2466 pthread_spinlock_t new_spinlock = new pthread_spinlock (pshared);
2467 if (!is_good_object (&new_spinlock))
2469 delete new_spinlock;
2470 return EAGAIN;
2473 __try
2475 *spinlock = new_spinlock;
2477 __except (NO_ERROR)
2479 delete new_spinlock;
2480 return EINVAL;
2482 __endtry
2483 pthread_printf ("*spinlock %p, pshared %d", *spinlock, pshared);
2484 return 0;
2487 /* Semaphores */
2489 List<semaphore> semaphore::semaphores;
2491 semaphore::semaphore (int pshared, unsigned int value)
2492 : verifyable_object (SEM_MAGIC),
2493 shared (pshared),
2494 currentvalue (-1),
2495 startvalue (value),
2496 fd (-1),
2497 hash (0ULL),
2498 sem (NULL)
2500 SECURITY_ATTRIBUTES sa = (pshared != PTHREAD_PROCESS_PRIVATE)
2501 ? sec_all : sec_none_nih;
2502 this->win32_obj_id = ::CreateSemaphore (&sa, value, INT32_MAX, NULL);
2503 if (!this->win32_obj_id)
2504 magic = 0;
2506 semaphores.insert (this);
2509 semaphore::semaphore (unsigned long long shash, LUID sluid, int sfd,
2510 sem_t *ssem, int oflag, mode_t mode, unsigned int value)
2511 : verifyable_object (SEM_MAGIC),
2512 shared (PTHREAD_PROCESS_SHARED),
2513 currentvalue (-1), /* Unused for named semaphores. */
2514 startvalue (value),
2515 fd (sfd),
2516 hash (shash),
2517 luid (sluid),
2518 sem (ssem)
2520 char name[MAX_PATH];
2522 __small_sprintf (name, "semaphore/%016X%08x%08x",
2523 hash, luid.HighPart, luid.LowPart);
2524 this->win32_obj_id = ::CreateSemaphore (&sec_all, value, INT32_MAX, name);
2525 if (!this->win32_obj_id)
2526 magic = 0;
2527 if (GetLastError () == ERROR_ALREADY_EXISTS && (oflag & O_EXCL))
2529 __seterrno ();
2530 CloseHandle (this->win32_obj_id);
2531 magic = 0;
2534 semaphores.insert (this);
2537 semaphore::~semaphore ()
2539 if (win32_obj_id)
2540 CloseHandle (win32_obj_id);
2542 semaphores.remove (this);
2545 void
2546 semaphore::_post ()
2548 LONG dummy;
2549 ReleaseSemaphore (win32_obj_id, 1, &dummy);
2553 semaphore::_getvalue (int *sval)
2555 NTSTATUS status;
2556 SEMAPHORE_BASIC_INFORMATION sbi;
2558 status = NtQuerySemaphore (win32_obj_id, SemaphoreBasicInformation, &sbi,
2559 sizeof sbi, NULL);
2560 int res;
2561 if (NT_SUCCESS (status))
2563 *sval = sbi.CurrentCount;
2564 res = 0;
2566 else
2568 *sval = startvalue;
2569 __seterrno_from_nt_status (status);
2570 res = -1;
2572 return res;
2576 semaphore::_trywait ()
2578 /* FIXME: signals should be able to interrupt semaphores...
2579 We probably need WaitForMultipleObjects here. */
2580 if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)
2582 set_errno (EAGAIN);
2583 return -1;
2585 return 0;
2589 semaphore::_wait (PLARGE_INTEGER timeout)
2591 __try
2593 switch (cygwait (win32_obj_id, timeout,
2594 cw_cancel | cw_cancel_self | cw_sig_eintr))
2596 case WAIT_OBJECT_0:
2597 break;
2598 case WAIT_SIGNALED:
2599 set_errno (EINTR);
2600 return -1;
2601 case WAIT_TIMEOUT:
2602 set_errno (ETIMEDOUT);
2603 return -1;
2604 default:
2605 pthread_printf ("cygwait failed. %E");
2606 __seterrno ();
2607 return -1;
2610 __except (NO_ERROR) {}
2611 __endtry
2612 return 0;
2615 void
2616 semaphore::_fixup_before_fork ()
2618 NTSTATUS status;
2619 SEMAPHORE_BASIC_INFORMATION sbi;
2621 status = NtQuerySemaphore (win32_obj_id, SemaphoreBasicInformation, &sbi,
2622 sizeof sbi, NULL);
2623 if (NT_SUCCESS (status))
2624 currentvalue = sbi.CurrentCount;
2625 else
2626 currentvalue = startvalue;
2629 void
2630 semaphore::_fixup_after_fork ()
2632 if (shared == PTHREAD_PROCESS_PRIVATE)
2634 pthread_printf ("sem %p", this);
2635 win32_obj_id = ::CreateSemaphore (&sec_none_nih, currentvalue,
2636 INT32_MAX, NULL);
2637 if (!win32_obj_id)
2638 api_fatal ("failed to create new win32 semaphore, "
2639 "currentvalue %ld, %E", currentvalue);
2643 void
2644 semaphore::_terminate ()
2646 int _sem_close (sem_t *, bool);
2648 if (sem)
2649 _sem_close (sem, false);
2652 /* static members */
2655 semaphore::init (sem_t *sem, int pshared, unsigned int value)
2658 We can't tell the difference between reinitialising an
2659 existing semaphore and initialising a semaphore who's
2660 contents happen to be a valid pointer
2662 if (is_good_object (sem))
2663 paranoid_printf ("potential attempt to reinitialise a semaphore");
2665 if (value > SEM_VALUE_MAX)
2667 set_errno(EINVAL);
2668 return -1;
2671 *sem = new semaphore (pshared, value);
2673 if (!is_good_object (sem))
2675 delete (*sem);
2676 *sem = NULL;
2677 set_errno(EAGAIN);
2678 return -1;
2680 return 0;
2684 semaphore::destroy (sem_t *sem)
2686 if (!is_good_object (sem))
2688 set_errno(EINVAL);
2689 return -1;
2692 /* It's invalid to destroy a semaphore not opened with sem_init. */
2693 if ((*sem)->fd != -1)
2695 set_errno(EINVAL);
2696 return -1;
2699 /* FIXME - new feature - test for busy against threads... */
2701 delete (*sem);
2702 *sem = NULL;
2703 return 0;
2707 semaphore::close (sem_t *sem)
2709 if (!is_good_object (sem))
2711 set_errno(EINVAL);
2712 return -1;
2715 /* It's invalid to close a semaphore not opened with sem_open. */
2716 if ((*sem)->fd == -1)
2718 set_errno(EINVAL);
2719 return -1;
2722 delete (*sem);
2723 delete sem;
2724 return 0;
2727 sem_t *
2728 semaphore::open (unsigned long long hash, LUID luid, int fd, int oflag,
2729 mode_t mode, unsigned int value, bool &wasopen)
2731 if (value > SEM_VALUE_MAX)
2733 set_errno (EINVAL);
2734 return NULL;
2737 /* sem_open is supposed to return the same pointer, if the same named
2738 semaphore is opened multiple times in the same process, as long as
2739 the semaphore hasn't been closed or unlinked in the meantime. */
2740 semaphores.mx.lock ();
2741 for (semaphore *sema = semaphores.head; sema; sema = sema->next)
2742 if (sema->fd >= 0 && sema->hash == hash
2743 && sema->luid.HighPart == luid.HighPart
2744 && sema->luid.LowPart == luid.LowPart)
2746 wasopen = true;
2747 semaphores.mx.unlock ();
2748 return sema->sem;
2750 semaphores.mx.unlock ();
2752 wasopen = false;
2753 sem_t *sem = new sem_t;
2754 if (!sem)
2756 set_errno (ENOMEM);
2757 return NULL;
2760 *sem = new semaphore (hash, luid, fd, sem, oflag, mode, value);
2762 if (!is_good_object (sem))
2764 delete *sem;
2765 delete sem;
2766 return NULL;
2768 return sem;
2772 semaphore::wait (sem_t *sem)
2774 pthread_testcancel ();
2776 if (!is_good_object (sem))
2778 set_errno (EINVAL);
2779 return -1;
2782 return (*sem)->_wait ();
2786 semaphore::trywait (sem_t *sem)
2788 if (!is_good_object (sem))
2790 set_errno (EINVAL);
2791 return -1;
2794 return (*sem)->_trywait ();
2798 semaphore::clockwait (sem_t *sem, clockid_t clock_id,
2799 const struct timespec *abstime)
2801 LARGE_INTEGER timeout;
2803 if (!is_good_object (sem))
2805 set_errno (EINVAL);
2806 return -1;
2809 /* According to SUSv3, abstime need not be checked for validity,
2810 if the semaphore can be locked immediately. */
2811 if (!(*sem)->_trywait ())
2812 return 0;
2814 __try
2816 int err = pthread_convert_abstime (clock_id, abstime, &timeout);
2817 if (err)
2818 return err;
2820 return (*sem)->_wait (&timeout);
2822 __except (NO_ERROR) {}
2823 __endtry
2824 return EINVAL;
2828 semaphore::post (sem_t *sem)
2830 if (!is_good_object (sem))
2832 set_errno (EINVAL);
2833 return -1;
2836 (*sem)->_post ();
2837 return 0;
2841 semaphore::getvalue (sem_t *sem, int *sval)
2843 __try
2845 if (is_good_object (sem))
2846 return (*sem)->_getvalue (sval);
2848 __except (NO_ERROR) {}
2849 __endtry
2850 set_errno (EINVAL);
2851 return -1;
2855 semaphore::getinternal (sem_t *sem, int *sfd, unsigned long long *shash,
2856 LUID *sluid, unsigned int *sval)
2858 __try
2860 if (!is_good_object (sem))
2861 __leave;
2862 if ((*sfd = (*sem)->fd) < 0)
2863 __leave;
2864 *shash = (*sem)->hash;
2865 *sluid = (*sem)->luid;
2866 /* POSIX defines the value in calls to sem_init/sem_open as unsigned,
2867 but the sem_getvalue gets a pointer to int to return the value.
2868 Go figure! */
2869 return (*sem)->_getvalue ((int *)sval);
2871 __except (NO_ERROR) {}
2872 __endtry
2873 set_errno (EINVAL);
2874 return -1;
2877 /* pthread_null */
2878 pthread *
2879 pthread_null::get_null_pthread ()
2881 /* because of weird entry points */
2882 _instance.magic = 0;
2883 return &_instance;
2886 pthread_null::pthread_null ()
2888 attr.joinable = PTHREAD_CREATE_DETACHED;
2889 /* Mark ourselves as invalid */
2890 magic = 0;
2893 pthread_null::~pthread_null ()
2897 bool
2898 pthread_null::create (void *(*)(void *), pthread_attr *, void *)
2900 return true;
2903 void
2904 pthread_null::exit (void *value_ptr)
2906 _my_tls.remove (INFINITE);
2907 ExitThread (0);
2911 pthread_null::cancel ()
2913 return 0;
2916 void
2917 pthread_null::testcancel ()
2922 pthread_null::setcancelstate (int state, int *oldstate)
2924 return EINVAL;
2928 pthread_null::setcanceltype (int type, int *oldtype)
2930 return EINVAL;
2933 void
2934 pthread_null::push_cleanup_handler (__pthread_cleanup_handler *handler)
2938 void
2939 pthread_null::pop_cleanup_handler (int const execute)
2943 unsigned long
2944 pthread_null::getsequence_np ()
2946 return 0;
2949 pthread_null pthread_null::_instance;
2952 pthread_barrier::init (const pthread_barrierattr_t * attr, unsigned count)
2954 pthread_mutex_t * mutex = NULL;
2956 if (unlikely ((attr != NULL
2957 && (! pthread_barrierattr::is_good_object (attr)
2958 || (*attr)->shared == PTHREAD_PROCESS_SHARED))
2959 || count == 0))
2960 return EINVAL;
2962 int retval = pthread_mutex_init (&mtx, NULL);
2963 if (unlikely (retval != 0))
2964 return retval;
2966 retval = pthread_cond_init (&cond, NULL);
2967 if (unlikely (retval != 0))
2969 int ret = pthread_mutex_destroy (mutex);
2970 if (ret != 0)
2971 api_fatal ("pthread_mutex_destroy (%p) = %d", mutex, ret);
2973 mtx = NULL;
2974 return retval;
2977 cnt = count;
2978 cyc = 0;
2979 wt = 0;
2981 return 0;
2985 pthread_barrier::destroy ()
2987 if (unlikely (wt != 0))
2988 return EBUSY;
2990 int retval = pthread_cond_destroy (&cond);
2991 if (unlikely (retval != 0))
2992 return retval;
2993 else
2994 cond = NULL;
2996 retval = pthread_mutex_destroy (&mtx);
2997 if (unlikely (retval != 0))
2998 return retval;
2999 else
3000 mtx = NULL;
3002 cnt = 0;
3003 cyc = 0;
3004 wt = 0;
3006 return 0;
3010 pthread_barrier::wait ()
3012 int retval = pthread_mutex_lock (&mtx);
3013 if (unlikely (retval != 0))
3014 return retval;
3016 if (unlikely (wt >= cnt))
3018 api_fatal ("wt >= cnt (%u >= %u)", wt, cnt);
3019 return EINVAL;
3022 if (unlikely (++wt == cnt))
3024 ++cyc;
3025 /* This is the last thread to reach the barrier. Signal the waiting
3026 threads to wake up and continue. */
3027 retval = pthread_cond_broadcast (&cond);
3028 if (unlikely (retval != 0))
3029 goto cond_error;
3031 wt = 0;
3032 retval = pthread_mutex_unlock (&mtx);
3033 if (unlikely (retval != 0))
3034 abort ();
3036 return PTHREAD_BARRIER_SERIAL_THREAD;
3038 else
3040 uint64_t cycle = cyc;
3043 retval = pthread_cond_wait (&cond, &mtx);
3044 if (unlikely (retval != 0))
3045 goto cond_error;
3047 while (unlikely (cycle == cyc));
3049 retval = pthread_mutex_unlock (&mtx);
3050 if (unlikely (retval != 0))
3051 api_fatal ("pthread_mutex_unlock (%p) = %d", &mtx, retval);
3053 return 0;
3056 cond_error:
3058 --wt;
3059 int ret = pthread_mutex_unlock (&mtx);
3060 if (unlikely (ret != 0))
3061 api_fatal ("pthread_mutex_unlock (%p) = %d", &mtx, ret);
3063 return retval;
3067 /* Returns running thread's name; works for both cygthreads and pthreads */
3068 char *
3069 mythreadname (void)
3071 char *result = (char *) cygthread::name ();
3073 if (result == _my_tls.locals.unknown_thread_name)
3075 result[0] = '\0';
3076 pthread_getname_np (pthread_self (), result, (size_t) THRNAMELEN);
3079 return result;
3082 extern "C"
3085 /* Thread creation */
3088 pthread_create (pthread_t *thread, const pthread_attr_t *attr,
3089 void *(*start_routine) (void *), void *arg)
3091 return pthread::create (thread, attr, start_routine, arg);
3095 pthread_once (pthread_once_t * once_control, void (*init_routine) (void))
3097 return pthread::once (once_control, init_routine);
3101 pthread_atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void))
3103 return pthread::atfork (prepare, parent, child);
3106 /* ID */
3108 pthread_t pthread_self ()
3110 return pthread::self ();
3114 pthread_equal (pthread_t t1, pthread_t t2)
3116 return pthread::equal (t1, t2);
3119 unsigned long
3120 pthread_getsequence_np (pthread_t * thread)
3122 if (!pthread::is_good_object (thread))
3123 return EINVAL;
3124 return (*thread)->getsequence_np ();
3127 /* Thread name */
3130 pthread_getname_np (pthread_t thread, char *buf, size_t buflen)
3132 char *name;
3134 if (!pthread::is_good_object (&thread))
3135 return ESRCH;
3137 if (!thread->attr.name)
3138 name = program_invocation_short_name;
3139 else
3140 name = thread->attr.name;
3142 /* Return ERANGE if the provided buffer is less than THRNAMELEN. Truncate
3143 and zero-terminate the name to fit in buf. This means we always return
3144 something if the buffer is THRNAMELEN or larger, but there is no way to
3145 tell if we have the whole name. */
3146 if (buflen < THRNAMELEN)
3147 return ERANGE;
3149 int ret = 0;
3150 __try
3152 strlcpy (buf, name, buflen);
3154 __except (NO_ERROR)
3156 ret = EFAULT;
3158 __endtry
3160 return ret;
3164 pthread_setname_np (pthread_t thread, const char *name)
3166 char *oldname, *cp;
3168 if (!pthread::is_good_object (&thread))
3169 return ESRCH;
3171 if (strlen (name) > THRNAMELEN)
3172 return ERANGE;
3174 cp = strdup (name);
3175 if (!cp)
3176 return ENOMEM;
3178 oldname = thread->attr.name;
3179 thread->attr.name = cp;
3181 SetThreadName (GetThreadId (thread->win32_obj_id), thread->attr.name);
3183 if (oldname)
3184 free (oldname);
3186 return 0;
3189 /* Thread exit */
3191 void
3192 pthread_exit (void *value_ptr)
3194 pthread::self ()->exit (value_ptr);
3195 __builtin_unreachable (); /* FIXME: don't know why this is necessary */
3199 pthread_detach (pthread_t thread)
3201 return pthread::detach (&thread);
3205 pthread_join (pthread_t thread, void **return_val)
3207 return pthread::join (&thread, (void **) return_val, NULL);
3211 pthread_tryjoin_np (pthread_t thread, void **return_val)
3213 LARGE_INTEGER timeout = { QuadPart:0LL };
3215 return pthread::join (&thread, (void **) return_val, &timeout);
3219 pthread_timedjoin_np (pthread_t thread, void **return_val,
3220 const struct timespec *abstime)
3222 LARGE_INTEGER timeout;
3224 int err = pthread_convert_abstime (CLOCK_REALTIME, abstime, &timeout);
3225 if (err)
3226 return err;
3227 return pthread::join (&thread, (void **) return_val, &timeout);
3230 /* Thread suspend/resume */
3232 /* This isn't a posix call... should we keep it? */
3234 pthread_suspend (pthread_t thread)
3236 return pthread::suspend (&thread);
3239 /* same */
3241 pthread_continue (pthread_t thread)
3243 return pthread::resume (&thread);
3246 /* Thread signal */
3249 pthread_kill (pthread_t thread, int sig)
3251 // lock myself, for the use of thread2signal
3252 // two different kills might clash: FIXME
3254 if (!pthread::is_good_object (&thread))
3255 return EINVAL;
3257 /* check that sig is in right range */
3258 if (sig < 0 || sig >= _NSIG)
3259 return EINVAL;
3261 siginfo_t si = {0};
3262 si.si_signo = sig;
3263 si.si_code = SI_USER;
3264 si.si_pid = myself->pid;
3265 si.si_uid = myself->uid;
3266 int rval;
3267 if (!thread->valid)
3268 rval = ESRCH;
3269 else if (sig)
3271 rval = (int) sig_send (NULL, si, thread->cygtls);
3272 if (rval == -1)
3273 rval = get_errno ();
3275 else
3276 switch (WaitForSingleObject (thread->win32_obj_id, 0))
3278 case WAIT_TIMEOUT:
3279 rval = 0;
3280 break;
3281 default:
3282 rval = ESRCH;
3283 break;
3286 // unlock myself
3287 return rval;
3291 pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set)
3293 int res = handle_sigprocmask (operation, set, old_set, _my_tls.sigmask);
3294 syscall_printf ("%d = pthread_sigmask(%d, %p, %p)",
3295 res, operation, set, old_set);
3296 return res;
3300 pthread_sigqueue (pthread_t *thread, int sig, const union sigval value)
3302 siginfo_t si = {0};
3304 if (!pthread::is_good_object (thread))
3305 return EINVAL;
3306 if (!(*thread)->valid)
3307 return ESRCH;
3309 si.si_signo = sig;
3310 si.si_code = SI_QUEUE;
3311 si.si_value = value;
3312 si.si_pid = myself->pid;
3313 si.si_uid = myself->uid;
3314 return (int) sig_send (NULL, si, (*thread)->cygtls);
3317 /* Cancelability */
3320 pthread_cancel (pthread_t thread)
3322 return pthread::cancel (thread);
3326 pthread_setcancelstate (int state, int *oldstate)
3328 return pthread::self ()->setcancelstate (state, oldstate);
3332 pthread_setcanceltype (int type, int *oldtype)
3334 return pthread::self ()->setcanceltype (type, oldtype);
3337 void
3338 pthread_testcancel ()
3340 pthread::self ()->testcancel ();
3343 void
3344 _pthread_cleanup_push (__pthread_cleanup_handler *handler)
3346 pthread::self ()->push_cleanup_handler (handler);
3349 void
3350 _pthread_cleanup_pop (int execute)
3352 pthread::self ()->pop_cleanup_handler (execute);
3355 /* provided for source level compatability.
3356 See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
3359 pthread_getconcurrency ()
3361 return MT_INTERFACE->concurrency;
3364 /* provided for source level compatability. See
3365 http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
3368 pthread_setconcurrency (int new_level)
3370 if (new_level < 0)
3371 return EINVAL;
3372 MT_INTERFACE->concurrency = new_level;
3373 return 0;
3376 /* Thread scheduling */
3378 /* keep this in sync with sched.cc */
3380 pthread_getschedparam (pthread_t thread, int *policy,
3381 struct sched_param *param)
3383 if (!pthread::is_good_object (&thread))
3384 return ESRCH;
3385 *policy = SCHED_FIFO;
3386 param->sched_priority = sched_get_thread_priority (thread->win32_obj_id);
3387 return 0;
3390 /* keep this in sync with sched.cc */
3392 pthread_setschedparam (pthread_t thread, int policy,
3393 const struct sched_param *param)
3395 if (!pthread::is_good_object (&thread))
3396 return ESRCH;
3397 if (policy != SCHED_FIFO)
3398 return ENOTSUP;
3399 if (!param)
3400 return EINVAL;
3401 int rv =
3402 sched_set_thread_priority (thread->win32_obj_id, param->sched_priority);
3403 if (!rv)
3404 thread->attr.schedparam.sched_priority = param->sched_priority;
3405 return rv;
3409 pthread_setschedprio (pthread_t thread, int priority)
3411 if (!pthread::is_good_object (&thread))
3412 return ESRCH;
3413 int rv =
3414 sched_set_thread_priority (thread->win32_obj_id, priority);
3415 if (!rv)
3416 thread->attr.schedparam.sched_priority = priority;
3417 return rv;
3420 /* Thread affinity */
3423 pthread_getaffinity_np (pthread_t thread, size_t sizeof_set, cpu_set_t *set)
3425 if (!pthread::is_good_object (&thread))
3426 return ESRCH;
3428 return sched_get_thread_affinity (thread->win32_obj_id, sizeof_set, set);
3432 pthread_setaffinity_np (pthread_t thread, size_t sizeof_set, const cpu_set_t *set)
3434 if (!pthread::is_good_object (&thread))
3435 return ESRCH;
3437 return sched_set_thread_affinity (thread->win32_obj_id, sizeof_set, set);
3440 /* pthread_attr */
3443 pthread_attr_init (pthread_attr_t *attr)
3445 *attr = new pthread_attr;
3446 if (!pthread_attr::is_good_object (attr))
3448 delete (*attr);
3449 *attr = NULL;
3450 return ENOMEM;
3452 return 0;
3456 pthread_attr_getinheritsched (const pthread_attr_t *attr,
3457 int *inheritsched)
3459 if (!pthread_attr::is_good_object (attr))
3460 return EINVAL;
3461 *inheritsched = (*attr)->inheritsched;
3462 return 0;
3466 pthread_attr_getschedparam (const pthread_attr_t *attr,
3467 struct sched_param *param)
3469 if (!pthread_attr::is_good_object (attr))
3470 return EINVAL;
3471 *param = (*attr)->schedparam;
3472 return 0;
3475 /* From a pure code point of view, this should call a helper in sched.cc,
3476 to allow for someone adding scheduler policy changes to win32 in the future.
3477 However that's extremely unlikely, so short and sweet will do us */
3479 pthread_attr_getschedpolicy (const pthread_attr_t *attr, int *policy)
3481 if (!pthread_attr::is_good_object (attr))
3482 return EINVAL;
3483 *policy = SCHED_FIFO;
3484 return 0;
3489 pthread_attr_getscope (const pthread_attr_t *attr, int *contentionscope)
3491 if (!pthread_attr::is_good_object (attr))
3492 return EINVAL;
3493 *contentionscope = (*attr)->contentionscope;
3494 return 0;
3498 pthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate)
3500 if (!pthread_attr::is_good_object (attr))
3501 return EINVAL;
3502 if (detachstate < 0 || detachstate > 1)
3503 return EINVAL;
3504 (*attr)->joinable = detachstate;
3505 return 0;
3509 pthread_attr_getdetachstate (const pthread_attr_t *attr, int *detachstate)
3511 if (!pthread_attr::is_good_object (attr))
3512 return EINVAL;
3513 *detachstate = (*attr)->joinable;
3514 return 0;
3518 pthread_attr_setinheritsched (pthread_attr_t *attr, int inheritsched)
3520 if (!pthread_attr::is_good_object (attr))
3521 return EINVAL;
3522 if (inheritsched != PTHREAD_INHERIT_SCHED
3523 && inheritsched != PTHREAD_EXPLICIT_SCHED)
3524 return ENOTSUP;
3525 (*attr)->inheritsched = inheritsched;
3526 return 0;
3530 pthread_attr_setschedparam (pthread_attr_t *attr,
3531 const struct sched_param *param)
3533 if (!pthread_attr::is_good_object (attr))
3534 return EINVAL;
3535 if (!valid_sched_parameters (param))
3536 return ENOTSUP;
3537 (*attr)->schedparam = *param;
3538 return 0;
3541 /* See __pthread_attr_getschedpolicy for some notes */
3543 pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy)
3545 if (!pthread_attr::is_good_object (attr))
3546 return EINVAL;
3547 if (policy != SCHED_FIFO)
3548 return ENOTSUP;
3549 return 0;
3553 pthread_attr_setscope (pthread_attr_t *attr, int contentionscope)
3555 if (!pthread_attr::is_good_object (attr))
3556 return EINVAL;
3557 if (contentionscope != PTHREAD_SCOPE_SYSTEM
3558 && contentionscope != PTHREAD_SCOPE_PROCESS)
3559 return EINVAL;
3560 /* In future, we may be able to support system scope by escalating the thread
3561 priority to exceed the priority class. For now we only support PROCESS scope. */
3562 if (contentionscope != PTHREAD_SCOPE_PROCESS)
3563 return ENOTSUP;
3564 (*attr)->contentionscope = contentionscope;
3565 return 0;
3569 pthread_attr_setstack (pthread_attr_t *attr, void *addr, size_t size)
3571 if (!pthread_attr::is_good_object (attr))
3572 return EINVAL;
3573 if (addr == NULL)
3574 return EINVAL;
3575 if (size < PTHREAD_STACK_MIN)
3576 return EINVAL;
3577 /* The incoming address addr points to the lowest addressable byte of a
3578 buffer of size bytes. Due to the way pthread_attr_setstackaddr is defined
3579 on Linux, the lowest address ot the stack can't be reliably computed when
3580 using pthread_attr_setstackaddr/pthread_attr_setstacksize. Therefore we
3581 store the uppermost address of the stack in stackaddr. See also the
3582 comment in pthread_attr_setstackaddr. */
3583 (*attr)->stackaddr = (caddr_t) addr + size;
3584 (*attr)->stacksize = size;
3585 return 0;
3589 pthread_attr_getstack (const pthread_attr_t *attr, void **addr, size_t *size)
3591 if (!pthread_attr::is_good_object (attr))
3592 return EINVAL;
3593 /* stackaddr holds the uppermost stack address. See the comment in
3594 pthread_attr_setstack. */
3595 *addr = (caddr_t) (*attr)->stackaddr - (*attr)->stacksize;
3596 *size = (*attr)->stacksize;
3597 return 0;
3601 pthread_attr_setstackaddr (pthread_attr_t *attr, void *addr)
3603 if (!pthread_attr::is_good_object (attr))
3604 return EINVAL;
3605 if (addr == NULL)
3606 return EINVAL;
3607 /* This function is deprecated in SUSv4, but SUSv3 didn't define
3608 if the incoming stack address is the lowest address of the memory
3609 area defined as stack, or if it's the start address of the stack
3610 at which it begins its growth. On Linux it's the latter which
3611 means the uppermost stack address on x86 based systems. See comment
3612 in pthread_attr_setstack as well. */
3613 (*attr)->stackaddr = addr;
3614 return 0;
3618 pthread_attr_getstackaddr (const pthread_attr_t *attr, void **addr)
3620 if (!pthread_attr::is_good_object (attr))
3621 return EINVAL;
3622 /* See comment in pthread_attr_setstackaddr. */
3623 *addr = (*attr)->stackaddr;
3624 return 0;
3628 pthread_attr_setstacksize (pthread_attr_t *attr, size_t size)
3630 if (!pthread_attr::is_good_object (attr))
3631 return EINVAL;
3632 if (size < PTHREAD_STACK_MIN)
3633 return EINVAL;
3634 (*attr)->stacksize = size;
3635 return 0;
3639 pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *size)
3641 if (!pthread_attr::is_good_object (attr))
3642 return EINVAL;
3643 /* If the stacksize has not been set by the application, return the
3644 default stacksize. Note that this is different from what
3645 pthread_attr_getstack returns. */
3646 *size = (*attr)->stacksize ?: get_rlimit_stack ();
3647 return 0;
3651 pthread_attr_setguardsize (pthread_attr_t *attr, size_t size)
3653 if (!pthread_attr::is_good_object (attr))
3654 return EINVAL;
3655 /* We don't support a guardsize of more than 1 Meg. */
3656 if (size > 1024 * 1024)
3657 return EINVAL;
3658 (*attr)->guardsize = size;
3659 return 0;
3663 pthread_attr_getguardsize (const pthread_attr_t *attr, size_t *size)
3665 if (!pthread_attr::is_good_object (attr))
3666 return EINVAL;
3667 *size = (*attr)->guardsize;
3668 return 0;
3672 pthread_attr_destroy (pthread_attr_t *attr)
3674 if (!pthread_attr::is_good_object (attr))
3675 return EINVAL;
3676 delete (*attr);
3677 *attr = NULL;
3678 return 0;
3682 pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
3684 THREAD_BASIC_INFORMATION tbi;
3685 NTSTATUS status;
3687 if (!pthread::is_good_object (&thread))
3688 return ESRCH;
3690 /* attr may not be pre-initialized */
3691 if (!pthread_attr::is_good_object (attr))
3693 int rv = pthread_attr_init (attr);
3694 if (rv != 0)
3695 return rv;
3698 (*attr)->joinable = thread->attr.joinable;
3699 (*attr)->contentionscope = thread->attr.contentionscope;
3700 (*attr)->inheritsched = thread->attr.inheritsched;
3701 (*attr)->schedparam = thread->attr.schedparam;
3702 (*attr)->guardsize = thread->attr.guardsize;
3704 status = NtQueryInformationThread (thread->win32_obj_id,
3705 ThreadBasicInformation,
3706 &tbi, sizeof (tbi), NULL);
3707 if (NT_SUCCESS (status))
3709 PTEB teb = (PTEB) tbi.TebBaseAddress;
3710 /* stackaddr holds the uppermost stack address. See the comments
3711 in pthread_attr_setstack and pthread_attr_setstackaddr for a
3712 description. */
3713 (*attr)->stackaddr = teb->Tib.StackBase;
3714 (*attr)->stacksize = (uintptr_t) teb->Tib.StackBase
3715 - (uintptr_t) (teb->DeallocationStack ?: teb->Tib.StackLimit);
3717 else
3719 debug_printf ("NtQueryInformationThread(ThreadBasicInformation), "
3720 "status %y", status);
3721 (*attr)->stackaddr = thread->attr.stackaddr;
3722 (*attr)->stacksize = thread->attr.stacksize;
3725 return 0;
3728 /* Thread Specific Data */
3731 pthread_key_create (pthread_key_t *key, void (*destructor) (void *))
3733 *key = new pthread_key (destructor);
3735 if (!pthread_key::is_good_object (key))
3737 delete (*key);
3738 *key = NULL;
3739 return EAGAIN;
3741 return 0;
3745 pthread_key_delete (pthread_key_t key)
3747 if (!pthread_key::is_good_object (&key))
3748 return EINVAL;
3750 delete (key);
3751 return 0;
3754 void *
3755 pthread_getspecific (pthread_key_t key)
3757 if (!pthread_key::is_good_object (&key))
3758 return NULL;
3760 return (key)->get ();
3764 pthread_setspecific (pthread_key_t key, const void *value)
3766 if (!pthread_key::is_good_object (&key))
3767 return EINVAL;
3768 (key)->set (value);
3769 return 0;
3772 /* Mutexes */
3775 pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr)
3777 return pthread_mutex::init (mutex, attr, NULL);
3781 pthread_mutex_getprioceiling (const pthread_mutex_t *mutex,
3782 int *prioceiling)
3784 /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
3785 mutex priorities.
3787 We can support mutex priorities in the future though:
3788 Store a priority with each mutex.
3789 When the mutex is optained, set the thread priority as appropriate
3790 When the mutex is released, reset the thread priority. */
3791 return ENOSYS;
3795 pthread_mutex_lock (pthread_mutex_t *mutex)
3797 if (pthread_mutex::is_initializer (mutex))
3798 pthread_mutex::init (mutex, NULL, *mutex);
3799 if (!pthread_mutex::is_good_object (mutex))
3800 return EINVAL;
3801 return (*mutex)->lock ();
3805 pthread_mutex_clocklock (pthread_mutex_t *mutex, clockid_t clock_id,
3806 const struct timespec *abstime)
3808 LARGE_INTEGER timeout;
3810 if (pthread_mutex::is_initializer (mutex))
3811 pthread_mutex::init (mutex, NULL, *mutex);
3812 if (!pthread_mutex::is_good_object (mutex))
3813 return EINVAL;
3815 /* According to SUSv3, abstime need not be checked for validity,
3816 if the mutex can be locked immediately. */
3817 if (!(*mutex)->trylock ())
3818 return 0;
3820 __try
3822 int err = pthread_convert_abstime (clock_id, abstime, &timeout);
3823 if (err)
3824 return err;
3826 return (*mutex)->lock (&timeout);
3828 __except (NO_ERROR) {}
3829 __endtry
3830 return EINVAL;
3834 pthread_mutex_timedlock (pthread_mutex_t *mutex, const struct timespec *abstime)
3836 return pthread_mutex_clocklock (mutex, CLOCK_REALTIME, abstime);
3840 pthread_mutex_trylock (pthread_mutex_t *mutex)
3842 if (pthread_mutex::is_initializer (mutex))
3843 pthread_mutex::init (mutex, NULL, *mutex);
3844 if (!pthread_mutex::is_good_object (mutex))
3845 return EINVAL;
3846 return (*mutex)->trylock ();
3850 pthread_mutex_unlock (pthread_mutex_t *mutex)
3852 if (pthread_mutex::is_initializer (mutex))
3853 pthread_mutex::init (mutex, NULL, *mutex);
3854 if (!pthread_mutex::is_good_object (mutex))
3855 return EINVAL;
3856 return (*mutex)->unlock ();
3860 pthread_mutex_destroy (pthread_mutex_t *mutex)
3862 int rv;
3864 if (pthread_mutex::is_initializer (mutex))
3865 return 0;
3866 if (!pthread_mutex::is_good_object (mutex))
3867 return EINVAL;
3869 rv = (*mutex)->destroy ();
3870 if (rv)
3871 return rv;
3873 *mutex = NULL;
3874 return 0;
3878 pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling,
3879 int *old_ceiling)
3881 return ENOSYS;
3884 /* Mutex attributes */
3886 /* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
3887 for more detail */
3889 pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr,
3890 int *protocol)
3892 if (!pthread_mutexattr::is_good_object (attr))
3893 return EINVAL;
3894 return ENOSYS;
3898 pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr,
3899 int *pshared)
3901 if (!pthread_mutexattr::is_good_object (attr))
3902 return EINVAL;
3903 *pshared = (*attr)->pshared;
3904 return 0;
3908 pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type)
3910 if (!pthread_mutexattr::is_good_object (attr))
3911 return EINVAL;
3912 *type = (*attr)->mutextype;
3913 return 0;
3916 /* FIXME: write and test process shared mutex's. */
3918 pthread_mutexattr_init (pthread_mutexattr_t *attr)
3920 *attr = new pthread_mutexattr ();
3921 if (!pthread_mutexattr::is_good_object (attr))
3923 delete (*attr);
3924 *attr = NULL;
3925 return ENOMEM;
3927 return 0;
3931 pthread_mutexattr_destroy (pthread_mutexattr_t *attr)
3933 if (!pthread_mutexattr::is_good_object (attr))
3934 return EINVAL;
3935 delete (*attr);
3936 *attr = NULL;
3937 return 0;
3941 /* Win32 doesn't support mutex priorities */
3943 pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, int protocol)
3945 if (!pthread_mutexattr::is_good_object (attr))
3946 return EINVAL;
3947 return ENOSYS;
3950 /* Win32 doesn't support mutex priorities */
3952 pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr,
3953 int prioceiling)
3955 if (!pthread_mutexattr::is_good_object (attr))
3956 return EINVAL;
3957 return ENOSYS;
3961 pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *attr,
3962 int *prioceiling)
3964 if (!pthread_mutexattr::is_good_object (attr))
3965 return EINVAL;
3966 return ENOSYS;
3970 pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared)
3972 if (!pthread_mutexattr::is_good_object (attr))
3973 return EINVAL;
3974 /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
3975 *functionality
3977 if (pshared != PTHREAD_PROCESS_PRIVATE)
3978 return EINVAL;
3979 (*attr)->pshared = pshared;
3980 return 0;
3983 /* see pthread_mutex_gettype */
3985 pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type)
3987 if (!pthread_mutexattr::is_good_object (attr))
3988 return EINVAL;
3990 switch (type)
3992 case PTHREAD_MUTEX_ERRORCHECK:
3993 case PTHREAD_MUTEX_RECURSIVE:
3994 case PTHREAD_MUTEX_NORMAL:
3995 (*attr)->mutextype = type;
3996 break;
3997 default:
3998 return EINVAL;
4001 return 0;
4004 /* Spinlocks */
4007 pthread_spin_init (pthread_spinlock_t *spinlock, int pshared)
4009 return pthread_spinlock::init (spinlock, pshared);
4013 pthread_spin_lock (pthread_spinlock_t *spinlock)
4015 if (!pthread_spinlock::is_good_object (spinlock))
4016 return EINVAL;
4017 return (*spinlock)->lock ();
4021 pthread_spin_trylock (pthread_spinlock_t *spinlock)
4023 if (!pthread_spinlock::is_good_object (spinlock))
4024 return EINVAL;
4025 return (*spinlock)->trylock ();
4029 pthread_spin_unlock (pthread_spinlock_t *spinlock)
4031 if (!pthread_spinlock::is_good_object (spinlock))
4032 return EINVAL;
4033 return (*spinlock)->unlock ();
4037 pthread_spin_destroy (pthread_spinlock_t *spinlock)
4039 if (!pthread_spinlock::is_good_object (spinlock))
4040 return EINVAL;
4041 return (*spinlock)->destroy ();
4044 /* Synchronisation */
4047 pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr)
4049 return pthread_cond::init (cond, attr);
4053 pthread_cond_destroy (pthread_cond_t *cond)
4055 if (pthread_cond::is_initializer (cond))
4056 return 0;
4057 if (!pthread_cond::is_good_object (cond))
4058 return EINVAL;
4060 /* reads are atomic */
4061 if ((*cond)->waiting)
4062 return EBUSY;
4064 delete (*cond);
4065 *cond = NULL;
4067 return 0;
4071 pthread_cond_broadcast (pthread_cond_t *cond)
4073 if (pthread_cond::is_initializer (cond))
4074 return 0;
4075 if (!pthread_cond::is_good_object (cond))
4076 return EINVAL;
4078 (*cond)->unblock (true);
4080 return 0;
4084 pthread_cond_signal (pthread_cond_t *cond)
4086 if (pthread_cond::is_initializer (cond))
4087 return 0;
4088 if (!pthread_cond::is_good_object (cond))
4089 return EINVAL;
4091 (*cond)->unblock (false);
4093 return 0;
4096 static int
4097 __pthread_cond_wait_init (pthread_cond_t *cond, pthread_mutex_t *mutex)
4099 if (!pthread_mutex::is_good_object (mutex))
4100 return EINVAL;
4101 if (!(*mutex)->can_be_unlocked ())
4102 return EPERM;
4104 if (pthread_cond::is_initializer (cond))
4105 pthread_cond::init (cond, NULL);
4106 if (!pthread_cond::is_good_object (cond))
4107 return EINVAL;
4109 return 0;
4112 static int
4113 __pthread_cond_clockwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
4114 clockid_t clock_id, const struct timespec *abstime)
4116 int err = 0;
4117 LARGE_INTEGER timeout;
4121 err = pthread_convert_abstime (clock_id, abstime, &timeout);
4122 if (err)
4123 break;
4125 err = (*cond)->wait (*mutex, &timeout);
4127 while (err == ETIMEDOUT);
4128 return err;
4132 pthread_cond_clockwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
4133 clockid_t clock_id, const struct timespec *abstime)
4135 int err = 0;
4137 pthread_testcancel ();
4139 __try
4141 err = __pthread_cond_wait_init (cond, mutex);
4142 if (err)
4143 __leave;
4144 err = __pthread_cond_clockwait (cond, mutex, clock_id, abstime);
4146 __except (NO_ERROR)
4148 return EINVAL;
4150 __endtry
4151 return err;
4155 pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
4156 const struct timespec *abstime)
4158 int err = 0;
4160 pthread_testcancel ();
4162 __try
4164 err = __pthread_cond_wait_init (cond, mutex);
4165 if (err)
4166 __leave;
4167 err = __pthread_cond_clockwait (cond, mutex, (*cond)->clock_id, abstime);
4169 __except (NO_ERROR)
4171 return EINVAL;
4173 __endtry
4174 return err;
4178 pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
4180 pthread_testcancel ();
4182 int err = __pthread_cond_wait_init (cond, mutex);
4183 if (err)
4184 return err;
4185 return (*cond)->wait (*mutex, NULL);
4188 /* Thread cond attributes */
4191 pthread_condattr_init (pthread_condattr_t *condattr)
4193 *condattr = new pthread_condattr;
4194 if (!pthread_condattr::is_good_object (condattr))
4196 delete (*condattr);
4197 *condattr = NULL;
4198 return ENOMEM;
4200 return 0;
4204 pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
4206 if (!pthread_condattr::is_good_object (attr))
4207 return EINVAL;
4208 *pshared = (*attr)->shared;
4209 return 0;
4213 pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared)
4215 if (!pthread_condattr::is_good_object (attr))
4216 return EINVAL;
4217 if ((pshared < 0) || (pshared > 1))
4218 return EINVAL;
4219 /* shared cond vars not currently supported */
4220 if (pshared != PTHREAD_PROCESS_PRIVATE)
4221 return EINVAL;
4222 (*attr)->shared = pshared;
4223 return 0;
4227 pthread_condattr_getclock (const pthread_condattr_t *attr, clockid_t *clock_id)
4229 if (!pthread_condattr::is_good_object (attr))
4230 return EINVAL;
4231 *clock_id = (*attr)->clock_id;
4232 return 0;
4236 pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock_id)
4238 if (!pthread_condattr::is_good_object (attr))
4239 return EINVAL;
4240 if (CLOCKID_IS_PROCESS (clock_id) || CLOCKID_IS_THREAD (clock_id)
4241 || clock_id >= MAX_CLOCKS)
4242 return EINVAL;
4243 (*attr)->clock_id = clock_id;
4244 return 0;
4248 pthread_condattr_destroy (pthread_condattr_t *condattr)
4250 if (!pthread_condattr::is_good_object (condattr))
4251 return EINVAL;
4252 delete (*condattr);
4253 *condattr = NULL;
4254 return 0;
4257 /* RW Locks */
4260 pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
4262 return pthread_rwlock::init (rwlock, attr);
4266 pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
4268 if (pthread_rwlock::is_initializer (rwlock))
4269 return 0;
4270 if (!pthread_rwlock::is_good_object (rwlock))
4271 return EINVAL;
4273 if ((*rwlock)->writer || (*rwlock)->readers ||
4274 (*rwlock)->waiting_readers || (*rwlock)->waiting_writers)
4275 return EBUSY;
4277 delete (*rwlock);
4278 *rwlock = NULL;
4280 return 0;
4284 pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
4286 pthread_testcancel ();
4288 if (pthread_rwlock::is_initializer (rwlock))
4289 pthread_rwlock::init (rwlock, NULL);
4290 if (!pthread_rwlock::is_good_object (rwlock))
4291 return EINVAL;
4293 return (*rwlock)->rdlock ();
4297 pthread_rwlock_clockrdlock (pthread_rwlock_t *rwlock, clockid_t clock_id,
4298 const struct timespec *abstime)
4300 LARGE_INTEGER timeout;
4302 pthread_testcancel ();
4304 if (pthread_rwlock::is_initializer (rwlock))
4305 pthread_rwlock::init (rwlock, NULL);
4306 if (!pthread_rwlock::is_good_object (rwlock))
4307 return EINVAL;
4309 /* According to SUSv3, abstime need not be checked for validity,
4310 if the rwlock can be locked immediately. */
4311 if (!(*rwlock)->tryrdlock ())
4312 return 0;
4314 __try
4316 int err = pthread_convert_abstime (clock_id, abstime, &timeout);
4317 if (err)
4318 return err;
4320 return (*rwlock)->rdlock (&timeout);
4322 __except (NO_ERROR) {}
4323 __endtry
4324 return EINVAL;
4328 pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
4329 const struct timespec *abstime)
4331 return pthread_rwlock_clockrdlock (rwlock, CLOCK_REALTIME, abstime);
4335 pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
4337 if (pthread_rwlock::is_initializer (rwlock))
4338 pthread_rwlock::init (rwlock, NULL);
4339 if (!pthread_rwlock::is_good_object (rwlock))
4340 return EINVAL;
4342 return (*rwlock)->tryrdlock ();
4346 pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
4348 pthread_testcancel ();
4350 if (pthread_rwlock::is_initializer (rwlock))
4351 pthread_rwlock::init (rwlock, NULL);
4352 if (!pthread_rwlock::is_good_object (rwlock))
4353 return EINVAL;
4355 return (*rwlock)->wrlock ();
4359 pthread_rwlock_clockwrlock (pthread_rwlock_t *rwlock, clockid_t clock_id,
4360 const struct timespec *abstime)
4362 LARGE_INTEGER timeout;
4364 pthread_testcancel ();
4366 if (pthread_rwlock::is_initializer (rwlock))
4367 pthread_rwlock::init (rwlock, NULL);
4368 if (!pthread_rwlock::is_good_object (rwlock))
4369 return EINVAL;
4371 /* According to SUSv3, abstime need not be checked for validity,
4372 if the rwlock can be locked immediately. */
4373 if (!(*rwlock)->trywrlock ())
4374 return 0;
4376 __try
4378 int err = pthread_convert_abstime (clock_id, abstime, &timeout);
4379 if (err)
4380 return err;
4382 return (*rwlock)->wrlock (&timeout);
4384 __except (NO_ERROR) {}
4385 __endtry
4386 return EINVAL;
4390 pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock,
4391 const struct timespec *abstime)
4393 return pthread_rwlock_clockwrlock (rwlock, CLOCK_REALTIME, abstime);
4397 pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
4399 if (pthread_rwlock::is_initializer (rwlock))
4400 pthread_rwlock::init (rwlock, NULL);
4401 if (!pthread_rwlock::is_good_object (rwlock))
4402 return EINVAL;
4404 return (*rwlock)->trywrlock ();
4408 pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
4410 if (pthread_rwlock::is_initializer (rwlock))
4411 return 0;
4412 if (!pthread_rwlock::is_good_object (rwlock))
4413 return EINVAL;
4415 return (*rwlock)->unlock ();
4418 /* RW Lock attributes */
4421 pthread_rwlockattr_init (pthread_rwlockattr_t *rwlockattr)
4423 *rwlockattr = new pthread_rwlockattr;
4424 if (!pthread_rwlockattr::is_good_object (rwlockattr))
4426 delete (*rwlockattr);
4427 *rwlockattr = NULL;
4428 return ENOMEM;
4430 return 0;
4434 pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared)
4436 if (!pthread_rwlockattr::is_good_object (attr))
4437 return EINVAL;
4438 *pshared = (*attr)->shared;
4439 return 0;
4443 pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
4445 if (!pthread_rwlockattr::is_good_object (attr))
4446 return EINVAL;
4447 if ((pshared < 0) || (pshared > 1))
4448 return EINVAL;
4449 /* shared rwlock vars not currently supported */
4450 if (pshared != PTHREAD_PROCESS_PRIVATE)
4451 return EINVAL;
4452 (*attr)->shared = pshared;
4453 return 0;
4457 pthread_rwlockattr_destroy (pthread_rwlockattr_t *rwlockattr)
4459 if (!pthread_rwlockattr::is_good_object (rwlockattr))
4460 return EINVAL;
4461 delete (*rwlockattr);
4462 *rwlockattr = NULL;
4463 return 0;
4466 /* Barriers */
4469 pthread_barrier_init (pthread_barrier_t * bar,
4470 const pthread_barrierattr_t * attr, unsigned count)
4472 if (unlikely (bar == NULL))
4473 return EINVAL;
4475 *bar = new pthread_barrier;
4476 return (*bar)->init (attr, count);
4480 pthread_barrier_destroy (pthread_barrier_t * bar)
4482 if (unlikely (! pthread_barrier::is_good_object (bar)))
4483 return EINVAL;
4485 int ret;
4486 ret = (*bar)->destroy ();
4487 if (ret == 0)
4488 delete_and_clear (bar);
4490 return ret;
4494 pthread_barrier_wait (pthread_barrier_t * bar)
4496 if (unlikely (! pthread_barrier::is_good_object (bar)))
4497 return EINVAL;
4499 return (*bar)->wait ();
4502 /* Barrier attributes */
4505 pthread_barrierattr_init (pthread_barrierattr_t * battr)
4507 if (unlikely (battr == NULL))
4508 return EINVAL;
4510 *battr = new pthread_barrierattr;
4511 (*battr)->shared = PTHREAD_PROCESS_PRIVATE;
4513 return 0;
4517 pthread_barrierattr_setpshared (pthread_barrierattr_t * battr, int shared)
4519 if (unlikely (! pthread_barrierattr::is_good_object (battr)))
4520 return EINVAL;
4522 if (unlikely (shared != PTHREAD_PROCESS_SHARED
4523 && shared != PTHREAD_PROCESS_PRIVATE))
4524 return EINVAL;
4526 (*battr)->shared = shared;
4527 return 0;
4531 pthread_barrierattr_getpshared (const pthread_barrierattr_t * battr,
4532 int * shared)
4534 if (unlikely (! pthread_barrierattr::is_good_object (battr)
4535 || shared == NULL))
4536 return EINVAL;
4538 *shared = (*battr)->shared;
4539 return 0;
4543 pthread_barrierattr_destroy (pthread_barrierattr_t * battr)
4545 if (unlikely (! pthread_barrierattr::is_good_object (battr)))
4546 return EINVAL;
4548 delete_and_clear (battr);
4549 return 0;
4552 /* Thread clock ID */
4555 pthread_getcpuclockid (pthread_t thread, clockid_t *clk_id)
4557 if (!pthread::is_good_object (&thread))
4558 return (ESRCH);
4559 *clk_id = (clockid_t) THREADID_TO_CLOCKID (thread->getsequence_np ());
4560 return 0;