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