diff options
Diffstat (limited to 'winsup/cygwin/thread.cc')
-rw-r--r-- | winsup/cygwin/thread.cc | 1001 |
1 files changed, 1001 insertions, 0 deletions
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc new file mode 100644 index 0000000..0ed42e7 --- /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 |