/* 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;
  ExitThread (0);
}

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 = _kill (myself->pid, 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