summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog21
-rw-r--r--FAQ14
-rw-r--r--condvar.c148
-rw-r--r--misc.c52
-rw-r--r--mutex.c133
-rw-r--r--pthread.h27
-rw-r--r--tests/ChangeLog5
-rw-r--r--tests/condvar3.c218
-rw-r--r--tests/condvar4.c239
-rw-r--r--tests/eyal1.c394
-rw-r--r--tests/mutex2.c6
-rw-r--r--tests/tsd1.c4
12 files changed, 657 insertions, 604 deletions
diff --git a/ChangeLog b/ChangeLog
index ebf4fa2..6f63ee6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+Thu Mar 11 09:01:48 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * 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 <rpj@ixobrychus.canberra.edu.au>
+
+ * misc.c (CancelableWait): Undo changes from Mar 8 and 7.
+
Mon Mar 8 11:18:59 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
* misc.c (CancelableWait): Ensure cancelEvent handle is the lowest
diff --git a/FAQ b/FAQ
index da9cd75..71e6359 100644
--- a/FAQ
+++ b/FAQ
@@ -5,22 +5,24 @@
INDEX
-----
-Q 1 How do I get pthreads-win32 to link under Cygwin or Mingw32?
+Q 1 Should I use Cygwin or Mingw32 as a development environment?
Q 2 Now that pthreads-win32 builds under Mingw32, why do I get
memory access violations?
=============================================================================
-Q 1 How do I get pthreads-win32 to link under Cygwin or Mingw32?
+Q 1 Should I use Cygwin or Mingw32 as a development environment?
---
A 1
---
-The following email from Anders Norlander explains how to solve this
-problem. I think the proviso is that the DLL and your application should
-both be built with the same development environment (cygwin, mingw,
-or MSVC etc).
+Important: see Q2 also.
+
+I short, use Mingw32 with the MSVCRT library to build applications that use
+the DLL. You cannot build the library itself with either yet because the
+library uses C++ EH which is not thread-safe in egcs yet. Use MSVC or grab
+the pre-build DLL etc.
Date: Mon, 07 Dec 1998 15:11:37 +0100
From: Anders Norlander <anorland@hem2.passagen.se>
diff --git a/condvar.c b/condvar.c
index 8fca94c..80dc1c4 100644
--- a/condvar.c
+++ b/condvar.c
@@ -19,7 +19,7 @@ _cond_check_need_init(pthread_cond_t *cond)
/*
* The following guarded test is specifically for statically
- * initialised condition variables (via PTHREAD_COND_INITIALIZER).
+ * initialised condition variables (via PTHREAD_OBJECT_INITIALIZER).
*
* Note that by not providing this synchronisation we risk
* introducing race conditions into applications which are
@@ -31,38 +31,23 @@ _cond_check_need_init(pthread_cond_t *cond)
* 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-cv state independently:
- * - cv staticinit (true iff cv is static and still
- * needs to be initialised)
- * - cv valid (false iff cv has been destroyed)
- *
- * For example, in this implementation a cv initialised by
- * PTHREAD_COND_INITIALIZER will be 'valid' but uninitialised until
- * the thread attempts to use it. It can also be destroyed (made invalid)
- * before ever being used.
*/
EnterCriticalSection(&_pthread_cond_test_init_lock);
/*
- * We got here because staticinit tested true, possibly under race
- * conditions. Check staticinit again inside the critical section
- * and only initialise if the cv is valid (not been destroyed).
+ * We got here possibly under race
+ * conditions. Check again inside the critical section.
* If a static cv has been destroyed, the application can
* re-initialise it only by calling pthread_cond_init()
* explicitly.
*/
- if (cond->staticinit && cond->valid)
+ if (*cond == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT)
{
result = pthread_cond_init(cond, NULL);
}
@@ -342,20 +327,13 @@ pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr)
*/
{
int result = EAGAIN;
+ pthread_cond_t cv;
if (cond == NULL)
{
return EINVAL;
}
- /*
- * Assuming any race condition here is harmless.
- */
- if (cond->valid && !cond->staticinit)
- {
- return EBUSY;
- }
-
if ((attr != NULL && *attr != NULL) &&
((*attr)->pshared == PTHREAD_PROCESS_SHARED))
{
@@ -368,34 +346,37 @@ pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr)
goto FAIL0;
}
- cond->waiters = 0;
- cond->wasBroadcast = FALSE;
+ cv = (pthread_cond_t) calloc (1, sizeof (*cv));
- if (_pthread_sem_init (&(cond->sema), 0, 0) != 0)
+ if (cv == NULL)
{
+ result = ENOMEM;
goto FAIL0;
}
- if (pthread_mutex_init (&(cond->waitersLock), NULL) != 0)
+
+ cv->waiters = 0;
+ cv->wasBroadcast = FALSE;
+
+ if (_pthread_sem_init (&(cv->sema), 0, 0) != 0)
+ {
+ goto FAIL0;
+ }
+ if (pthread_mutex_init (&(cv->waitersLock), NULL) != 0)
{
goto FAIL1;
}
- cond->waitersDone = CreateEvent (
- 0,
- (int) FALSE, /* manualReset */
- (int) FALSE, /* setSignaled */
- NULL);
+ cv->waitersDone = CreateEvent (
+ 0,
+ (int) FALSE, /* manualReset */
+ (int) FALSE, /* setSignaled */
+ NULL);
- if (cond->waitersDone == NULL)
+ if (cv->waitersDone == NULL)
{
goto FAIL2;
}
- cond->staticinit = 0;
-
- /* Mark as valid. */
- cond->valid = 1;
-
result = 0;
goto DONE;
@@ -406,13 +387,15 @@ pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr)
* -------------
*/
FAIL2:
- (void) pthread_mutex_destroy (&(cond->waitersLock));
+ (void) pthread_mutex_destroy (&(cv->waitersLock));
FAIL1:
- (void) _pthread_sem_destroy (&(cond->sema));
+ (void) _pthread_sem_destroy (&(cv->sema));
FAIL0:
DONE:
+ *cond = cv;
+
return (result);
} /* pthread_cond_init */
@@ -447,25 +430,30 @@ pthread_cond_destroy (pthread_cond_t * cond)
*/
{
int result = 0;
+ pthread_cond_t cv;
/*
* Assuming any race condition here is harmless.
*/
- if (cond == NULL || cond->valid == 0 || cond->staticinit == 1)
+ if (cond == NULL
+ || *cond == NULL)
{
return EINVAL;
}
- if (cond->waiters > 0)
+ cv = *cond;
+
+ if (cv->waiters > 0)
{
return EBUSY;
}
- (void) _pthread_sem_destroy (&(cond->sema));
- (void) pthread_mutex_destroy (&(cond->waitersLock));
- (void) CloseHandle (cond->waitersDone);
-
- cond->valid = 0;
+ (void) _pthread_sem_destroy (&(cv->sema));
+ (void) pthread_mutex_destroy (&(cv->waitersLock));
+ (void) CloseHandle (cv->waitersDone);
+
+ free(cv);
+ *cond = NULL;
return (result);
}
@@ -478,14 +466,22 @@ cond_timedwait (pthread_cond_t * cond,
int result = 0;
int internal_result = 0;
int lastWaiter = FALSE;
+ pthread_cond_t cv;
+
+ if (cond == NULL || *cond == NULL)
+ {
+ return EINVAL;
+ }
+
+ cv = *cond;
/*
* We do a quick check to see if we need to do more work
- * to initialise a static condition variable. We check 'staticinit'
+ * to initialise a static condition variable. We check
* again inside the guarded section of _cond_check_need_init()
* to avoid race conditions.
*/
- if (cond->staticinit == 1)
+ if (cv == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT)
{
result = _cond_check_need_init(cond);
}
@@ -493,7 +489,7 @@ cond_timedwait (pthread_cond_t * cond,
/*
* OK to increment cond->waiters because the caller locked 'mutex'
*/
- cond->waiters++;
+ cv->waiters++;
/*
* We keep the lock held just long enough to increment the count of
@@ -518,23 +514,23 @@ cond_timedwait (pthread_cond_t * cond,
*/
pthread_cleanup_push (pthread_mutex_lock, mutex);
- result = _pthread_sem_timedwait (&(cond->sema), abstime);
+ result = _pthread_sem_timedwait (&(cv->sema), abstime);
pthread_cleanup_pop (0);
}
- if ((internal_result = pthread_mutex_lock (&(cond->waitersLock))) == 0)
+ if ((internal_result = pthread_mutex_lock (&(cv->waitersLock))) == 0)
{
/*
* By making the waiter responsible for decrementing
* its count we don't have to worry about having an internal
* mutex.
*/
- cond->waiters--;
+ cv->waiters--;
- lastWaiter = cond->wasBroadcast && (cond->waiters == 0);
+ lastWaiter = cv->wasBroadcast && (cv->waiters == 0);
- internal_result = pthread_mutex_unlock (&(cond->waitersLock));
+ internal_result = pthread_mutex_unlock (&(cv->waitersLock));
}
if (result == 0 && internal_result == 0)
@@ -545,7 +541,7 @@ cond_timedwait (pthread_cond_t * cond,
* If we are the last waiter on this broadcast
* let the thread doing the broadcast proceed
*/
- if (!SetEvent (cond->waitersDone))
+ if (!SetEvent (cv->waitersDone))
{
result = EINVAL;
}
@@ -727,16 +723,19 @@ pthread_cond_signal (pthread_cond_t * cond)
*/
{
int result = 0;
+ pthread_cond_t cv;
- if (cond == NULL || cond->valid == 0)
+ if (cond == NULL || *cond == NULL)
{
return EINVAL;
}
+ cv = *cond;
+
/*
* No-op if the CV is static and hasn't been initialised yet.
*/
- if (cond->staticinit == 1)
+ if (cv == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT)
{
return 0;
}
@@ -744,9 +743,9 @@ pthread_cond_signal (pthread_cond_t * cond)
/*
* If there aren't any waiters, then this is a no-op.
*/
- if (cond->waiters > 0)
+ if (cv->waiters > 0)
{
- result = _pthread_sem_post (&(cond->sema));
+ result = _pthread_sem_post (&(cv->sema));
}
return (result);
@@ -793,18 +792,21 @@ pthread_cond_broadcast (pthread_cond_t * cond)
{
int result = 0;
int i;
+ pthread_cond_t cv;
- if (cond == NULL || cond->valid == 0)
+ if (cond == NULL || *cond == NULL)
{
return EINVAL;
}
- cond->wasBroadcast = TRUE;
+ cv = *cond;
+
+ cv->wasBroadcast = TRUE;
/*
* No-op if the CV is static and hasn't been initialised yet.
*/
- if (cond->staticinit == 1)
+ if (cv == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT)
{
return 0;
}
@@ -812,24 +814,21 @@ pthread_cond_broadcast (pthread_cond_t * cond)
/*
* Wake up all waiters
*/
- for (i = cond->waiters; i > 0 && result == 0; i--)
+ for (i = cv->waiters; i > 0 && result == 0; i--)
{
-
- result = _pthread_sem_post (&(cond->sema));
+ result = _pthread_sem_post (&(cv->sema));
}
- if (cond->waiters > 0 && result == 0)
+ if (cv->waiters > 0 && result == 0)
{
/*
* Wait for all the awakened threads to acquire their part of
* the counting semaphore
*/
- if (WaitForSingleObject (cond->waitersDone, INFINITE) !=
+ if (WaitForSingleObject (cv->waitersDone, INFINITE) !=
WAIT_OBJECT_0)
{
-
result = 0;
-
}
else
{
@@ -839,6 +838,7 @@ pthread_cond_broadcast (pthread_cond_t * cond)
}
return (result);
+
}
/* </JEB> */
diff --git a/misc.c b/misc.c
index df7af10..b5cbecf 100644
--- a/misc.c
+++ b/misc.c
@@ -213,12 +213,8 @@ CancelableWait (HANDLE waitHandle, DWORD timeout)
DWORD nHandles = 1;
DWORD status;
- /*
- * If both objects are signaled, then (status - WAIT_OBJECT_0)
- * will be the lowest index value of all the signaled objects.
- * We must ensure that a cancelation is recognised if this occurs by
- * placing the cancelEvent handle first in the handle table.
- */
+ handles[0] = waitHandle;
+
if ((self = (pthread_t) pthread_getspecific (_pthread_selfThreadKey))
!= NULL)
{
@@ -228,14 +224,16 @@ CancelableWait (HANDLE waitHandle, DWORD timeout)
if (self->cancelState == PTHREAD_CANCEL_ENABLE)
{
- if ((handles[0] = self->cancelEvent) != NULL)
+ if ((handles[1] = self->cancelEvent) != NULL)
{
nHandles++;
}
}
}
-
- handles[nHandles - 1] = waitHandle;
+ else
+ {
+ handles[1] = NULL;
+ }
status = WaitForMultipleObjects (
nHandles,
@@ -243,36 +241,41 @@ CancelableWait (HANDLE waitHandle, DWORD timeout)
FALSE,
timeout);
+
if (status == WAIT_FAILED)
{
result = EINVAL;
+
}
else if (status == WAIT_TIMEOUT)
{
result = ETIMEDOUT;
}
- else if (status >= WAIT_ABANDONED_0 && status <= WAIT_ABANDONED_0 + nHandles - 1)
+ else if (status == WAIT_ABANDONED_0)
{
- /*
- * The waitHandle was a mutex object that was abandoned.
- */
result = EINVAL;
}
else
{
/*
- * Either got the object or the cancel event
- * was signaled, or both in which case the cancel
- * event will be acted on.
+ * Either got the mutex or the cancel event
+ * was signaled
*/
- switch (status - WAIT_OBJECT_0 + 2 - nHandles)
+ switch (status - WAIT_OBJECT_0)
{
case 0:
/*
- * Got cancel request.
+ * Got the mutex
+ */
+ result = 0;
+ break;
+
+ case 1:
+ /*
+ * Got cancel request
*/
- ResetEvent (handles[0]);
+ ResetEvent (handles[1]);
if (self != NULL && !self->implicit)
{
@@ -304,15 +307,8 @@ CancelableWait (HANDLE waitHandle, DWORD timeout)
#endif /* _MSC_VER */
}
- /* Should never get to here. */
- result = EINVAL;
- break;
-
- case 1:
- /*
- * Got the object.
- */
- result = 0;
+ /* Should never get to here. */
+ result = EINVAL;
break;
default:
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)
{
diff --git a/pthread.h b/pthread.h
index da40f48..8f66e48 100644
--- a/pthread.h
+++ b/pthread.h
@@ -419,9 +419,9 @@ extern "C"
typedef struct pthread_attr_t_ *pthread_attr_t;
typedef struct pthread_once_t_ pthread_once_t;
typedef struct pthread_key_t_ *pthread_key_t;
- typedef struct pthread_mutex_t_ pthread_mutex_t;
+ typedef struct pthread_mutex_t_ *pthread_mutex_t;
typedef struct pthread_mutexattr_t_ *pthread_mutexattr_t;
- typedef struct pthread_cond_t_ pthread_cond_t;
+ typedef struct pthread_cond_t_ *pthread_cond_t;
typedef struct pthread_condattr_t_ *pthread_condattr_t;
@@ -567,16 +567,19 @@ struct pthread_attr_t_ {
/*
* ====================
* ====================
- * Mutex
+ * Mutexes and Condition Variables
* ====================
* ====================
*/
-#define PTHREAD_MUTEX_INITIALIZER { 1, 1 /* Remaining are all 0 */ }
+enum {
+ _PTHREAD_OBJECT_INVALID = 0, /* NULL */
+ _PTHREAD_OBJECT_AUTO_INIT
+};
+
+#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT)
struct pthread_mutex_t_ {
- int staticinit; /* Needs implicit init if 1. */
- int valid; /* Not destroyed if 1. */
HANDLE mutex;
CRITICAL_SECTION cs;
};
@@ -596,21 +599,11 @@ struct pthread_key_t_ {
};
-/*
- * ====================
- * ====================
- * Condition Variable
- * ====================
- * ====================
- */
-
-#define PTHREAD_COND_INITIALIZER { 1, 1 /* Remaining are all 0 */ }
+#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT)
typedef HANDLE _pthread_sem_t;
struct pthread_cond_t_ {
- int staticinit; /* Needs implicit init if 1. */
- int valid; /* Not destroyed if 1. */
long waiters; /* # waiting threads */
pthread_mutex_t waitersLock; /* Mutex that guards access to
waiter count */
diff --git a/tests/ChangeLog b/tests/ChangeLog
index aef418f..0304802 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+Fri Mar 12 08:34:15 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
+
+ * eyal1.c (main): Fix trylock loop; was not waiting for thread to lock
+ the "started" mutex.
+
Sun Mar 7 10:41:52 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
* Makefile (condvar3, condvar4): Add tests.
diff --git a/tests/condvar3.c b/tests/condvar3.c
index 8dc56af..27223ab 100644
--- a/tests/condvar3.c
+++ b/tests/condvar3.c
@@ -1,109 +1,109 @@
-/*
- * File: condvar3.c
- *
- * Test Synopsis:
- * - Test basic function of a CV
- *
- * Test Method (Validation or Falsification):
- * - Validation
- *
- * Requirements Tested:
- * -
- *
- * Features Tested:
- * -
- *
- * Cases Tested:
- * -
- *
- * Description:
- * - The primary thread takes the lock before creating any threads.
- * The secondary thread blocks on the lock allowing the primary
- * thread to enter the cv wait state which releases the lock.
- * The secondary thread then takes the lock and signals the waiting
- * primary thread.
- *
- * Environment:
- * -
- *
- * Input:
- * - None.
- *
- * Output:
- * - File name, Line number, and failed expression on failure.
- * - No output on success.
- *
- * Assumptions:
- * -
- *
- * Pass Criteria:
- * - pthread_cond_timedwait returns 0.
- * - Process returns zero exit status.
- *
- * Fail Criteria:
- * - pthread_cond_timedwait returns ETIMEDOUT.
- * - Process returns non-zero exit status.
- */
-
-#include "test.h"
-#include <sys/timeb.h>
-
-pthread_cond_t cv;
-pthread_mutex_t mutex;
-
-enum {
- NUMTHREADS = 2 /* Including the primary thread. */
-};
-
-void *
-mythread(void * arg)
-{
- Sleep(1);
-
- assert(pthread_mutex_lock(&mutex) == 0);
-
- assert(pthread_cond_signal(&cv) == 0);
-
- assert(pthread_mutex_unlock(&mutex) == 0);
-
- return 0;
-}
-
-int
-main()
-{
- pthread_t t[NUMTHREADS];
- struct timespec abstime = { 0, 0 };
-#if defined(__MINGW32__)
- struct timeb currSysTime;
-#else
- struct _timeb currSysTime;
-#endif
- const DWORD NANOSEC_PER_MILLISEC = 1000000;
-
- assert((t[0] = pthread_self()) != NULL);
-
- assert(pthread_cond_init(&cv, NULL) == 0);
-
- assert(pthread_mutex_init(&mutex, NULL) == 0);
-
- assert(pthread_mutex_lock(&mutex) == 0);
-
- /* get current system time */
- _ftime(&currSysTime);
-
- abstime.tv_sec = currSysTime.time;
- abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
-
- assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0);
-
- abstime.tv_sec += 5;
-
- assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == 0);
-
- assert(pthread_mutex_unlock(&mutex) == 0);
-
- assert(pthread_cond_destroy(&cv) == 0);
-
- return 0;
-}
+/*
+ * File: condvar3.c
+ *
+ * Test Synopsis:
+ * - Test basic function of a CV
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * -
+ *
+ * Features Tested:
+ * -
+ *
+ * Cases Tested:
+ * -
+ *
+ * Description:
+ * - The primary thread takes the lock before creating any threads.
+ * The secondary thread blocks on the lock allowing the primary
+ * thread to enter the cv wait state which releases the lock.
+ * The secondary thread then takes the lock and signals the waiting
+ * primary thread.
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * -
+ *
+ * Pass Criteria:
+ * - pthread_cond_timedwait returns 0.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_timedwait returns ETIMEDOUT.
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+pthread_cond_t cv;
+pthread_mutex_t mutex;
+
+enum {
+ NUMTHREADS = 2 /* Including the primary thread. */
+};
+
+void *
+mythread(void * arg)
+{
+ Sleep(1);
+
+ assert(pthread_mutex_lock(&mutex) == 0);
+
+ assert(pthread_cond_signal(&cv) == 0);
+
+ assert(pthread_mutex_unlock(&mutex) == 0);
+
+ return 0;
+}
+
+int
+main()
+{
+ pthread_t t[NUMTHREADS];
+ struct timespec abstime = { 0, 0 };
+#if defined(__MINGW32__)
+ struct timeb currSysTime;
+#else
+ struct _timeb currSysTime;
+#endif
+ const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+ assert((t[0] = pthread_self()) != NULL);
+
+ assert(pthread_cond_init(&cv, NULL) == 0);
+
+ assert(pthread_mutex_init(&mutex, NULL) == 0);
+
+ assert(pthread_mutex_lock(&mutex) == 0);
+
+ /* get current system time */
+ _ftime(&currSysTime);
+
+ abstime.tv_sec = currSysTime.time;
+ abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+ assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0);
+
+ abstime.tv_sec += 5;
+
+ assert(pthread_cond_timedwait(&cv, &mutex, &abstime) == 0);
+
+ assert(pthread_mutex_unlock(&mutex) == 0);
+
+ assert(pthread_cond_destroy(&cv) == 0);
+
+ return 0;
+}
diff --git a/tests/condvar4.c b/tests/condvar4.c
index 4c5fc38..f93db27 100644
--- a/tests/condvar4.c
+++ b/tests/condvar4.c
@@ -1,121 +1,118 @@
-/*
- * File: condvar1.c
- *
- * Test Synopsis:
- * - Test PTHREAD_COND_INITIALIZER.
- *
- * Test Method (Validation or Falsification):
- * - Validation
- *
- * Requirements Tested:
- * -
- *
- * Features Tested:
- * -
- *
- * Cases Tested:
- * -
- *
- * Description:
- * - Test basic CV function but starting with a static initialised
- * CV.
- *
- * Environment:
- * -
- *
- * Input:
- * - None.
- *
- * Output:
- * - File name, Line number, and failed expression on failure.
- * - No output on success.
- *
- * Assumptions:
- * -
- *
- * Pass Criteria:
- * - pthread_cond_timedwait returns 0.
- * - Process returns zero exit status.
- *
- * Fail Criteria:
- * - pthread_cond_timedwait returns ETIMEDOUT.
- * - Process returns non-zero exit status.
- */
-
-#include "test.h"
-#include <sys/timeb.h>
-
-typedef struct cvthing_t_ cvthing_t;
-
-struct cvthing_t_ {
- pthread_cond_t notbusy;
- pthread_mutex_t lock;
-};
-
-static cvthing_t cvthing = {
- PTHREAD_MUTEX_INITIALIZER,
- PTHREAD_COND_INITIALIZER,
-};
-
-enum {
- NUMTHREADS = 2
-};
-
-void *
-mythread(void * arg)
-{
- assert(pthread_mutex_lock(&cvthing.lock) == 0);
-
- assert(pthread_cond_signal(&cvthing.notbusy) == 0);
-
- assert(pthread_mutex_unlock(&cvthing.lock) == 0);
-
- return 0;
-}
-
-int
-main()
-{
- pthread_t t[NUMTHREADS];
- struct timespec abstime = { 0, 0 };
-#if defined(__MINGW32__)
- struct timeb currSysTime;
-#else
- struct _timeb currSysTime;
-#endif
- const DWORD NANOSEC_PER_MILLISEC = 1000000;
-
- assert(cvthing.notbusy.staticinit == 1);
- assert(cvthing.notbusy.valid == 1);
-
- assert((t[0] = pthread_self()) != NULL);
-
- assert(pthread_mutex_lock(&cvthing.lock) == 0);
-
- /* get current system time */
- _ftime(&currSysTime);
-
- abstime.tv_sec = currSysTime.time;
- abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
-
- abstime.tv_sec += 5;
-
- assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == ETIMEDOUT);
-
- assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0);
-
- _ftime(&currSysTime);
-
- abstime.tv_sec = currSysTime.time;
- abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
-
- abstime.tv_sec += 5;
-
- assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
-
- assert(pthread_mutex_unlock(&cvthing.lock) == 0);
-
- assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
-
- return 0;
-}
+/*
+ * File: condvar1.c
+ *
+ * Test Synopsis:
+ * - Test PTHREAD_COND_INITIALIZER.
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * -
+ *
+ * Features Tested:
+ * -
+ *
+ * Cases Tested:
+ * -
+ *
+ * Description:
+ * - Test basic CV function but starting with a static initialised
+ * CV.
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * -
+ *
+ * Pass Criteria:
+ * - pthread_cond_timedwait returns 0.
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - pthread_cond_timedwait returns ETIMEDOUT.
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+#include <sys/timeb.h>
+
+typedef struct cvthing_t_ cvthing_t;
+
+struct cvthing_t_ {
+ pthread_cond_t notbusy;
+ pthread_mutex_t lock;
+};
+
+static cvthing_t cvthing = {
+ PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_COND_INITIALIZER,
+};
+
+enum {
+ NUMTHREADS = 2
+};
+
+void *
+mythread(void * arg)
+{
+ assert(pthread_mutex_lock(&cvthing.lock) == 0);
+
+ assert(pthread_cond_signal(&cvthing.notbusy) == 0);
+
+ assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+ return 0;
+}
+
+int
+main()
+{
+ pthread_t t[NUMTHREADS];
+ struct timespec abstime = { 0, 0 };
+#if defined(__MINGW32__)
+ struct timeb currSysTime;
+#else
+ struct _timeb currSysTime;
+#endif
+ const DWORD NANOSEC_PER_MILLISEC = 1000000;
+
+ assert((t[0] = pthread_self()) != NULL);
+
+ assert(pthread_mutex_lock(&cvthing.lock) == 0);
+
+ /* get current system time */
+ _ftime(&currSysTime);
+
+ abstime.tv_sec = currSysTime.time;
+ abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+ abstime.tv_sec += 5;
+
+ assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == ETIMEDOUT);
+
+ assert(pthread_create(&t[1], NULL, mythread, (void *) 1) == 0);
+
+ _ftime(&currSysTime);
+
+ abstime.tv_sec = currSysTime.time;
+ abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
+
+ abstime.tv_sec += 5;
+
+ assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
+
+ assert(pthread_mutex_unlock(&cvthing.lock) == 0);
+
+ assert(pthread_cond_destroy(&cvthing.notbusy) == 0);
+
+ return 0;
+}
diff --git a/tests/eyal1.c b/tests/eyal1.c
index 4345452..533822d 100644
--- a/tests/eyal1.c
+++ b/tests/eyal1.c
@@ -49,15 +49,16 @@
#include <math.h>
struct thread_control {
- int id;
- pthread_t thread; /* thread id */
- pthread_mutex_t mutex_start;
- pthread_mutex_t mutex_started;
- pthread_mutex_t mutex_end;
- pthread_mutex_t mutex_ended;
- long work; /* work done */
- int stat; /* pthread_init status */
+ int id;
+ pthread_t thread; /* thread id */
+ pthread_mutex_t mutex_start;
+ pthread_mutex_t mutex_started;
+ pthread_mutex_t mutex_end;
+ pthread_mutex_t mutex_ended;
+ long work; /* work done */
+ int stat; /* pthread_init status */
};
+
typedef struct thread_control TC;
static TC *tcs = NULL;
@@ -70,229 +71,250 @@ static int todo = -1;
static pthread_mutex_t mutex_todo = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t mutex_stdout = PTHREAD_MUTEX_INITIALIZER;
-/*static pthread_attr_t pthread_attr_default;*/
-
static void
die (int ret)
{
- if (NULL != tcs) {
- free (tcs);
- tcs = NULL;
- }
-
- if (ret)
- exit (ret);
+ if (NULL != tcs)
+ {
+ free (tcs);
+ tcs = NULL;
+ }
+
+ if (ret)
+ exit (ret);
}
static void
waste_time (int n)
{
- int i;
- double f;
+ int i;
+ double f;
- f = rand ();
+ f = rand ();
- for (i = n*100; i > 0; --i) {
- f = sqrt (f) * f + 10000.0;
- }
+ for (i = n*100; i > 0; --i)
+ {
+ f = sqrt (f) * f + 10000.0;
+ }
}
static int
do_work_unit (int who, int n)
{
- int i;
- static int nchars = 0;
+ int i;
+ static int nchars = 0;
- if (quiet)
- i = 0;
- else {
-/* get lock on stdout
-*/
- assert(pthread_mutex_lock (&mutex_stdout) == 0);
+ if (quiet)
+ i = 0;
+ else {
+ /*
+ * get lock on stdout
+ */
+ assert(pthread_mutex_lock (&mutex_stdout) == 0);
-/* do our job
-*/
- i = printf ("%c",
- "0123456789abcdefghijklmnopqrstuvwxyz"[who]);
- if (!(++nchars % 50))
- printf ("\n");
- fflush (stdout);
+ /*
+ * do our job
+ */
+ i = printf ("%c", "0123456789abcdefghijklmnopqrstuvwxyz"[who]);
-/* release lock on stdout
-*/
- assert(pthread_mutex_unlock (&mutex_stdout) == 0);
- }
+ if (!(++nchars % 50))
+ printf ("\n");
- n = rand () % 10000; /* ignore incoming 'n' */
- waste_time (n);
+ fflush (stdout);
- return (n);
+ /*
+ * release lock on stdout
+ */
+ assert(pthread_mutex_unlock (&mutex_stdout) == 0);
+ }
+
+ n = rand () % 10000; /* ignore incoming 'n' */
+ waste_time (n);
+
+ return (n);
}
static int
print_server (void *ptr)
{
- int mywork;
- int n;
- TC *tc = (TC *)ptr;
-
- assert(pthread_mutex_lock (&tc->mutex_started) == 0);
-
- for (;;) {
- assert(pthread_mutex_lock (&tc->mutex_start) == 0);
- assert(pthread_mutex_unlock (&tc->mutex_start) == 0);
- assert(pthread_mutex_lock (&tc->mutex_ended) == 0);
- assert(pthread_mutex_unlock (&tc->mutex_started) == 0);
+ int mywork;
+ int n;
+ TC *tc = (TC *)ptr;
+
+ assert(pthread_mutex_lock (&tc->mutex_started) == 0);
+
+ for (;;)
+ {
+ assert(pthread_mutex_lock (&tc->mutex_start) == 0);
+ assert(pthread_mutex_unlock (&tc->mutex_start) == 0);
+ assert(pthread_mutex_lock (&tc->mutex_ended) == 0);
+ assert(pthread_mutex_unlock (&tc->mutex_started) == 0);
+
+ for (;;)
+ {
+
+ /*
+ * get lock on todo list
+ */
+ assert(pthread_mutex_lock (&mutex_todo) == 0);
+
+ mywork = todo;
+ if (todo >= 0)
+ {
+ ++todo;
+ if (todo >= nwork)
+ todo = -1;
+ }
+ assert(pthread_mutex_unlock (&mutex_todo) == 0);
+
+ if (mywork < 0)
+ break;
+
+ assert((n = do_work_unit (tc->id, mywork)) >= 0);
+ tc->work += n;
+ }
- for (;;) {
+ assert(pthread_mutex_lock (&tc->mutex_end) == 0);
+ assert(pthread_mutex_unlock (&tc->mutex_end) == 0);
+ assert(pthread_mutex_lock (&tc->mutex_started) == 0);
+ assert(pthread_mutex_unlock (&tc->mutex_ended) == 0);
-/* get lock on todo list
-*/
- assert(pthread_mutex_lock (&mutex_todo) == 0);
-
- mywork = todo;
- if (todo >= 0) {
- ++todo;
- if (todo >= nwork)
- todo = -1;
- }
- assert(pthread_mutex_unlock (&mutex_todo) == 0);
-
- if (mywork < 0)
- break;
-
- assert((n = do_work_unit (tc->id, mywork)) >= 0);
- tc->work += n;
- }
-
- assert(pthread_mutex_lock (&tc->mutex_end) == 0);
- assert(pthread_mutex_unlock (&tc->mutex_end) == 0);
- assert(pthread_mutex_lock (&tc->mutex_started) == 0);
- assert(pthread_mutex_unlock (&tc->mutex_ended) == 0);
-
- if (-2 == mywork)
- break;
- }
+ if (-2 == mywork)
+ break;
+ }
- assert(pthread_mutex_unlock (&tc->mutex_started) == 0);
+ assert(pthread_mutex_unlock (&tc->mutex_started) == 0);
- return (0);
+ return (0);
}
static void
dosync (void)
{
- int i;
-
- for (i = 0; i < nthreads; ++i) {
- assert(pthread_mutex_lock (&tcs[i].mutex_end) == 0);
- assert(pthread_mutex_unlock (&tcs[i].mutex_start) == 0);
- assert(pthread_mutex_lock (&tcs[i].mutex_started) == 0);
- assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0);
- }
-
-/* Now threads do their work
-*/
- for (i = 0; i < nthreads; ++i) {
- assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0);
- assert(pthread_mutex_unlock (&tcs[i].mutex_end) == 0);
- assert(pthread_mutex_lock (&tcs[i].mutex_ended) == 0);
- assert(pthread_mutex_unlock (&tcs[i].mutex_ended) == 0);
- }
+ int i;
+
+ for (i = 0; i < nthreads; ++i)
+ {
+ assert(pthread_mutex_lock (&tcs[i].mutex_end) == 0);
+ assert(pthread_mutex_unlock (&tcs[i].mutex_start) == 0);
+ assert(pthread_mutex_lock (&tcs[i].mutex_started) == 0);
+ assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0);
+ }
+
+ /*
+ * Now threads do their work
+ */
+ for (i = 0; i < nthreads; ++i)
+ {
+ assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0);
+ assert(pthread_mutex_unlock (&tcs[i].mutex_end) == 0);
+ assert(pthread_mutex_lock (&tcs[i].mutex_ended) == 0);
+ assert(pthread_mutex_unlock (&tcs[i].mutex_ended) == 0);
+ }
}
static void
dowork (void)
{
- todo = 0;
- dosync();
+ todo = 0;
+ dosync();
- todo = 0;
- dosync();
+ todo = 0;
+ dosync();
}
int
main (int argc, char *argv[])
{
- int i;
-
- assert(NULL != (tcs = calloc (nthreads, sizeof (*tcs))));
-
-/* Launch threads
-*/
- for (i = 0; i < nthreads; ++i) {
- tcs[i].id = i;
-
- assert(pthread_mutex_init (&tcs[i].mutex_start, NULL) == 0);
- assert(pthread_mutex_init (&tcs[i].mutex_started, NULL) == 0);
- assert(pthread_mutex_init (&tcs[i].mutex_end, NULL) == 0);
- assert(pthread_mutex_init (&tcs[i].mutex_ended, NULL) == 0);
-
- tcs[i].work = 0;
-
- assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0);
- assert((tcs[i].stat =
- pthread_create (&tcs[i].thread,
- NULL,
- (void*)&print_server, (void *)&tcs[i])
- ) == 0);
-
-/* Wait for thread initialisation
-*/
- while (1)
- {
- int trylock;
-
- trylock = pthread_mutex_trylock(&tcs[i].mutex_started);
- assert(trylock == 0 || trylock == EBUSY);
-
- if (trylock == 0)
- {
- assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0);
- break;
- }
- }
- }
-
- dowork ();
-
-/* Terminate threads
-*/
- todo = -2; /* please terminate */
- dosync();
-
- for (i = 0; i < nthreads; ++i) {
- if (0 == tcs[i].stat)
- assert(pthread_join (tcs[i].thread, NULL) == 0);
- }
-
-/* destroy locks
-*/
- assert(pthread_mutex_destroy (&mutex_stdout) == 0);
- assert(pthread_mutex_destroy (&mutex_todo) == 0);
-
-/* Cleanup
-*/
- printf ("\n");
-
-/* Show results
-*/
- for (i = 0; i < nthreads; ++i) {
- printf ("%2d ", i);
- if (0 == tcs[i].stat)
- printf ("%10ld\n", tcs[i].work);
- else
- printf ("failed %d\n", tcs[i].stat);
-
- assert(pthread_mutex_destroy (&tcs[i].mutex_start) == 0);
- assert(pthread_mutex_destroy (&tcs[i].mutex_started) == 0);
- assert(pthread_mutex_destroy (&tcs[i].mutex_end) == 0);
- assert(pthread_mutex_destroy (&tcs[i].mutex_ended) == 0);
- }
-
- die (0);
-
- return (0);
+ int i;
+
+ assert(NULL != (tcs = calloc (nthreads, sizeof (*tcs))));
+
+ /*
+ * Launch threads
+ */
+ for (i = 0; i < nthreads; ++i)
+ {
+ tcs[i].id = i;
+
+ assert(pthread_mutex_init (&tcs[i].mutex_start, NULL) == 0);
+ assert(pthread_mutex_init (&tcs[i].mutex_started, NULL) == 0);
+ assert(pthread_mutex_init (&tcs[i].mutex_end, NULL) == 0);
+ assert(pthread_mutex_init (&tcs[i].mutex_ended, NULL) == 0);
+
+ tcs[i].work = 0;
+
+ assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0);
+ assert((tcs[i].stat =
+ pthread_create (&tcs[i].thread,
+ NULL,
+ (void*)&print_server, (void *)&tcs[i])
+ ) == 0);
+
+ /*
+ * Wait for thread initialisation
+ */
+ {
+ int trylock = 0;
+
+ while (trylock == 0)
+ {
+ trylock = pthread_mutex_trylock(&tcs[i].mutex_started);
+ assert(trylock == 0 || trylock == EBUSY);
+
+ if (trylock == 0)
+ {
+ assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0);
+ }
+ }
+ }
+ }
+
+ dowork ();
+
+ /*
+ * Terminate threads
+ */
+ todo = -2; /* please terminate */
+ dosync();
+
+ for (i = 0; i < nthreads; ++i)
+ {
+ if (0 == tcs[i].stat)
+ assert(pthread_join (tcs[i].thread, NULL) == 0);
+ }
+
+ /*
+ * destroy locks
+ */
+ assert(pthread_mutex_destroy (&mutex_stdout) == 0);
+ assert(pthread_mutex_destroy (&mutex_todo) == 0);
+
+ /*
+ * Cleanup
+ */
+ printf ("\n");
+
+ /*
+ * Show results
+ */
+ for (i = 0; i < nthreads; ++i)
+ {
+ printf ("%2d ", i);
+ if (0 == tcs[i].stat)
+ printf ("%10ld\n", tcs[i].work);
+ else
+ printf ("failed %d\n", tcs[i].stat);
+
+ assert(pthread_mutex_destroy (&tcs[i].mutex_start) == 0);
+ assert(pthread_mutex_destroy (&tcs[i].mutex_started) == 0);
+ assert(pthread_mutex_destroy (&tcs[i].mutex_end) == 0);
+ assert(pthread_mutex_destroy (&tcs[i].mutex_ended) == 0);
+ }
+
+ die (0);
+
+ return (0);
}
diff --git a/tests/mutex2.c b/tests/mutex2.c
index 7956f14..b161899 100644
--- a/tests/mutex2.c
+++ b/tests/mutex2.c
@@ -16,8 +16,14 @@ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int
main()
{
+ assert(mutex == PTHREAD_MUTEX_INITIALIZER);
+
assert(pthread_mutex_lock(&mutex) == 0);
+ assert(mutex != PTHREAD_MUTEX_INITIALIZER);
+
+ assert(mutex != NULL);
+
assert(pthread_mutex_unlock(&mutex) == 0);
return 0;
diff --git a/tests/tsd1.c b/tests/tsd1.c
index 93403b1..9448c10 100644
--- a/tests/tsd1.c
+++ b/tests/tsd1.c
@@ -146,7 +146,7 @@ main()
assert(pthread_key_delete(key) == 0);
- for (i = 0; i < 10; i++)
+ for (i = 1; i < 10; i++)
{
/*
* The counter is incremented once when the key is set to
@@ -165,5 +165,5 @@ main()
fflush(stderr);
- return (fail) ? 1 : 0;
+ return (fail);
}