Sun Apr 22 20:22:00 2001 Robert Collins <rbtcollins@hotmail.com>

* passwd.cc (getpwuid): Check for thread cancellation.
	(getpwuid_r): Ditto.
	(getpwname): Ditto.
	(getpwnam_r): Ditto.
	* thread.h (pthread_mutex): New constructors for pshared operation.
	(MTinterface): Associative array for pshared mutex's.
	* thread.cc (MTinterface::Init): Initailize pshared mutex array.
	(pthread_cond::BroadCast): Implementation notes.
	(pthread_cond::TimedWait): Remove use of SignalObjectAndWait on non-NT systems.
	(pthread_mutex::pthread_mutex(unsigned short)): New function.
	(pthread_mutex::pthread_mutex (pthread_mutex_t *, pthread_mutexattr *)):New function.
	(pthread_mutex::pthread_mutex(pthread_mutexattr *)): Fail on pshared mutex's.
	(__pthread_mutex_getpshared): New function.
	(__pthread_join): Check for thread cancellation.
	(__pthread_cond_timedwait): Support pshared mutex's.
	(__pthread_cond_wait): Ditto.
	(__pthread_condattr_setpshared): Error on PROCESS_SHARED requests.
	(__pthread_mutex_init): Support pshared mutex's.
	(__pthread_mutex_getprioceiling): Ditto.
	(__pthread_mutex_lock): Ditto.
	(__pthread_mutex_trylock): Ditto.
	(__pthread_mutex_unlock): Ditto.
	(__pthread_mutex_destroy): Ditto.
	(__pthread_mutex_setprioceiling): Ditto.
	(__pthread_mutexattr_setpshared): Support PTHREAD_PROCESS_PSHARED requests.
This commit is contained in:
Robert Collins 2001-04-21 14:23:47 +00:00
parent 8c9df1d571
commit 9450ad0d02
4 changed files with 276 additions and 37 deletions

View File

@ -1,3 +1,31 @@
Sun Apr 22 00:22:00 2001 Robert Collins <rbtcollins@hotmail.com>
* passwd.cc (getpwuid): Check for thread cancellation.
(getpwuid_r): Ditto.
(getpwname): Ditto.
(getpwnam_r): Ditto.
* thread.h (pthread_mutex): New constructors for pshared operation.
(MTinterface): Associative array for pshared mutex's.
* thread.cc (MTinterface::Init): Initailize pshared mutex array.
(pthread_cond::BroadCast): Implementation notes.
(pthread_cond::TimedWait): Remove use of SignalObjectAndWait on non-NT systems.
(pthread_mutex::pthread_mutex(unsigned short)): New function.
(pthread_mutex::pthread_mutex (pthread_mutex_t *, pthread_mutexattr *)):New function.
(pthread_mutex::pthread_mutex(pthread_mutexattr *)): Fail on pshared mutex's.
(__pthread_mutex_getpshared): New function.
(__pthread_join): Check for thread cancellation.
(__pthread_cond_timedwait): Support pshared mutex's.
(__pthread_cond_wait): Ditto.
(__pthread_condattr_setpshared): Error on PROCESS_SHARED requests.
(__pthread_mutex_init): Support pshared mutex's.
(__pthread_mutex_getprioceiling): Ditto.
(__pthread_mutex_lock): Ditto.
(__pthread_mutex_trylock): Ditto.
(__pthread_mutex_unlock): Ditto.
(__pthread_mutex_destroy): Ditto.
(__pthread_mutex_setprioceiling): Ditto.
(__pthread_mutexattr_setpshared): Support PTHREAD_PROCESS_PSHARED requests.
Fri Apr 20 19:38:29 2001 Christopher Faylor <cgf@cygnus.com>
* cygwin.din: Add *scanf and *scan_r functions.

View File

