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