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