Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/thread.cc')
-rw-r--r--winsup/cygwin/thread.cc1001
1 files changed, 1001 insertions, 0 deletions
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
new file mode 100644
index 000000000..0ed42e7d8
--- /dev/null
+++ b/winsup/cygwin/thread.cc
@@ -0,0 +1,1001 @@
+/* thread.cc: Locking and threading module functions
+
+ Copyright 1998, 2000 Cygnus Solutions.
+
+ Written by Marco Fuykschot <marco@ddi.nl>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef _MT_SAFE
+#include <errno.h>
+#include "winsup.h"
+#include <assert.h>
+
+#include <stdlib.h>
+#include <syslog.h>
+
+extern int threadsafe;
+
+#define MT_INTERFACE user_data->threadinterface
+
+#define NOT_IMP(n) system_printf("not implemented %s\n",n); return 0;
+
+#define CHECKHANDLE(rval,release) \
+ if ( ! item->HandleOke() ) { \
+ if ( release ) item->used=false; \
+ return rval; };
+
+#define GETTHREAD(n) \
+ if ( ! thread ) system_printf("thread is NULL");\
+ SetResourceLock(LOCK_THREAD_LIST,READ_LOCK,n);\
+ ThreadItem *item=user_data->threadinterface->GetThread(thread); \
+ ReleaseResourceLock(LOCK_THREAD_LIST,READ_LOCK,n); \
+ if ( ! item ) return EINVAL; \
+ CHECKHANDLE(EINVAL,0);
+
+#define GETMUTEX(n) \
+ SetResourceLock(LOCK_MUTEX_LIST,READ_LOCK,n); \
+ MutexItem* item=user_data->threadinterface->GetMutex(mutex); \
+ ReleaseResourceLock(LOCK_MUTEX_LIST,READ_LOCK,n); \
+ if ( ! item ) return EINVAL; \
+ CHECKHANDLE(EINVAL,0);
+
+#define GETSEMA(n) \
+ SetResourceLock(LOCK_SEM_LIST,READ_LOCK,n); \
+ SemaphoreItem* item=user_data->threadinterface->GetSemaphore(sem); \
+ ReleaseResourceLock(LOCK_SEM_LIST,READ_LOCK,n); \
+ if ( ! item ) return EINVAL; \
+ CHECKHANDLE(EINVAL,0);
+
+#define CHECKITEM(rn,rm,fn) \
+ if ( ! item ) { \
+ ReleaseResourceLock(rn,rm,fn); \
+ return EINVAL; }; \
+
+struct _reent *
+_reent_clib ()
+{
+ int tmp = GetLastError ();
+ struct __reent_t *_r = (struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index);
+
+#ifdef _CYG_THREAD_FAILSAFE
+ if (_r == 0)
+ {
+ system_printf ("local thread storage not inited");
+ }
+#endif
+
+ SetLastError (tmp);
+ return _r->_clib;
+};
+
+struct _winsup_t *
+_reent_winsup ()
+{
+ int tmp = GetLastError ();
+ struct __reent_t *_r;
+ _r = (struct __reent_t *) TlsGetValue (MT_INTERFACE->reent_index);
+#ifdef _CYG_THREAD_FAILSAFE
+ if (_r == 0)
+ {
+ system_printf ("local thread storage not inited");
+ }
+#endif
+ SetLastError (tmp);
+ return _r->_winsup;
+};
+
+void
+SetResourceLock (int _res_id, int _mode, const char *_function)
+{
+#if 0
+ if (!threadsafe)
+ return;
+#endif
+ thread_printf ("Set resource lock %d mode %d for %s start", _res_id, _mode, _function);
+ EnterCriticalSection (user_data->resourcelocks->Lock (_res_id));
+
+#ifdef _CYG_THREAD_FAILSAFE
+ user_data->resourcelocks->owner = GetCurrentThreadId ();
+ user_data->resourcelocks->count++;
+#endif
+}
+
+void
+ReleaseResourceLock (int _res_id, int _mode, const char *_function)
+{
+#if 0
+ if (!threadsafe)
+ return;
+#endif
+ thread_printf ("Release resource lock %d mode %d for %s done", _res_id, _mode, _function);
+
+#ifdef _CYG_THREAD_FAILSAFE
+ AssertResourceOwner (_res_id, _mode);
+ user_data->resourcelocks->count--;
+ if (user_data->resourcelocks->count == 0)
+ user_data->resourcelocks->owner = 0;
+#endif
+
+ LeaveCriticalSection (user_data->resourcelocks->Lock (_res_id));
+};
+
+#ifdef _CYG_THREAD_FAILSAFE
+void
+AssertResourceOwner (int _res_id, int _mode)
+{
+
+ 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);
+ if (user_data && (user_data->resourcelocks->owner != GetCurrentThreadId ()))
+ {
+ system_printf ("assertion failed, not the resource owner");
+ };
+}
+
+#endif
+
+LPCRITICAL_SECTION
+ResourceLocks::Lock (int _resid)
+{
+ if (!inited)
+ {
+ system_printf ("lock called before initialization");
+ };
+
+ thread_printf ("Get Resource lock %d ==> %p for %p , real : %d , threadid %d ", _resid, &lock, user_data, (myself ? myself->pid : -1), GetCurrentThreadId ());
+ return &lock;
+};
+
+void
+ResourceLocks::Init ()
+{
+ thread_printf ("Init resource lock %p -> %p", this, &lock);
+
+ InitializeCriticalSection (&lock);
+ inited = true;
+
+#ifdef _CYG_THREAD_FAILSAFE
+ owner = 0;
+ count = 0;
+#endif
+
+ thread_printf ("Resource lock %p inited by %p , %d", &lock, user_data, (myself ? myself->pid : -1));
+};
+
+void
+ResourceLocks::Delete ()
+{
+ if (inited)
+ {
+ thread_printf ("Close Resource Locks %p ", &lock);
+ DeleteCriticalSection (&lock);
+ inited = false;
+ };
+};
+
+
+// Thread interface
+
+void
+MTinterface::ReleaseItem (MTitem * _item)
+{
+ _item->used = false;
+};
+
+MTitem *
+MTinterface::Find (void *_value, int (*comp) (void *, void *), register int &_index, MTList * _list)
+{
+ register MTitem *current = NULL;
+ for (; _index < _list->index; _index++)
+ {
+ current = _list->items[_index];
+ if (current->used && comp (current, _value))
+ break;
+ current = NULL;
+ };
+ return current;
+};
+
+int
+MTinterface::Find (MTitem & _item, MTList * _list)
+{
+ register MTitem *current;
+ register int _index = 0;
+ for (; _index < _list->index; _index++)
+ {
+ current = _list->items[_index];
+ if (current->used && current == &_item)
+ break;
+ };
+ return (_index == _list->index ? -1 : _index);
+};
+
+int
+MTinterface::FindNextUnused (MTList * _list)
+{
+ register int i = 0;
+ for (; i < _list->index && _list->items[i] != NULL && _list->items[i]->used && _list->items[i]->joinable != 'Y'; i++);
+ return i;
+};
+
+MTitem *
+MTinterface::GetItem (int _index, MTList * _list)
+{
+ return (_index < _list->index ? _list->items[_index] : NULL);
+};
+
+MTitem *
+MTinterface::SetItem (int _index, MTitem * _item, MTList * _list)
+{
+ if (_index == _list->index && _list->index < MT_MAX_ITEMS)
+ _list->index++;
+ return (_index < _list->index ? _list->items[_index] = _item : NULL);
+};
+
+int
+CmpPthreadObj (void *_i, void *_value)
+{
+ return ((MTitem *) _i)->Id () == *(int *) _value;
+};
+
+int
+CmpThreadId (void *_i, void *_id)
+{
+ return ((ThreadItem *) _i)->thread_id == *(DWORD *) _id;
+};
+
+void
+MTinterface::Init0 ()
+{
+ for (int i = 0; i < MT_MAX_ITEMS; i++)
+ {
+ threadlist.items[i] = NULL;
+ mutexlist.items[i] = NULL;
+ semalist.items[i] = NULL;
+ };
+
+ threadlist.index = 0;
+ mutexlist.index = 0;
+ semalist.index = 0;
+
+ reent_index = TlsAlloc ();
+
+ reents._clib = _impure_ptr;
+ reents._winsup = &winsup_reent;
+
+ winsup_reent._process_logmask = LOG_UPTO (LOG_DEBUG);
+ winsup_reent._grp_pos = 0;
+ winsup_reent._process_ident = 0;
+ winsup_reent._process_logopt = 0;
+ winsup_reent._process_facility = 0;
+
+ TlsSetValue (reent_index, &reents);
+ // the static reent_data will be used in the main thread
+
+};
+
+void
+MTinterface::Init1 ()
+{
+ // create entry for main thread
+
+ int i = FindNextUnused (&threadlist);
+ assert (i == 0);
+ ThreadItem *item = (ThreadItem *) GetItem (i, &threadlist);
+
+ item = (ThreadItem *) SetItem (i, &mainthread, &threadlist);
+ item->used = true;
+ item->win32_obj_id = myself->hProcess;
+ item->thread_id = GetCurrentThreadId ();
+ item->function = NULL;
+
+ item->sigs = NULL;
+ item->sigmask = NULL;
+ item->sigtodo = NULL;
+};
+
+void
+MTinterface::ClearReent ()
+{
+ struct _reent *r = _REENT;
+ memset (r, 0, sizeof (struct _reent));
+
+ r->_errno = 0;
+ r->_stdin = &r->__sf[0];
+ r->_stdout = &r->__sf[1];
+ r->_stderr = &r->__sf[2];
+
+};
+
+
+ThreadItem *
+MTinterface::CreateThread (pthread_t * t, TFD (func), void *arg, pthread_attr_t a)
+{
+ AssertResourceOwner (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK);
+
+ int i = FindNextUnused (&threadlist);
+
+ ThreadItem *item = (ThreadItem *) GetItem (i, &threadlist);
+ if (!item)
+ item = (ThreadItem *) SetItem (i, new ThreadItem (), &threadlist);
+ if (!item)
+ system_printf ("thread creation failed");
+
+ item->used = true;
+ item->function = func;
+ item->arg = arg;
+ item->attr = a;
+
+ item->win32_obj_id = ::CreateThread (&sec_none_nih, item->attr.stacksize,
+ (LPTHREAD_START_ROUTINE) thread_init_wrapper, item, 0, &item->thread_id);
+
+ CHECKHANDLE (NULL, 1);
+
+ *t = (pthread_t) item->win32_obj_id;
+
+ return item;
+};
+
+
+MutexItem *
+MTinterface::CreateMutex (pthread_mutex_t * mutex)
+{
+ AssertResourceOwner (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK);
+
+ int i = FindNextUnused (&mutexlist);
+
+ MutexItem *item = (MutexItem *) GetItem (i, &mutexlist);
+ if (!item)
+ item = (MutexItem *) SetItem (i, new MutexItem (), &mutexlist);
+ if (!item)
+ system_printf ("mutex creation failed");
+ item->used = true;
+
+ item->win32_obj_id = ::CreateMutex (&sec_none_nih, false, NULL);
+
+ CHECKHANDLE (NULL, 1);
+
+ *mutex = (pthread_mutex_t) item->win32_obj_id;
+
+ return item;
+}
+
+ThreadItem *
+MTinterface::GetCallingThread ()
+{
+ AssertResourceOwner (LOCK_THREAD_LIST, READ_LOCK);
+ DWORD id = GetCurrentThreadId ();
+ int index = 0;
+ return (ThreadItem *) Find (&id, &CmpThreadId, index, &threadlist);
+};
+
+ThreadItem *
+MTinterface::GetThread (pthread_t * _t)
+{
+ AssertResourceOwner (LOCK_THREAD_LIST, READ_LOCK);
+ int index = 0;
+ return (ThreadItem *) Find (_t, &CmpPthreadObj, index, &threadlist);
+};
+
+MutexItem *
+MTinterface::GetMutex (pthread_mutex_t * mp)
+{
+ AssertResourceOwner (LOCK_MUTEX_LIST, READ_LOCK);
+ int index = 0;
+ return (MutexItem *) Find (mp, &CmpPthreadObj, index, &mutexlist);
+}
+
+SemaphoreItem *
+MTinterface::GetSemaphore (sem_t * sp)
+{
+ AssertResourceOwner (LOCK_SEM_LIST, READ_LOCK);
+ int index = 0;
+ return (SemaphoreItem *) Find (sp, &CmpPthreadObj, index, &semalist);
+}
+
+
+void
+MTitem::Destroy ()
+{
+ CloseHandle (win32_obj_id);
+};
+
+int
+MutexItem::Lock ()
+{
+ return WaitForSingleObject (win32_obj_id, INFINITE);
+};
+
+int
+MutexItem::TryLock ()
+{
+ return WaitForSingleObject (win32_obj_id, 0);
+};
+
+int
+MutexItem::UnLock ()
+{
+ return ReleaseMutex (win32_obj_id);
+}
+
+SemaphoreItem *
+MTinterface::CreateSemaphore (sem_t * _s, int pshared, int _v)
+{
+ AssertResourceOwner (LOCK_SEM_LIST, WRITE_LOCK | READ_LOCK);
+
+ int i = FindNextUnused (&semalist);
+
+ SemaphoreItem *item = (SemaphoreItem *) GetItem (i, &semalist);
+ if (!item)
+ item = (SemaphoreItem *) SetItem (i, new SemaphoreItem (), &semalist);
+ if (!item)
+ system_printf ("semaphore creation failed");
+ item->used = true;
+ item->shared = pshared;
+
+ item->win32_obj_id = ::CreateSemaphore (&sec_none_nih, _v, _v, NULL);
+
+ CHECKHANDLE (NULL, 1);
+
+ *_s = (sem_t) item->win32_obj_id;
+
+ return item;
+};
+
+int
+SemaphoreItem::Wait ()
+{
+ return WaitForSingleObject (win32_obj_id, INFINITE);
+};
+
+int
+SemaphoreItem::Post ()
+{
+ long pc;
+ return ReleaseSemaphore (win32_obj_id, 1, &pc);
+};
+
+int
+SemaphoreItem::TryWait ()
+{
+ return WaitForSingleObject (win32_obj_id, 0);
+};
+
+
+////////////////////////// Pthreads
+
+void *
+thread_init_wrapper (void *_arg)
+{
+// Setup the local/global storage of this thread
+
+ ThreadItem *thread = (ThreadItem *) _arg;
+ struct __reent_t local_reent;
+ struct _winsup_t local_winsup;
+ struct _reent local_clib;
+
+ struct sigaction _sigs[NSIG];
+ sigset_t _sig_mask; /* one set for everything to ignore. */
+ LONG _sigtodo[NSIG + __SIGOFFSET];
+
+// setup signal structures
+ thread->sigs = _sigs;
+ thread->sigmask = &_sig_mask;
+ thread->sigtodo = _sigtodo;
+
+ memset (&local_clib, 0, sizeof (struct _reent));
+ memset (&local_winsup, 0, sizeof (struct _winsup_t));
+
+ local_clib._errno = 0;
+ local_clib._stdin = &local_clib.__sf[0];
+ local_clib._stdout = &local_clib.__sf[1];
+ local_clib._stderr = &local_clib.__sf[2];
+
+ local_reent._clib = &local_clib;
+ local_reent._winsup = &local_winsup;
+
+ local_winsup._process_logmask = LOG_UPTO (LOG_DEBUG);
+
+
+ if (!TlsSetValue (MT_INTERFACE->reent_index, &local_reent))
+ system_printf ("local storage for thread couldn't be set");
+
+#ifdef _CYG_THREAD_FAILSAFE
+ if (_REENT == _impure_ptr)
+ system_printf ("local storage for thread isn't setup correctly");
+#endif
+
+
+ thread_printf ("started thread %p %p %p %p %p %p", _arg, &local_clib, _impure_ptr, thread, thread->function, thread->arg);
+
+
+// call the user's thread
+ void *ret = thread->function (thread->arg);
+
+// FIX ME : cleanup code
+
+// thread->used = false; // release thread entry
+ thread->return_ptr = ret;
+ return ret;
+}
+
+int
+__pthread_create (pthread_t * thread, const pthread_attr_t * attr, TFD (start_routine), void *arg)
+{
+ SetResourceLock (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK, "__pthread_create");
+
+ pthread_attr_t a;
+ ThreadItem *item;
+
+ if (attr)
+ item = MT_INTERFACE->CreateThread (thread, start_routine, arg, *attr);
+ else
+ {
+ __pthread_attr_init (&a);
+ item = MT_INTERFACE->CreateThread (thread, start_routine, arg, a);
+ };
+
+
+
+ CHECKITEM (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK, "__pthread_create")
+
+ ReleaseResourceLock (LOCK_THREAD_LIST, WRITE_LOCK | READ_LOCK, "__pthread_create");
+ return 0;
+};
+
+int
+__pthread_attr_init (pthread_attr_t * attr)
+{
+ attr->stacksize = 0;
+ return 0;
+};
+
+int
+__pthread_attr_setstacksize (pthread_attr_t * attr, size_t size)
+{
+ attr->stacksize = size;
+ return 0;
+};
+
+int
+__pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size)
+{
+ *size = attr->stacksize;
+ return 0;
+};
+
+int
+__pthread_attr_destroy (pthread_attr_t * attr)
+{
+ return 0;
+};
+
+int
+__pthread_exit (void *value_ptr)
+{
+ ThreadItem *item = MT_INTERFACE->GetCallingThread();
+ item->return_ptr = value_ptr;
+ ExitThread(0);
+ return 0;
+}
+
+int
+__pthread_join(pthread_t * thread, void **return_val)
+{
+ ThreadItem *item=user_data->threadinterface->GetThread(thread);
+
+
+ if (!item)
+ return ESRCH;
+
+ if (item->joinable == 'N')
+ {
+ if (return_val)
+ *return_val = NULL;
+ return EINVAL;
+ }
+ else
+ {
+ item->joinable = 'N';
+ WaitForSingleObject((HANDLE)*thread, INFINITE);
+ if (return_val)
+ *return_val = item->return_ptr;
+ }/* End if*/
+
+ return 0;
+};
+
+int
+__pthread_detach(pthread_t * thread)
+{
+ ThreadItem *item=user_data->threadinterface->GetThread(thread);
+ if (!item)
+ return ESRCH;
+
+ if (item->joinable == 'N')
+ {
+ item->return_ptr = NULL;
+ return EINVAL;
+ }
+
+ item->joinable = 'N';
+ return 0;
+}
+
+int
+__pthread_suspend(pthread_t * thread)
+{
+ ThreadItem *item=user_data->threadinterface->GetThread(thread);
+ if (!item)
+ return ESRCH;
+
+ if (item->suspended == false)
+ {
+ item->suspended = true;
+ SuspendThread( (HANDLE)*thread);
+ }
+
+ return 0;
+}
+
+
+int
+__pthread_continue(pthread_t * thread)
+{
+ ThreadItem *item=user_data->threadinterface->GetThread(thread);
+ if (!item)
+ return ESRCH;
+
+ if (item->suspended == true)
+ ResumeThread( (HANDLE)*thread);
+ item->suspended = false;
+
+ return 0;
+}
+
+
+
+
+unsigned long
+__pthread_getsequence_np (pthread_t * thread)
+{
+ GETTHREAD ("__pthread_getsequence_np");
+ return item->GetThreadId ();
+};
+
+/* Thread SpecificData */
+int
+__pthread_key_create (pthread_key_t * key)
+{
+ NOT_IMP ("_p_key_create\n");
+};
+
+int
+__pthread_key_delete (pthread_key_t * key)
+{
+ NOT_IMP ("_p_key_delete\n");
+};
+int
+__pthread_setspecific (pthread_key_t * key, const void *value)
+{
+ NOT_IMP ("_p_key_setsp\n");
+};
+void *
+__pthread_getspecific (pthread_key_t * key)
+{
+ NOT_IMP ("_p_key_getsp\n");
+};
+
+/* Thread signal */
+int
+__pthread_kill (pthread_t * thread, int sig)
+{
+// lock myself, for the use of thread2signal
+ // two differ kills might clash: FIX ME
+ GETTHREAD ("__pthread_kill");
+
+ if (item->sigs)
+ myself->setthread2signal (item);
+
+ int rval = sig_send (myself, sig);
+
+// unlock myself
+ return rval;
+
+};
+
+int
+__pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set)
+{
+ SetResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_sigmask");
+ ThreadItem *item = MT_INTERFACE->GetCallingThread ();
+ ReleaseResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_sigmask");
+
+// lock this myself, for the use of thread2signal
+ // two differt kills might clash: FIX ME
+
+ if (item->sigs)
+ myself->setthread2signal (item);
+
+ int rval = sigprocmask (operation, set, old_set);
+
+// unlock this myself
+
+ return rval;
+};
+
+/* ID */
+pthread_t
+__pthread_self ()
+{
+ SetResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_self");
+
+ ThreadItem *item = MT_INTERFACE->GetCallingThread ();
+
+ ReleaseResourceLock (LOCK_THREAD_LIST, READ_LOCK, "__pthread_self");
+ return (pthread_t) item->Id ();
+
+};
+
+int
+__pthread_equal (pthread_t * t1, pthread_t * t2)
+{
+ return (*t1 - *t2);
+};
+
+/* Mutexes */
+
+int
+__pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * _attr)
+{
+ SetResourceLock (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init");
+
+ MutexItem *item = MT_INTERFACE->CreateMutex (mutex);
+
+ CHECKITEM (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init");
+
+ ReleaseResourceLock (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init");
+ return 0;
+};
+
+int
+__pthread_mutex_lock (pthread_mutex_t * mutex)
+{
+ GETMUTEX ("_ptherad_mutex_lock");
+
+ item->Lock ();
+
+ return 0;
+};
+
+int
+__pthread_mutex_trylock (pthread_mutex_t * mutex)
+{
+ GETMUTEX ("_ptherad_mutex_lock");
+
+ if (item->TryLock () == WAIT_TIMEOUT)
+ return EBUSY;
+
+ return 0;
+};
+
+int
+__pthread_mutex_unlock (pthread_mutex_t * mutex)
+{
+ GETMUTEX ("_ptherad_mutex_lock");
+
+ item->UnLock ();
+
+ return 0;
+};
+
+int
+__pthread_mutex_destroy (pthread_mutex_t * mutex)
+{
+ SetResourceLock (LOCK_MUTEX_LIST, READ_LOCK | WRITE_LOCK, "__pthread_mutex_destroy");
+
+ MutexItem *item = MT_INTERFACE->GetMutex (mutex);
+
+ CHECKITEM (LOCK_MUTEX_LIST, WRITE_LOCK | READ_LOCK, "__pthread_mutex_init");
+
+ item->Destroy ();
+
+ MT_INTERFACE->ReleaseItem (item);
+
+ ReleaseResourceLock (LOCK_MUTEX_LIST, READ_LOCK | WRITE_LOCK, "__pthread_mutex_destroy");
+ return 0;
+};
+
+/* Semaphores */
+int
+__sem_init (sem_t * sem, int pshared, unsigned int value)
+{
+ SetResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init");
+
+ SemaphoreItem *item = MT_INTERFACE->CreateSemaphore (sem, pshared, value);
+
+ CHECKITEM (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init");
+
+ ReleaseResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init");
+ return 0;
+};
+
+int
+__sem_destroy (sem_t * sem)
+{
+ SetResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_destroy");
+
+ SemaphoreItem *item = MT_INTERFACE->GetSemaphore (sem);
+
+ CHECKITEM (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_init");
+
+ item->Destroy ();
+
+ MT_INTERFACE->ReleaseItem (item);
+
+ ReleaseResourceLock (LOCK_SEM_LIST, READ_LOCK | WRITE_LOCK, "__sem_destroy");
+ return 0;
+};
+
+int
+__sem_wait (sem_t * sem)
+{
+ GETSEMA ("__sem_wait");
+
+ item->Wait ();
+
+ return 0;
+};
+
+int
+__sem_trywait (sem_t * sem)
+{
+ GETSEMA ("__sem_trywait");
+
+ if (item->TryWait () == WAIT_TIMEOUT)
+ return EAGAIN;
+
+ return 0;
+};
+
+int
+__sem_post (sem_t * sem)
+{
+ GETSEMA ("__sem_post");
+
+ item->Post ();
+
+ return 0;
+};
+
+
+#else
+
+// empty functions needed when makeing the dll without mt_safe support
+extern "C"
+{
+ int __pthread_create (pthread_t *, const pthread_attr_t *, TFD (start_routine), void *arg)
+ {
+ return -1;
+ };
+ int __pthread_attr_init (pthread_attr_t * attr)
+ {
+ return -1;
+ };
+ int __pthread_attr_destroy (pthread_attr_t * attr)
+ {
+ return -1;
+ };
+ int __pthread_attr_setstacksize (pthread_attr_t * attr, size_t size)
+ {
+ return -1;
+ };
+ int __pthread_attr_getstacksize (pthread_attr_t * attr, size_t * size)
+ {
+ return -1;
+ };
+/*
+ __pthread_attr_setstackaddr(...){ return -1; };
+ __pthread_attr_getstackaddr(...){ return -1; };
+ */
+ int __pthread_exit (void *value_ptr)
+ {
+ return -1;
+ };
+
+ int __pthread_join(pthread_t thread_id, void **return_val)
+ {
+ return -1;
+ }
+
+ unsigned long __pthread_getsequence_np (pthread_t * thread)
+ {
+ return 0;
+ };
+ int __pthread_key_create (pthread_key_t * key)
+ {
+ return -1;
+ };
+ int __pthread_key_delete (pthread_key_t * key)
+ {
+ return -1;
+ };
+ int __pthread_setspecific (pthread_key_t * key, const void *value)
+ {
+ return -1;
+ };
+ void *__pthread_getspecific (pthread_key_t * key)
+ {
+ return NULL;
+ };
+ int __pthread_kill (pthread_t * thread, int sig)
+ {
+ return -1;
+ };
+ int __pthread_sigmask (int operation, const sigset_t * set, sigset_t * old_set)
+ {
+ return -1;
+ };
+ pthread_t __pthread_self ()
+ {
+ return -1;
+ };
+ int __pthread_equal (pthread_t * t1, pthread_t * t2)
+ {
+ return -1;
+ };
+ int __pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *)
+ {
+ return -1;
+ };
+ int __pthread_mutex_lock (pthread_mutex_t *)
+ {
+ return -1;
+ };
+ int __pthread_mutex_trylock (pthread_mutex_t *)
+ {
+ return -1;
+ };
+ int __pthread_mutex_unlock (pthread_mutex_t *)
+ {
+ return -1;
+ };
+ int __pthread_mutex_destroy (pthread_mutex_t *)
+ {
+ return -1;
+ };
+ int __sem_init (sem_t * sem, int pshared, unsigned int value)
+ {
+ return -1;
+ };
+ int __sem_destroy (sem_t * sem)
+ {
+ return -1;
+ };
+ int __sem_wait (sem_t * sem)
+ {
+ return -1;
+ };
+ int __sem_trywait (sem_t * sem)
+ {
+ return -1;
+ };
+ int __sem_post (sem_t * sem)
+ {
+ return -1;
+ };
+ struct _reent *_reent_clib ()
+ {
+ return NULL;
+ };
+}
+
+#endif // MT_SAFE