]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/thread.cc
2002-09-11 Robert Collins <rbtcollins@hotmail.com>
[newlib-cygwin.git] / winsup / cygwin / thread.cc
CommitLineData
7b80d68f 1/* thread.cc: Locking and threading module functions
1fd5e000 2
ce006ffa 3 Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
1fd5e000 4
94b03f23 5 Originally written by Marco Fuykschot <marco@ddi.nl>
7b80d68f 6 Substantialy enhanced by Robert Collins <rbtcollins@hotmail.com>
1fd5e000
CF
7
8This file is part of Cygwin.
9
10This software is a copyrighted work licensed under the terms of the
11Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12details. */
13
ff6e295e 14/* Implementation overview and caveats:
5c83f260 15
ff6e295e
CF
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.
5c83f260 20
ff6e295e
CF
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.
5c83f260 25
ff6e295e 26 R.Collins, April 2001. */
5c83f260 27
1fd5e000
CF
28#ifdef HAVE_CONFIG_H
29# include "config.h"
30#endif
31
32#ifdef _MT_SAFE
1fd5e000 33#include "winsup.h"
a5e570bc 34#include <limits.h>
4c8d72de 35#include <errno.h>
9a08b2c0 36#include "cygerrno.h"
1fd5e000 37#include <assert.h>
1fd5e000
CF
38#include <stdlib.h>
39#include <syslog.h>
e2ebe117 40#include "pinfo.h"
f0338f54
CF
41#include "perprocess.h"
42#include "security.h"
9a08b2c0 43#include <semaphore.h>
9450ad0d 44#include <stdio.h>
462f4eff 45#include <sys/timeb.h>
1fd5e000
CF
46
47extern int threadsafe;
48
f9f2c119
CF
49/*pthread_key_destructor_list class: to-be threadsafe single linked list
50 *FIXME: Put me in a dedicated file, or a least a tools area !
5c83f260
RC
51 */
52
53pthread_key_destructor *
f9f2c119 54pthread_key_destructor::InsertAfter (pthread_key_destructor *node)
5c83f260
RC
55{
56 pthread_key_destructor *temp = next;
57 next = node;
58 return temp;
59}
60
61pthread_key_destructor *
62pthread_key_destructor::UnlinkNext ()
63{
64 pthread_key_destructor *temp = next;
65 if (next)
66 next = next->Next ();
67 return temp;
68}
1fd5e000 69
5c83f260
RC
70pthread_key_destructor *
71pthread_key_destructor::Next ()
72{
73 return next;
74}
75
76void
f9f2c119 77pthread_key_destructor_list::Insert (pthread_key_destructor *node)
5c83f260
RC
78{
79 if (!node)
80 return;
81 head = node->InsertAfter (head);
82 if (!head)
f9f2c119 83 head = node; /*first node special case */
5c83f260
RC
84}
85
f9f2c119 86 /*remove a given dataitem, wherever in the list it is */
5c83f260 87pthread_key_destructor *
f9f2c119 88pthread_key_destructor_list::Remove (pthread_key *key)
5c83f260
RC
89{
90 if (!key)
91 return NULL;
92 if (!head)
93 return NULL;
94 if (key == head->key)
95 return Pop ();
96 pthread_key_destructor *temp = head;
97 while (temp && temp->Next () && !(key == temp->Next ()->key))
98 {
99 temp = temp->Next ();
100 }
101 if (temp)
102 return temp->UnlinkNext ();
103 return NULL;
104}
105
f9f2c119 106 /*get the first item and remove at the same time */
5c83f260
RC
107pthread_key_destructor *
108pthread_key_destructor_list::Pop ()
109{
110 pthread_key_destructor *temp = head;
111 head = head->Next ();
112 return temp;
113}
114
115pthread_key_destructor::
f9f2c119 116pthread_key_destructor (void (*thedestructor) (void *), pthread_key *key)
5c83f260
RC
117{
118 destructor = thedestructor;
119 next = NULL;
120 this->key = key;
121}
122
123void
124pthread_key_destructor_list::IterateNull ()
125{
126 pthread_key_destructor *temp = head;
127 while (temp)
128 {
129 temp->destructor ((temp->key)->get ());
130 temp = temp->Next ();
131 }
132}
133
134
135#define MT_INTERFACE user_data->threadinterface
91892f50 136
1fd5e000
CF
137struct _reent *
138_reent_clib ()
139{
140 int tmp = GetLastError ();
9a08b2c0
CF
141 struct __reent_t *_r =
142 (struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index);
1fd5e000
CF
143
144#ifdef _CYG_THREAD_FAILSAFE
145 if (_r == 0)
91892f50 146 system_printf ("local thread storage not inited");
1fd5e000
CF
147#endif
148
149 SetLastError (tmp);
150 return _r->_clib;
166b2571 151}
1fd5e000
CF
152
153struct _winsup_t *
154_reent_winsup ()
155{
156 int tmp = GetLastError ();
157 struct __reent_t *_r;
158 _r = (struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index);
159#ifdef _CYG_THREAD_FAILSAFE
160 if (_r == 0)
91892f50 161 system_printf ("local thread storage not inited");
1fd5e000
CF
162#endif
163 SetLastError (tmp);
164 return _r->_winsup;
166b2571 165}
1fd5e000 166
91892f50
CF
167inline LPCRITICAL_SECTION
168ResourceLocks::Lock (int _resid)
169{
170#ifdef _CYG_THREAD_FAILSAFE
171 if (!inited)
172 system_printf ("lock called before initialization");
173
9a08b2c0
CF
174 thread_printf
175 ("Get Resource lock %d ==> %p for %p , real : %d , threadid %d ", _resid,
176 &lock, user_data, myself->pid, GetCurrentThreadId ());
91892f50
CF
177#endif
178 return &lock;
166b2571 179}
91892f50 180
1fd5e000
CF
181void
182SetResourceLock (int _res_id, int _mode, const char *_function)
183{
91892f50
CF
184#ifdef _CYG_THREAD_FAILSAFE
185 thread_printf ("Set resource lock %d mode %d for %s start",
186 _res_id, _mode, _function);
1fd5e000 187#endif
1fd5e000
CF
188 EnterCriticalSection (user_data->resourcelocks->Lock (_res_id));
189
190#ifdef _CYG_THREAD_FAILSAFE
191 user_data->resourcelocks->owner = GetCurrentThreadId ();
192 user_data->resourcelocks->count++;
193#endif
194}
195
196void
197ReleaseResourceLock (int _res_id, int _mode, const char *_function)
198{
91892f50 199#ifdef _CYG_THREAD_FAILSAFE
9a08b2c0
CF
200 thread_printf ("Release resource lock %d mode %d for %s done", _res_id,
201 _mode, _function);
1fd5e000 202
1fd5e000
CF
203 AssertResourceOwner (_res_id, _mode);
204 user_data->resourcelocks->count--;
205 if (user_data->resourcelocks->count == 0)
206 user_data->resourcelocks->owner = 0;
207#endif
208
209 LeaveCriticalSection (user_data->resourcelocks->Lock (_res_id));
166b2571 210}
1fd5e000
CF
211
212#ifdef _CYG_THREAD_FAILSAFE
213void
214AssertResourceOwner (int _res_id, int _mode)
215{
216
9a08b2c0
CF
217 thread_printf
218 ("Assert Resource lock %d ==> for %p , real : %d , threadid %d count %d owner %d",
219 _res_id, user_data, myself->pid, GetCurrentThreadId (),
220 user_data->resourcelocks->count, user_data->resourcelocks->owner);
1fd5e000 221 if (user_data && (user_data->resourcelocks->owner != GetCurrentThreadId ()))
91892f50 222 system_printf ("assertion failed, not the resource owner");
1fd5e000
CF
223}
224
225#endif
226
1fd5e000
CF
227void
228ResourceLocks::Init ()
229{
1fd5e000
CF
230 InitializeCriticalSection (&lock);
231 inited = true;
232
233#ifdef _CYG_THREAD_FAILSAFE
234 owner = 0;
235 count = 0;
236#endif
237
166b2571
CF
238 thread_printf ("lock %p inited by %p , %d", &lock, user_data, myself->pid);
239}
1fd5e000
CF
240
241void
242ResourceLocks::Delete ()
243{
244 if (inited)
245 {
246 thread_printf ("Close Resource Locks %p ", &lock);
247 DeleteCriticalSection (&lock);
248 inited = false;
91892f50 249 }
166b2571 250}
1fd5e000 251
1fd5e000 252void
166b2571 253MTinterface::Init (int forked)
1fd5e000 254{
166b2571 255#if 0
1fd5e000
CF
256 for (int i = 0; i < MT_MAX_ITEMS; i++)
257 {
258 threadlist.items[i] = NULL;
259 mutexlist.items[i] = NULL;
260 semalist.items[i] = NULL;
91892f50 261 }
1fd5e000
CF
262
263 threadlist.index = 0;
264 mutexlist.index = 0;
265 semalist.index = 0;
166b2571 266#endif
1fd5e000
CF
267
268 reent_index = TlsAlloc ();
1fd5e000
CF
269 reents._clib = _impure_ptr;
270 reents._winsup = &winsup_reent;
271
272 winsup_reent._process_logmask = LOG_UPTO (LOG_DEBUG);
166b2571 273#if 0
1fd5e000
CF
274 winsup_reent._grp_pos = 0;
275 winsup_reent._process_ident = 0;
276 winsup_reent._process_logopt = 0;
277 winsup_reent._process_facility = 0;
166b2571 278#endif
1fd5e000
CF
279
280 TlsSetValue (reent_index, &reents);
281 // the static reent_data will be used in the main thread
282
9a08b2c0
CF
283
284 if (!indexallocated)
285 {
9a08b2c0
CF
286 thread_self_dwTlsIndex = TlsAlloc ();
287 if (thread_self_dwTlsIndex == TLS_OUT_OF_INDEXES)
288 system_printf
4d029f39 289 ("local storage for thread couldn't be set\nThis means that we are not thread safe!");
4e786173
RC
290 else
291 indexallocated = (-1);
9a08b2c0
CF
292 }
293
5c83f260 294 concurrency = 0;
f9f2c119 295 threadcount = 1; /*1 current thread when Init occurs.*/
5c83f260 296
4e786173 297 pthread::initMainThread(&mainthread, myself->hProcess);
9672024b 298
166b2571
CF
299 if (forked)
300 return;
1fd5e000 301
f9229ef7
RC
302 mutexs = NULL;
303 conds = NULL;
304 semaphores = NULL;
305
f9f2c119 306 /*possible the atfork lists should be inited here as well */
1fd5e000 307
166b2571 308#if 0
1fd5e000
CF
309 item->function = NULL;
310
311 item->sigs = NULL;
312 item->sigmask = NULL;
313 item->sigtodo = NULL;
166b2571 314#endif
166b2571 315}
1fd5e000 316
f9229ef7
RC
317/* This function is called from a single threaded process */
318void
319MTinterface::fixup_after_fork (void)
320{
321 pthread_mutex *mutex = mutexs;
4d029f39 322 debug_printf ("mutexs is %x",mutexs);
f9229ef7
RC
323 while (mutex)
324 {
325 mutex->fixup_after_fork ();
326 mutex = mutex->next;
327 }
328 pthread_cond *cond = conds;
4d029f39 329 debug_printf ("conds is %x",conds);
f9229ef7
RC
330 while (cond)
331 {
332 cond->fixup_after_fork ();
333 cond = cond->next;
334 }
335 semaphore *sem = semaphores;
4d029f39 336 debug_printf ("semaphores is %x",semaphores);
f9229ef7
RC
337 while (sem)
338 {
339 sem->fixup_after_fork ();
340 sem = sem->next;
341 }
342}
343
007276b3
RC
344/* pthread calls */
345
346/* static methods */
4e786173
RC
347void
348pthread::initMainThread(pthread *mainThread, HANDLE win32_obj_id)
349{
350 mainThread->win32_obj_id = win32_obj_id;
351 mainThread->setThreadIdtoCurrent ();
352 setTlsSelfPointer(mainThread);
353}
007276b3
RC
354
355pthread *
356pthread::self ()
357{
4e786173
RC
358 pthread *temp = (pthread *) TlsGetValue (MT_INTERFACE->thread_self_dwTlsIndex);
359 if (temp)
360 return temp;
361 temp = new pthread ();
362 temp->precreate (NULL);
363 if (!temp->magic) {
364 delete temp;
365 return pthreadNull::getNullpthread();
366 }
367 temp->postcreate ();
368 return temp;
369}
370
371void
372pthread::setTlsSelfPointer(pthread *thisThread)
373{
374 /*the OS doesn't check this for <= 64 Tls entries (pre win2k) */
375 TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thisThread);
007276b3
RC
376}
377
378/* member methods */
5c83f260 379pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),
d288c1c7
RC
380 cancelstate (0), canceltype (0), cancel_event(0),
381 joiner (NULL), cleanup_stack(NULL)
1fd5e000 382{
9a08b2c0 383}
1fd5e000 384
9a08b2c0
CF
385pthread::~pthread ()
386{
387 if (win32_obj_id)
388 CloseHandle (win32_obj_id);
d288c1c7
RC
389 if (cancel_event)
390 CloseHandle (cancel_event);
9a08b2c0 391}
1fd5e000 392
4e786173
RC
393void
394pthread::setThreadIdtoCurrent ()
395{
396 thread_id = GetCurrentThreadId ();
397}
1fd5e000 398
9a08b2c0 399void
4e786173 400pthread::precreate (pthread_attr *newattr)
9a08b2c0 401{
f6709c07
RC
402 pthread_mutex *verifyable_mutex_obj = &mutex;
403
f9f2c119 404 /*already running ? */
9a08b2c0
CF
405 if (win32_obj_id)
406 return;
1fd5e000 407
9a08b2c0
CF
408 if (newattr)
409 {
410 attr.joinable = newattr->joinable;
5c83f260
RC
411 attr.contentionscope = newattr->contentionscope;
412 attr.inheritsched = newattr->inheritsched;
9a08b2c0
CF
413 attr.stacksize = newattr->stacksize;
414 }
1fd5e000 415
f6709c07 416 if (verifyable_object_isvalid (&verifyable_mutex_obj, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
43c3c4e3
RC
417 {
418 thread_printf ("New thread object access mutex is not valid. this %p",
419 this);
420 magic = 0;
421 return;
422 }
423
d288c1c7
RC
424 cancel_event = ::CreateEvent (NULL,TRUE,FALSE,NULL);
425 if (!cancel_event)
426 {
427 system_printf ("couldn't create cancel event, this %p LastError %d", this, GetLastError () );
428 /*we need the event for correct behaviour */
429 magic = 0;
430 return;
431 }
4e786173
RC
432}
433
434void
435pthread::create (void *(*func) (void *), pthread_attr *newattr,
436 void *threadarg)
437{
438 precreate (newattr);
439 if (!magic)
440 return;
441 function = func;
442 arg = threadarg;
d288c1c7 443
4d029f39 444 win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize,
9a08b2c0
CF
445 (LPTHREAD_START_ROUTINE) thread_init_wrapper,
446 this, CREATE_SUSPENDED, &thread_id);
1fd5e000 447
9a08b2c0 448 if (!win32_obj_id)
196cdd45
CF
449 {
450 thread_printf ("CreateThread failed: this %p LastError %E", this);
451 magic = 0;
452 }
4e786173
RC
453 else {
454 postcreate ();
5c83f260 455 ResumeThread (win32_obj_id);
4e786173
RC
456 }
457}
458
459void
460pthread::postcreate ()
461{
462 InterlockedIncrement (&MT_INTERFACE->threadcount);
463 /*FIXME: set the priority appropriately for system contention scope */
464 if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED)
465 {
466 /*FIXME: set the scheduling settings for the new thread */
467 /*sched_thread_setparam (win32_obj_id, attr.schedparam); */
468 }
9a08b2c0 469}
1fd5e000 470
d288c1c7
RC
471void
472pthread::exit (void *value_ptr)
473{
474 class pthread *thread = this;
475
476 // run cleanup handlers
477 pop_all_cleanup_handlers ();
478
479 MT_INTERFACE->destructors.IterateNull ();
480
481 mutex.Lock ();
482 // cleanup if thread is in detached state and not joined
483 if( __pthread_equal(&joiner, &thread ) )
484 delete this;
485 else
486 {
487 return_ptr = value_ptr;
488 mutex.UnLock ();
489 }
490
4e786173
RC
491 /* Prevent DLL_THREAD_DETACH Attempting to clean us up */
492 setTlsSelfPointer(0);
493
d288c1c7
RC
494 if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0)
495 ::exit (0);
496 else
497 ExitThread (0);
498}
499
500int
501pthread::cancel (void)
502{
503 class pthread *thread = this;
504 class pthread *self = pthread::self ();
505
506 mutex.Lock ();
507
508 if (canceltype == PTHREAD_CANCEL_DEFERRED ||
509 cancelstate == PTHREAD_CANCEL_DISABLE)
510 {
511 // cancel deferred
512 mutex.UnLock ();
513 SetEvent (cancel_event);
514 return 0;
515 }
516
517 else if (__pthread_equal(&thread, &self))
518 {
519 mutex.UnLock ();
520 cancel_self ();
521 return 0; // Never reached
522 }
523
524 // cancel asynchronous
525 SuspendThread (win32_obj_id);
526 if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)
527 {
528 CONTEXT context;
529 context.ContextFlags = CONTEXT_CONTROL;
530 GetThreadContext (win32_obj_id, &context);
531 context.Eip = (DWORD) pthread::static_cancel_self;
532 SetThreadContext (win32_obj_id, &context);
533 }
534 mutex.UnLock ();
535 ResumeThread (win32_obj_id);
536
537 return 0;
538/*
539 TODO: insert pthread_testcancel into the required functions
540 the required function list is: *indicates done, X indicates not present in cygwin.
541aio_suspend ()
542*close ()
543*creat ()
544fcntl ()
545fsync ()
546getmsg ()
547getpmsg ()
548lockf ()
549mq_receive ()
550mq_send ()
551msgrcv ()
552msgsnd ()
553msync ()
554nanosleep ()
555open ()
556pause ()
557poll ()
558pread ()
559pthread_cond_timedwait ()
560pthread_cond_wait ()
561*pthread_join ()
562pthread_testcancel ()
563putmsg ()
564putpmsg ()
565pwrite ()
566read ()
567readv ()
568select ()
569sem_wait ()
570sigpause ()
571sigsuspend ()
572sigtimedwait ()
573sigwait ()
574sigwaitinfo ()
575*sleep ()
576system ()
577tcdrain ()
578*usleep ()
579wait ()
580wait3()
581waitid ()
582waitpid ()
583write ()
584writev ()
585
586the optional list is:
587catclose ()
588catgets ()
589catopen ()
590closedir ()
591closelog ()
592ctermid ()
593dbm_close ()
594dbm_delete ()
595dbm_fetch ()
596dbm_nextkey ()
597dbm_open ()
598dbm_store ()
599dlclose ()
600dlopen ()
601endgrent ()
602endpwent ()
603endutxent ()
604fclose ()
605fcntl ()
606fflush ()
607fgetc ()
608fgetpos ()
609fgets ()
610fgetwc ()
611fgetws ()
612fopen ()
613fprintf ()
614fputc ()
615fputs ()
616fputwc ()
617fputws ()
618fread ()
619freopen ()
620fscanf ()
621fseek ()
622fseeko ()
623fsetpos ()
624ftell ()
625ftello ()
626ftw ()
627fwprintf ()
628fwrite ()
629fwscanf ()
630getc ()
631getc_unlocked ()
632getchar ()
633getchar_unlocked ()
634getcwd ()
635getdate ()
636getgrent ()
637getgrgid ()
638getgrgid_r ()
639getgrnam ()
640getgrnam_r ()
641getlogin ()
642getlogin_r ()
643getpwent ()
644*getpwnam ()
645*getpwnam_r ()
646*getpwuid ()
647*getpwuid_r ()
648gets ()
649getutxent ()
650getutxid ()
651getutxline ()
652getw ()
653getwc ()
654getwchar ()
655getwd ()
656glob ()
657iconv_close ()
658iconv_open ()
659ioctl ()
660lseek ()
661mkstemp ()
662nftw ()
663opendir ()
664openlog ()
665pclose ()
666perror ()
667popen ()
668printf ()
669putc ()
670putc_unlocked ()
671putchar ()
672putchar_unlocked ()
673puts ()
674pututxline ()
675putw ()
676putwc ()
677putwchar ()
678readdir ()
679readdir_r ()
680remove ()
681rename ()
682rewind ()
683rewinddir ()
684scanf ()
685seekdir ()
686semop ()
687setgrent ()
688setpwent ()
689setutxent ()
690strerror ()
691syslog ()
692tmpfile ()
693tmpnam ()
694ttyname ()
695ttyname_r ()
696ungetc ()
697ungetwc ()
698unlink ()
699vfprintf ()
700vfwprintf ()
701vprintf ()
702vwprintf ()
703wprintf ()
704wscanf ()
705
706Note, that for fcntl (), for any value of the cmd argument.
707
708And we must not introduce cancellation points anywhere else that's part of the posix or
709opengroup specs.
710 */
711}
712
713void
714pthread::testcancel (void)
715{
716 if (cancelstate == PTHREAD_CANCEL_DISABLE)
717 return;
718
719 if( WAIT_OBJECT_0 == WaitForSingleObject (cancel_event, 0 ) )
720 cancel_self ();
721}
722
723void
724pthread::static_cancel_self (void)
725{
726 pthread::self()->cancel_self ();
727}
728
729
730int
731pthread::setcancelstate (int state, int *oldstate)
732{
733 int result = 0;
734
735 mutex.Lock ();
736
737 if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)
738 result = EINVAL;
739 else
740 {
741 if (oldstate)
742 *oldstate = cancelstate;
743 cancelstate = state;
744 }
745
746 mutex.UnLock ();
747
748 return result;
749}
750
751int
752pthread::setcanceltype (int type, int *oldtype)
753{
754 int result = 0;
755
756 mutex.Lock ();
757
758 if (type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS)
759 result = EINVAL;
760 else
761 {
762 if (oldtype)
763 *oldtype = canceltype;
764 canceltype = type;
765 }
766
767 mutex.UnLock ();
768
769 return result;
770}
771
007276b3
RC
772void
773pthread::push_cleanup_handler (__pthread_cleanup_handler *handler)
774{
775 if (this != self ())
776 // TODO: do it?
777 api_fatal ("Attempt to push a cleanup handler across threads");
f6709c07
RC
778 handler->next = cleanup_stack;
779 InterlockedExchangePointer( &cleanup_stack, handler );
007276b3
RC
780}
781
782void
783pthread::pop_cleanup_handler (int const execute)
784{
785 if (this != self ())
786 // TODO: send a signal or something to the thread ?
787 api_fatal ("Attempt to execute a cleanup handler across threads");
788
d288c1c7
RC
789 mutex.Lock ();
790
f6709c07 791 if (cleanup_stack != NULL)
007276b3 792 {
f6709c07 793 __pthread_cleanup_handler *handler = cleanup_stack;
007276b3
RC
794
795 if (execute)
f6709c07
RC
796 (*handler->function) (handler->arg);
797 cleanup_stack = handler->next;
007276b3 798 }
d288c1c7
RC
799
800 mutex.UnLock ();
007276b3
RC
801}
802
803void
804pthread::pop_all_cleanup_handlers ()
805{
f6709c07 806 while (cleanup_stack != NULL)
007276b3
RC
807 pop_cleanup_handler (1);
808}
809
4e786173
RC
810void
811pthread::cancel_self()
812{
813 exit (PTHREAD_CANCELED);
814}
815
816DWORD
817pthread::getThreadId()
818{
819 return thread_id;
820}
821
9a08b2c0 822pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC),
5c83f260
RC
823joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS),
824inheritsched (PTHREAD_INHERIT_SCHED), stacksize (0)
9a08b2c0 825{
5c83f260 826 schedparam.sched_priority = 0;
166b2571 827}
1fd5e000 828
9a08b2c0 829pthread_attr::~pthread_attr ()
1fd5e000 830{
9a08b2c0 831}
1fd5e000 832
5c83f260
RC
833pthread_condattr::pthread_condattr ():verifyable_object
834 (PTHREAD_CONDATTR_MAGIC), shared (PTHREAD_PROCESS_PRIVATE)
9a08b2c0
CF
835{
836}
1fd5e000 837
9a08b2c0
CF
838pthread_condattr::~pthread_condattr ()
839{
840}
1fd5e000 841
f9f2c119 842pthread_cond::pthread_cond (pthread_condattr *attr):verifyable_object (PTHREAD_COND_MAGIC)
9a08b2c0 843{
68ebd3f6 844 int temperr;
9a08b2c0
CF
845 this->shared = attr ? attr->shared : PTHREAD_PROCESS_PRIVATE;
846 this->mutex = NULL;
847 this->waiting = 0;
1fd5e000 848
4d029f39 849 this->win32_obj_id = ::CreateEvent (&sec_none_nih, false, /*auto signal reset - which I think is pthreads like ? */
f9f2c119
CF
850 false, /*start non signaled */
851 NULL /*no name */);
852 /*TODO: make a shared mem mutex if out attributes request shared mem cond */
4d029f39 853 cond_access = NULL;
462f4eff 854 if ((temperr = pthread_mutex_init (&this->cond_access, NULL)))
68ebd3f6 855 {
4d029f39 856 system_printf ("couldn't init mutex, this %p errno %d", this, temperr);
f9f2c119 857 /*we need the mutex for correct behaviour */
32c30349 858 magic = 0;
68ebd3f6 859 }
1fd5e000 860
9a08b2c0
CF
861 if (!this->win32_obj_id)
862 magic = 0;
f9229ef7 863 /* threadsafe addition is easy */
7b80d68f 864 next = (pthread_cond *) InterlockedExchangePointer (&MT_INTERFACE->conds, this);
9a08b2c0 865}
1fd5e000 866
9a08b2c0
CF
867pthread_cond::~pthread_cond ()
868{
869 if (win32_obj_id)
870 CloseHandle (win32_obj_id);
68ebd3f6 871 pthread_mutex_destroy (&cond_access);
f9229ef7
RC
872 /* I'm not 100% sure the next bit is threadsafe. I think it is... */
873 if (MT_INTERFACE->conds == this)
24a930fa 874 InterlockedExchangePointer (&MT_INTERFACE->conds, this->next);
f9229ef7
RC
875 else
876 {
877 pthread_cond *tempcond = MT_INTERFACE->conds;
878 while (tempcond->next && tempcond->next != this)
ff6e295e 879 tempcond = tempcond->next;
f9229ef7 880 /* but there may be a race between the loop above and this statement */
24a930fa 881 InterlockedExchangePointer (&tempcond->next, this->next);
f9229ef7 882 }
1fd5e000
CF
883}
884
9a08b2c0
CF
885void
886pthread_cond::BroadCast ()
1fd5e000 887{
86336f4f 888 /* TODO: implement the same race fix as Signal has */
68ebd3f6 889 if (pthread_mutex_lock (&cond_access))
4d029f39 890 system_printf ("Failed to lock condition variable access mutex, this %p", this);
68ebd3f6 891 int count = waiting;
86336f4f 892 if (verifyable_object_isvalid (&mutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
68ebd3f6
RC
893 {
894 if (pthread_mutex_unlock (&cond_access))
4d029f39 895 system_printf ("Failed to unlock condition variable access mutex, this %p", this);
f9f2c119 896 /*This isn't and API error - users are allowed to call this when no threads
462f4eff 897 are waiting
4d029f39 898 system_printf ("Broadcast called with invalid mutex");
56918810 899 */
68ebd3f6
RC
900 return;
901 }
902 while (count--)
9a08b2c0 903 PulseEvent (win32_obj_id);
68ebd3f6 904 if (pthread_mutex_unlock (&cond_access))
4d029f39 905 system_printf ("Failed to unlock condition variable access mutex, this %p", this);
166b2571 906}
1fd5e000 907
9a08b2c0
CF
908void
909pthread_cond::Signal ()
910{
68ebd3f6 911 if (pthread_mutex_lock (&cond_access))
4d029f39 912 system_printf ("Failed to lock condition variable access mutex, this %p", this);
86336f4f 913 if (verifyable_object_isvalid (&mutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
47132198
CF
914 {
915 if (pthread_mutex_unlock (&cond_access))
4d029f39 916 system_printf ("Failed to unlock condition variable access mutex, this %p",
462f4eff 917 this);
47132198
CF
918 return;
919 }
86336f4f
RC
920 int temp = waiting;
921 if (!temp)
922 /* nothing to signal */
923 {
924 if (pthread_mutex_unlock (&cond_access))
4d029f39 925 system_printf ("Failed to unlock condition variable access mutex, this %p", this);
86336f4f
RC
926 return;
927 }
cbce4980
RC
928 /* Prime the detection flag */
929 ExitingWait = 1;
930 /* Signal any waiting thread */
9a08b2c0 931 PulseEvent (win32_obj_id);
86336f4f
RC
932 /* No one can start waiting until we release the condition access mutex */
933 /* The released thread will decrement waiting when it gets a time slice...
934 without waiting for the access mutex
cbce4980
RC
935 * InterLockedIncrement on 98 +, NT4 + returns the incremented value.
936 * On 95, nt 3.51 < it returns a sign correct number - 0=0, + for greater than 0, -
937 * for less than 0.
938 * Because of this we cannot spin on the waiting count, but rather we need a
939 * dedicated flag for a thread exiting the Wait function.
940 * Also not that Interlocked* sync CPU caches with memory.
86336f4f
RC
941 */
942 int spins = 10;
cbce4980
RC
943 /* When ExitingWait is nonzero after a decrement, the leaving thread has
944 * done it's thing
945 */
946 while (InterlockedDecrement (&ExitingWait) == 0 && spins)
86336f4f 947 {
cbce4980 948 InterlockedIncrement (&ExitingWait);
86336f4f
RC
949 /* give up the cpu to force a context switch. */
950 Sleep (0);
951 if (spins == 5)
cbce4980 952 /* we've had 5 timeslices, and the woken thread still hasn't done it's
86336f4f
RC
953 * thing - maybe we raced it with the event? */
954 PulseEvent (win32_obj_id);
955 spins--;
956 }
cbce4980
RC
957 if (waiting + 1 != temp)
958 system_printf ("Released too many threads - %d now %d originally", waiting, temp);
68ebd3f6 959 if (pthread_mutex_unlock (&cond_access))
4d029f39 960 system_printf ("Failed to unlock condition variable access mutex, this %p", this);
9a08b2c0
CF
961}
962
963int
964pthread_cond::TimedWait (DWORD dwMilliseconds)
1fd5e000 965{
9450ad0d 966 DWORD rv;
ba946828 967 if (!wincap.has_signal_object_and_wait ())
9450ad0d
RC
968 {
969 // FIXME: race condition (potentially drop events
970 // Possible solution (single process only) - place this in a critical section.
3c76c076
CF
971 ReleaseMutex (mutex->win32_obj_id);
972 rv = WaitForSingleObject (win32_obj_id, dwMilliseconds);
9450ad0d
RC
973 }
974 else
8e4d9692
RC
975 {
976 LeaveCriticalSection (&mutex->criticalsection);
977 rv = WaitForSingleObject (win32_obj_id, dwMilliseconds);
978#if 0
979 /* we need to use native win32 mutex's here, because the cygwin ones now use
980 * critical sections, which are faster, but introduce a race _here_. Until then
981 * The NT variant of the code is redundant.
982 */
ff6e295e 983
9450ad0d 984 rv = SignalObjectAndWait (mutex->win32_obj_id, win32_obj_id, dwMilliseconds,
9a08b2c0 985 false);
8e4d9692
RC
986#endif
987 }
9a08b2c0
CF
988 switch (rv)
989 {
990 case WAIT_FAILED:
f9f2c119 991 return 0; /*POSIX doesn't allow errors after we modify the mutex state */
9a08b2c0 992 case WAIT_ABANDONED:
462f4eff 993 case WAIT_TIMEOUT:
9a08b2c0
CF
994 return ETIMEDOUT;
995 case WAIT_OBJECT_0:
f9f2c119 996 return 0; /*we have been signaled */
9a08b2c0
CF
997 default:
998 return 0;
999 }
166b2571 1000}
1fd5e000 1001
f9229ef7
RC
1002void
1003pthread_cond::fixup_after_fork ()
1004{
4d029f39 1005 debug_printf ("cond %x in fixup_after_fork", this);
f9229ef7 1006 if (shared != PTHREAD_PROCESS_PRIVATE)
4d029f39 1007 api_fatal ("doesn't understand PROCESS_SHARED condition variables");
f9229ef7 1008 /* FIXME: duplicate code here and in the constructor. */
4d029f39 1009 this->win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL);
f9229ef7 1010 if (!win32_obj_id)
4d029f39 1011 api_fatal ("failed to create new win32 mutex");
8e4d9692 1012#if DETECT_BAD_APPS
f9229ef7 1013 if (waiting)
4d029f39 1014 api_fatal ("Forked () while a condition variable has waiting threads.\nReport to cygwin@cygwin.com");
8e4d9692
RC
1015#else
1016 waiting = 0;
1017 mutex = NULL;
1018#endif
f9229ef7
RC
1019}
1020
1021
5c83f260 1022pthread_key::pthread_key (void (*destructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC)
1fd5e000 1023{
9a08b2c0
CF
1024 dwTlsIndex = TlsAlloc ();
1025 if (dwTlsIndex == TLS_OUT_OF_INDEXES)
1026 magic = 0;
5c83f260
RC
1027 else if (destructor)
1028 {
1029 MT_INTERFACE->destructors.
1030 Insert (new pthread_key_destructor (destructor, this));
1031 }
1fd5e000
CF
1032}
1033
9a08b2c0
CF
1034pthread_key::~pthread_key ()
1035{
f9f2c119 1036 if (pthread_key_destructor *dest = MT_INTERFACE->destructors.Remove (this))
5c83f260 1037 delete dest;
9a08b2c0 1038 TlsFree (dwTlsIndex);
3c76c076 1039}
9a08b2c0
CF
1040
1041int
1042pthread_key::set (const void *value)
1fd5e000 1043{
f9f2c119 1044 /*the OS function doesn't perform error checking */
9a08b2c0
CF
1045 TlsSetValue (dwTlsIndex, (void *) value);
1046 return 0;
1fd5e000
CF
1047}
1048
9a08b2c0
CF
1049void *
1050pthread_key::get ()
5ccbf4b6 1051{
9a08b2c0
CF
1052 set_errno (0);
1053 return TlsGetValue (dwTlsIndex);
5ccbf4b6 1054}
1fd5e000 1055
f9f2c119 1056/*pshared mutexs:
ac9841a0
RC
1057
1058 * REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
1059 gymnastics can be a lot easier.
1060
f9f2c119
CF
1061 *the mutex_t (size 4) is not used as a verifyable object because we cannot
1062 *guarantee the same address space for all processes.
1063 *we use the following:
1064 *high bit set (never a valid address).
1065 *second byte is reserved for the priority.
1066 *third byte is reserved
1067 *fourth byte is the mutex id. (max 255 cygwin mutexs system wide).
1068 *creating mutex's does get slower and slower, but as creation is a one time
1069 *job, it should never become an issue
9450ad0d 1070 *
f9f2c119
CF
1071 *And if you're looking at this and thinking, why not an array in cygwin for all mutexs,
1072 *- you incur a penalty on _every_ mutex call and you have toserialise them all.
1073 *... Bad karma.
9450ad0d 1074 *
f9f2c119
CF
1075 *option 2? put everything in userspace and update the ABI?
1076 *- bad karma as well - the HANDLE, while identical across process's,
1077 *Isn't duplicated, it's reopened.
9450ad0d
RC
1078 */
1079
f9f2c119 1080pthread_mutex::pthread_mutex (pthread_mutexattr *attr):verifyable_object (PTHREAD_MUTEX_MAGIC)
1fd5e000 1081{
f9f2c119 1082 /*attr checked in the C call */
4d029f39 1083 if (attr && attr->pshared == PTHREAD_PROCESS_SHARED)
9450ad0d 1084 {
ac9841a0 1085 // fail
9450ad0d
RC
1086 magic = 0;
1087 return;
1088 }
ba946828 1089 if (wincap.has_try_enter_critical_section ())
8e4d9692
RC
1090 InitializeCriticalSection (&criticalsection);
1091 else
1092 {
4d029f39 1093 this->win32_obj_id = ::CreateMutex (&sec_none_nih, false, NULL);
8e4d9692 1094 if (!win32_obj_id)
ff6e295e 1095 magic = 0;
8e4d9692 1096 }
9a08b2c0 1097 condwaits = 0;
9450ad0d 1098 pshared = PTHREAD_PROCESS_PRIVATE;
f9229ef7 1099 /* threadsafe addition is easy */
7b80d68f 1100 next = (pthread_mutex *) InterlockedExchangePointer (&MT_INTERFACE->mutexs, this);
5c83f260 1101}
9a08b2c0
CF
1102
1103pthread_mutex::~pthread_mutex ()
1104{
ba946828 1105 if (wincap.has_try_enter_critical_section ())
8e4d9692
RC
1106 DeleteCriticalSection (&criticalsection);
1107 else
1108 {
1109 if (win32_obj_id)
ff6e295e 1110 CloseHandle (win32_obj_id);
8e4d9692
RC
1111 win32_obj_id = NULL;
1112 }
f9229ef7
RC
1113 /* I'm not 100% sure the next bit is threadsafe. I think it is... */
1114 if (MT_INTERFACE->mutexs == this)
8e4d9692
RC
1115 /* TODO: printf an error if the return value != this */
1116 InterlockedExchangePointer (&MT_INTERFACE->mutexs, next);
f9229ef7
RC
1117 else
1118 {
1119 pthread_mutex *tempmutex = MT_INTERFACE->mutexs;
1120 while (tempmutex->next && tempmutex->next != this)
1121 tempmutex = tempmutex->next;
1122 /* but there may be a race between the loop above and this statement */
8e4d9692 1123 /* TODO: printf an error if the return value != this */
24a930fa 1124 InterlockedExchangePointer (&tempmutex->next, this->next);
f9229ef7 1125 }
166b2571 1126}
1fd5e000
CF
1127
1128int
9a08b2c0 1129pthread_mutex::Lock ()
1fd5e000 1130{
ba946828 1131 if (wincap.has_try_enter_critical_section ())
8e4d9692
RC
1132 {
1133 EnterCriticalSection (&criticalsection);
1134 return 0;
1135 }
1136 /* FIXME: Return 0 on success */
1fd5e000 1137 return WaitForSingleObject (win32_obj_id, INFINITE);
166b2571 1138}
1fd5e000 1139
8e4d9692 1140/* returns non-zero on failure */
1fd5e000 1141int
9a08b2c0 1142pthread_mutex::TryLock ()
1fd5e000 1143{
ba946828 1144 if (wincap.has_try_enter_critical_section ())
8e4d9692
RC
1145 return (!TryEnterCriticalSection (&criticalsection));
1146 return (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT);
166b2571 1147}
1fd5e000
CF
1148
1149int
9a08b2c0 1150pthread_mutex::UnLock ()
1fd5e000 1151{
ba946828 1152 if (wincap.has_try_enter_critical_section ())
8e4d9692
RC
1153 {
1154 LeaveCriticalSection (&criticalsection);
1155 return 0;
1156 }
1157 return (!ReleaseMutex (win32_obj_id));
1fd5e000
CF
1158}
1159
f9229ef7
RC
1160void
1161pthread_mutex::fixup_after_fork ()
1162{
4d029f39 1163 debug_printf ("mutex %x in fixup_after_fork", this);
f9229ef7 1164 if (pshared != PTHREAD_PROCESS_PRIVATE)
4d029f39 1165 api_fatal ("pthread_mutex::fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's");
f9229ef7 1166 /* FIXME: duplicate code here and in the constructor. */
ba946828 1167 if (wincap.has_try_enter_critical_section ())
4d029f39 1168 InitializeCriticalSection (&criticalsection);
8e4d9692
RC
1169 else
1170 {
4d029f39 1171 win32_obj_id = ::CreateMutex (&sec_none_nih, false, NULL);
8e4d9692 1172 if (!win32_obj_id)
4d029f39 1173 api_fatal ("pthread_mutex::fixup_after_fork () failed to create new win32 mutex");
8e4d9692
RC
1174 }
1175#if DETECT_BAD_APPS
f9229ef7 1176 if (condwaits)
4d029f39 1177 api_fatal ("Forked () while a mutex has condition variables waiting on it.\nReport to cygwin@cygwin.com");
8e4d9692
RC
1178#else
1179 condwaits = 0;
1180#endif
f9229ef7
RC
1181}
1182
5c83f260
RC
1183pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC),
1184pshared (PTHREAD_PROCESS_PRIVATE), mutextype (PTHREAD_MUTEX_DEFAULT)
1185{
1186}
1187
1188pthread_mutexattr::~pthread_mutexattr ()
1189{
3c76c076 1190}
5c83f260 1191
9a08b2c0 1192semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MAGIC)
1fd5e000 1193{
4d029f39 1194 this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, value, LONG_MAX,
9a08b2c0
CF
1195 NULL);
1196 if (!this->win32_obj_id)
1197 magic = 0;
1198 this->shared = pshared;
f9229ef7
RC
1199 currentvalue = value;
1200 /* threadsafe addition is easy */
7b80d68f 1201 next = (semaphore *) InterlockedExchangePointer (&MT_INTERFACE->semaphores, this);
166b2571 1202}
1fd5e000 1203
9a08b2c0 1204semaphore::~semaphore ()
1fd5e000 1205{
9a08b2c0
CF
1206 if (win32_obj_id)
1207 CloseHandle (win32_obj_id);
f9229ef7
RC
1208 /* I'm not 100% sure the next bit is threadsafe. I think it is... */
1209 if (MT_INTERFACE->semaphores == this)
24a930fa 1210 InterlockedExchangePointer (&MT_INTERFACE->semaphores, this->next);
f9229ef7
RC
1211 else
1212 {
1213 semaphore *tempsem = MT_INTERFACE->semaphores;
1214 while (tempsem->next && tempsem->next != this)
ff6e295e 1215 tempsem = tempsem->next;
f9229ef7 1216 /* but there may be a race between the loop above and this statement */
24a930fa 1217 InterlockedExchangePointer (&tempsem->next, this->next);
f9229ef7 1218 }
166b2571 1219}
1fd5e000 1220
9a08b2c0
CF
1221void
1222semaphore::Post ()
1fd5e000 1223{
f9229ef7
RC
1224 /* we can't use the currentvalue, because the wait functions don't let us access it */
1225 ReleaseSemaphore (win32_obj_id, 1, NULL);
1226 currentvalue++;
166b2571 1227}
1fd5e000
CF
1228
1229int
9a08b2c0 1230semaphore::TryWait ()
1fd5e000 1231{
f9f2c119
CF
1232 /*FIXME: signals should be able to interrupt semaphores...
1233 *We probably need WaitForMultipleObjects here.
9a08b2c0
CF
1234 */
1235 if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)
062401c9
RC
1236 {
1237 set_errno (EAGAIN);
1238 return -1;
1239 }
f9229ef7
RC
1240 currentvalue--;
1241 return 0;
166b2571 1242}
1fd5e000 1243
9a08b2c0
CF
1244void
1245semaphore::Wait ()
5ccbf4b6 1246{
9a08b2c0 1247 WaitForSingleObject (win32_obj_id, INFINITE);
f9229ef7
RC
1248 currentvalue--;
1249}
1250
1251void
1252semaphore::fixup_after_fork ()
1253{
4d029f39 1254 debug_printf ("sem %x in fixup_after_fork", this);
f9229ef7 1255 if (shared != PTHREAD_PROCESS_PRIVATE)
4d029f39 1256 api_fatal ("doesn't understand PROCESS_SHARED semaphores variables");
f9229ef7 1257 /* FIXME: duplicate code here and in the constructor. */
4d029f39 1258 this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, currentvalue, LONG_MAX, NULL);
f9229ef7 1259 if (!win32_obj_id)
4d029f39 1260 api_fatal ("failed to create new win32 semaphore");
5ccbf4b6
CF
1261}
1262
9a08b2c0
CF
1263verifyable_object::verifyable_object (long verifyer):
1264magic (verifyer)
5ccbf4b6 1265{
5ccbf4b6
CF
1266}
1267
9a08b2c0 1268verifyable_object::~verifyable_object ()
5ccbf4b6 1269{
9a08b2c0 1270 magic = 0;
5ccbf4b6
CF
1271}
1272
f9f2c119 1273/*Generic memory acccess routine - where should it live ? */
9a08b2c0 1274int __stdcall
86336f4f 1275check_valid_pointer (void const *pointer)
9a08b2c0 1276{
86336f4f 1277 if (!pointer || IsBadWritePtr ((void *) pointer, sizeof (verifyable_object)))
9a08b2c0
CF
1278 return EFAULT;
1279 return 0;
5ccbf4b6
CF
1280}
1281
86336f4f
RC
1282verifyable_object_state
1283verifyable_object_isvalid (void const * objectptr, long magic, void *static_ptr)
5ccbf4b6 1284{
c918cf94 1285 verifyable_object **object = (verifyable_object **)objectptr;
9a08b2c0 1286 if (check_valid_pointer (object))
86336f4f
RC
1287 return INVALID_OBJECT;
1288 if (!*object)
1289 return INVALID_OBJECT;
1290 if (static_ptr && *object == static_ptr)
1291 return VALID_STATIC_OBJECT;
c918cf94 1292 if (check_valid_pointer (*object))
86336f4f 1293 return INVALID_OBJECT;
c918cf94 1294 if ((*object)->magic != magic)
86336f4f
RC
1295 return INVALID_OBJECT;
1296 return VALID_OBJECT;
1297}
1298
1299verifyable_object_state
1300verifyable_object_isvalid (void const * objectptr, long magic)
1301{
1302 return verifyable_object_isvalid (objectptr, magic, NULL);
5ccbf4b6 1303}
1fd5e000 1304
f9f2c119 1305/* Pthreads */
1fd5e000 1306void *
43c3c4e3 1307pthread::thread_init_wrapper (void *_arg)
1fd5e000 1308{
94b03f23 1309 // Setup the local/global storage of this thread
1fd5e000 1310
9a08b2c0 1311 pthread *thread = (pthread *) _arg;
1fd5e000
CF
1312 struct __reent_t local_reent;
1313 struct _winsup_t local_winsup;
cba63823 1314 struct _reent local_clib = _REENT_INIT(local_clib);
1fd5e000
CF
1315
1316 struct sigaction _sigs[NSIG];
f9f2c119 1317 sigset_t _sig_mask; /*one set for everything to ignore. */
1fd5e000
CF
1318 LONG _sigtodo[NSIG + __SIGOFFSET];
1319
94b03f23 1320 // setup signal structures
1fd5e000
CF
1321 thread->sigs = _sigs;
1322 thread->sigmask = &_sig_mask;
1323 thread->sigtodo = _sigtodo;
1324
1fd5e000
CF
1325 memset (&local_winsup, 0, sizeof (struct _winsup_t));
1326
1fd5e000
CF
1327 local_reent._clib = &local_clib;
1328 local_reent._winsup = &local_winsup;
1329
1330 local_winsup._process_logmask = LOG_UPTO (LOG_DEBUG);
1331
f9f2c119 1332 /*This is not checked by the OS !! */
1fd5e000
CF
1333 if (!TlsSetValue (MT_INTERFACE->reent_index, &local_reent))
1334 system_printf ("local storage for thread couldn't be set");
1335
4e786173 1336 setTlsSelfPointer(thread);
9a08b2c0 1337
d288c1c7 1338 thread->mutex.Lock ();
e9259cb2 1339 // if thread is detached force cleanup on exit
007276b3
RC
1340 if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL)
1341 thread->joiner = pthread::self ();
d288c1c7 1342 thread->mutex.UnLock ();
e9259cb2 1343
1fd5e000
CF
1344#ifdef _CYG_THREAD_FAILSAFE
1345 if (_REENT == _impure_ptr)
1346 system_printf ("local storage for thread isn't setup correctly");
1347#endif
1348
9a08b2c0
CF
1349 thread_printf ("started thread %p %p %p %p %p %p", _arg, &local_clib,
1350 _impure_ptr, thread, thread->function, thread->arg);
1fd5e000 1351
94b03f23 1352 // call the user's thread
1fd5e000
CF
1353 void *ret = thread->function (thread->arg);
1354
d288c1c7 1355 thread->exit (ret);
1fd5e000 1356
9a08b2c0
CF
1357#if 0
1358// ??? This code only runs if the thread exits by returning.
3c76c076 1359// it's all now in __pthread_exit ();
9a08b2c0 1360#endif
f9f2c119 1361 /*never reached */
9a08b2c0 1362 return 0;
1fd5e000
CF
1363}
1364
4e786173
RC
1365bool
1366pthread::isGoodObject (pthread_t *thread)
1367{
1368 if (verifyable_object_isvalid (thread, PTHREAD_MAGIC) != VALID_OBJECT)
1369 return false;
1370 return true;
1371}
1372
1373unsigned long
1374pthread::getsequence_np ()
1375{
1376 return getThreadId ();
1377}
1378
1fd5e000 1379int
f9f2c119 1380__pthread_create (pthread_t *thread, const pthread_attr_t *attr,
9a08b2c0 1381 void *(*start_routine) (void *), void *arg)
1fd5e000 1382{
4d029f39 1383 DECLARE_TLS_STORAGE;
86336f4f 1384 if (attr && verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
9a08b2c0 1385 return EINVAL;
1fd5e000 1386
9a08b2c0
CF
1387 *thread = new pthread ();
1388 (*thread)->create (start_routine, attr ? *attr : NULL, arg);
4e786173 1389 if (!pthread::isGoodObject (thread))
1fd5e000 1390 {
9a08b2c0
CF
1391 delete (*thread);
1392 *thread = NULL;
1393 return EAGAIN;
91892f50 1394 }
1fd5e000 1395
1fd5e000 1396 return 0;
166b2571 1397}
1fd5e000 1398
5c83f260 1399int
f9f2c119 1400__pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
5c83f260 1401{
f6709c07
RC
1402 // already done ?
1403 if (once_control->state)
1404 return 0;
1405
5c83f260 1406 pthread_mutex_lock (&once_control->mutex);
f9f2c119
CF
1407 /*Here we must set a cancellation handler to unlock the mutex if needed */
1408 /*but a cancellation handler is not the right thing. We need this in the thread
1409 *cleanup routine. Assumption: a thread can only be in one pthread_once routine
1410 *at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
1411 *on pthread_exit ();
5c83f260 1412 */
f6709c07 1413 if (!once_control->state)
5c83f260
RC
1414 {
1415 init_routine ();
1416 once_control->state = 1;
1417 }
f9f2c119 1418 /*Here we must remove our cancellation handler */
5c83f260
RC
1419 pthread_mutex_unlock (&once_control->mutex);
1420 return 0;
1421}
1422
5c83f260
RC
1423int
1424__pthread_cancel (pthread_t thread)
1425{
4e786173 1426 if (!pthread::isGoodObject (&thread))
5c83f260 1427 return ESRCH;
5c83f260 1428
d288c1c7 1429 return thread->cancel ();
5c83f260
RC
1430}
1431
39b6859a 1432/*
f9f2c119
CF
1433 *Races in pthread_atfork:
1434 *We are race safe in that any additions to the lists are made via
1435 *InterlockedExchangePointer.
1436 *However, if the user application doesn't perform syncronisation of some sort
1437 *It's not guaranteed that a near simultaneous call to pthread_atfork and fork
1438 *will result in the new atfork handlers being calls.
1439 *More rigorous internal syncronisation isn't needed as the user program isn't
1440 *guaranteeing their own state.
39b6859a 1441 *
f9f2c119
CF
1442 *as far as multiple calls to pthread_atfork, the worst case is simultaneous calls
1443 *will result in an indeterminate order for parent and child calls (what gets inserted
1444 *first isn't guaranteed.)
39b6859a 1445 *
f9f2c119
CF
1446 *There is one potential race... Does the result of InterlockedExchangePointer
1447 *get committed to the return location _before_ any context switches can occur?
1448 *If yes, we're safe, if no, we're not.
39b6859a
CF
1449 */
1450void
3c76c076 1451__pthread_atforkprepare (void)
39b6859a 1452{
3c76c076 1453 callback *cb = MT_INTERFACE->pthread_prepare;
39b6859a
CF
1454 while (cb)
1455 {
3c76c076
CF
1456 cb->cb ();
1457 cb = cb->next;
39b6859a
CF
1458 }
1459}
1460
3c76c076
CF
1461void
1462__pthread_atforkparent (void)
39b6859a 1463{
3c76c076 1464 callback *cb = MT_INTERFACE->pthread_parent;
39b6859a
CF
1465 while (cb)
1466 {
3c76c076
CF
1467 cb->cb ();
1468 cb = cb->next;
39b6859a
CF
1469 }
1470}
1471
1472void
3c76c076 1473__pthread_atforkchild (void)
39b6859a 1474{
3c76c076 1475 callback *cb = MT_INTERFACE->pthread_child;
39b6859a
CF
1476 while (cb)
1477 {
3c76c076
CF
1478 cb->cb ();
1479 cb = cb->next;
39b6859a
CF
1480 }
1481}
1482
f9f2c119
CF
1483/*Register a set of functions to run before and after fork.
1484 *prepare calls are called in LI-FC order.
1485 *parent and child calls are called in FI-FC order.
39b6859a
CF
1486 */
1487int
3c76c076 1488__pthread_atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void))
39b6859a 1489{
f9f2c119 1490 callback *prepcb = NULL, *parentcb = NULL, *childcb = NULL;
39b6859a
CF
1491 if (prepare)
1492 {
1493 prepcb = new callback;
1494 if (!prepcb)
1495 return ENOMEM;
1496 }
1497 if (parent)
1498 {
1499 parentcb = new callback;
1500 if (!parentcb)
1501 {
1502 if (prepcb)
1503 delete prepcb;
1504 return ENOMEM;
1505 }
1506 }
1507 if (child)
1508 {
1509 childcb = new callback;
1510 if (!childcb)
1511 {
1512 if (prepcb)
1513 delete prepcb;
1514 if (parentcb)
1515 delete parentcb;
1516 return ENOMEM;
1517 }
1518 }
1519
1520 if (prepcb)
1521 {
1522 prepcb->cb = prepare;
7b80d68f 1523 prepcb->next = (callback *) InterlockedExchangePointer ((LONG *) &MT_INTERFACE->pthread_prepare, (long int) prepcb);
39b6859a
CF
1524 }
1525 if (parentcb)
1526 {
1527 parentcb->cb = parent;
f9f2c119 1528 callback **t = &MT_INTERFACE->pthread_parent;
39b6859a
CF
1529 while (*t)
1530 t = &(*t)->next;
f9f2c119 1531 /*t = pointer to last next in the list */
7b80d68f 1532 parentcb->next = (callback *) InterlockedExchangePointer ((LONG *) t, (long int) parentcb);
39b6859a
CF
1533 }
1534 if (childcb)
1535 {
1536 childcb->cb = child;
f9f2c119 1537 callback **t = &MT_INTERFACE->pthread_child;
39b6859a
CF
1538 while (*t)
1539 t = &(*t)->next;
f9f2c119 1540 /*t = pointer to last next in the list */
7b80d68f 1541 childcb->next = (callback *) InterlockedExchangePointer ((LONG *) t, (long int) childcb);
39b6859a
CF
1542 }
1543 return 0;
1544}
1545
1fd5e000 1546int
f9f2c119 1547__pthread_attr_init (pthread_attr_t *attr)
1fd5e000 1548{
86336f4f
RC
1549 if (check_valid_pointer (attr))
1550 return EINVAL;
9a08b2c0 1551 *attr = new pthread_attr;
86336f4f 1552 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
1553 {
1554 delete (*attr);
1555 *attr = NULL;
1556 return EAGAIN;
1557 }
1558 return 0;
1559}
1560
5c83f260 1561int
f9f2c119 1562__pthread_attr_getinheritsched (const pthread_attr_t *attr,
5c83f260
RC
1563 int *inheritsched)
1564{
86336f4f 1565 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
1566 return EINVAL;
1567 *inheritsched = (*attr)->inheritsched;
1568 return 0;
1569}
1570
1571int
f9f2c119 1572__pthread_attr_getschedparam (const pthread_attr_t *attr,
5c83f260
RC
1573 struct sched_param *param)
1574{
86336f4f 1575 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
1576 return EINVAL;
1577 *param = (*attr)->schedparam;
1578 return 0;
1579}
1580
f9f2c119
CF
1581/*From a pure code point of view, this should call a helper in sched.cc,
1582 *to allow for someone adding scheduler policy changes to win32 in the future.
1583 *However that's extremely unlikely, so short and sweet will do us
5c83f260
RC
1584 */
1585int
f9f2c119 1586__pthread_attr_getschedpolicy (const pthread_attr_t *attr, int *policy)
5c83f260 1587{
86336f4f 1588 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
1589 return EINVAL;
1590 *policy = SCHED_FIFO;
1591 return 0;
1592}
1593
1594
1595int
f9f2c119 1596__pthread_attr_getscope (const pthread_attr_t *attr, int *contentionscope)
5c83f260 1597{
86336f4f 1598 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
1599 return EINVAL;
1600 *contentionscope = (*attr)->contentionscope;
1601 return 0;
1602}
1603
9a08b2c0 1604int
f9f2c119 1605__pthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate)
9a08b2c0 1606{
86336f4f 1607 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
1608 return EINVAL;
1609 if (detachstate < 0 || detachstate > 1)
1610 return EINVAL;
1611 (*attr)->joinable = detachstate;
1612 return 0;
1613}
1614
1615int
f9f2c119 1616__pthread_attr_getdetachstate (const pthread_attr_t *attr, int *detachstate)
9a08b2c0 1617{
86336f4f 1618 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
1619 return EINVAL;
1620 *detachstate = (*attr)->joinable;
1fd5e000 1621 return 0;
166b2571 1622}
1fd5e000 1623
5c83f260 1624int
f9f2c119 1625__pthread_attr_setinheritsched (pthread_attr_t *attr, int inheritsched)
5c83f260 1626{
86336f4f 1627 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
1628 return EINVAL;
1629 if (inheritsched != PTHREAD_INHERIT_SCHED
1630 && inheritsched != PTHREAD_EXPLICIT_SCHED)
1631 return ENOTSUP;
1632 (*attr)->inheritsched = inheritsched;
1633 return 0;
1634}
1635
1636int
f9f2c119 1637__pthread_attr_setschedparam (pthread_attr_t *attr,
5c83f260
RC
1638 const struct sched_param *param)
1639{
86336f4f 1640 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
1641 return EINVAL;
1642 if (!valid_sched_parameters (param))
1643 return ENOTSUP;
1644 (*attr)->schedparam = *param;
1645 return 0;
1646}
1647
f9f2c119 1648/*See __pthread_attr_getschedpolicy for some notes */
5c83f260 1649int
f9f2c119 1650__pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy)
5c83f260 1651{
86336f4f 1652 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
1653 return EINVAL;
1654 if (policy != SCHED_FIFO)
1655 return ENOTSUP;
1656 return 0;
1657}
1658
1659int
f9f2c119 1660__pthread_attr_setscope (pthread_attr_t *attr, int contentionscope)
5c83f260 1661{
86336f4f 1662 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
1663 return EINVAL;
1664 if (contentionscope != PTHREAD_SCOPE_SYSTEM
1665 && contentionscope != PTHREAD_SCOPE_PROCESS)
1666 return EINVAL;
f9f2c119
CF
1667 /*In future, we may be able to support system scope by escalating the thread
1668 *priority to exceed the priority class. For now we only support PROCESS scope. */
5c83f260
RC
1669 if (contentionscope != PTHREAD_SCOPE_PROCESS)
1670 return ENOTSUP;
1671 (*attr)->contentionscope = contentionscope;
1672 return 0;
1673}
1674
1fd5e000 1675int
f9f2c119 1676__pthread_attr_setstacksize (pthread_attr_t *attr, size_t size)
1fd5e000 1677{
86336f4f 1678 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
1679 return EINVAL;
1680 (*attr)->stacksize = size;
1fd5e000 1681 return 0;
166b2571 1682}
1fd5e000
CF
1683
1684int
f9f2c119 1685__pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *size)
1fd5e000 1686{
86336f4f 1687 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
1688 return EINVAL;
1689 *size = (*attr)->stacksize;
1fd5e000 1690 return 0;
166b2571 1691}
1fd5e000
CF
1692
1693int
f9f2c119 1694__pthread_attr_destroy (pthread_attr_t *attr)
1fd5e000 1695{
86336f4f 1696 if (verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
1697 return EINVAL;
1698 delete (*attr);
1699 *attr = NULL;
1fd5e000 1700 return 0;
166b2571 1701}
1fd5e000 1702
1fd5e000 1703int
f9f2c119 1704__pthread_join (pthread_t *thread, void **return_val)
1fd5e000 1705{
007276b3 1706 pthread_t joiner = pthread::self ();
e9259cb2 1707
f6709c07
RC
1708 // Initialize return val with NULL
1709 if (return_val)
1710 *return_val = NULL;
1711
f9f2c119 1712 /*FIXME: wait on the thread cancellation event as well - we are a cancellation point*/
4e786173 1713 if (!pthread::isGoodObject (thread))
9a08b2c0 1714 return ESRCH;
1fd5e000 1715
f6709c07
RC
1716 if (__pthread_equal(thread,&joiner))
1717 return EDEADLK;
e9259cb2 1718
43c3c4e3
RC
1719 (*thread)->mutex.Lock ();
1720
1721 if((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
e9259cb2 1722 {
43c3c4e3
RC
1723 (*thread)->mutex.UnLock ();
1724 return EINVAL;
e9259cb2 1725 }
1fd5e000 1726 else
9a08b2c0 1727 {
e9259cb2 1728 (*thread)->joiner = joiner;
007276b3 1729 (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
43c3c4e3 1730 (*thread)->mutex.UnLock ();
9a08b2c0
CF
1731 WaitForSingleObject ((*thread)->win32_obj_id, INFINITE);
1732 if (return_val)
7c02f861 1733 *return_val = (*thread)->return_ptr;
e9259cb2
RC
1734 // cleanup
1735 delete (*thread);
f9f2c119 1736 } /*End if */
9450ad0d 1737
3c76c076 1738 pthread_testcancel ();
1fd5e000
CF
1739
1740 return 0;
166b2571 1741}
1fd5e000
CF
1742
1743int
f9f2c119 1744__pthread_detach (pthread_t *thread)
1fd5e000 1745{
4e786173 1746 if (!pthread::isGoodObject (thread))
9a08b2c0 1747 return ESRCH;
1fd5e000 1748
43c3c4e3 1749 (*thread)->mutex.Lock ();
5c83f260 1750 if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
9a08b2c0 1751 {
43c3c4e3 1752 (*thread)->mutex.UnLock ();
9a08b2c0
CF
1753 return EINVAL;
1754 }
1fd5e000 1755
43c3c4e3
RC
1756 // check if thread is still alive
1757 if (WAIT_TIMEOUT == WaitForSingleObject ((*thread)->win32_obj_id, 0) )
1758 {
1759 // force cleanup on exit
1760 (*thread)->joiner = *thread;
1761 (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
1762 (*thread)->mutex.UnLock ();
1763 }
1764 else
f6709c07
RC
1765 {
1766 // thread has already terminated.
1767 (*thread)->mutex.UnLock ();
43c3c4e3 1768 delete (*thread);
f6709c07 1769 }
e9259cb2 1770
1fd5e000
CF
1771 return 0;
1772}
1773
1774int
f9f2c119 1775__pthread_suspend (pthread_t *thread)
1fd5e000 1776{
4e786173 1777 if (!pthread::isGoodObject (thread))
9a08b2c0 1778 return ESRCH;
1fd5e000 1779
9a08b2c0
CF
1780 if ((*thread)->suspended == false)
1781 {
1782 (*thread)->suspended = true;
1783 SuspendThread ((*thread)->win32_obj_id);
1784 }
1fd5e000
CF
1785
1786 return 0;
1787}
1788
1789
1790int
f9f2c119 1791__pthread_continue (pthread_t *thread)
1fd5e000 1792{
4e786173 1793 if (!pthread::isGoodObject (thread))
9a08b2c0 1794 return ESRCH;
1fd5e000 1795
9a08b2c0
CF
1796 if ((*thread)->suspended == true)
1797 ResumeThread ((*thread)->win32_obj_id);
1798 (*thread)->suspended = false;
1fd5e000
CF
1799
1800 return 0;
1801}
1802
f9f2c119
CF
1803/*provided for source level compatability.
1804 *See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
5c83f260
RC
1805 */
1806int
1807__pthread_getconcurrency (void)
1808{
1809 return MT_INTERFACE->concurrency;
1810}
1811
f9f2c119 1812/*keep this in sync with sched.cc */
5c83f260
RC
1813int
1814__pthread_getschedparam (pthread_t thread, int *policy,
1815 struct sched_param *param)
1816{
4e786173 1817 if (!pthread::isGoodObject (&thread))
5c83f260
RC
1818 return ESRCH;
1819 *policy = SCHED_FIFO;
f9f2c119
CF
1820 /*we don't return the current effective priority, we return the current requested
1821 *priority */
5c83f260
RC
1822 *param = thread->attr.schedparam;
1823 return 0;
1824}
1825
f9f2c119 1826/*Thread SpecificData */
1fd5e000 1827int
f9f2c119 1828__pthread_key_create (pthread_key_t *key, void (*destructor) (void *))
1fd5e000 1829{
f9f2c119
CF
1830 /*The opengroup docs don't define if we should check this or not,
1831 *but creation is relatively rare..
9a08b2c0 1832 */
86336f4f 1833 if (verifyable_object_isvalid (key, PTHREAD_KEY_MAGIC) == VALID_OBJECT)
9a08b2c0
CF
1834 return EBUSY;
1835
5c83f260 1836 *key = new pthread_key (destructor);
9a08b2c0 1837
86336f4f 1838 if (verifyable_object_isvalid (key, PTHREAD_KEY_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
1839 {
1840 delete (*key);
1841 *key = NULL;
1842 return EAGAIN;
1843 }
1844 return 0;
166b2571 1845}
1fd5e000
CF
1846
1847int
5c83f260 1848__pthread_key_delete (pthread_key_t key)
1fd5e000 1849{
86336f4f 1850 if (verifyable_object_isvalid (&key, PTHREAD_KEY_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
1851 return EINVAL;
1852
5c83f260
RC
1853 delete (key);
1854 return 0;
1855}
1856
f9f2c119
CF
1857/*provided for source level compatability.
1858 *See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
5c83f260
RC
1859 */
1860int
1861__pthread_setconcurrency (int new_level)
1862{
1863 if (new_level < 0)
1864 return EINVAL;
1865 MT_INTERFACE->concurrency = new_level;
9a08b2c0 1866 return 0;
166b2571 1867}
9a08b2c0 1868
f9f2c119 1869/*keep syncronised with sched.cc */
5c83f260
RC
1870int
1871__pthread_setschedparam (pthread_t thread, int policy,
1872 const struct sched_param *param)
1873{
4e786173 1874 if (!pthread::isGoodObject (&thread))
5c83f260
RC
1875 return ESRCH;
1876 if (policy != SCHED_FIFO)
1877 return ENOTSUP;
1878 if (!param)
1879 return EINVAL;
1880 int rv =
1881 sched_set_thread_priority (thread->win32_obj_id, param->sched_priority);
1882 if (!rv)
1883 thread->attr.schedparam.sched_priority = param->sched_priority;
1884 return rv;
1885}
1886
9a08b2c0 1887
1fd5e000 1888int
9a08b2c0 1889__pthread_setspecific (pthread_key_t key, const void *value)
1fd5e000 1890{
86336f4f 1891 if (verifyable_object_isvalid (&key, PTHREAD_KEY_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
1892 return EINVAL;
1893 (key)->set (value);
1894 return 0;
166b2571 1895}
9a08b2c0 1896
1fd5e000 1897void *
9a08b2c0 1898__pthread_getspecific (pthread_key_t key)
1fd5e000 1899{
86336f4f 1900 if (verifyable_object_isvalid (&key, PTHREAD_KEY_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
1901 return NULL;
1902
1903 return (key)->get ();
1904
166b2571 1905}
1fd5e000 1906
f9f2c119 1907/*Thread synchronisation */
5ccbf4b6
CF
1908
1909int
f9f2c119 1910__pthread_cond_destroy (pthread_cond_t *cond)
5ccbf4b6 1911{
f38ac9b7
ED
1912 if (check_valid_pointer (cond) && (*cond == PTHREAD_COND_INITIALIZER))
1913 return 0;
86336f4f 1914 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
9a08b2c0 1915 return EINVAL;
5ccbf4b6 1916
f9f2c119 1917 /*reads are atomic */
9a08b2c0
CF
1918 if ((*cond)->waiting)
1919 return EBUSY;
5ccbf4b6 1920
9a08b2c0
CF
1921 delete (*cond);
1922 *cond = NULL;
5ccbf4b6 1923
5ccbf4b6
CF
1924 return 0;
1925}
1926
1927int
f9f2c119 1928__pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr)
5ccbf4b6 1929{
86336f4f 1930 if (attr && verifyable_object_isvalid (attr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
5ccbf4b6 1931 return EINVAL;
5ccbf4b6 1932
f38ac9b7 1933 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) == VALID_OBJECT)
9a08b2c0 1934 return EBUSY;
5ccbf4b6 1935
9a08b2c0 1936 *cond = new pthread_cond (attr ? (*attr) : NULL);
5ccbf4b6 1937
86336f4f 1938 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
1939 {
1940 delete (*cond);
1941 *cond = NULL;
1942 return EAGAIN;
1943 }
5ccbf4b6 1944
9a08b2c0 1945 return 0;
5ccbf4b6
CF
1946}
1947
94b03f23 1948int
f9f2c119 1949__pthread_cond_broadcast (pthread_cond_t *cond)
5ccbf4b6 1950{
f38ac9b7
ED
1951 if (*cond == PTHREAD_COND_INITIALIZER)
1952 __pthread_cond_init (cond, NULL);
86336f4f 1953 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
9a08b2c0 1954 return EINVAL;
94b03f23 1955
9a08b2c0 1956 (*cond)->BroadCast ();
5ccbf4b6
CF
1957
1958 return 0;
1959}
1960
94b03f23 1961int
f9f2c119 1962__pthread_cond_signal (pthread_cond_t *cond)
5ccbf4b6 1963{
f38ac9b7
ED
1964 if (*cond == PTHREAD_COND_INITIALIZER)
1965 __pthread_cond_init (cond, NULL);
86336f4f 1966 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
9a08b2c0 1967 return EINVAL;
5ccbf4b6 1968
9a08b2c0 1969 (*cond)->Signal ();
5ccbf4b6
CF
1970
1971 return 0;
1972}
1973
94b03f23 1974int
86336f4f
RC
1975__pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex,
1976 long waitlength)
5ccbf4b6 1977{
462f4eff 1978// and yes cond_access here is still open to a race. (we increment, context swap,
68ebd3f6 1979// broadcast occurs - we miss the broadcast. the functions aren't split properly.
5ccbf4b6 1980 int rv;
3c76c076 1981 pthread_mutex **themutex = NULL;
5c83f260
RC
1982 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
1983 __pthread_mutex_init (mutex, NULL);
ac9841a0 1984 themutex = mutex;
f38ac9b7
ED
1985 if (*cond == PTHREAD_COND_INITIALIZER)
1986 __pthread_cond_init (cond, NULL);
9450ad0d 1987
86336f4f 1988 if (verifyable_object_isvalid (themutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
5ccbf4b6 1989 return EINVAL;
86336f4f 1990 if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
5ccbf4b6 1991 return EINVAL;
462f4eff 1992
f9f2c119 1993 /*if the cond variable is blocked, then the above timer test maybe wrong. *shrug**/
68ebd3f6 1994 if (pthread_mutex_lock (&(*cond)->cond_access))
4d029f39 1995 system_printf ("Failed to lock condition variable access mutex, this %p", *cond);
68ebd3f6 1996
9a08b2c0 1997 if ((*cond)->waiting)
9450ad0d 1998 if ((*cond)->mutex && ((*cond)->mutex != (*themutex)))
68ebd3f6 1999 {
462f4eff 2000 if (pthread_mutex_unlock (&(*cond)->cond_access))
4d029f39 2001 system_printf ("Failed to unlock condition variable access mutex, this %p", *cond);
462f4eff 2002 return EINVAL;
68ebd3f6 2003 }
63b61cd1 2004 InterlockedIncrement (&((*cond)->waiting));
9a08b2c0 2005
9450ad0d 2006 (*cond)->mutex = (*themutex);
63b61cd1 2007 InterlockedIncrement (&((*themutex)->condwaits));
68ebd3f6 2008 if (pthread_mutex_unlock (&(*cond)->cond_access))
4d029f39 2009 system_printf ("Failed to unlock condition variable access mutex, this %p", *cond);
37143995
RC
2010 /* At this point calls to Signal will progress evebn if we aren' yet waiting
2011 * However, the loop there should allow us to get scheduled and call wait,
2012 * and have them call PulseEvent again if we dont' respond.
2013 */
462f4eff 2014 rv = (*cond)->TimedWait (waitlength);
9c510edc 2015 /* this may allow a race on the mutex acquisition and waits..
86336f4f
RC
2016 * But doing this within the cond access mutex creates a different race
2017 */
37143995 2018 InterlockedDecrement (&((*cond)->waiting));
cbce4980
RC
2019 /* Tell Signal that we have been released */
2020 InterlockedDecrement (&((*cond)->ExitingWait));
38102913 2021 (*themutex)->Lock ();
68ebd3f6 2022 if (pthread_mutex_lock (&(*cond)->cond_access))
4d029f39 2023 system_printf ("Failed to lock condition variable access mutex, this %p", *cond);
37143995
RC
2024 if ((*cond)->waiting == 0)
2025 (*cond)->mutex = NULL;
63b61cd1 2026 InterlockedDecrement (&((*themutex)->condwaits));
68ebd3f6 2027 if (pthread_mutex_unlock (&(*cond)->cond_access))
4d029f39 2028 system_printf ("Failed to unlock condition variable access mutex, this %p", *cond);
5ccbf4b6
CF
2029
2030 return rv;
2031}
2032
86336f4f
RC
2033extern "C" int
2034pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
2035 const struct timespec *abstime)
94b03f23 2036{
4d029f39 2037 if (check_valid_pointer (abstime))
94b03f23 2038 return EINVAL;
86336f4f
RC
2039 struct timeb currSysTime;
2040 long waitlength;
4d029f39 2041 ftime (&currSysTime);
86336f4f
RC
2042 waitlength = (abstime->tv_sec - currSysTime.time) *1000;
2043 if (waitlength < 0)
2044 return ETIMEDOUT;
2045 return __pthread_cond_dowait (cond, mutex, waitlength);
2046}
9a08b2c0 2047
86336f4f
RC
2048extern "C" int
2049pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
2050{
2051 return __pthread_cond_dowait (cond, mutex, INFINITE);
5ccbf4b6
CF
2052}
2053
2054int
f9f2c119 2055__pthread_condattr_init (pthread_condattr_t *condattr)
5ccbf4b6 2056{
9a08b2c0 2057 *condattr = new pthread_condattr;
86336f4f 2058 if (verifyable_object_isvalid (condattr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
2059 {
2060 delete (*condattr);
2061 *condattr = NULL;
2062 return EAGAIN;
2063 }
5ccbf4b6
CF
2064 return 0;
2065}
2066
2067int
f9f2c119 2068__pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
5ccbf4b6 2069{
86336f4f 2070 if (verifyable_object_isvalid (attr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
5ccbf4b6 2071 return EINVAL;
9a08b2c0 2072 *pshared = (*attr)->shared;
5ccbf4b6
CF
2073 return 0;
2074}
2075
2076int
f9f2c119 2077__pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared)
5ccbf4b6 2078{
86336f4f 2079 if (verifyable_object_isvalid (attr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
5ccbf4b6 2080 return EINVAL;
9a08b2c0
CF
2081 if ((pshared < 0) || (pshared > 1))
2082 return EINVAL;
f9f2c119 2083 /*shared cond vars not currently supported */
9450ad0d
RC
2084 if (pshared != PTHREAD_PROCESS_PRIVATE)
2085 return EINVAL;
9a08b2c0 2086 (*attr)->shared = pshared;
5ccbf4b6
CF
2087 return 0;
2088}
2089
2090int
f9f2c119 2091__pthread_condattr_destroy (pthread_condattr_t *condattr)
5ccbf4b6 2092{
86336f4f 2093 if (verifyable_object_isvalid (condattr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
2094 return EINVAL;
2095 delete (*condattr);
2096 *condattr = NULL;
5ccbf4b6
CF
2097 return 0;
2098}
2099
f9f2c119 2100/*Thread signal */
1fd5e000 2101int
5c83f260 2102__pthread_kill (pthread_t thread, int sig)
1fd5e000 2103{
9a08b2c0 2104// lock myself, for the use of thread2signal
ac9841a0 2105 // two different kills might clash: FIXME
1fd5e000 2106
4e786173 2107 if (!pthread::isGoodObject (&thread))
9a08b2c0
CF
2108 return EINVAL;
2109
5c83f260
RC
2110 if (thread->sigs)
2111 myself->setthread2signal (thread);
1fd5e000 2112
6201d15e 2113 int rval = _kill (myself->pid, sig);
1fd5e000 2114
94b03f23 2115 // unlock myself
1fd5e000 2116 return rval;
166b2571 2117}
1fd5e000
CF
2118
2119int
f9f2c119 2120__pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set)
1fd5e000 2121{
007276b3 2122 pthread *thread = pthread::self ();
1fd5e000 2123
94b03f23
CF
2124 // lock this myself, for the use of thread2signal
2125 // two differt kills might clash: FIXME
1fd5e000 2126
9a08b2c0
CF
2127 if (thread->sigs)
2128 myself->setthread2signal (thread);
1fd5e000
CF
2129
2130 int rval = sigprocmask (operation, set, old_set);
2131
94b03f23 2132 // unlock this myself
1fd5e000
CF
2133
2134 return rval;
166b2571 2135}
1fd5e000 2136
f9f2c119 2137/* ID */
1fd5e000
CF
2138
2139int
f9f2c119 2140__pthread_equal (pthread_t *t1, pthread_t *t2)
1fd5e000 2141{
f9f2c119 2142 return (*t1 == *t2);
166b2571 2143}
1fd5e000 2144
f9f2c119 2145/*Mutexes */
1fd5e000 2146
f9f2c119
CF
2147/*FIXME: there's a potential race with PTHREAD_MUTEX_INITALIZER:
2148 *the mutex is not actually inited until the first use.
2149 *So two threads trying to lock/trylock may collide.
2150 *Solution: we need a global mutex on mutex creation, or possibly simply
2151 *on all constructors that allow INITIALIZER macros.
2152 *the lock should be very small: only around the init routine, not
2153 *every test, or all mutex access will be synchronised.
5c83f260
RC
2154 */
2155
1fd5e000 2156int
f9f2c119
CF
2157__pthread_mutex_init (pthread_mutex_t *mutex,
2158 const pthread_mutexattr_t *attr)
1fd5e000 2159{
86336f4f 2160 if (attr && verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT || check_valid_pointer (mutex))
9a08b2c0 2161 return EINVAL;
1fd5e000 2162
f38ac9b7 2163 if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC, PTHREAD_MUTEX_INITIALIZER) == VALID_OBJECT)
9a08b2c0 2164 return EBUSY;
1fd5e000 2165
9a08b2c0 2166 *mutex = new pthread_mutex (attr ? (*attr) : NULL);
86336f4f 2167 if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
2168 {
2169 delete (*mutex);
2170 *mutex = NULL;
2171 return EAGAIN;
2172 }
1fd5e000 2173 return 0;
166b2571 2174}
1fd5e000 2175
5c83f260 2176int
f9f2c119 2177__pthread_mutex_getprioceiling (const pthread_mutex_t *mutex,
5c83f260
RC
2178 int *prioceiling)
2179{
4d029f39 2180 pthread_mutex_t *themutex = (pthread_mutex_t *) mutex;
5c83f260
RC
2181 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
2182 __pthread_mutex_init ((pthread_mutex_t *) mutex, NULL);
86336f4f 2183 if (verifyable_object_isvalid (themutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
5c83f260 2184 return EINVAL;
f9f2c119
CF
2185 /*We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
2186 *mutex priorities.
5c83f260 2187 *
f9f2c119
CF
2188 *We can support mutex priorities in the future though:
2189 *Store a priority with each mutex.
2190 *When the mutex is optained, set the thread priority as appropriate
ac9841a0 2191 *When the mutex is released, reset the thread priority.
5c83f260
RC
2192 */
2193 return ENOSYS;
2194}
2195
1fd5e000 2196int
f9f2c119 2197__pthread_mutex_lock (pthread_mutex_t *mutex)
1fd5e000 2198{
3c76c076 2199 pthread_mutex_t *themutex = mutex;
86336f4f 2200 switch (verifyable_object_isvalid (themutex, PTHREAD_MUTEX_MAGIC, PTHREAD_MUTEX_INITIALIZER))
c918cf94 2201 {
86336f4f
RC
2202 case INVALID_OBJECT:
2203 return EINVAL;
2204 break;
2205 case VALID_STATIC_OBJECT:
2206 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
9c510edc
CF
2207 {
2208 int rv = __pthread_mutex_init (mutex, NULL);
2209 if (rv)
86336f4f 2210 return rv;
9c510edc 2211 }
86336f4f
RC
2212 break;
2213 case VALID_OBJECT:
2214 break;
c918cf94 2215 }
9450ad0d 2216 (*themutex)->Lock ();
1fd5e000 2217 return 0;
166b2571 2218}
1fd5e000
CF
2219
2220int
f9f2c119 2221__pthread_mutex_trylock (pthread_mutex_t *mutex)
1fd5e000 2222{
3c76c076 2223 pthread_mutex_t *themutex = mutex;
5c83f260
RC
2224 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
2225 __pthread_mutex_init (mutex, NULL);
86336f4f 2226 if (verifyable_object_isvalid (themutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
9a08b2c0 2227 return EINVAL;
8e4d9692 2228 if ((*themutex)->TryLock ())
1fd5e000 2229 return EBUSY;
1fd5e000 2230 return 0;
166b2571 2231}
1fd5e000
CF
2232
2233int
f9f2c119 2234__pthread_mutex_unlock (pthread_mutex_t *mutex)
1fd5e000 2235{
5c83f260
RC
2236 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
2237 __pthread_mutex_init (mutex, NULL);
86336f4f 2238 if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
2239 return EINVAL;
2240 (*mutex)->UnLock ();
1fd5e000 2241 return 0;
166b2571 2242}
1fd5e000
CF
2243
2244int
f9f2c119 2245__pthread_mutex_destroy (pthread_mutex_t *mutex)
1fd5e000 2246{
8e4d9692 2247 if (check_valid_pointer (mutex) && (*mutex == PTHREAD_MUTEX_INITIALIZER))
5c83f260 2248 return 0;
86336f4f 2249 if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
9a08b2c0 2250 return EINVAL;
1fd5e000 2251
f9f2c119 2252 /*reading a word is atomic */
9a08b2c0
CF
2253 if ((*mutex)->condwaits)
2254 return EBUSY;
1fd5e000 2255
9a08b2c0
CF
2256 delete (*mutex);
2257 *mutex = NULL;
1fd5e000 2258 return 0;
166b2571 2259}
1fd5e000 2260
5c83f260 2261int
f9f2c119 2262__pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling,
5c83f260
RC
2263 int *old_ceiling)
2264{
3c76c076 2265 pthread_mutex_t *themutex = mutex;
5c83f260
RC
2266 if (*mutex == PTHREAD_MUTEX_INITIALIZER)
2267 __pthread_mutex_init (mutex, NULL);
86336f4f 2268 if (verifyable_object_isvalid (themutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
5c83f260
RC
2269 return EINVAL;
2270 return ENOSYS;
2271}
2272
f9f2c119
CF
2273/*Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
2274 *for more detail */
5c83f260 2275int
f9f2c119 2276__pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr,
5c83f260
RC
2277 int *protocol)
2278{
86336f4f 2279 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
2280 return EINVAL;
2281 return ENOSYS;
2282}
2283
2284int
f9f2c119 2285__pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr,
5c83f260
RC
2286 int *pshared)
2287{
86336f4f 2288 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
2289 return EINVAL;
2290 *pshared = (*attr)->pshared;
2291 return 0;
2292}
2293
f9f2c119
CF
2294/*Win32 mutex's are equivalent to posix RECURSIVE mutexs.
2295 *We need to put glue in place to support other types of mutex's. We map
2296 *PTHREAD_MUTEX_DEFAULT to PTHREAD_MUTEX_RECURSIVE and return EINVAL for other types.
5c83f260
RC
2297 */
2298int
f9f2c119 2299__pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type)
5c83f260 2300{
86336f4f 2301 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
2302 return EINVAL;
2303 *type = (*attr)->mutextype;
2304 return 0;
2305}
2306
f9f2c119
CF
2307/*Currently pthread_mutex_init ignores the attr variable, this is because
2308 *none of the variables have any impact on it's behaviour.
5c83f260 2309 *
f9f2c119 2310 *FIXME: write and test process shared mutex's.
5c83f260
RC
2311 */
2312int
f9f2c119 2313__pthread_mutexattr_init (pthread_mutexattr_t *attr)
5c83f260 2314{
86336f4f 2315 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != INVALID_OBJECT)
5c83f260
RC
2316 return EBUSY;
2317
2318 *attr = new pthread_mutexattr ();
86336f4f 2319 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
2320 {
2321 delete (*attr);
2322 *attr = NULL;
2323 return ENOMEM;
2324 }
2325 return 0;
2326}
2327
2328int
f9f2c119 2329__pthread_mutexattr_destroy (pthread_mutexattr_t *attr)
5c83f260 2330{
86336f4f 2331 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
2332 return EINVAL;
2333 delete (*attr);
2334 *attr = NULL;
2335 return 0;
2336}
2337
2338
f9f2c119 2339/*Win32 doesn't support mutex priorities */
5c83f260 2340int
f9f2c119 2341__pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, int protocol)
5c83f260 2342{
86336f4f 2343 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
2344 return EINVAL;
2345 return ENOSYS;
2346}
2347
f9f2c119 2348/*Win32 doesn't support mutex priorities */
5c83f260 2349int
f9f2c119 2350__pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr,
5c83f260
RC
2351 int prioceiling)
2352{
86336f4f 2353 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
2354 return EINVAL;
2355 return ENOSYS;
2356}
2357
2358int
f9f2c119 2359__pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *attr,
5c83f260
RC
2360 int *prioceiling)
2361{
86336f4f 2362 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
2363 return EINVAL;
2364 return ENOSYS;
2365}
2366
2367int
f9f2c119 2368__pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared)
5c83f260 2369{
86336f4f 2370 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
5c83f260 2371 return EINVAL;
f9f2c119
CF
2372 /*we don't use pshared for anything as yet. We need to test PROCESS_SHARED
2373 *functionality
5c83f260 2374 */
ac9841a0 2375 if (pshared != PTHREAD_PROCESS_PRIVATE)
5c83f260
RC
2376 return EINVAL;
2377 (*attr)->pshared = pshared;
2378 return 0;
2379}
2380
f9f2c119 2381/*see __pthread_mutex_gettype */
5c83f260 2382int
f9f2c119 2383__pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type)
5c83f260 2384{
86336f4f 2385 if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
5c83f260
RC
2386 return EINVAL;
2387 if (type != PTHREAD_MUTEX_RECURSIVE)
2388 return EINVAL;
2389 (*attr)->mutextype = type;
2390 return 0;
2391}
2392
f9f2c119 2393/*Semaphores */
1fd5e000 2394int
f9f2c119 2395__sem_init (sem_t *sem, int pshared, unsigned int value)
1fd5e000 2396{
f9f2c119 2397 /*opengroup calls this undefined */
86336f4f 2398 if (verifyable_object_isvalid (sem, SEM_MAGIC) != INVALID_OBJECT)
9a08b2c0 2399 return EBUSY;
1fd5e000 2400
9a08b2c0
CF
2401 if (value > SEM_VALUE_MAX)
2402 return EINVAL;
1fd5e000 2403
9a08b2c0 2404 *sem = new semaphore (pshared, value);
1fd5e000 2405
86336f4f 2406 if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
9a08b2c0
CF
2407 {
2408 delete (*sem);
2409 *sem = NULL;
2410 return EAGAIN;
2411 }
1fd5e000 2412 return 0;
166b2571 2413}
1fd5e000
CF
2414
2415int
f9f2c119 2416__sem_destroy (sem_t *sem)
1fd5e000 2417{
86336f4f 2418 if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
9a08b2c0 2419 return EINVAL;
1fd5e000 2420
f9f2c119 2421 /*FIXME - new feature - test for busy against threads... */
1fd5e000 2422
9a08b2c0
CF
2423 delete (*sem);
2424 *sem = NULL;
1fd5e000 2425 return 0;
166b2571 2426}
1fd5e000
CF
2427
2428int
f9f2c119 2429__sem_wait (sem_t *sem)
1fd5e000 2430{
86336f4f 2431 if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
062401c9
RC
2432 {
2433 set_errno (EINVAL);
2434 return -1;
2435 }
1fd5e000 2436
9a08b2c0 2437 (*sem)->Wait ();
1fd5e000 2438 return 0;
166b2571 2439}
1fd5e000
CF
2440
2441int
f9f2c119 2442__sem_trywait (sem_t *sem)
1fd5e000 2443{
86336f4f 2444 if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
062401c9
RC
2445 {
2446 set_errno (EINVAL);
2447 return -1;
2448 }
1fd5e000 2449
9a08b2c0 2450 return (*sem)->TryWait ();
166b2571 2451}
1fd5e000
CF
2452
2453int
f9f2c119 2454__sem_post (sem_t *sem)
1fd5e000 2455{
86336f4f 2456 if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
9a08b2c0 2457 return EINVAL;
1fd5e000 2458
9a08b2c0 2459 (*sem)->Post ();
1fd5e000 2460 return 0;
166b2571 2461}
1fd5e000 2462
4e786173
RC
2463/* pthreadNull */
2464pthread *
2465pthreadNull::getNullpthread()
2466{
2467 /* because of weird entry points */
2468 _instance.magic = 0;
2469 return &_instance;
2470}
2471
2472pthreadNull::pthreadNull()
2473{
2474 /* Mark ourselves as invalid */
2475 magic = 0;
2476}
2477
2478pthreadNull::~pthreadNull()
2479{
2480}
2481
2482void
2483pthreadNull::create (void *(*)(void *), pthread_attr *, void *)
2484{
2485}
2486
2487void
2488pthreadNull::exit (void *value_ptr)
2489{
2490}
2491
2492int
2493pthreadNull::cancel ()
2494{
2495 return 0;
2496}
2497
2498void
2499pthreadNull::testcancel ()
2500{
2501}
2502
2503int
2504pthreadNull::setcancelstate (int state, int *oldstate)
2505{
2506 return EINVAL;
2507}
2508
2509int
2510pthreadNull::setcanceltype (int type, int *oldtype)
2511{
2512 return EINVAL;
2513}
2514
2515void
2516pthreadNull::push_cleanup_handler (__pthread_cleanup_handler *handler)
2517{
2518}
2519
2520void
2521pthreadNull::pop_cleanup_handler (int const execute)
2522{
2523}
2524unsigned long
2525pthreadNull::getsequence_np()
2526{
2527 return 0;
2528}
2529
2530pthreadNull pthreadNull::_instance = pthreadNull ();
2531
5c83f260 2532#endif // MT_SAFE
This page took 0.471604 seconds and 5 git commands to generate.