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