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