void
pthread::setTlsSelfPointer (pthread *thisThread)
{
- /*the OS doesn't check this for <= 64 Tls entries (pre win2k) */
+ /* the OS doesn't check this for <= 64 Tls entries (pre win2k) */
TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thisThread);
}
{
pthread_mutex *verifyable_mutex_obj = &mutex;
- /*already running ? */
+ /* already running ? */
if (win32_obj_id)
return;
cancel_event = ::CreateEvent (NULL,TRUE,FALSE,NULL);
if (!cancel_event)
{
- system_printf ("couldn't create cancel event, this %p LastError %d", this, GetLastError () );
- /*we need the event for correct behaviour */
+ system_printf ("couldn't create cancel event, this %p LastError %E", this);
+ /* we need the event for correct behaviour */
magic = 0;
return;
}
pthread::postcreate ()
{
InterlockedIncrement (&MT_INTERFACE->threadcount);
- /*FIXME: set the priority appropriately for system contention scope */
+ /* FIXME: set the priority appropriately for system contention scope */
if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED)
{
- /*FIXME: set the scheduling settings for the new thread */
- /*sched_thread_setparam (win32_obj_id, attr.schedparam); */
+ /* FIXME: set the scheduling settings for the new thread */
+ /* sched_thread_setparam (win32_obj_id, attr.schedparam); */
}
}
mutex.Lock ();
// cleanup if thread is in detached state and not joined
- if (__pthread_equal (&joiner, &thread ) )
+ if (__pthread_equal (&joiner, &thread))
delete this;
else
{
if (cancelstate == PTHREAD_CANCEL_DISABLE)
return;
- if (WAIT_OBJECT_0 == WaitForSingleObject (cancel_event, 0 ) )
+ if (WAIT_OBJECT_0 == WaitForSingleObject (cancel_event, 0))
cancel_self ();
}
// TODO: do it?
api_fatal ("Attempt to push a cleanup handler across threads");
handler->next = cleanup_stack;
- InterlockedExchangePointer (&cleanup_stack, handler );
+ InterlockedExchangePointer (&cleanup_stack, handler);
}
void
this->mutex = NULL;
this->waiting = 0;
- this->win32_obj_id = ::CreateEvent (&sec_none_nih, false, /*auto signal reset - which I think is pthreads like ? */
- false, /*start non signaled */
- NULL /*no name */);
- /*TODO: make a shared mem mutex if out attributes request shared mem cond */
+ this->win32_obj_id = ::CreateEvent (&sec_none_nih, false, /* auto signal reset - which I think is pthreads like ? */
+ false, /* start non signaled */
+ NULL /* no name */);
+ /* TODO: make a shared mem mutex if out attributes request shared mem cond */
cond_access = NULL;
if ((temperr = pthread_mutex_init (&this->cond_access, NULL)))
{
system_printf ("couldn't init mutex, this %p errno %d", this, temperr);
- /*we need the mutex for correct behaviour */
+ /* we need the mutex for correct behaviour */
magic = 0;
}
{
if (pthread_mutex_unlock (&cond_access))
system_printf ("Failed to unlock condition variable access mutex, this %p", this);
- /*This isn't and API error - users are allowed to call this when no threads
+ /* This isn't and API error - users are allowed to call this when no threads
are waiting
system_printf ("Broadcast called with invalid mutex");
*/
switch (rv)
{
case WAIT_FAILED:
- return 0; /*POSIX doesn't allow errors after we modify the mutex state */
+ return 0; /* POSIX doesn't allow errors after we modify the mutex state */
case WAIT_ABANDONED:
case WAIT_TIMEOUT:
return ETIMEDOUT;
case WAIT_OBJECT_0:
- return 0; /*we have been signaled */
+ return 0; /* we have been signaled */
default:
return 0;
}
int
pthread_key::set (const void *value)
{
- /*the OS function doesn't perform error checking */
+ /* the OS function doesn't perform error checking */
TlsSetValue (dwTlsIndex, (void *) value);
return 0;
}
void
pthread_key::run_destructor ()
{
- if (destructor)
+ if (destructor)
{
- void *oldValue = get();
+ void *oldValue = get ();
if (oldValue)
{
set (NULL);
}
}
-/*pshared mutexs:
-
- * REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
- gymnastics can be a lot easier.
-
- *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.
- */
+/* pshared mutexs:
+
+ REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
+ gymnastics can be a lot easier.
+
+ 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. */
/* static members */
bool
HANDLE pthread_mutex::mutexInitializationLock;
/* We can only be called once.
- * TODO: (no rush) use a non copied memory section to
- * hold an initialization flag.
- */
+ TODO: (no rush) use a non copied memory section to
+ hold an initialization flag. */
void
pthread_mutex::initMutex ()
{
mutexInitializationLock = CreateMutex (NULL, FALSE, NULL);
if (!mutexInitializationLock)
- api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support. The error code was %d\n", GetLastError());
-
+ api_fatal ("Could not create win32 Mutex for pthread mutex static initializer support. The error code was %E");
+
}
pthread_mutex::pthread_mutex (pthread_mutexattr *attr):verifyable_object (PTHREAD_MUTEX_MAGIC)
{
- /*attr checked in the C call */
+ /* attr checked in the C call */
if (attr && attr->pshared == PTHREAD_PROCESS_SHARED)
{
// fail
int
semaphore::TryWait ()
{
- /*FIXME: signals should be able to interrupt semaphores...
+ /* FIXME: signals should be able to interrupt semaphores...
*We probably need WaitForMultipleObjects here.
*/
if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)
magic = 0;
}
-/*Generic memory acccess routine - where should it live ? */
+/* Generic memory acccess routine - where should it live ? */
int __stdcall
check_valid_pointer (void const *pointer)
{
struct _reent local_clib = _REENT_INIT (local_clib);
struct sigaction _sigs[NSIG];
- sigset_t _sig_mask; /*one set for everything to ignore. */
+ sigset_t _sig_mask; /* one set for everything to ignore. */
LONG _sigtodo[NSIG + __SIGOFFSET];
// setup signal structures
local_winsup._process_logmask = LOG_UPTO (LOG_DEBUG);
- /*This is not checked by the OS !! */
+ /* This is not checked by the OS !! */
if (!TlsSetValue (MT_INTERFACE->reent_index, &local_reent))
system_printf ("local storage for thread couldn't be set");
// ??? This code only runs if the thread exits by returning.
// it's all now in __pthread_exit ();
#endif
- /*never reached */
+ /* never reached */
return 0;
}
return 0;
pthread_mutex_lock (&once_control->mutex);
- /*Here we must set a cancellation handler to unlock the mutex if needed */
- /*but a cancellation handler is not the right thing. We need this in the thread
+ /* Here we must set a cancellation handler to unlock the mutex if needed */
+ /* but a cancellation handler is not the right thing. We need this in the thread
*cleanup routine. Assumption: a thread can only be in one pthread_once routine
*at a time. Stote a mutex_t *in the pthread_structure. if that's non null unlock
*on pthread_exit ();
init_routine ();
once_control->state = 1;
}
- /*Here we must remove our cancellation handler */
+ /* Here we must remove our cancellation handler */
pthread_mutex_unlock (&once_control->mutex);
return 0;
}
return thread->cancel ();
}
-/*
- *Races in pthread_atfork:
- *We are race safe in that any additions to the lists are made via
- *InterlockedExchangePointer.
- *However, if the user application doesn't perform syncronisation of some sort
- *It's not guaranteed that a near simultaneous call to pthread_atfork and fork
- *will result in the new atfork handlers being calls.
- *More rigorous internal syncronisation isn't needed as the user program isn't
- *guaranteeing their own state.
- *
- *as far as multiple calls to pthread_atfork, the worst case is simultaneous calls
- *will result in an indeterminate order for parent and child calls (what gets inserted
- *first isn't guaranteed.)
- *
- *There is one potential race... Does the result of InterlockedExchangePointer
- *get committed to the return location _before_ any context switches can occur?
- *If yes, we're safe, if no, we're not.
- */
+/* Races in pthread_atfork:
+ We are race safe in that any additions to the lists are made via
+ InterlockedExchangePointer.
+ However, if the user application doesn't perform syncronisation of some sort
+ It's not guaranteed that a near simultaneous call to pthread_atfork and fork
+ will result in the new atfork handlers being calls.
+ More rigorous internal syncronisation isn't needed as the user program isn't
+ guaranteeing their own state.
+
+ as far as multiple calls to pthread_atfork, the worst case is simultaneous calls
+ will result in an indeterminate order for parent and child calls (what gets inserted
+ first isn't guaranteed.)
+
+ There is one potential race... Does the result of InterlockedExchangePointer
+ get committed to the return location _before_ any context switches can occur?
+ If yes, we're safe, if no, we're not. */
void
pthread::atforkprepare (void)
{
}
}
-/*Register a set of functions to run before and after fork.
- *prepare calls are called in LI-FC order.
- *parent and child calls are called in FI-FC order.
- */
+/* Register a set of functions to run before and after fork.
+ prepare calls are called in LI-FC order.
+ parent and child calls are called in FI-FC order. */
int
pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void))
{
callback **t = &MT_INTERFACE->pthread_parent;
while (*t)
t = &(*t)->next;
- /*t = pointer to last next in the list */
+ /* t = pointer to last next in the list */
parentcb->next = (callback *) InterlockedExchangePointer ((LONG *) t, (long int) parentcb);
}
if (childcb)
callback **t = &MT_INTERFACE->pthread_child;
while (*t)
t = &(*t)->next;
- /*t = pointer to last next in the list */
+ /* t = pointer to last next in the list */
childcb->next = (callback *) InterlockedExchangePointer ((LONG *) t, (long int) childcb);
}
return 0;
return 0;
}
-/*From a pure code point of view, this should call a helper in sched.cc,
- *to allow for someone adding scheduler policy changes to win32 in the future.
- *However that's extremely unlikely, so short and sweet will do us
- */
+/* From a pure code point of view, this should call a helper in sched.cc,
+ to allow for someone adding scheduler policy changes to win32 in the future.
+ However that's extremely unlikely, so short and sweet will do us */
int
__pthread_attr_getschedpolicy (const pthread_attr_t *attr, int *policy)
{
return 0;
}
-/*See __pthread_attr_getschedpolicy for some notes */
+/* See __pthread_attr_getschedpolicy for some notes */
int
__pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy)
{
if (contentionscope != PTHREAD_SCOPE_SYSTEM
&& contentionscope != PTHREAD_SCOPE_PROCESS)
return EINVAL;
- /*In future, we may be able to support system scope by escalating the thread
- *priority to exceed the priority class. For now we only support PROCESS scope. */
+ /* In future, we may be able to support system scope by escalating the thread
+ priority to exceed the priority class. For now we only support PROCESS scope. */
if (contentionscope != PTHREAD_SCOPE_PROCESS)
return ENOTSUP;
(*attr)->contentionscope = contentionscope;
if (return_val)
*return_val = NULL;
- /*FIXME: wait on the thread cancellation event as well - we are a cancellation point*/
+ /* FIXME: wait on the thread cancellation event as well - we are a cancellation point*/
if (!isGoodObject (thread))
return ESRCH;
*return_val = (*thread)->return_ptr;
// cleanup
delete (*thread);
- } /*End if */
+ } /* End if */
pthread_testcancel ();
}
// check if thread is still alive
- if (WAIT_TIMEOUT == WaitForSingleObject ((*thread)->win32_obj_id, 0) )
+ if (WAIT_TIMEOUT == WaitForSingleObject ((*thread)->win32_obj_id, 0))
{
// force cleanup on exit
(*thread)->joiner = *thread;
return 0;
}
-/*provided for source level compatability.
- *See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
- */
+/* provided for source level compatability.
+ See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
+*/
int
__pthread_getconcurrency (void)
{
return MT_INTERFACE->concurrency;
}
-/*keep this in sync with sched.cc */
+/* keep this in sync with sched.cc */
int
__pthread_getschedparam (pthread_t thread, int *policy,
struct sched_param *param)
if (!pthread::isGoodObject (&thread))
return ESRCH;
*policy = SCHED_FIFO;
- /*we don't return the current effective priority, we return the current requested
- *priority */
+ /* we don't return the current effective priority, we return the current
+ requested priority */
*param = thread->attr.schedparam;
return 0;
}
-/*Thread SpecificData */
+/* Thread SpecificData */
int
__pthread_key_create (pthread_key_t *key, void (*destructor) (void *))
{
- /*The opengroup docs don't define if we should check this or not,
- *but creation is relatively rare..
- */
+ /* The opengroup docs don't define if we should check this or not,
+ but creation is relatively rare. */
if (pthread_key::isGoodObject (key))
return EBUSY;
return 0;
}
-/*provided for source level compatability.
- *See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
- */
+/* provided for source level compatability. See
+http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
+*/
int
__pthread_setconcurrency (int new_level)
{
return 0;
}
-/*keep syncronised with sched.cc */
+/* keep syncronised with sched.cc */
int
__pthread_setschedparam (pthread_t thread, int policy,
const struct sched_param *param)
}
-/*Thread synchronisation */
+/* Thread synchronisation */
bool
pthread_cond::isGoodObject (pthread_cond_t const *cond)
{
if (!pthread_cond::isGoodObject (cond))
return EINVAL;
- /*reads are atomic */
+ /* reads are atomic */
if ((*cond)->waiting)
return EBUSY;
if (!pthread_cond::isGoodObject (cond))
return EINVAL;
- /*if the cond variable is blocked, then the above timer test maybe wrong. *shrug**/
+ /* if the cond variable is blocked, then the above timer test maybe wrong. *shrug**/
if (pthread_mutex_lock (&(*cond)->cond_access))
system_printf ("Failed to lock condition variable access mutex, this %p", *cond);
if (pthread_mutex_unlock (&(*cond)->cond_access))
system_printf ("Failed to unlock condition variable access mutex, this %p", *cond);
/* At this point calls to Signal will progress evebn if we aren' yet waiting
- * However, the loop there should allow us to get scheduled and call wait,
- * and have them call PulseEvent again if we dont' respond.
- */
+ However, the loop there should allow us to get scheduled and call wait,
+ and have them call PulseEvent again if we dont' respond. */
rv = (*cond)->TimedWait (waitlength);
- /* this may allow a race on the mutex acquisition and waits..
- * But doing this within the cond access mutex creates a different race
- */
+ /* this may allow a race on the mutex acquisition and waits.
+ But doing this within the cond access mutex creates a different race */
InterlockedDecrement (&((*cond)->waiting));
/* Tell Signal that we have been released */
InterlockedDecrement (&((*cond)->ExitingWait));
return EINVAL;
if ((pshared < 0) || (pshared > 1))
return EINVAL;
- /*shared cond vars not currently supported */
+ /* shared cond vars not currently supported */
if (pshared != PTHREAD_PROCESS_PRIVATE)
return EINVAL;
(*attr)->shared = pshared;
return 0;
}
-/*Thread signal */
+/* Thread signal */
int
__pthread_kill (pthread_t thread, int sig)
{
-// lock myself, for the use of thread2signal
+ // lock myself, for the use of thread2signal
// two different kills might clash: FIXME
if (!pthread::isGoodObject (&thread))
return (*t1 == *t2);
}
-/*Mutexes */
+/* Mutexes */
/* FIXME: there's a potential race with PTHREAD_MUTEX_INITALIZER:
the mutex is not actually inited until the first use.
DWORD waitResult = WaitForSingleObject (mutexInitializationLock, INFINITE);
if (waitResult != WAIT_OBJECT_0)
{
- system_printf ("Recieved a unexpected wait result on mutexInitializationLock %d\n", waitResult);
+ system_printf ("Received a unexpected wait result on mutexInitializationLock %d\n", waitResult);
return EINVAL;
}
/* FIXME: bugfix: we should check *mutex being a valid address */
if (isGoodObject (mutex))
{
- if (! ReleaseMutex(mutexInitializationLock))
- system_printf ("Recieved a unexpected result releasing mutexInitializationLock %d\n", GetLastError());
+ if (!ReleaseMutex (mutexInitializationLock))
+ system_printf ("Received a unexpected result releasing mutexInitializationLock %E");
return EBUSY;
}
{
delete (*mutex);
*mutex = NULL;
- if (! ReleaseMutex(mutexInitializationLock))
- system_printf ("Recieved a unexpected result releasing mutexInitializationLock %d\n", GetLastError());
+ if (!ReleaseMutex (mutexInitializationLock))
+ system_printf ("Received a unexpected result releasing mutexInitializationLock %E");
return EAGAIN;
}
- if (! ReleaseMutex(mutexInitializationLock))
- system_printf ("Recieved a unexpected result releasing mutexInitializationLock %d\n", GetLastError());
+ if (!ReleaseMutex (mutexInitializationLock))
+ system_printf ("Received a unexpected result releasing mutexInitializationLock %E");
return 0;
}
pthread_mutex::init ((pthread_mutex_t *) mutex, NULL);
if (!pthread_mutex::isGoodObject (themutex))
return EINVAL;
- /*We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
- *mutex priorities.
- *
- *We can support mutex priorities in the future though:
- *Store a priority with each mutex.
- *When the mutex is optained, set the thread priority as appropriate
- *When the mutex is released, reset the thread priority.
- */
+ /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support
+ mutex priorities.
+
+ We can support mutex priorities in the future though:
+ Store a priority with each mutex.
+ When the mutex is optained, set the thread priority as appropriate
+ When the mutex is released, reset the thread priority. */
return ENOSYS;
}
pthread_mutex_t *themutex = mutex;
/* This could be simplified via isGoodInitializerOrObject
and isGoodInitializer, but in a performance critical call like this....
- no.
- */
+ no. */
switch (verifyable_object_isvalid (themutex, PTHREAD_MUTEX_MAGIC, PTHREAD_MUTEX_INITIALIZER))
{
case INVALID_OBJECT:
if (pthread_mutex::isGoodInitializer (mutex))
{
int rv = pthread_mutex::init (mutex, NULL);
- if (rv)
+ if (rv && rv != EBUSY)
return rv;
}
/* No else needed. If it's been initialized while we waited,
- * we can just attempt to lock it
- */
+ we can just attempt to lock it */
break;
case VALID_OBJECT:
break;
if (!pthread_mutex::isGoodObject (mutex))
return EINVAL;
- /*reading a word is atomic */
+ /* reading a word is atomic */
if ((*mutex)->condwaits)
return EBUSY;
return ENOSYS;
}
-/*Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
- *for more detail */
+/* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
+ for more detail */
int
__pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr,
int *protocol)
return 0;
}
-/*Win32 mutex's are equivalent to posix RECURSIVE mutexs.
- *We need to put glue in place to support other types of mutex's. We map
- *PTHREAD_MUTEX_DEFAULT to PTHREAD_MUTEX_RECURSIVE and return EINVAL for other types.
- */
+/* Win32 mutex's are equivalent to posix RECURSIVE mutexs.
+ We need to put glue in place to support other types of mutex's. We map
+ PTHREAD_MUTEX_DEFAULT to PTHREAD_MUTEX_RECURSIVE and return EINVAL for
+ other types. */
int
__pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type)
{
return 0;
}
-/*Currently pthread_mutex_init ignores the attr variable, this is because
- *none of the variables have any impact on it's behaviour.
- *
- *FIXME: write and test process shared mutex's.
- */
+/* Currently pthread_mutex_init ignores the attr variable, this is because
+ none of the variables have any impact on it's behaviour.
+
+ FIXME: write and test process shared mutex's. */
int
__pthread_mutexattr_init (pthread_mutexattr_t *attr)
{
}
-/*Win32 doesn't support mutex priorities */
+/* Win32 doesn't support mutex priorities */
int
__pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, int protocol)
{
return ENOSYS;
}
-/*Win32 doesn't support mutex priorities */
+/* Win32 doesn't support mutex priorities */
int
__pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr,
int prioceiling)
{
if (!pthread_mutexattr::isGoodObject (attr))
return EINVAL;
- /*we don't use pshared for anything as yet. We need to test PROCESS_SHARED
+ /* we don't use pshared for anything as yet. We need to test PROCESS_SHARED
*functionality
*/
if (pshared != PTHREAD_PROCESS_PRIVATE)
return 0;
}
-/*see __pthread_mutex_gettype */
+/* see __pthread_mutex_gettype */
int
__pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type)
{
return 0;
}
-/*Semaphores */
+/* Semaphores */
/* static members */
bool
int
semaphore::init (sem_t *sem, int pshared, unsigned int value)
{
- /*opengroup calls this undefined */
+ /* opengroup calls this undefined */
if (isGoodObject (sem))
return EBUSY;
if (!isGoodObject (sem))
return EINVAL;
- /*FIXME - new feature - test for busy against threads... */
+ /* FIXME - new feature - test for busy against threads... */
delete (*sem);
*sem = NULL;