]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/thread.cc
* fhandler_windows.cc (fhandler_windows::read): Use
[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 || &_my_tls != _main_tls)
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), 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_setstacksize (pthread_attr_t *attr, size_t size)
2242 {
2243 if (!pthread_attr::is_good_object (attr))
2244 return EINVAL;
2245 (*attr)->stacksize = size;
2246 return 0;
2247 }
2248
2249 extern "C" int
2250 pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *size)
2251 {
2252 if (!pthread_attr::is_good_object (attr))
2253 return EINVAL;
2254 *size = (*attr)->stacksize;
2255 return 0;
2256 }
2257
2258 extern "C" int
2259 pthread_attr_destroy (pthread_attr_t *attr)
2260 {
2261 if (!pthread_attr::is_good_object (attr))
2262 return EINVAL;
2263 delete (*attr);
2264 *attr = NULL;
2265 return 0;
2266 }
2267
2268 int
2269 pthread::join (pthread_t *thread, void **return_val)
2270 {
2271 pthread_t joiner = self ();
2272
2273 joiner->testcancel ();
2274
2275 // Initialize return val with NULL
2276 if (return_val)
2277 *return_val = NULL;
2278
2279 if (!is_good_object (&joiner))
2280 return EINVAL;
2281
2282 if (!is_good_object (thread))
2283 return ESRCH;
2284
2285 if (equal (*thread,joiner))
2286 return EDEADLK;
2287
2288 (*thread)->mutex.lock ();
2289
2290 if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
2291 {
2292 (*thread)->mutex.unlock ();
2293 return EINVAL;
2294 }
2295 else
2296 {
2297 (*thread)->joiner = joiner;
2298 (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
2299 (*thread)->mutex.unlock ();
2300
2301 switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, cw_no_cancel_self, cw_sig_resume))
2302 {
2303 case WAIT_OBJECT_0:
2304 if (return_val)
2305 *return_val = (*thread)->return_ptr;
2306 delete (*thread);
2307 break;
2308 case WAIT_CANCELED:
2309 // set joined thread back to joinable since we got canceled
2310 (*thread)->joiner = NULL;
2311 (*thread)->attr.joinable = PTHREAD_CREATE_JOINABLE;
2312 joiner->cancel_self ();
2313 // never reached
2314 break;
2315 default:
2316 // should never happen
2317 return EINVAL;
2318 }
2319 }
2320
2321 return 0;
2322 }
2323
2324 int
2325 pthread::detach (pthread_t *thread)
2326 {
2327 if (!is_good_object (thread))
2328 return ESRCH;
2329
2330 (*thread)->mutex.lock ();
2331 if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
2332 {
2333 (*thread)->mutex.unlock ();
2334 return EINVAL;
2335 }
2336
2337 // check if thread is still alive
2338 if ((*thread)->valid && WaitForSingleObject ((*thread)->win32_obj_id, 0) == WAIT_TIMEOUT)
2339 {
2340 // force cleanup on exit
2341 (*thread)->joiner = *thread;
2342 (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
2343 (*thread)->mutex.unlock ();
2344 }
2345 else
2346 {
2347 // thread has already terminated.
2348 (*thread)->mutex.unlock ();
2349 delete (*thread);
2350 }
2351
2352 return 0;
2353 }
2354
2355 int
2356 pthread::suspend (pthread_t *thread)
2357 {
2358 if (!is_good_object (thread))
2359 return ESRCH;
2360
2361 if ((*thread)->suspended == false)
2362 {
2363 (*thread)->suspended = true;
2364 SuspendThread ((*thread)->win32_obj_id);
2365 }
2366
2367 return 0;
2368 }
2369
2370
2371 int
2372 pthread::resume (pthread_t *thread)
2373 {
2374 if (!is_good_object (thread))
2375 return ESRCH;
2376
2377 if ((*thread)->suspended == true)
2378 ResumeThread ((*thread)->win32_obj_id);
2379 (*thread)->suspended = false;
2380
2381 return 0;
2382 }
2383
2384 /* provided for source level compatability.
2385 See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2386 */
2387 extern "C" int
2388 pthread_getconcurrency ()
2389 {
2390 return MT_INTERFACE->concurrency;
2391 }
2392
2393 /* keep this in sync with sched.cc */
2394 extern "C" int
2395 pthread_getschedparam (pthread_t thread, int *policy,
2396 struct sched_param *param)
2397 {
2398 if (!pthread::is_good_object (&thread))
2399 return ESRCH;
2400 *policy = SCHED_FIFO;
2401 /* we don't return the current effective priority, we return the current
2402 requested priority */
2403 *param = thread->attr.schedparam;
2404 return 0;
2405 }
2406
2407 /* Thread Specific Data */
2408 extern "C" int
2409 pthread_key_create (pthread_key_t *key, void (*destructor) (void *))
2410 {
2411 *key = new pthread_key (destructor);
2412
2413 if (!pthread_key::is_good_object (key))
2414 {
2415 delete (*key);
2416 *key = NULL;
2417 return EAGAIN;
2418 }
2419 return 0;
2420 }
2421
2422 extern "C" int
2423 pthread_key_delete (pthread_key_t key)
2424 {
2425 if (!pthread_key::is_good_object (&key))
2426 return EINVAL;
2427
2428 delete (key);
2429 return 0;
2430 }
2431
2432 /* provided for source level compatability. See
2433 http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
2434 */
2435 extern "C" int
2436 pthread_setconcurrency (int new_level)
2437 {
2438 if (new_level < 0)
2439 return EINVAL;
2440 MT_INTERFACE->concurrency = new_level;
2441 return 0;
2442 }
2443
2444 /* keep syncronised with sched.cc */
2445 extern "C" int
2446 pthread_setschedparam (pthread_t thread, int policy,
2447 const struct sched_param *param)
2448 {
2449 if (!pthread::is_good_object (&thread))
2450 return ESRCH;
2451 if (policy != SCHED_FIFO)
2452 return ENOTSUP;
2453 if (!param)
2454 return EINVAL;
2455 int rv =
2456 sched_set_thread_priority (thread->win32_obj_id, param->sched_priority);
2457 if (!rv)
2458 thread->attr.schedparam.sched_priority = param->sched_priority;
2459 return rv;
2460 }
2461
2462 extern "C" int
2463 pthread_setschedprio (pthread_t thread, int priority)
2464 {
2465 if (!pthread::is_good_object (&thread))
2466 return ESRCH;
2467 int rv =
2468 sched_set_thread_priority (thread->win32_obj_id, priority);
2469 if (!rv)
2470 thread->attr.schedparam.sched_priority = priority;
2471 return rv;
2472 }
2473
2474 extern "C" int
2475 pthread_setspecific (pthread_key_t key, const void *value)
2476 {
2477 if (!pthread_key::is_good_object (&key))
2478 return EINVAL;
2479 (key)->set (value);
2480 return 0;
2481 }
2482
2483 extern "C" void *
2484 pthread_getspecific (pthread_key_t key)
2485 {
2486 if (!pthread_key::is_good_object (&key))
2487 return NULL;
2488
2489 return (key)->get ();
2490
2491 }
2492
2493 extern "C" int
2494 pthread_cond_destroy (pthread_cond_t *cond)
2495 {
2496 if (pthread_cond::is_initializer (cond))
2497 return 0;
2498 if (!pthread_cond::is_good_object (cond))
2499 return EINVAL;
2500
2501 /* reads are atomic */
2502 if ((*cond)->waiting)
2503 return EBUSY;
2504
2505 delete (*cond);
2506 *cond = NULL;
2507
2508 return 0;
2509 }
2510
2511 int
2512 pthread_cond::init (pthread_cond_t *cond, const pthread_condattr_t *attr)
2513 {
2514 pthread_cond_t new_cond;
2515
2516 if (attr && !pthread_condattr::is_good_object (attr))
2517 return EINVAL;
2518
2519 cond_initialization_lock.lock ();
2520
2521 new_cond = new pthread_cond (attr ? (*attr) : NULL);
2522 if (!is_good_object (&new_cond))
2523 {
2524 delete new_cond;
2525 cond_initialization_lock.unlock ();
2526 return EAGAIN;
2527 }
2528
2529 myfault efault;
2530 if (efault.faulted ())
2531 {
2532 delete new_cond;
2533 cond_initialization_lock.unlock ();
2534 return EINVAL;
2535 }
2536
2537 *cond = new_cond;
2538 cond_initialization_lock.unlock ();
2539
2540 return 0;
2541 }
2542
2543 extern "C" int
2544 pthread_cond_broadcast (pthread_cond_t *cond)
2545 {
2546 if (pthread_cond::is_initializer (cond))
2547 return 0;
2548 if (!pthread_cond::is_good_object (cond))
2549 return EINVAL;
2550
2551 (*cond)->unblock (true);
2552
2553 return 0;
2554 }
2555
2556 extern "C" int
2557 pthread_cond_signal (pthread_cond_t *cond)
2558 {
2559 if (pthread_cond::is_initializer (cond))
2560 return 0;
2561 if (!pthread_cond::is_good_object (cond))
2562 return EINVAL;
2563
2564 (*cond)->unblock (false);
2565
2566 return 0;
2567 }
2568
2569 static int
2570 __pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex,
2571 DWORD waitlength)
2572 {
2573 if (!pthread_mutex::is_good_object (mutex))
2574 return EINVAL;
2575 if (!(*mutex)->can_be_unlocked ())
2576 return EPERM;
2577
2578 if (pthread_cond::is_initializer (cond))
2579 pthread_cond::init (cond, NULL);
2580 if (!pthread_cond::is_good_object (cond))
2581 return EINVAL;
2582
2583 return (*cond)->wait (*mutex, waitlength);
2584 }
2585
2586 extern "C" int
2587 pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
2588 const struct timespec *abstime)
2589 {
2590 struct timeval tv;
2591 DWORD waitlength;
2592
2593 myfault efault;
2594 if (efault.faulted ())
2595 return EINVAL;
2596
2597 pthread_testcancel ();
2598
2599 /* According to SUSv3, the abstime value must be checked for validity. */
2600 if (abstime->tv_sec < 0
2601 || abstime->tv_nsec < 0
2602 || abstime->tv_nsec > 999999999)
2603 return EINVAL;
2604
2605 gettimeofday (&tv, NULL);
2606 /* Check for immediate timeout before converting to microseconds, since
2607 the resulting value can easily overflow long. This also allows to
2608 evaluate microseconds directly in DWORD. */
2609 if (tv.tv_sec > abstime->tv_sec
2610 || (tv.tv_sec == abstime->tv_sec
2611 && tv.tv_usec > abstime->tv_nsec / 1000))
2612 return ETIMEDOUT;
2613
2614 waitlength = (abstime->tv_sec - tv.tv_sec) * 1000;
2615 waitlength += (abstime->tv_nsec / 1000 - tv.tv_usec) / 1000;
2616 return __pthread_cond_dowait (cond, mutex, waitlength);
2617 }
2618
2619 extern "C" int
2620 pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
2621 {
2622 pthread_testcancel ();
2623
2624 return __pthread_cond_dowait (cond, mutex, INFINITE);
2625 }
2626
2627 extern "C" int
2628 pthread_condattr_init (pthread_condattr_t *condattr)
2629 {
2630 if (pthread_condattr::is_good_object (condattr))
2631 return EBUSY;
2632
2633 *condattr = new pthread_condattr;
2634 if (!pthread_condattr::is_good_object (condattr))
2635 {
2636 delete (*condattr);
2637 *condattr = NULL;
2638 return ENOMEM;
2639 }
2640 return 0;
2641 }
2642
2643 extern "C" int
2644 pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
2645 {
2646 if (!pthread_condattr::is_good_object (attr))
2647 return EINVAL;
2648 *pshared = (*attr)->shared;
2649 return 0;
2650 }
2651
2652 extern "C" int
2653 pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared)
2654 {
2655 if (!pthread_condattr::is_good_object (attr))
2656 return EINVAL;
2657 if ((pshared < 0) || (pshared > 1))
2658 return EINVAL;
2659 /* shared cond vars not currently supported */
2660 if (pshared != PTHREAD_PROCESS_PRIVATE)
2661 return EINVAL;
2662 (*attr)->shared = pshared;
2663 return 0;
2664 }
2665
2666 extern "C" int
2667 pthread_condattr_destroy (pthread_condattr_t *condattr)
2668 {
2669 if (!pthread_condattr::is_good_object (condattr))
2670 return EINVAL;
2671 delete (*condattr);
2672 *condattr = NULL;
2673 return 0;
2674 }
2675
2676 extern "C" int
2677 pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
2678 {
2679 if (pthread_rwlock::is_initializer (rwlock))
2680 return 0;
2681 if (!pthread_rwlock::is_good_object (rwlock))
2682 return EINVAL;
2683
2684 if ((*rwlock)->writer || (*rwlock)->readers ||
2685 (*rwlock)->waiting_readers || (*rwlock)->waiting_writers)
2686 return EBUSY;
2687
2688 delete (*rwlock);
2689 *rwlock = NULL;
2690
2691 return 0;
2692 }
2693
2694 int
2695 pthread_rwlock::init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
2696 {
2697 pthread_rwlock_t new_rwlock;
2698
2699 if (attr && !pthread_rwlockattr::is_good_object (attr))
2700 return EINVAL;
2701
2702 rwlock_initialization_lock.lock ();
2703
2704 new_rwlock = new pthread_rwlock (attr ? (*attr) : NULL);
2705 if (!is_good_object (&new_rwlock))
2706 {
2707 delete new_rwlock;
2708 rwlock_initialization_lock.unlock ();
2709 return EAGAIN;
2710 }
2711
2712 myfault efault;
2713 if (efault.faulted ())
2714 {
2715 delete new_rwlock;
2716 rwlock_initialization_lock.unlock ();
2717 return EINVAL;
2718 }
2719
2720 *rwlock = new_rwlock;
2721 rwlock_initialization_lock.unlock ();
2722
2723 return 0;
2724 }
2725
2726 extern "C" int
2727 pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
2728 {
2729 pthread_testcancel ();
2730
2731 if (pthread_rwlock::is_initializer (rwlock))
2732 pthread_rwlock::init (rwlock, NULL);
2733 if (!pthread_rwlock::is_good_object (rwlock))
2734 return EINVAL;
2735
2736 return (*rwlock)->rdlock ();
2737 }
2738
2739 extern "C" int
2740 pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
2741 {
2742 if (pthread_rwlock::is_initializer (rwlock))
2743 pthread_rwlock::init (rwlock, NULL);
2744 if (!pthread_rwlock::is_good_object (rwlock))
2745 return EINVAL;
2746
2747 return (*rwlock)->tryrdlock ();
2748 }
2749
2750 extern "C" int
2751 pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
2752 {
2753 pthread_testcancel ();
2754
2755 if (pthread_rwlock::is_initializer (rwlock))
2756 pthread_rwlock::init (rwlock, NULL);
2757 if (!pthread_rwlock::is_good_object (rwlock))
2758 return EINVAL;
2759
2760 return (*rwlock)->wrlock ();
2761 }
2762
2763 extern "C" int
2764 pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
2765 {
2766 if (pthread_rwlock::is_initializer (rwlock))
2767 pthread_rwlock::init (rwlock, NULL);
2768 if (!pthread_rwlock::is_good_object (rwlock))
2769 return EINVAL;
2770
2771 return (*rwlock)->trywrlock ();
2772 }
2773
2774 extern "C" int
2775 pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
2776 {
2777 if (pthread_rwlock::is_initializer (rwlock))
2778 return 0;
2779 if (!pthread_rwlock::is_good_object (rwlock))
2780 return EINVAL;
2781
2782 return (*rwlock)->unlock ();
2783 }
2784
2785 extern "C" int
2786 pthread_rwlockattr_init (pthread_rwlockattr_t *rwlockattr)
2787 {
2788 if (pthread_rwlockattr::is_good_object (rwlockattr))
2789 return EBUSY;
2790
2791 *rwlockattr = new pthread_rwlockattr;
2792 if (!pthread_rwlockattr::is_good_object (rwlockattr))
2793 {
2794 delete (*rwlockattr);
2795 *rwlockattr = NULL;
2796 return ENOMEM;
2797 }
2798 return 0;
2799 }
2800
2801 extern "C" int
2802 pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared)
2803 {
2804 if (!pthread_rwlockattr::is_good_object (attr))
2805 return EINVAL;
2806 *pshared = (*attr)->shared;
2807 return 0;
2808 }
2809
2810 extern "C" int
2811 pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
2812 {
2813 if (!pthread_rwlockattr::is_good_object (attr))
2814 return EINVAL;
2815 if ((pshared < 0) || (pshared > 1))
2816 return EINVAL;
2817 /* shared rwlock vars not currently supported */
2818 if (pshared != PTHREAD_PROCESS_PRIVATE)
2819 return EINVAL;
2820 (*attr)->shared = pshared;
2821 return 0;
2822 }
2823
2824 extern "C" int
2825 pthread_rwlockattr_destroy (pthread_rwlockattr_t *rwlockattr)
2826 {
2827 if (!pthread_rwlockattr::is_good_object (rwlockattr))
2828 return EINVAL;
2829 delete (*rwlockattr);
2830 *rwlockattr = NULL;
2831 return 0;
2832 }
2833
2834 /* Thread signal */
2835 extern "C" int
2836 pthread_kill (pthread_t thread, int sig)
2837 {
2838 // lock myself, for the use of thread2signal
2839 // two different kills might clash: FIXME
2840
2841 if (!pthread::is_good_object (&thread))
2842 return EINVAL;
2843
2844 siginfo_t si = {0};
2845 si.si_signo = sig;
2846 si.si_code = SI_USER;
2847 si.si_pid = myself->pid;
2848 si.si_uid = myself->uid;
2849 int rval;
2850 if (!thread->valid)
2851 rval = ESRCH;
2852 else if (sig)
2853 {
2854 thread->cygtls->set_threadkill ();
2855 rval = sig_send (NULL, si, thread->cygtls);
2856 }
2857 else
2858 switch (WaitForSingleObject (thread->win32_obj_id, 0))
2859 {
2860 case WAIT_TIMEOUT:
2861 rval = 0;
2862 break;
2863 default:
2864 rval = ESRCH;
2865 break;
2866 }
2867
2868 // unlock myself
2869 return rval;
2870 }
2871
2872 extern "C" int
2873 pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set)
2874 {
2875 return handle_sigprocmask (operation, set, old_set, _my_tls.sigmask);
2876 }
2877
2878 /* ID */
2879
2880 extern "C" int
2881 pthread_equal (pthread_t t1, pthread_t t2)
2882 {
2883 return pthread::equal (t1, t2);
2884 }
2885
2886 /* Mutexes */
2887
2888 int
2889 pthread_mutex::init (pthread_mutex_t *mutex,
2890 const pthread_mutexattr_t *attr,
2891 const pthread_mutex_t initializer)
2892 {
2893 if (attr && !pthread_mutexattr::is_good_object (attr))
2894 return EINVAL;
2895
2896 mutex_initialization_lock.lock ();
2897 if (initializer == NULL || pthread_mutex::is_initializer (mutex))
2898 {
2899 pthread_mutex_t new_mutex = new pthread_mutex (attr ? (*attr) : NULL);
2900 if (!is_good_object (&new_mutex))
2901 {
2902 delete new_mutex;
2903 mutex_initialization_lock.unlock ();
2904 return EAGAIN;
2905 }
2906
2907 if (!attr && initializer)
2908 {
2909 if (initializer == PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
2910 new_mutex->type = PTHREAD_MUTEX_RECURSIVE;
2911 else if (initializer == PTHREAD_NORMAL_MUTEX_INITIALIZER_NP)
2912 new_mutex->type = PTHREAD_MUTEX_NORMAL;
2913 else if (initializer == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)
2914 new_mutex->type = PTHREAD_MUTEX_ERRORCHECK;
2915 }
2916
2917 myfault efault;
2918 if (efault.faulted ())
2919 {
2920 delete new_mutex;
2921 mutex_initialization_lock.unlock ();
2922 return EINVAL;
2923 }
2924
2925 *mutex = new_mutex;
2926 }
2927 mutex_initialization_lock.unlock ();
2928 pthread_printf ("*mutex %p, attr %p, initializer %p", *mutex, attr, initializer);
2929
2930 return 0;
2931 }
2932
2933 extern "C" int
2934 pthread_mutex_getprioceiling (const pthread_mutex_t *mutex,
2935 int *prioceiling)
2936 {
2937 /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
2938 mutex priorities.
2939
2940 We can support mutex priorities in the future though:
2941 Store a priority with each mutex.
2942 When the mutex is optained, set the thread priority as appropriate
2943 When the mutex is released, reset the thread priority. */
2944 return ENOSYS;
2945 }
2946
2947 extern "C" int
2948 pthread_mutex_lock (pthread_mutex_t *mutex)
2949 {
2950 if (pthread_mutex::is_initializer (mutex))
2951 pthread_mutex::init (mutex, NULL, *mutex);
2952 if (!pthread_mutex::is_good_object (mutex))
2953 return EINVAL;
2954 return (*mutex)->lock ();
2955 }
2956
2957 extern "C" int
2958 pthread_mutex_trylock (pthread_mutex_t *mutex)
2959 {
2960 if (pthread_mutex::is_initializer (mutex))
2961 pthread_mutex::init (mutex, NULL, *mutex);
2962 if (!pthread_mutex::is_good_object (mutex))
2963 return EINVAL;
2964 return (*mutex)->trylock ();
2965 }
2966
2967 extern "C" int
2968 pthread_mutex_unlock (pthread_mutex_t *mutex)
2969 {
2970 if (pthread_mutex::is_initializer (mutex))
2971 return EPERM;
2972 if (!pthread_mutex::is_good_object (mutex))
2973 return EINVAL;
2974 return (*mutex)->unlock ();
2975 }
2976
2977 extern "C" int
2978 pthread_mutex_destroy (pthread_mutex_t *mutex)
2979 {
2980 int rv;
2981
2982 if (pthread_mutex::is_initializer (mutex))
2983 return 0;
2984 if (!pthread_mutex::is_good_object (mutex))
2985 return EINVAL;
2986
2987 rv = (*mutex)->destroy ();
2988 if (rv)
2989 return rv;
2990
2991 *mutex = NULL;
2992 return 0;
2993 }
2994
2995 extern "C" int
2996 pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling,
2997 int *old_ceiling)
2998 {
2999 return ENOSYS;
3000 }
3001
3002 /* Spinlocks */
3003
3004 int
3005 pthread_spinlock::init (pthread_spinlock_t *spinlock, int pshared)
3006 {
3007 pthread_spinlock_t new_spinlock = new pthread_spinlock (pshared);
3008 if (!is_good_object (&new_spinlock))
3009 {
3010 delete new_spinlock;
3011 return EAGAIN;
3012 }
3013
3014 myfault efault;
3015 if (efault.faulted ())
3016 {
3017 delete new_spinlock;
3018 return EINVAL;
3019 }
3020
3021 *spinlock = new_spinlock;
3022 pthread_printf ("*spinlock %p, pshared %d", *spinlock, pshared);
3023
3024 return 0;
3025 }
3026
3027 extern "C" int
3028 pthread_spin_lock (pthread_spinlock_t *spinlock)
3029 {
3030 if (!pthread_spinlock::is_good_object (spinlock))
3031 return EINVAL;
3032 return (*spinlock)->lock ();
3033 }
3034
3035 extern "C" int
3036 pthread_spin_trylock (pthread_spinlock_t *spinlock)
3037 {
3038 if (!pthread_spinlock::is_good_object (spinlock))
3039 return EINVAL;
3040 return (*spinlock)->trylock ();
3041 }
3042
3043 extern "C" int
3044 pthread_spin_unlock (pthread_spinlock_t *spinlock)
3045 {
3046 if (!pthread_spinlock::is_good_object (spinlock))
3047 return EINVAL;
3048 return (*spinlock)->unlock ();
3049 }
3050
3051 extern "C" int
3052 pthread_spin_destroy (pthread_spinlock_t *spinlock)
3053 {
3054 if (!pthread_spinlock::is_good_object (spinlock))
3055 return EINVAL;
3056 return (*spinlock)->destroy ();
3057 }
3058
3059 /* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
3060 for more detail */
3061 extern "C" int
3062 pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr,
3063 int *protocol)
3064 {
3065 if (!pthread_mutexattr::is_good_object (attr))
3066 return EINVAL;
3067 return ENOSYS;
3068 }
3069
3070 extern "C" int
3071 pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr,
3072 int *pshared)
3073 {
3074 if (!pthread_mutexattr::is_good_object (attr))
3075 return EINVAL;
3076 *pshared = (*attr)->pshared;
3077 return 0;
3078 }
3079
3080 extern "C" int
3081 pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type)
3082 {
3083 if (!pthread_mutexattr::is_good_object (attr))
3084 return EINVAL;
3085 *type = (*attr)->mutextype;
3086 return 0;
3087 }
3088
3089 /* FIXME: write and test process shared mutex's. */
3090 extern "C" int
3091 pthread_mutexattr_init (pthread_mutexattr_t *attr)
3092 {
3093 if (pthread_mutexattr::is_good_object (attr))
3094 return EBUSY;
3095
3096 *attr = new pthread_mutexattr ();
3097 if (!pthread_mutexattr::is_good_object (attr))
3098 {
3099 delete (*attr);
3100 *attr = NULL;
3101 return ENOMEM;
3102 }
3103 return 0;
3104 }
3105
3106 extern "C" int
3107 pthread_mutexattr_destroy (pthread_mutexattr_t *attr)
3108 {
3109 if (!pthread_mutexattr::is_good_object (attr))
3110 return EINVAL;
3111 delete (*attr);
3112 *attr = NULL;
3113 return 0;
3114 }
3115
3116
3117 /* Win32 doesn't support mutex priorities */
3118 extern "C" int
3119 pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, int protocol)
3120 {
3121 if (!pthread_mutexattr::is_good_object (attr))
3122 return EINVAL;
3123 return ENOSYS;
3124 }
3125
3126 /* Win32 doesn't support mutex priorities */
3127 extern "C" int
3128 pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr,
3129 int prioceiling)
3130 {
3131 if (!pthread_mutexattr::is_good_object (attr))
3132 return EINVAL;
3133 return ENOSYS;
3134 }
3135
3136 extern "C" int
3137 pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *attr,
3138 int *prioceiling)
3139 {
3140 if (!pthread_mutexattr::is_good_object (attr))
3141 return EINVAL;
3142 return ENOSYS;
3143 }
3144
3145 extern "C" int
3146 pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared)
3147 {
3148 if (!pthread_mutexattr::is_good_object (attr))
3149 return EINVAL;
3150 /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
3151 *functionality
3152 */
3153 if (pshared != PTHREAD_PROCESS_PRIVATE)
3154 return EINVAL;
3155 (*attr)->pshared = pshared;
3156 return 0;
3157 }
3158
3159 /* see pthread_mutex_gettype */
3160 extern "C" int
3161 pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type)
3162 {
3163 if (!pthread_mutexattr::is_good_object (attr))
3164 return EINVAL;
3165
3166 switch (type)
3167 {
3168 case PTHREAD_MUTEX_ERRORCHECK:
3169 case PTHREAD_MUTEX_RECURSIVE:
3170 case PTHREAD_MUTEX_NORMAL:
3171 (*attr)->mutextype = type;
3172 break;
3173 default:
3174 return EINVAL;
3175 }
3176
3177 return 0;
3178 }
3179
3180 /* Semaphores */
3181
3182 List<semaphore> semaphore::semaphores;
3183
3184 semaphore::semaphore (int pshared, unsigned int value)
3185 : verifyable_object (SEM_MAGIC),
3186 shared (pshared),
3187 currentvalue (value),
3188 fd (-1),
3189 hash (0ULL),
3190 sem (NULL)
3191 {
3192 SECURITY_ATTRIBUTES sa = (pshared != PTHREAD_PROCESS_PRIVATE)
3193 ? sec_all : sec_none_nih;
3194 this->win32_obj_id = ::CreateSemaphore (&sa, value, LONG_MAX, NULL);
3195 if (!this->win32_obj_id)
3196 magic = 0;
3197
3198 semaphores.insert (this);
3199 }
3200
3201 semaphore::semaphore (unsigned long long shash, LUID sluid, int sfd,
3202 sem_t *ssem, int oflag, mode_t mode, unsigned int value)
3203 : verifyable_object (SEM_MAGIC),
3204 shared (PTHREAD_PROCESS_SHARED),
3205 currentvalue (value), /* Unused for named semaphores. */
3206 fd (sfd),
3207 hash (shash),
3208 luid (sluid),
3209 sem (ssem)
3210 {
3211 char name[MAX_PATH];
3212
3213 __small_sprintf (name, "semaphore/%016X%08x%08x",
3214 hash, luid.HighPart, luid.LowPart);
3215 this->win32_obj_id = ::CreateSemaphore (&sec_all, value, LONG_MAX, name);
3216 if (!this->win32_obj_id)
3217 magic = 0;
3218 if (GetLastError () == ERROR_ALREADY_EXISTS && (oflag & O_EXCL))
3219 {
3220 __seterrno ();
3221 CloseHandle (this->win32_obj_id);
3222 magic = 0;
3223 }
3224
3225 semaphores.insert (this);
3226 }
3227
3228 semaphore::~semaphore ()
3229 {
3230 if (win32_obj_id)
3231 CloseHandle (win32_obj_id);
3232
3233 semaphores.remove (this);
3234 }
3235
3236 void
3237 semaphore::_post ()
3238 {
3239 if (ReleaseSemaphore (win32_obj_id, 1, &currentvalue))
3240 currentvalue++;
3241 }
3242
3243 int
3244 semaphore::_getvalue (int *sval)
3245 {
3246 long val;
3247
3248 switch (WaitForSingleObject (win32_obj_id, 0))
3249 {
3250 case WAIT_OBJECT_0:
3251 ReleaseSemaphore (win32_obj_id, 1, &val);
3252 *sval = val + 1;
3253 break;
3254 case WAIT_TIMEOUT:
3255 *sval = 0;
3256 break;
3257 default:
3258 set_errno (EAGAIN);
3259 return -1;
3260 }
3261 return 0;
3262 }
3263
3264 int
3265 semaphore::_trywait ()
3266 {
3267 /* FIXME: signals should be able to interrupt semaphores...
3268 We probably need WaitForMultipleObjects here. */
3269 if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)
3270 {
3271 set_errno (EAGAIN);
3272 return -1;
3273 }
3274 currentvalue--;
3275 return 0;
3276 }
3277
3278 int
3279 semaphore::_timedwait (const struct timespec *abstime)
3280 {
3281 struct timeval tv;
3282 long waitlength;
3283
3284 myfault efault;
3285 if (efault.faulted ())
3286 {
3287 /* According to SUSv3, abstime need not be checked for validity,
3288 if the semaphore can be locked immediately. */
3289 if (!_trywait ())
3290 return 0;
3291 set_errno (EINVAL);
3292 return -1;
3293 }
3294
3295 gettimeofday (&tv, NULL);
3296 waitlength = abstime->tv_sec * 1000 + abstime->tv_nsec / (1000 * 1000);
3297 waitlength -= tv.tv_sec * 1000 + tv.tv_usec / 1000;
3298 if (waitlength < 0)
3299 waitlength = 0;
3300 switch (cancelable_wait (win32_obj_id, waitlength, cw_cancel_self, cw_sig_eintr))
3301 {
3302 case WAIT_OBJECT_0:
3303 currentvalue--;
3304 break;
3305 case WAIT_SIGNALED:
3306 set_errno (EINTR);
3307 return -1;
3308 case WAIT_TIMEOUT:
3309 set_errno (ETIMEDOUT);
3310 return -1;
3311 default:
3312 pthread_printf ("cancelable_wait failed. %E");
3313 __seterrno ();
3314 return -1;
3315 }
3316 return 0;
3317 }
3318
3319 int
3320 semaphore::_wait ()
3321 {
3322 switch (cancelable_wait (win32_obj_id, INFINITE, cw_cancel_self, cw_sig_eintr))
3323 {
3324 case WAIT_OBJECT_0:
3325 currentvalue--;
3326 break;
3327 case WAIT_SIGNALED:
3328 set_errno (EINTR);
3329 return -1;
3330 default:
3331 pthread_printf ("cancelable_wait failed. %E");
3332 break;
3333 }
3334 return 0;
3335 }
3336
3337 void
3338 semaphore::_fixup_after_fork ()
3339 {
3340 if (shared == PTHREAD_PROCESS_PRIVATE)
3341 {
3342 pthread_printf ("sem %x", this);
3343 /* FIXME: duplicate code here and in the constructor. */
3344 this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, currentvalue,
3345 LONG_MAX, NULL);
3346 if (!win32_obj_id)
3347 api_fatal ("failed to create new win32 semaphore, error %d");
3348 }
3349 }
3350
3351 void
3352 semaphore::_terminate ()
3353 {
3354 int _sem_close (sem_t *, bool);
3355
3356 if (sem)
3357 _sem_close (sem, false);
3358 }
3359
3360 /* static members */
3361
3362 int
3363 semaphore::init (sem_t *sem, int pshared, unsigned int value)
3364 {
3365 /*
3366 We can't tell the difference between reinitialising an
3367 existing semaphore and initialising a semaphore who's
3368 contents happen to be a valid pointer
3369 */
3370 if (is_good_object (sem))
3371 {
3372 paranoid_printf ("potential attempt to reinitialise a semaphore");
3373 }
3374
3375 if (value > SEM_VALUE_MAX)
3376 {
3377 set_errno(EINVAL);
3378 return -1;
3379 }
3380
3381 *sem = new semaphore (pshared, value);
3382
3383 if (!is_good_object (sem))
3384 {
3385 delete (*sem);
3386 *sem = NULL;
3387 set_errno(EAGAIN);
3388 return -1;
3389 }
3390 return 0;
3391 }
3392
3393 int
3394 semaphore::destroy (sem_t *sem)
3395 {
3396 if (!is_good_object (sem))
3397 {
3398 set_errno(EINVAL);
3399 return -1;
3400 }
3401
3402 /* It's invalid to destroy a semaphore not opened with sem_init. */
3403 if ((*sem)->fd != -1)
3404 {
3405 set_errno(EINVAL);
3406 return -1;
3407 }
3408
3409 /* FIXME - new feature - test for busy against threads... */
3410
3411 delete (*sem);
3412 *sem = NULL;
3413 return 0;
3414 }
3415
3416 int
3417 semaphore::close (sem_t *sem)
3418 {
3419 if (!is_good_object (sem))
3420 {
3421 set_errno(EINVAL);
3422 return -1;
3423 }
3424
3425 /* It's invalid to close a semaphore not opened with sem_open. */
3426 if ((*sem)->fd == -1)
3427 {
3428 set_errno(EINVAL);
3429 return -1;
3430 }
3431
3432 delete (*sem);
3433 delete sem;
3434 return 0;
3435 }
3436
3437 sem_t *
3438 semaphore::open (unsigned long long hash, LUID luid, int fd, int oflag,
3439 mode_t mode, unsigned int value, bool &wasopen)
3440 {
3441 if (value > SEM_VALUE_MAX)
3442 {
3443 set_errno (EINVAL);
3444 return NULL;
3445 }
3446
3447 /* sem_open is supposed to return the same pointer, if the same named
3448 semaphore is opened multiple times in the same process, as long as
3449 the semaphore hasn't been closed or unlinked in the meantime. */
3450 semaphores.mx.lock ();
3451 for (semaphore *sema = semaphores.head; sema; sema = sema->next)
3452 if (sema->fd >= 0 && sema->hash == hash
3453 && sema->luid.HighPart == luid.HighPart
3454 && sema->luid.LowPart == sema->luid.LowPart)
3455 {
3456 wasopen = true;
3457 semaphores.mx.unlock ();
3458 return sema->sem;
3459 }
3460 semaphores.mx.unlock ();
3461
3462 wasopen = false;
3463 sem_t *sem = new sem_t;
3464 if (!sem)
3465 {
3466 set_errno (ENOMEM);
3467 return NULL;
3468 }
3469
3470 *sem = new semaphore (hash, luid, fd, sem, oflag, mode, value);
3471
3472 if (!is_good_object (sem))
3473 {
3474 delete *sem;
3475 delete sem;
3476 return NULL;
3477 }
3478 return sem;
3479 }
3480
3481 int
3482 semaphore::wait (sem_t *sem)
3483 {
3484 pthread_testcancel ();
3485
3486 if (!is_good_object (sem))
3487 {
3488 set_errno (EINVAL);
3489 return -1;
3490 }
3491
3492 return (*sem)->_wait ();
3493 }
3494
3495 int
3496 semaphore::trywait (sem_t *sem)
3497 {
3498 if (!is_good_object (sem))
3499 {
3500 set_errno (EINVAL);
3501 return -1;
3502 }
3503
3504 return (*sem)->_trywait ();
3505 }
3506
3507 int
3508 semaphore::timedwait (sem_t *sem, const struct timespec *abstime)
3509 {
3510 if (!is_good_object (sem))
3511 {
3512 set_errno (EINVAL);
3513 return -1;
3514 }
3515
3516 return (*sem)->_timedwait (abstime);
3517 }
3518
3519 int
3520 semaphore::post (sem_t *sem)
3521 {
3522 if (!is_good_object (sem))
3523 {
3524 set_errno (EINVAL);
3525 return -1;
3526 }
3527
3528 (*sem)->_post ();
3529 return 0;
3530 }
3531
3532 int
3533 semaphore::getvalue (sem_t *sem, int *sval)
3534 {
3535 myfault efault;
3536 if (efault.faulted () || !is_good_object (sem))
3537 {
3538 set_errno (EINVAL);
3539 return -1;
3540 }
3541
3542 return (*sem)->_getvalue (sval);
3543 }
3544
3545 int
3546 semaphore::getinternal (sem_t *sem, int *sfd, unsigned long long *shash,
3547 LUID *sluid, unsigned int *sval)
3548 {
3549 myfault efault;
3550 if (efault.faulted () || !is_good_object (sem))
3551 {
3552 set_errno (EINVAL);
3553 return -1;
3554 }
3555 if ((*sfd = (*sem)->fd) < 0)
3556 {
3557 set_errno (EINVAL);
3558 return -1;
3559 }
3560 *shash = (*sem)->hash;
3561 *sluid = (*sem)->luid;
3562 /* POSIX defines the value in calls to sem_init/sem_open as unsigned, but
3563 the sem_getvalue gets a pointer to int to return the value. Go figure! */
3564 return (*sem)->_getvalue ((int *)sval);
3565 }
3566
3567 /* pthread_null */
3568 pthread *
3569 pthread_null::get_null_pthread ()
3570 {
3571 /* because of weird entry points */
3572 _instance.magic = 0;
3573 return &_instance;
3574 }
3575
3576 pthread_null::pthread_null ()
3577 {
3578 attr.joinable = PTHREAD_CREATE_DETACHED;
3579 /* Mark ourselves as invalid */
3580 magic = 0;
3581 }
3582
3583 pthread_null::~pthread_null ()
3584 {
3585 }
3586
3587 bool
3588 pthread_null::create (void *(*)(void *), pthread_attr *, void *)
3589 {
3590 return true;
3591 }
3592
3593 void
3594 pthread_null::exit (void *value_ptr)
3595 {
3596 _my_tls.remove (INFINITE);
3597 ExitThread (0);
3598 }
3599
3600 int
3601 pthread_null::cancel ()
3602 {
3603 return 0;
3604 }
3605
3606 void
3607 pthread_null::testcancel ()
3608 {
3609 }
3610
3611 int
3612 pthread_null::setcancelstate (int state, int *oldstate)
3613 {
3614 return EINVAL;
3615 }
3616
3617 int
3618 pthread_null::setcanceltype (int type, int *oldtype)
3619 {
3620 return EINVAL;
3621 }
3622
3623 void
3624 pthread_null::push_cleanup_handler (__pthread_cleanup_handler *handler)
3625 {
3626 }
3627
3628 void
3629 pthread_null::pop_cleanup_handler (int const execute)
3630 {
3631 }
3632
3633 unsigned long
3634 pthread_null::getsequence_np ()
3635 {
3636 return 0;
3637 }
3638
3639 pthread_null pthread_null::_instance;
This page took 0.184363 seconds and 6 git commands to generate.