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