* 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:
parent
881ffcb478
commit
79ed43004f
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue