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