@ -205,6 +205,8 @@ getpwuid (uid_t uid)
{
if (passwd_state <= initializing)
read_etc_passwd ();
pthread_testcancel();
return search_for (uid, 0);
}
@ -220,6 +222,8 @@ getpwuid_r (uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct
if (passwd_state <= initializing)
read_etc_passwd ();
pthread_testcancel();
struct passwd *temppw = search_for (uid, 0);
if (!temppw)
@ -248,6 +252,8 @@ getpwnam (const char *name)
{
if (passwd_state <= initializing)
read_etc_passwd ();
pthread_testcancel();
return search_for (0, name);
}
@ -268,6 +274,8 @@ getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, s
if (passwd_state <= initializing)
read_etc_passwd ();
pthread_testcancel();
struct passwd *temppw = search_for (0, nam);
if (!temppw)

View File

@ -43,6 +43,7 @@ details. */
#include "perprocess.h"
#include "security.h"
#include <semaphore.h>
#include <stdio.h>
extern int threadsafe;
@ -296,11 +297,17 @@ MTinterface::Init (int forked)
if (forked)
return;
/* shm areas a inherited when forking */
shm_head = NULL;
/* possible the atfork lists should be inited here as well */
mainthread.win32_obj_id = myself->hProcess;
mainthread.setThreadIdtoCurrent ();
/* store the main thread's self pointer */
TlsSetValue (thread_self_dwTlsIndex, &mainthread);
for (int i =0;i<256;i++)pshared_mutexs[i]=NULL;
#if 0
item->function = NULL;
@ -401,6 +408,8 @@ pthread_cond::~pthread_cond ()
void
pthread_cond::BroadCast ()
{
// This potentially has an unfairness bug. We should
// consider preventing the wakeups from resuming until we finish signalling.
if (!verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC))
return;
PulseEvent (win32_obj_id);
@ -420,8 +429,16 @@ pthread_cond::Signal ()
int
pthread_cond::TimedWait (DWORD dwMilliseconds)
{
DWORD rv =
SignalObjectAndWait (mutex->win32_obj_id, win32_obj_id, dwMilliseconds,
DWORD rv;
if (os_being_run != winNT)
{
// FIXME: race condition (potentially drop events
// Possible solution (single process only) - place this in a critical section.
ReleaseMutex(mutex->win32_obj_id);
rv = WaitForSingleObject(win32_obj_id, dwMilliseconds);
}
else
rv = SignalObjectAndWait (mutex->win32_obj_id, win32_obj_id, dwMilliseconds,
false);
switch (rv)
{
@ -450,11 +467,6 @@ pthread_key::pthread_key (void (*destructor) (void *)):verifyable_object (PTHREA
pthread_key::~pthread_key ()
{
/* FIXME: New feature completeness.
* bracketed code is to called when the thread exists, not when delete is called
* if (destructor && TlsGetValue(dwTlsIndex))
* destructor (TlsGetValue(dwTlsIndex));
*/
if (pthread_key_destructor * dest = MT_INTERFACE->destructors.Remove (this))
delete dest;
TlsFree (dwTlsIndex);
@ -475,18 +487,126 @@ pthread_key::get ()
return TlsGetValue (dwTlsIndex);
}
#define SYS_BASE (unsigned char) 0xC0
// Note: the order is important. This is an overloaded pthread_mutex_t from
// userland
typedef struct _pshared_mutex {
unsigned char id;
unsigned char reserved;
unsigned char reserved2;
unsigned char flags;
} pshared_mutex;
/* pshared mutexs:
* the mutex_t (size 4) is not used as a verifyable object because we cannot
* guarantee the same address space for all processes.
* we use the following:
* high bit set (never a valid address).
* second byte is reserved for the priority.
* third byte is reserved
* fourth byte is the mutex id. (max 255 cygwin mutexs system wide).
* creating mutex's does get slower and slower, but as creation is a one time
* job, it should never become an issue
*
* And if you're looking at this and thinking, why not an array in cygwin for all mutexs,
* - you incur a penalty on _every_ mutex call and you have toserialise them all.
* ... Bad karma.
*
* option 2? put everything in userspace and update the ABI?
* - bad karma as well - the HANDLE, while identical across process's,
* Isn't duplicated, it's reopened.
*/
pthread_mutex::pthread_mutex (unsigned short id):verifyable_object (PTHREAD_MUTEX_MAGIC)
{
//FIXME: set an appropriate security mask - probably everyone.
if (MT_INTERFACE->pshared_mutexs[id])
return;
char stringbuf[29];
snprintf(stringbuf, 29, "CYGWINMUTEX0x%0x", id & 0x000f);
system_printf("name of mutex to transparently open %s\n",stringbuf);
this->win32_obj_id =::CreateMutex (&sec_none_nih, false, stringbuf);
if (win32_obj_id==0 || (win32_obj_id && GetLastError() != ERROR_ALREADY_EXISTS))
{
// the mutex has been deleted or we couldn't get access.
// the error_already_exists test is because we are only opening an
// existint mutex here
system_printf("couldn't get pshared mutex %x, %d\n",win32_obj_id, GetLastError());
CloseHandle(win32_obj_id);
magic=0;
win32_obj_id=NULL;
return;
}
pshared = PTHREAD_PROCESS_SHARED;
MT_INTERFACE->pshared_mutexs[id]=this;
}
pthread_mutex::pthread_mutex (pthread_mutex_t *mutex, pthread_mutexattr * attr):verifyable_object (PTHREAD_MUTEX_MAGIC)
{
/* attr checked in the C call */
if (attr && attr->pshared==PTHREAD_PROCESS_SHARED)
{
//FIXME: set an appropriate security mask - probably everyone.
// This does open a D.O.S. - the name is guessable (if you are willing to run
// thru all possible address values :]
char stringbuf[29];
unsigned short id=1;
while (id < 256)
{
snprintf(stringbuf, 29, "CYGWINMUTEX0x%0x", id & 0x000f);
system_printf("name of mutex to create %s\n",stringbuf);
this->win32_obj_id =::CreateMutex (&sec_none_nih, false, stringbuf);
if (this->win32_obj_id && GetLastError() != ERROR_ALREADY_EXISTS)
{
MT_INTERFACE->pshared_mutexs[id]=this;
pshared_mutex *pmutex=(pshared_mutex *)(mutex);
pmutex->id=id;
pmutex->flags=SYS_BASE;
pshared=PTHREAD_PROCESS_SHARED;
condwaits = 0;
return;
}
id++;
CloseHandle(win32_obj_id);
}
magic=0;
win32_obj_id=NULL;
}
else
{
this->win32_obj_id =::CreateMutex (&sec_none_nih, false, NULL);
if (!win32_obj_id)
magic = 0;
condwaits = 0;
pshared = PTHREAD_PROCESS_PRIVATE;
}
}
pthread_mutex::pthread_mutex (pthread_mutexattr * attr):verifyable_object (PTHREAD_MUTEX_MAGIC)
{
/* attr checked in the C call */
if (attr && attr->pshared==PTHREAD_PROCESS_SHARED)
{
/* for pshared mutex's we need the mutex address */
magic = 0;
return;
}
this->win32_obj_id =::CreateMutex (&sec_none_nih, false, NULL);
if (!this->win32_obj_id)
if (!win32_obj_id)
magic = 0;
condwaits = 0;
pshared = PTHREAD_PROCESS_PRIVATE;
}
pthread_mutex::~pthread_mutex ()
{
if (win32_obj_id)
CloseHandle (win32_obj_id);
win32_obj_id=NULL;
}
int
@ -507,6 +627,26 @@ pthread_mutex::UnLock ()
return ReleaseMutex (win32_obj_id);
}
pthread_mutex **
__pthread_mutex_getpshared(pthread_mutex_t *mutex)
{
if ((((pshared_mutex *)(mutex))->flags & SYS_BASE) != SYS_BASE )
return (pthread_mutex **)mutex;
pshared_mutex *pmutex=(pshared_mutex *)(mutex);
if ((MT_INTERFACE->pshared_mutexs[pmutex->id]) != NULL )
return &(MT_INTERFACE->pshared_mutexs[pmutex->id]);
/* attempt to get the existing mutex */
pthread_mutex * newmutex;
newmutex = new pthread_mutex (pmutex->id);
if (!verifyable_object_isvalid (newmutex, PTHREAD_MUTEX_MAGIC))
{
delete (newmutex);
MT_INTERFACE->pshared_mutexs[pmutex->id]=NULL;
return &(MT_INTERFACE->pshared_mutexs[0]);
}
return &(MT_INTERFACE->pshared_mutexs[pmutex->id]);
}
pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC),
pshared (PTHREAD_PROCESS_PRIVATE), mutextype (PTHREAD_MUTEX_DEFAULT)
{
@ -730,10 +870,10 @@ __pthread_cancel (pthread_t thread)
we return ESRCH until all the required functions call testcancel();
this will give applications predictable behaviour.
the required function list is:
the required function list is: * indicates done, X indicates not present in cygwin.
aio_suspend()
close()
creat()
*close()
*creat()
fcntl()
fsync()
getmsg()
@ -751,7 +891,7 @@ poll()
pread()
pthread_cond_timedwait()
pthread_cond_wait()
pthread_join()
*pthread_join()
pthread_testcancel()
putmsg()
putpmsg()
@ -765,10 +905,10 @@ sigsuspend()
sigtimedwait()
sigwait()
sigwaitinfo()
sleep()
*sleep()
system()
tcdrain()
usleep()
*usleep()
wait()
wait3()
waitid()
@ -834,10 +974,10 @@ getgrnam_r()
getlogin()
getlogin_r()
getpwent()
getpwnam()
getpwnam_r()
getpwuid()
getpwuid_r()
* getpwnam()
* getpwnam_r()
* getpwuid()
* getpwuid_r()
gets()
getutxent()
getutxid()
@ -1227,6 +1367,7 @@ __pthread_exit (void *value_ptr)
int
__pthread_join (pthread_t * thread, void **return_val)
{
/* FIXME: wait on the thread cancellation event as well - we are a cancellation point*/
if (!verifyable_object_isvalid (*thread, PTHREAD_MAGIC))
return ESRCH;
@ -1242,7 +1383,9 @@ __pthread_join (pthread_t * thread, void **return_val)
WaitForSingleObject ((*thread)->win32_obj_id, INFINITE);
if (return_val)
*return_val = (*thread)->return_ptr;
} /* End if */
} /* End if */
pthread_testcancel();
return 0;
}
@ -1466,6 +1609,8 @@ __pthread_cond_signal (pthread_cond_t * cond)
return 0;
}
// FIXME: pshared mutexs have the cond count in the shared memory area.
// We need to accomodate that.
int
__pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex,
const struct timespec *abstime)
@ -1473,25 +1618,30 @@ __pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex,
int rv;
if (!abstime)
return EINVAL;
pthread_mutex **themutex=NULL;
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
__pthread_mutex_init (mutex, NULL);
if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
if (( ((pshared_mutex *)(mutex))->flags & SYS_BASE == SYS_BASE ))
// a pshared mutex
themutex = __pthread_mutex_getpshared(mutex);
if (!verifyable_object_isvalid (*themutex, PTHREAD_MUTEX_MAGIC))
return EINVAL;
if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC))
return EINVAL;
if ((*cond)->waiting)
if ((*cond)->mutex && ((*cond)->mutex != (*mutex)))
if ((*cond)->mutex && ((*cond)->mutex != (*themutex)))
return EINVAL;
InterlockedIncrement (&((*cond)->waiting));
(*cond)->mutex = (*mutex);
InterlockedIncrement (&((*mutex)->condwaits));
(*cond)->mutex = (*themutex);
InterlockedIncrement (&((*themutex)->condwaits));
rv = (*cond)->TimedWait (abstime->tv_sec * 1000);
(*cond)->mutex->Lock ();
if (InterlockedDecrement (&((*cond)->waiting)) == 0)
(*cond)->mutex = NULL;
InterlockedDecrement (&((*mutex)->condwaits));
InterlockedDecrement (&((*themutex)->condwaits));
return rv;
}
@ -1500,25 +1650,29 @@ int
__pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
{
int rv;
pthread_mutex_t *themutex=mutex;
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
__pthread_mutex_init (mutex, NULL);
if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
if (( ((pshared_mutex *)(mutex))->flags & SYS_BASE == SYS_BASE ))
// a pshared mutex
themutex = __pthread_mutex_getpshared(mutex);
if (!verifyable_object_isvalid (*themutex, PTHREAD_MUTEX_MAGIC))
return EINVAL;
if (!verifyable_object_isvalid (*cond, PTHREAD_COND_MAGIC))
return EINVAL;
if ((*cond)->waiting)
if ((*cond)->mutex && ((*cond)->mutex != (*mutex)))
if ((*cond)->mutex && ((*cond)->mutex != (*themutex)))
return EINVAL;
InterlockedIncrement (&((*cond)->waiting));
(*cond)->mutex = (*mutex);
InterlockedIncrement (&((*mutex)->condwaits));
(*cond)->mutex = (*themutex);
InterlockedIncrement (&((*themutex)->condwaits));
rv = (*cond)->TimedWait (INFINITE);
(*cond)->mutex->Lock ();
if (InterlockedDecrement (&((*cond)->waiting)) == 0)
(*cond)->mutex = NULL;
InterlockedDecrement (&((*mutex)->condwaits));
InterlockedDecrement (&((*themutex)->condwaits));
return rv;
}
@ -1552,6 +1706,9 @@ __pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared)
return EINVAL;
if ((pshared < 0) || (pshared > 1))
return EINVAL;
/* shared cond vars not currently supported */
if (pshared != PTHREAD_PROCESS_PRIVATE)
return EINVAL;
(*attr)->shared = pshared;
return 0;
}
@ -1631,12 +1788,28 @@ int
__pthread_mutex_init (pthread_mutex_t * mutex,
const pthread_mutexattr_t * attr)
{
if (( ((pshared_mutex *)(mutex))->flags & SYS_BASE == SYS_BASE ))
// a pshared mutex
return EBUSY;
if (attr && !verifyable_object_isvalid (*attr, PTHREAD_MUTEXATTR_MAGIC))
return EINVAL;
if (verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
return EBUSY;
if (attr && (*attr)->pshared == PTHREAD_PROCESS_SHARED)
{
pthread_mutex_t throwaway = new pthread_mutex (mutex, (*attr));
mutex = __pthread_mutex_getpshared((pthread_mutex_t *)mutex);
if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
{
delete throwaway;
*mutex = NULL;
return EAGAIN;
}
return 0;
}
*mutex = new pthread_mutex (attr ? (*attr) : NULL);
if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
{
@ -1651,9 +1824,13 @@ int
__pthread_mutex_getprioceiling (const pthread_mutex_t * mutex,
int *prioceiling)
{
pthread_mutex_t *themutex=(pthread_mutex_t *)mutex;
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
__pthread_mutex_init ((pthread_mutex_t *) mutex, NULL);
if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
if (( ((pshared_mutex *)(mutex))->flags & SYS_BASE == SYS_BASE ))
// a pshared mutex
themutex = __pthread_mutex_getpshared((pthread_mutex_t *)mutex);
if (!verifyable_object_isvalid (*themutex, PTHREAD_MUTEX_MAGIC))
return EINVAL;
/* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
* mutex priorities.
@ -1669,22 +1846,30 @@ __pthread_mutex_getprioceiling (const pthread_mutex_t * mutex,
int
__pthread_mutex_lock (pthread_mutex_t * mutex)
{
pthread_mutex_t *themutex=mutex;
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
__pthread_mutex_init (mutex, NULL);
if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
if (( ((pshared_mutex *)(mutex))->flags & SYS_BASE) == SYS_BASE )
// a pshared mutex
themutex = __pthread_mutex_getpshared(mutex);
if (!verifyable_object_isvalid (*themutex, PTHREAD_MUTEX_MAGIC))
return EINVAL;
(*mutex)->Lock ();
(*themutex)->Lock ();
return 0;
}
int
__pthread_mutex_trylock (pthread_mutex_t * mutex)
{
pthread_mutex_t *themutex=mutex;
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
__pthread_mutex_init (mutex, NULL);
if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
if (( ((pshared_mutex *)(mutex))->flags & SYS_BASE) == SYS_BASE )
// a pshared mutex
themutex = __pthread_mutex_getpshared(mutex);
if (!verifyable_object_isvalid (*themutex, PTHREAD_MUTEX_MAGIC))
return EINVAL;
if ((*mutex)->TryLock () == WAIT_TIMEOUT)
if ((*themutex)->TryLock () == WAIT_TIMEOUT)
return EBUSY;
return 0;
}
@ -1694,6 +1879,9 @@ __pthread_mutex_unlock (pthread_mutex_t * mutex)
{
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
__pthread_mutex_init (mutex, NULL);
if (( ((pshared_mutex *)(mutex))->flags & SYS_BASE) == SYS_BASE )
// a pshared mutex
mutex = __pthread_mutex_getpshared(mutex);
if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
return EINVAL;
(*mutex)->UnLock ();
@ -1705,6 +1893,9 @@ __pthread_mutex_destroy (pthread_mutex_t * mutex)
{
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
return 0;
if (( ((pshared_mutex *)(mutex))->flags & SYS_BASE) == SYS_BASE )
// a pshared mutex
mutex = __pthread_mutex_getpshared(mutex);
if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
return EINVAL;
@ -1721,9 +1912,13 @@ int
__pthread_mutex_setprioceiling (pthread_mutex_t * mutex, int prioceiling,
int *old_ceiling)
{
pthread_mutex_t *themutex=mutex;
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
__pthread_mutex_init (mutex, NULL);
if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
if (( ((pshared_mutex *)(mutex))->flags & SYS_BASE == SYS_BASE ))
// a pshared mutex
themutex = __pthread_mutex_getpshared(mutex);
if (!verifyable_object_isvalid (*themutex, PTHREAD_MUTEX_MAGIC))
return EINVAL;
return ENOSYS;
}
@ -1830,7 +2025,7 @@ __pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, int pshared)
/* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
* functionality
*/
if (pshared != PTHREAD_PROCESS_PRIVATE)
if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
return EINVAL;
(*attr)->pshared = pshared;
return 0;

View File

@ -263,12 +263,15 @@ class pthread_mutex:public verifyable_object
public:
HANDLE win32_obj_id;
LONG condwaits;
int pshared;
int Lock ();
int TryLock ();
int UnLock ();
pthread_mutex (unsigned short);
pthread_mutex (pthread_mutexattr *);
pthread_mutex (pthread_mutex_t *, pthread_mutexattr *);
~pthread_mutex ();
};
@ -345,6 +348,11 @@ public:
callback *pthread_child;
callback *pthread_parent;
/* this is an associative array for the _exclusive_ use of pshared mutex's
* normal mutex's don't go here to reduce overhead and prevent serialisation.
*/
class pthread_mutex * pshared_mutexs[256];
void Init (int);
MTinterface ():reent_index (0), indexallocated (0), threadcount (1)