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