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