From b14e60afab45a7bc5eff231f408505a1bec6b436 Mon Sep 17 00:00:00 2001 From: rpj Date: Thu, 11 Mar 1999 15:06:20 +0000 Subject: Thu Mar 11 09:01:48 1999 Ross Johnson * pthread.h (pthread_mutex_t): revert to (pthread_mutex_t *); define a value to serve as PTHREAD_MUTEX_INITIALIZER. (pthread_mutex_t_): remove staticinit and valid elements. (pthread_cond_t): revert to (pthread_cond_t_ *); define a value to serve as PTHREAD_COND_INITIALIZER. (pthread_cond_t_): remove staticinit and valid elements. * mutex.c (pthread_mutex_t args): adjust indirection of references. (all functions): check for PTHREAD_MUTEX_INITIALIZER value; check for NULL (invalid). * condvar.c (pthread_cond_t args): adjust indirection of references. (all functions): check for PTHREAD_COND_INITIALIZER value; check for NULL (invalid). Wed Mar 10 17:18:12 1999 Ross Johnson * misc.c (CancelableWait): Undo changes from Mar 8 and 7. tests/ChangeLog Fri Mar 12 08:34:15 1999 Ross Johnson * eyal1.c (main): Fix trylock loop; was not waiting for thread to lock the "started" mutex. --- mutex.c | 133 +++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 72 insertions(+), 61 deletions(-) (limited to 'mutex.c') diff --git a/mutex.c b/mutex.c index b88eac4..da4a196 100644 --- a/mutex.c +++ b/mutex.c @@ -30,38 +30,24 @@ _mutex_check_need_init(pthread_mutex_t *mutex) * so we can serialise access to internal state using * Win32 Critical Sections rather than Win32 Mutexes. * - * We still have a problem in that we would like a per-mutex - * lock, but attempting to create one will again lead - * to a race condition. We are forced to use a global - * lock in this instance. - * * If using a single global lock slows applications down too much, * multiple global locks could be created and hashed on some random * value associated with each mutex, the pointer perhaps. At a guess, * a good value for the optimal number of global locks might be * the number of processors + 1. * - * We need to maintain the following per-mutex state independently: - * - mutex staticinit (true iff mutex is static and still - * needs to be initialised) - * - mutex valid (false iff mutex has been destroyed) - * - * For example, in this implementation a mutex initialised by - * PTHREAD_MUTEX_INITIALIZER will be 'valid' but uninitialised until - * the thread attempts to lock it. It can also be destroyed (made invalid) - * before ever being locked. */ EnterCriticalSection(&_pthread_mutex_test_init_lock); /* - * We got here because staticinit tested true, possibly under race - * conditions. Check staticinit again inside the critical section + * We got here possibly under race + * conditions. Check again inside the critical section * and only initialise if the mutex is valid (not been destroyed). * If a static mutex has been destroyed, the application can * re-initialise it only by calling pthread_mutex_init() * explicitly. */ - if (mutex->staticinit && mutex->valid) + if (*mutex == (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT) { result = pthread_mutex_init(mutex, NULL); } @@ -75,22 +61,25 @@ int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { int result = 0; + pthread_mutex_t mx; if (mutex == NULL) { return EINVAL; } - mutex->mutex = 0; + mx = *mutex; - /* - * Assuming any race condition here is harmless. - */ - if (mutex->valid && !mutex->staticinit) + mx = (pthread_mutex_t) calloc(1, sizeof(*mx)); + + if (mx == NULL) { - return EBUSY; + result = ENOMEM; + goto FAIL0; } + mx->mutex = 0; + if (attr != NULL && *attr != NULL && (*attr)->pshared == PTHREAD_PROCESS_SHARED @@ -108,11 +97,11 @@ pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) #error ERROR [__FILE__, line __LINE__]: Process shared mutexes are not supported yet. - mutex->mutex = CreateMutex ( + mx->mutex = CreateMutex ( NULL, FALSE, ????); - result = (mutex->mutex == 0) ? EAGAIN : 0; + result = (mx->mutex == 0) ? EAGAIN : 0; #else @@ -131,7 +120,7 @@ pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) /* * Create a critical section. */ - InitializeCriticalSection(&mutex->cs); + InitializeCriticalSection(&mx->cs); } else { @@ -139,20 +128,21 @@ pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) * Create a mutex that can only be used within the * current process */ - mutex->mutex = CreateMutex (NULL, - FALSE, - NULL); - result = (mutex->mutex == 0) ? EAGAIN : 0; + mx->mutex = CreateMutex (NULL, + FALSE, + NULL); + + if (mx->mutex == 0) + { + result = EAGAIN; + mx = NULL; + goto FAIL0; + } } } - if (result == 0) - { - mutex->staticinit = 0; - - /* Mark as valid. */ - mutex->valid = 1; - } +FAIL0: + *mutex = mx; return(result); } @@ -161,33 +151,35 @@ int pthread_mutex_destroy(pthread_mutex_t *mutex) { int result = 0; + pthread_mutex_t mx; - if (mutex == NULL) + if (mutex == NULL + || *mutex == NULL) { return EINVAL; } + mx = *mutex; + /* * Check to see if we have something to delete. */ - if (!mutex->staticinit) + if (mx != (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT) { - if (mutex->mutex == 0) + if (mx->mutex == 0) { - DeleteCriticalSection(&mutex->cs); + DeleteCriticalSection(&mx->cs); } else { - result = (CloseHandle (mutex->mutex) ? 0 : EINVAL); + result = (CloseHandle (mx->mutex) ? 0 : EINVAL); } } if (result == 0) { - mutex->mutex = 0; - - /* Mark as invalid. */ - mutex->valid = 0; + mx->mutex = 0; + *mutex = NULL; } return(result); @@ -444,27 +436,35 @@ int pthread_mutex_lock(pthread_mutex_t *mutex) { int result = 0; + pthread_mutex_t mx; + + if (mutex == NULL || *mutex == NULL) + { + return EINVAL; + } /* * We do a quick check to see if we need to do more work - * to initialise a static mutex. We check 'staticinit' + * to initialise a static mutex. We check * again inside the guarded section of _mutex_check_need_init() * to avoid race conditions. */ - if (mutex->staticinit == 1) + if (*mutex == (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT) { result = _mutex_check_need_init(mutex); } + mx = *mutex; + if (result == 0) { - if (mutex->mutex == 0) + if (mx->mutex == 0) { - EnterCriticalSection(&mutex->cs); + EnterCriticalSection(&mx->cs); } else { - result = (WaitForSingleObject(mutex->mutex, INFINITE) + result = (WaitForSingleObject(mx->mutex, INFINITE) == WAIT_OBJECT_0) ? 0 : EINVAL; @@ -478,21 +478,29 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex) { int result = 0; + pthread_mutex_t mx; + + if (mutex == NULL || *mutex == NULL) + { + return EINVAL; + } + + mx = *mutex; /* * If the thread calling us holds the mutex then there is no * race condition. If another thread holds the * lock then we shouldn't be in here. */ - if (!mutex->staticinit && mutex->valid) + if (mx != (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT) { - if (mutex->mutex == 0) + if (mx->mutex == 0) { - LeaveCriticalSection(&mutex->cs); + LeaveCriticalSection(&mx->cs); } else { - result = (ReleaseMutex (mutex->mutex) ? 0 : EINVAL); + result = (ReleaseMutex (mx->mutex) ? 0 : EINVAL); } } else @@ -507,28 +515,31 @@ int pthread_mutex_trylock(pthread_mutex_t *mutex) { int result = 0; + pthread_mutex_t mx; - if (mutex == NULL) + if (mutex == NULL || *mutex == NULL) { return EINVAL; } /* * We do a quick check to see if we need to do more work - * to initialise a static mutex. We check 'staticinit' + * to initialise a static mutex. We check * again inside the guarded section of _mutex_check_need_init() * to avoid race conditions. */ - if (mutex->staticinit) + if (*mutex == (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT) { result = _mutex_check_need_init(mutex); } + mx = *mutex; + if (result == 0) { - if (mutex->mutex == 0) + if (mx->mutex == 0) { - if ((*_pthread_try_enter_critical_section)(&mutex->cs) != TRUE) + if ((*_pthread_try_enter_critical_section)(&mx->cs) != TRUE) { result = EBUSY; } @@ -537,7 +548,7 @@ pthread_mutex_trylock(pthread_mutex_t *mutex) { DWORD status; - status = WaitForSingleObject (mutex->mutex, 0); + status = WaitForSingleObject (mx->mutex, 0); if (status != WAIT_OBJECT_0) { -- cgit v1.2.3