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