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