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