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