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