]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/thread.cc
import winsup-2000-02-17 snapshot
[newlib-cygwin.git] / winsup / cygwin / thread.cc
CommitLineData
1fd5e000
CF
1/* thread.cc: Locking and threading module functions
2
3 Copyright 1998, 2000 Cygnus Solutions.
4
5 Written by Marco Fuykschot <marco@ddi.nl>
6
7This file is part of Cygwin.
8
9This software is a copyrighted work licensed under the terms of the
10Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11details. */
12
13#ifdef HAVE_CONFIG_H
14# include "config.h"
15#endif
16
17#ifdef _MT_SAFE
18#include <errno.h>
19#include "winsup.h"
20#include <assert.h>
21
22#include <stdlib.h>
23#include <syslog.h>
24
25extern int threadsafe;
26
27#define MT_INTERFACE user_data->threadinterface
28
29#define NOT_IMP(n) system_printf("not implemented %s\n",n); return 0;
30
31#define CHECKHANDLE(rval,release) \
32 if ( ! item->HandleOke() ) { \
33 if ( release ) item->used=false; \
34 return rval; };
35
36#define GETTHREAD(n) \
37 if ( ! thread ) system_printf("thread is NULL");\
38 SetResourceLock(LOCK_THREAD_LIST,READ_LOCK,n);\
39 ThreadItem *item=user_data->threadinterface->GetThread(thread); \
40 ReleaseResourceLock(LOCK_THREAD_LIST,READ_LOCK,n); \
41 if ( ! item ) return EINVAL; \
42 CHECKHANDLE(EINVAL,0);
43
44#define GETMUTEX(n) \
45 SetResourceLock(LOCK_MUTEX_LIST,READ_LOCK,n); \
46 MutexItem* item=user_data->threadinterface->GetMutex(mutex); \
47 ReleaseResourceLock(LOCK_MUTEX_LIST,READ_LOCK,n); \
48 if ( ! item ) return EINVAL; \
49 CHECKHANDLE(EINVAL,0);
50
51#define GETSEMA(n) \
52 SetResourceLock(LOCK_SEM_LIST,READ_LOCK,n); \
53 SemaphoreItem* item=user_data->threadinterface->GetSemaphore(sem); \
54 ReleaseResourceLock(LOCK_SEM_LIST,READ_LOCK,n); \
55 if ( ! item ) return EINVAL; \
56 CHECKHANDLE(EINVAL,0);
57
58#define CHECKITEM(rn,rm,fn) \
59 if ( ! item ) { \
60 ReleaseResourceLock(rn,rm,fn); \
61 return EINVAL; }; \
62
63struct _reent *
64_reent_clib ()
65{
66 int tmp = GetLastError ();
67 struct __reent_t *_r = (struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index);
68
69#ifdef _CYG_THREAD_FAILSAFE
70 if (_r == 0)
71 {
72 system_printf ("local thread storage not inited");
73 }
74#endif
75
76 SetLastError (tmp);
77 return _r->_clib;
78};
79
80struct _winsup_t *
81_reent_winsup ()
82{
83 int tmp = GetLastError ();
84 struct __reent_t *_r;
85 _r = (struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index);
86#ifdef _CYG_THREAD_FAILSAFE
87 if (_r == 0)
88 {
89 system_printf ("local thread storage not inited");
90 }
91#endif
92 SetLastError (tmp);
93 return _r->_winsup;
94};
95
96void
97SetResourceLock (int _res_id, int _mode, const char *_function)
98{
99#if 0
100 if (!threadsafe)
101 return;
102#endif
103 thread_printf ("Set resource lock %d mode %d for %s start", _res_id, _mode, _function);
104 EnterCriticalSection (user_data->resourcelocks->Lock (_res_id));
105
106#ifdef _CYG_THREAD_FAILSAFE
107 user_data->resourcelocks->owner = GetCurrentThreadId ();
108 user_data->resourcelocks->count++;
109#endif
110}
111
112void
113ReleaseResourceLock (int _res_id, int _mode, const char *_function)
114{
115#if 0
116 if (!threadsafe)
117 return;
118#endif
119 thread_printf ("Release resource lock %d mode %d for %s done", _res_id, _mode, _function);
120
121#ifdef _CYG_THREAD_FAILSAFE
122 AssertResourceOwner (_res_id, _mode);
123 user_data->resourcelocks->count--;
124 if (user_data->resourcelocks->count == 0)
125 user_data->resourcelocks->owner = 0;
126#endif
127
128 LeaveCriticalSection (user_data->resourcelocks->Lock (_res_id));
129};
130
131#ifdef _CYG_THREAD_FAILSAFE
132void
133AssertResourceOwner (int _res_id, int _mode)
134{
135
136 thread_printf ("Assert Resource lock %d ==> for %p , real : %d , threadid %d count %d owner %d", _res_id, user_data, (myself ? myself->pid : -1), GetCurrentThreadId (), user_data->resourcelocks->count, user_data->resourcelocks->owner);
137 if (user_data && (user_data->resourcelocks->owner != GetCurrentThreadId ()))
138 {
139 system_printf ("assertion failed, not the resource owner");
140 };
141}
142
143#endif
144
145LPCRITICAL_SECTION
146ResourceLocks::Lock (int _resid)
147{
148 if (!inited)
149 {
150 system_printf ("lock called before initialization");
151 };
152
153 thread_printf ("Get Resource lock %d ==> %p for %p , real : %d , threadid %d ", _resid, &lock, user_data, (myself ? myself->pid : -1), GetCurrentThreadId ());
154 return &lock;
155};
156
157void
158ResourceLocks::Init ()
159{
160 thread_printf ("Init resource lock %p -> %p", this, &lock);
161
162 InitializeCriticalSection (&lock);
163 inited = true;
164
165#ifdef _CYG_THREAD_FAILSAFE
166 owner = 0;
167 count = 0;
168#endif
169
170 thread_printf ("Resource lock %p inited by %p , %d", &lock, user_data, (myself ? myself->pid : -1));
171};
172
173void
174ResourceLocks::Delete ()
175{
176 if (inited)
177 {
178 thread_printf ("Close Resource Locks %p ", &lock);
179 DeleteCriticalSection (&lock);
180 inited = false;
181 };
182};
183
184
185// Thread interface
186
187void
188MTinterface::ReleaseItem (MTitem * _item)
189{
190 _item->used = false;
191};
192
193MTitem *
194MTinterface::Find (void *_value, int (*comp) (void *, void *), register int &_index, MTList * _list)
195{
196 register MTitem *current = NULL;
197 for (; _index < _list->index; _index++)
198 {
199 current = _list->items[_index];
200 if (current->used && comp (current, _value))
201 break;
202 current = NULL;
203 };
204 return current;
205};
206
207int
208MTinterface::Find (MTitem & _item, MTList * _list)
209{
210 register MTitem *current;
211 register int _index = 0;
212 for (; _index < _list->index; _index++)
213 {
214 current = _list->items[_index];
215 if (current->used && current == &_item)
216 break;
217 };
218 return (_index == _list->index ? -1 : _index);
219};
220
221int
222MTinterface::FindNextUnused (MTList * _list)
223{
224 register int i = 0;
225 for (; i < _list->index && _list->items[i] != NULL && _list->items[i]->used && _list->items[i]->joinable != 'Y'; i++);
226 return i;
227};
228
229MTitem *
230MTinterface::GetItem (int _index, MTList * _list)
231{
232 return (_index < _list->index ? _list->items[_index] : NULL);
233};
234
235MTitem *
236MTinterface::SetItem (int _index, MTitem * _item, MTList * _list)
237{
238 if (_index == _list->index && _list->index < MT_MAX_ITEMS)
239 _list->index++;
240 return (_index < _list->index ? _list->items[_index] = _item : NULL);
241};
242
243int
244CmpPthreadObj (void *_i, void *_value)
245{
246 return ((MTitem *) _i)->Id () == *(int *) _value;
247};
248
249int
250CmpThreadId (void *_i, void *_id)
251{
252 return ((ThreadItem *) _i)->thread_id == *(DWORD *) _id;
253};
254
255void
256MTinterface::Init0 ()
257{
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;
263 };
264
265 threadlist.index = 0;
266 mutexlist.index = 0;
267 semalist.index = 0;
268
269 reent_index = TlsAlloc ();
270
271 reents._clib = _impure_ptr;
272 reents._winsup = &winsup_reent;
273
274 winsup_reent._process_logmask = LOG_UPTO (LOG_DEBUG);
275 winsup_reent._grp_pos = 0;
276 winsup_reent._process_ident = 0;
277 winsup_reent._process_logopt = 0;
278 winsup_reent._process_facility = 0;
279
280 TlsSetValue (reent_index, &reents);
281 // the static reent_data will be used in the main thread
282
283};
284
285void
286MTinterface::Init1 ()
287{
288 // create entry for main thread
289
290 int i = FindNextUnused (&threadlist);
291 assert (i == 0);
292 ThreadItem *item = (ThreadItem *) GetItem (i, &threadlist);
293
294 item = (ThreadItem *) SetItem (i, &mainthread, &threadlist);
295 item->used = true;
296 item->win32_obj_id = myself->hProcess;
297 item->thread_id = GetCurrentThreadId ();
298 item->function = NULL;
299
300 item->sigs = NULL;
301 item->sigmask = NULL;
302 item->sigtodo = NULL;
303};
304
305void
306MTinterface::ClearReent ()
307{
308 struct _reent *r = _REENT;
309 memset (r, 0, sizeof (struct _reent));
310
311 r->_errno = 0;
312 r->_stdin = &r->__sf[0];
313 r->_stdout = &r->__sf[1];
314 r->_stderr = &r->__sf[2];
315
316};
317
318
319ThreadItem *
320MTinterface::CreateThread (pthread_t * t, TFD (func), void *arg, pthread_attr_t a)
321{
322 AssertResourceOwner (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK);
323
324 int i = FindNextUnused (&threadlist);
325
326 ThreadItem *item = (ThreadItem *) GetItem (i, &threadlist);
327 if (!item)
328 item = (ThreadItem *) SetItem (i, new ThreadItem (), &threadlist);
329 if (!item)
330 system_printf ("thread creation failed");
331
332 item->used = true;
333 item->function = func;
334 item->arg = arg;
335 item->attr = a;
336
337 item->win32_obj_id = ::CreateThread (&sec_none_nih, item->attr.stacksize,
338 (LPTHREAD_START_ROUTINE) thread_init_wrapper, item, 0, &item->thread_id);
339
340 CHECKHANDLE (NULL, 1);
341
342 *t = (pthread_t) item->win32_obj_id;
343
344 return item;
345};
346
347
348MutexItem *
349MTinterface::CreateMutex (pthread_mutex_t * mutex)
350{
351 AssertResourceOwner (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK);
352
353 int i = FindNextUnused (&mutexlist);
354
355 MutexItem *item = (MutexItem *) GetItem (i, &mutexlist);
356 if (!item)
357 item = (MutexItem *) SetItem (i, new MutexItem (), &mutexlist);
358 if (!item)
359 system_printf ("mutex creation failed");
360 item->used = true;
361
362 item->win32_obj_id = ::CreateMutex (&sec_none_nih, false, NULL);
363
364 CHECKHANDLE (NULL, 1);
365
366 *mutex = (pthread_mutex_t) item->win32_obj_id;
367
368 return item;
369}
370
371ThreadItem *
372MTinterface::GetCallingThread ()
373{
374 AssertResourceOwner (LOCK_THREAD_LIST, READ_LOCK);
375 DWORD id = GetCurrentThreadId ();
376 int index = 0;
377 return (ThreadItem *) Find (&id, &CmpThreadId, index, &threadlist);
378};
379
380ThreadItem *
381MTinterface::GetThread (pthread_t * _t)
382{
383 AssertResourceOwner (LOCK_THREAD_LIST, READ_LOCK);
384 int index = 0;
385 return (ThreadItem *) Find (_t, &CmpPthreadObj, index, &threadlist);
386};
387
388MutexItem *
389MTinterface::GetMutex (pthread_mutex_t * mp)
390{
391 AssertResourceOwner (LOCK_MUTEX_LIST, READ_LOCK);
392 int index = 0;
393 return (MutexItem *) Find (mp, &CmpPthreadObj, index, &mutexlist);
394}
395
396SemaphoreItem *
397MTinterface::GetSemaphore (sem_t * sp)
398{
399 AssertResourceOwner (LOCK_SEM_LIST, READ_LOCK);
400 int index = 0;
401 return (SemaphoreItem *) Find (sp, &CmpPthreadObj, index, &semalist);
402}
403
404
405void
406MTitem::Destroy ()
407{
408 CloseHandle (win32_obj_id);
409};
410
411int
412MutexItem::Lock ()
413{
414 return WaitForSingleObject (win32_obj_id, INFINITE);
415};
416
417int
418MutexItem::TryLock ()
419{
420 return WaitForSingleObject (win32_obj_id, 0);
421};
422
423int
424MutexItem::UnLock ()
425{
426 return ReleaseMutex (win32_obj_id);
427}
428
429SemaphoreItem *
430MTinterface::CreateSemaphore (sem_t * _s, int pshared, int _v)
431{
432 AssertResourceOwner (LOCK_SEM_LIST, WRITE_LOCK | READ_LOCK);
433
434 int i = FindNextUnused (&semalist);
435
436 SemaphoreItem *item = (SemaphoreItem *) GetItem (i, &semalist);
437 if (!item)
438 item = (SemaphoreItem *) SetItem (i, new SemaphoreItem (), &semalist);
439 if (!item)
440 system_printf ("semaphore creation failed");
441 item->used = true;
442 item->shared = pshared;
443
444 item->win32_obj_id = ::CreateSemaphore (&sec_none_nih, _v, _v, NULL);
445
446 CHECKHANDLE (NULL, 1);
447
448 *_s = (sem_t) item->win32_obj_id;
449
450 return item;
451};
452
453int
454SemaphoreItem::Wait ()
455{
456 return WaitForSingleObject (win32_obj_id, INFINITE);
457};
458
459int
460SemaphoreItem::Post ()
461{
462 long pc;
463 return ReleaseSemaphore (win32_obj_id, 1, &pc);
464};
465
466int
467SemaphoreItem::TryWait ()
468{
469 return WaitForSingleObject (win32_obj_id, 0);
470};
471
472
473////////////////////////// Pthreads
474
475void *
476thread_init_wrapper (void *_arg)
477{
478// Setup the local/global storage of this thread
479
480 ThreadItem *thread = (ThreadItem *) _arg;
481 struct __reent_t local_reent;
482 struct _winsup_t local_winsup;
483 struct _reent local_clib;
484
485 struct sigaction _sigs[NSIG];
486 sigset_t _sig_mask; /* one set for everything to ignore. */
487 LONG _sigtodo[NSIG + __SIGOFFSET];
488
489// setup signal structures
490 thread->sigs = _sigs;
491 thread->sigmask = &_sig_mask;
492 thread->sigtodo = _sigtodo;
493
494 memset (&local_clib, 0, sizeof (struct _reent));
495 memset (&local_winsup, 0, sizeof (struct _winsup_t));
496
497 local_clib._errno = 0;
498 local_clib._stdin = &local_clib.__sf[0];
499 local_clib._stdout = &local_clib.__sf[1];
500 local_clib._stderr = &local_clib.__sf[2];
501
502 local_reent._clib = &local_clib;
503 local_reent._winsup = &local_winsup;
504
505 local_winsup._process_logmask = LOG_UPTO (LOG_DEBUG);
506
507
508 if (!TlsSetValue (MT_INTERFACE->reent_index, &local_reent))
509 system_printf ("local storage for thread couldn't be set");
510
511#ifdef _CYG_THREAD_FAILSAFE
512 if (_REENT == _impure_ptr)
513 system_printf ("local storage for thread isn't setup correctly");
514#endif
515
516
517 thread_printf ("started thread %p %p %p %p %p %p", _arg, &local_clib, _impure_ptr, thread, thread->function, thread->arg);
518
519
520// call the user's thread
521 void *ret = thread->function (thread->arg);
522
523// FIX ME : cleanup code
524
525// thread->used = false; // release thread entry
526 thread->return_ptr = ret;
527 return ret;
528}
529
530int
531__pthread_create (pthread_t * thread, const pthread_attr_t * attr, TFD (start_routine), void *arg)
532{
533 SetResourceLock (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK, "__pthread_create");
534
535 pthread_attr_t a;
536 ThreadItem *item;
537
538 if (attr)
539 item = MT_INTERFACE->CreateThread (thread, start_routine, arg, *attr);
540 else
541 {
542 __pthread_attr_init (&a);
543 item = MT_INTERFACE->CreateThread (thread, start_routine, arg, a);
544 };
545
546
547
548 CHECKITEM (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK, "__pthread_create")
549
550 ReleaseResourceLock (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK, "__pthread_create");
551 return 0;
552};
553
554int
555__pthread_attr_init (pthread_attr_t * attr)
556{
557 attr->stacksize = 0;
558 return 0;
559};
560
561int
562__pthread_attr_setstacksize (pthread_attr_t * attr, size_t size)
563{
564 attr->stacksize = size;
565 return 0;
566};
567
568int
569__pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size)
570{
571 *size = attr->stacksize;
572 return 0;
573};
574
575int
576__pthread_attr_destroy (pthread_attr_t * attr)
577{
578 return 0;
579};
580
581int
582__pthread_exit (void *value_ptr)
583{
584 ThreadItem *item = MT_INTERFACE->GetCallingThread();
585 item->return_ptr = value_ptr;
586 ExitThread(0);
587 return 0;
588}
589
590int
591__pthread_join(pthread_t * thread, void **return_val)
592{
593 ThreadItem *item=user_data->threadinterface->GetThread(thread);
594
595
596 if (!item)
597 return ESRCH;
598
599 if (item->joinable == 'N')
600 {
601 if (return_val)
602 *return_val = NULL;
603 return EINVAL;
604 }
605 else
606 {
607 item->joinable = 'N';
608 WaitForSingleObject((HANDLE)*thread, INFINITE);
609 if (return_val)
610 *return_val = item->return_ptr;
611 }/* End if*/
612
613 return 0;
614};
615
616int
617__pthread_detach(pthread_t * thread)
618{
619 ThreadItem *item=user_data->threadinterface->GetThread(thread);
620 if (!item)
621 return ESRCH;
622
623 if (item->joinable == 'N')
624 {
625 item->return_ptr = NULL;
626 return EINVAL;
627 }
628
629 item->joinable = 'N';
630 return 0;
631}
632
633int
634__pthread_suspend(pthread_t * thread)
635{
636 ThreadItem *item=user_data->threadinterface->GetThread(thread);
637 if (!item)
638 return ESRCH;
639
640 if (item->suspended == false)
641 {
642 item->suspended = true;
643 SuspendThread( (HANDLE)*thread);
644 }
645
646 return 0;
647}
648
649
650int
651__pthread_continue(pthread_t * thread)
652{
653 ThreadItem *item=user_data->threadinterface->GetThread(thread);
654 if (!item)
655 return ESRCH;
656
657 if (item->suspended == true)
658 ResumeThread( (HANDLE)*thread);
659 item->suspended = false;
660
661 return 0;
662}
663
664
665
666
667unsigned long
668__pthread_getsequence_np (pthread_t * thread)
669{
670 GETTHREAD ("__pthread_getsequence_np");
671 return item->GetThreadId ();
672};
673
674/* Thread SpecificData */
675int
676__pthread_key_create (pthread_key_t * key)
677{
678 NOT_IMP ("_p_key_create\n");
679};
680
681int
682__pthread_key_delete (pthread_key_t * key)
683{
684 NOT_IMP ("_p_key_delete\n");
685};
686int
687__pthread_setspecific (pthread_key_t * key, const void *value)
688{
689 NOT_IMP ("_p_key_setsp\n");
690};
691void *
692__pthread_getspecific (pthread_key_t * key)
693{
694 NOT_IMP ("_p_key_getsp\n");
695};
696
697/* Thread signal */
698int
699__pthread_kill (pthread_t * thread, int sig)
700{
701// lock myself, for the use of thread2signal
702 // two differ kills might clash: FIX ME
703 GETTHREAD ("__pthread_kill");
704
705 if (item->sigs)
706 myself->setthread2signal (item);
707
708 int rval = sig_send (myself, sig);
709
710// unlock myself
711 return rval;
712
713};
714
715int
716__pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set)
717{
718 SetResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_sigmask");
719 ThreadItem *item = MT_INTERFACE->GetCallingThread ();
720 ReleaseResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_sigmask");
721
722// lock this myself, for the use of thread2signal
723 // two differt kills might clash: FIX ME
724
725 if (item->sigs)
726 myself->setthread2signal (item);
727
728 int rval = sigprocmask (operation, set, old_set);
729
730// unlock this myself
731
732 return rval;
733};
734
735/* ID */
736pthread_t
737__pthread_self ()
738{
739 SetResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_self");
740
741 ThreadItem *item = MT_INTERFACE->GetCallingThread ();
742
743 ReleaseResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_self");
744 return (pthread_t) item->Id ();
745
746};
747
748int
749__pthread_equal (pthread_t * t1, pthread_t * t2)
750{
751 return (*t1 - *t2);
752};
753
754/* Mutexes */
755
756int
757__pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * _attr)
758{
759 SetResourceLock (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init");
760
761 MutexItem *item = MT_INTERFACE->CreateMutex (mutex);
762
763 CHECKITEM (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init");
764
765 ReleaseResourceLock (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init");
766 return 0;
767};
768
769int
770__pthread_mutex_lock (pthread_mutex_t * mutex)
771{
772 GETMUTEX ("_ptherad_mutex_lock");
773
774 item->Lock ();
775
776 return 0;
777};
778
779int
780__pthread_mutex_trylock (pthread_mutex_t * mutex)
781{
782 GETMUTEX ("_ptherad_mutex_lock");
783
784 if (item->TryLock () == WAIT_TIMEOUT)
785 return EBUSY;
786
787 return 0;
788};
789
790int
791__pthread_mutex_unlock (pthread_mutex_t * mutex)
792{
793 GETMUTEX ("_ptherad_mutex_lock");
794
795 item->UnLock ();
796
797 return 0;
798};
799
800int
801__pthread_mutex_destroy (pthread_mutex_t * mutex)
802{
803 SetResourceLock (LOCK_MUTEX_LIST, READ_LOCK | WRITE_LOCK, "__pthread_mutex_destroy");
804
805 MutexItem *item = MT_INTERFACE->GetMutex (mutex);
806
807 CHECKITEM (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init");
808
809 item->Destroy ();
810
811 MT_INTERFACE->ReleaseItem (item);
812
813 ReleaseResourceLock (LOCK_MUTEX_LIST, READ_LOCK | WRITE_LOCK, "__pthread_mutex_destroy");
814 return 0;
815};
816
817/* Semaphores */
818int
819__sem_init (sem_t * sem, int pshared, unsigned int value)
820{
821 SetResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init");
822
823 SemaphoreItem *item = MT_INTERFACE->CreateSemaphore (sem, pshared, value);
824
825 CHECKITEM (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init");
826
827 ReleaseResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init");
828 return 0;
829};
830
831int
832__sem_destroy (sem_t * sem)
833{
834 SetResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_destroy");
835
836 SemaphoreItem *item = MT_INTERFACE->GetSemaphore (sem);
837
838 CHECKITEM (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init");
839
840 item->Destroy ();
841
842 MT_INTERFACE->ReleaseItem (item);
843
844 ReleaseResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_destroy");
845 return 0;
846};
847
848int
849__sem_wait (sem_t * sem)
850{
851 GETSEMA ("__sem_wait");
852
853 item->Wait ();
854
855 return 0;
856};
857
858int
859__sem_trywait (sem_t * sem)
860{
861 GETSEMA ("__sem_trywait");
862
863 if (item->TryWait () == WAIT_TIMEOUT)
864 return EAGAIN;
865
866 return 0;
867};
868
869int
870__sem_post (sem_t * sem)
871{
872 GETSEMA ("__sem_post");
873
874 item->Post ();
875
876 return 0;
877};
878
879
880#else
881
882// empty functions needed when makeing the dll without mt_safe support
883extern "C"
884{
885 int __pthread_create (pthread_t *, const pthread_attr_t *, TFD (start_routine), void *arg)
886 {
887 return -1;
888 };
889 int __pthread_attr_init (pthread_attr_t * attr)
890 {
891 return -1;
892 };
893 int __pthread_attr_destroy (pthread_attr_t * attr)
894 {
895 return -1;
896 };
897 int __pthread_attr_setstacksize (pthread_attr_t * attr, size_t size)
898 {
899 return -1;
900 };
901 int __pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size)
902 {
903 return -1;
904 };
905/*
906 __pthread_attr_setstackaddr(...){ return -1; };
907 __pthread_attr_getstackaddr(...){ return -1; };
908 */
909 int __pthread_exit (void *value_ptr)
910 {
911 return -1;
912 };
913
914 int __pthread_join(pthread_t thread_id, void **return_val)
915 {
916 return -1;
917 }
918
919 unsigned long __pthread_getsequence_np (pthread_t * thread)
920 {
921 return 0;
922 };
923 int __pthread_key_create (pthread_key_t * key)
924 {
925 return -1;
926 };
927 int __pthread_key_delete (pthread_key_t * key)
928 {
929 return -1;
930 };
931 int __pthread_setspecific (pthread_key_t * key, const void *value)
932 {
933 return -1;
934 };
935 void *__pthread_getspecific (pthread_key_t * key)
936 {
937 return NULL;
938 };
939 int __pthread_kill (pthread_t * thread, int sig)
940 {
941 return -1;
942 };
943 int __pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set)
944 {
945 return -1;
946 };
947 pthread_t __pthread_self ()
948 {
949 return -1;
950 };
951 int __pthread_equal (pthread_t * t1, pthread_t * t2)
952 {
953 return -1;
954 };
955 int __pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *)
956 {
957 return -1;
958 };
959 int __pthread_mutex_lock (pthread_mutex_t *)
960 {
961 return -1;
962 };
963 int __pthread_mutex_trylock (pthread_mutex_t *)
964 {
965 return -1;
966 };
967 int __pthread_mutex_unlock (pthread_mutex_t *)
968 {
969 return -1;
970 };
971 int __pthread_mutex_destroy (pthread_mutex_t *)
972 {
973 return -1;
974 };
975 int __sem_init (sem_t * sem, int pshared, unsigned int value)
976 {
977 return -1;
978 };
979 int __sem_destroy (sem_t * sem)
980 {
981 return -1;
982 };
983 int __sem_wait (sem_t * sem)
984 {
985 return -1;
986 };
987 int __sem_trywait (sem_t * sem)
988 {
989 return -1;
990 };
991 int __sem_post (sem_t * sem)
992 {
993 return -1;
994 };
995 struct _reent *_reent_clib ()
996 {
997 return NULL;
998 };
999}
1000
1001#endif // MT_SAFE
This page took 0.113604 seconds and 5 git commands to generate.