* thread.cc: Use "%E" in *_printf throughout rather than calling GetLastError.

GNUify comments.
(__pthread_mutex_lock): Don't return error on EBUSY since that just means that
the mutex has already been initialized.
This commit is contained in:
Christopher Faylor 2002-09-30 01:19:45 +00:00
parent 881ffcb478
commit 79ed43004f
2 changed files with 150 additions and 156 deletions

View File

@ -1,3 +1,10 @@
2002-09-29 Christopher Faylor <cgf@redhat.com>
* thread.cc: Use "%E" in *_printf throughout rather than calling
GetLastError. GNUify comments.
(__pthread_mutex_lock): Don't return error on EBUSY since that just
means that the mutex has already been initialized.
2002-09-30 Robert Collins <rbtcollins@hotmail.com>
* pthread.cc (pthread_mutex_init): Use new pthread_mutex::init.

View File

@ -320,7 +320,7 @@ pthread::precreate (pthread_attr *newattr)
cancel_event = ::CreateEvent (NULL,TRUE,FALSE,NULL);
if (!cancel_event)
{
system_printf ("couldn't create cancel event, this %p LastError %d", this, GetLastError () );
system_printf ("couldn't create cancel event, this %p LastError %E", this);
/* we need the event for correct behaviour */
magic = 0;
return;
@ -1051,27 +1051,26 @@ pthread_key::run_destructor ()
/* pshared mutexs:
* REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
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.
*/
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
@ -1101,15 +1100,14 @@ pthread_mutex::isGoodInitializerOrObject (pthread_mutex_t const *mutex)
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");
}
@ -1473,24 +1471,22 @@ pthread::cancel (pthread_t thread)
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)
{
@ -1529,9 +1525,8 @@ pthread::atforkchild (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.
*/
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))
{
@ -1627,9 +1622,8 @@ __pthread_attr_getschedparam (const pthread_attr_t *attr,
}
/* 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
*/
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)
{
@ -1713,7 +1707,7 @@ __pthread_attr_setscope (pthread_attr_t *attr, int contentionscope)
&& 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. */
priority to exceed the priority class. For now we only support PROCESS scope. */
if (contentionscope != PTHREAD_SCOPE_PROCESS)
return ENOTSUP;
(*attr)->contentionscope = contentionscope;
@ -1849,7 +1843,7 @@ pthread::resume (pthread_t *thread)
}
/* provided for source level compatability.
*See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
*/
int
__pthread_getconcurrency (void)
@ -1865,8 +1859,8 @@ __pthread_getschedparam (pthread_t thread, int *policy,
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;
}
@ -1876,8 +1870,7 @@ 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..
*/
but creation is relatively rare. */
if (pthread_key::isGoodObject (key))
return EBUSY;
@ -1902,8 +1895,8 @@ __pthread_key_delete (pthread_key_t key)
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)
@ -2079,13 +2072,11 @@ __pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex,
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));
@ -2234,7 +2225,7 @@ pthread_mutex::init (pthread_mutex_t *mutex,
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;
}
@ -2242,7 +2233,7 @@ pthread_mutex::init (pthread_mutex_t *mutex,
if (isGoodObject (mutex))
{
if (!ReleaseMutex (mutexInitializationLock))
system_printf ("Recieved a unexpected result releasing mutexInitializationLock %d\n", GetLastError());
system_printf ("Received a unexpected result releasing mutexInitializationLock %E");
return EBUSY;
}
@ -2252,11 +2243,11 @@ pthread_mutex::init (pthread_mutex_t *mutex,
delete (*mutex);
*mutex = NULL;
if (!ReleaseMutex (mutexInitializationLock))
system_printf ("Recieved a unexpected result releasing mutexInitializationLock %d\n", GetLastError());
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());
system_printf ("Received a unexpected result releasing mutexInitializationLock %E");
return 0;
}
@ -2270,13 +2261,12 @@ __pthread_mutex_getprioceiling (const pthread_mutex_t *mutex,
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.
*/
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;
}
@ -2286,8 +2276,7 @@ __pthread_mutex_lock (pthread_mutex_t *mutex)
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:
@ -2297,12 +2286,11 @@ __pthread_mutex_lock (pthread_mutex_t *mutex)
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;
@ -2365,7 +2353,7 @@ __pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling,
}
/* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling
*for more detail */
for more detail */
int
__pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr,
int *protocol)
@ -2386,9 +2374,9 @@ __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr,
}
/* 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.
*/
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)
{
@ -2399,10 +2387,9 @@ __pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type)
}
/* 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.
*/
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)
{