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