summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog26
-rw-r--r--condvar.c149
-rw-r--r--implement.h2
-rw-r--r--misc.c6
-rw-r--r--pthread.h5
-rw-r--r--semaphore.c61
6 files changed, 180 insertions, 69 deletions
diff --git a/ChangeLog b/ChangeLog
index 4adbc7e..170f913 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+Fri Jan 15 15:41:28 1999 Ross Johnson <rpj@swan.canberra.edu.au>
+
+ * pthread.h: Add new 'abstime' arg to pthreadCancelableWait()
+ prototype.
+
+ * condvar.c (cond_timedwait): New generalised function called by
+ both pthread_cond_wait() and pthread_cond_timedwait(). This is
+ essentially pthread_cond_wait() renamed and modified to add the
+ 'abstime' arg and call the new _pthread_sem_timedwait() instead of
+ sem_wait().
+ (pthread_cond_wait): Now just calls the internal static
+ function cond_timedwait() with an INFINITE wait.
+ (pthread_cond_timedwait): Now implemented. Calls the internal
+ static function cond_timedwait().
+
+ * implement.h (_pthread_sem_timedwait): New internal function
+ prototype.
+
+ * misc.c (pthreadCancelableWait): Added new 'abstime' argument
+ to allow shorter than INFINITE wait.
+
+ * semaphore.c (_pthread_sem_timedwait): New function for internal
+ use. This is essentially sem_wait() modified to add the
+ 'abstime' arg and call the modified (see above)
+ pthreadCancelableWait().
+
Thu Jan 14 14:27:13 1999 Ross Johnson <rpj@swan.canberra.edu.au>
* cleanup.c: Correct _cplusplus to __cplusplus wherever used.
diff --git a/condvar.c b/condvar.c
index c4e846b..5bf99e8 100644
--- a/condvar.c
+++ b/condvar.c
@@ -400,53 +400,10 @@ pthread_cond_destroy (pthread_cond_t * cond)
return (result);
}
-int
-pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
- /*
- * ------------------------------------------------------
- * DOCPUBLIC
- * This function waits on a condition variable until
- * awakened by a signal or broadcast.
- *
- * Caller MUST be holding the mutex lock; the
- * lock is released and the caller is blocked waiting
- * on 'cond'. When 'cond' is signaled, the mutex
- * is re-acquired before returning to the caller.
- *
- * PARAMETERS
- * cond
- * pointer to an instance of pthread_cond_t
- *
- * mutex
- * pointer to an instance of pthread_mutex_t
- *
- *
- * DESCRIPTION
- * This function waits on a condition variable until
- * awakened by a signal or broadcast.
- *
- * NOTES:
- * 1) The function must be called with 'mutex' LOCKED
- * by the calling thread, or undefined behaviour
- * will result.
- *
- * 2) This routine atomically releases 'mutex' and causes
- * the calling thread to block on the condition variable.
- * The blocked thread may be awakened by
- * pthread_cond_signal or
- * pthread_cond_broadcast.
- *
- * Upon successful completion, the 'mutex' has been locked and
- * is owned by the calling thread.
- *
- * RESULTS
- * 0 caught condition; mutex released,
- * EINVAL 'cond' or 'mutex' is invalid,
- * EINVAL different mutexes for concurrent waits,
- * EINVAL mutex is not held by the calling thread,
- *
- * ------------------------------------------------------
- */
+static int
+cond_timedwait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex,
+ const struct timespec *abstime)
{
int result = 0;
pthread_cond_t cv;
@@ -457,9 +414,9 @@ pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
/*
* OK to increment cv->waiters because the caller locked 'mutex'
*
- * FIXME: This is true. However, it is technically possible to call cond_wait
- * on this cv with a different mutex. The standard leaves the result of such an
- * action as undefined. (RPJ)
+ * [RPJ] FIXME: This can still lead to race conditions, which I think
+ * are NOT the same as the unpredictable scheduling behaviour noted in the
+ * POSIX Pthread specs.
*/
cv->waiters++;
@@ -478,14 +435,15 @@ pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
* pthread_cond_broadcast
*
* Note:
- * sem_wait is a cancellation point, hence providing the
+ * _pthread_sem_timedwait is a cancellation point,
+ * hence providing the
* mechanism for making pthread_cond_wait a cancellation
* point. We use the cleanup mechanism to ensure we
* re-lock the mutex if we are cancelled.
*/
pthread_cleanup_push (pthread_mutex_lock, mutex);
- result = sem_wait (&(cv->sema));
+ result = _pthread_sem_timedwait (&(cv->sema), abstime);
pthread_cleanup_pop (0);
}
@@ -529,18 +487,74 @@ pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex)
return (result);
+} /* cond_timedwait */
+
+
+int
+pthread_cond_wait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function waits on a condition variable until
+ * awakened by a signal or broadcast.
+ *
+ * Caller MUST be holding the mutex lock; the
+ * lock is released and the caller is blocked waiting
+ * on 'cond'. When 'cond' is signaled, the mutex
+ * is re-acquired before returning to the caller.
+ *
+ * PARAMETERS
+ * cond
+ * pointer to an instance of pthread_cond_t
+ *
+ * mutex
+ * pointer to an instance of pthread_mutex_t
+ *
+ *
+ * DESCRIPTION
+ * This function waits on a condition variable until
+ * awakened by a signal or broadcast.
+ *
+ * NOTES:
+ * 1) The function must be called with 'mutex' LOCKED
+ * by the calling thread, or undefined behaviour
+ * will result.
+ *
+ * 2) This routine atomically releases 'mutex' and causes
+ * the calling thread to block on the condition variable.
+ * The blocked thread may be awakened by
+ * pthread_cond_signal or
+ * pthread_cond_broadcast.
+ *
+ * Upon successful completion, the 'mutex' has been locked and
+ * is owned by the calling thread.
+ *
+ *
+ * RESULTS
+ * 0 caught condition; mutex released,
+ * EINVAL 'cond' or 'mutex' is invalid,
+ * EINVAL different mutexes for concurrent waits,
+ * EINVAL mutex is not held by the calling thread,
+ *
+ * ------------------------------------------------------
+ */
+{
+ /* The NULL abstime arg means INFINITE waiting. */
+ return(cond_timedwait(cond, mutex, NULL));
} /* pthread_cond_wait */
int
-pthread_cond_timedwait (pthread_cond_t * cond,
- pthread_mutex_t * mutex,
- const struct timespec *abstime)
+pthread_cond_timedwait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex,
+ const struct timespec *abstime)
/*
* ------------------------------------------------------
* DOCPUBLIC
- * This function initializes an unnamed semaphore. the
- * initial value of the semaphore is 'value'
+ * This function waits on a condition variable either until
+ * awakened by a signal or broadcast; or until the time
+ * specified by abstime passes.
*
* PARAMETERS
* cond
@@ -569,21 +583,30 @@ pthread_cond_timedwait (pthread_cond_t * cond,
* pthread_cond_signal or
* pthread_cond_broadcast.
*
+ *
* RESULTS
* 0 caught condition; mutex released,
- * EINVAL 'cond' or 'mutex' is invalid,
+ * EINVAL 'cond', 'mutex', or abstime is invalid,
* EINVAL different mutexes for concurrent waits,
* EINVAL mutex is not held by the calling thread,
+ * ETIMEDOUT abstime ellapsed before cond was signaled.
*
* ------------------------------------------------------
*/
{
int result = 0;
- /*
- * NOT IMPLEMENTED YET!!!
- */
- return (result);
-}
+
+ if (abstime == NULL)
+ {
+ result = EINVAL;
+ }
+ else
+ {
+ result = cond_timedwait(cond, mutex, abstime);
+ }
+
+ return(result);
+} /* pthread_cond_timedwait */
int
diff --git a/implement.h b/implement.h
index 79342e1..be71b7e 100644
--- a/implement.h
+++ b/implement.h
@@ -166,6 +166,8 @@ int _pthread_tkAssocCreate (ThreadKeyAssoc ** assocP,
void _pthread_tkAssocDestroy (ThreadKeyAssoc * assoc);
+int _pthread_sem_timedwait (sem_t * sem, const struct timespec * abstime);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/misc.c b/misc.c
index f49cd51..d6c4b2f 100644
--- a/misc.c
+++ b/misc.c
@@ -130,7 +130,7 @@ pthread_equal (pthread_t t1, pthread_t t2)
int
-pthreadCancelableWait (HANDLE waitHandle)
+pthreadCancelableWait (HANDLE waitHandle, DWORD abstime)
/*
* -------------------------------------------------------------------
* This provides an extra hook into the pthread_cancel
@@ -177,7 +177,7 @@ pthreadCancelableWait (HANDLE waitHandle)
nHandles,
handles,
FALSE,
- INFINITE);
+ abstime);
if (status == WAIT_FAILED)
@@ -187,7 +187,7 @@ pthreadCancelableWait (HANDLE waitHandle)
}
else if (status == WAIT_ABANDONED_0)
{
- result = EINVAL;
+ result = ETIMEDOUT;
}
else
diff --git a/pthread.h b/pthread.h
index 455cf19..861a0e8 100644
--- a/pthread.h
+++ b/pthread.h
@@ -918,9 +918,10 @@ int pthread_attr_setschedparam (pthread_attr_t *attr,
* WaitForMultipleObjects
*
* on 'waitHandle' and a manually reset WIN32 Event
- * used to implement pthread_cancel.
+ * used to implement pthread_cancel. The 'abstime'
+ * argument is simply passed to WaitForMultipleObjects.
*/
-int pthreadCancelableWait (HANDLE waitHandle);
+int pthreadCancelableWait (HANDLE waitHandle, DWORD abstime);
/*
* Thread-Safe C Runtime Library Mappings
diff --git a/semaphore.c b/semaphore.c
index 8ab326b..fc24b1a 100644
--- a/semaphore.c
+++ b/semaphore.c
@@ -203,7 +203,7 @@ sem_wait (sem_t * sem)
* a signal.
*
* RESULTS
- * 0 successfully destroyed semaphore,
+ * 0 successfully decreased semaphore,
* EINVAL 'sem' is not a valid semaphore,
* ENOSYS semaphores are not supported,
* EINTR the function was interrupted by a signal,
@@ -222,6 +222,65 @@ sem_wait (sem_t * sem)
int
+_pthread_sem_timedwait (sem_t * sem, const struct timespec * abstime)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * This function waits on a semaphore for at most
+ * 'abstime'.
+ *
+ * PARAMETERS
+ * sem
+ * pointer to an instance of sem_t
+ *
+ * abstime
+ * pointer to an instance of struct timespec
+ *
+ * DESCRIPTION
+ * This function waits on a semaphore. If the
+ * semaphore value is greater than zero, it decreases
+ * its value by one. If the semaphore value is zero, then
+ * the calling thread (or process) is blocked until it can
+ * successfully decrease the value or until interrupted by
+ * a signal.
+ *
+ * If 'abstime' is a NULL pointer then this function will
+ * block until it can successfully decrease the value or
+ * until interrupted by a signal.
+ *
+ * RESULTS
+ * 0 successfully decreased semaphore,
+ * EINVAL 'sem' is not a valid semaphore,
+ * ENOSYS semaphores are not supported,
+ * EINTR the function was interrupted by a signal,
+ * EDEADLK a deadlock condition was detected.
+ * ETIMEDOUT abstime elapsed before success.
+ *
+ * ------------------------------------------------------
+ */
+{
+ DWORD msecs;
+
+ if (abstime == NULL)
+ {
+ msecs = INFINITE;
+ }
+ else
+ {
+ /* Calculate the number of milliseconds in abstime. */
+ msecs = abstime->tv_sec * 1000;
+ msecs += abstime->tv_nsec / 1000000;
+ }
+
+ return ((sem == NULL)
+ ? EINVAL
+ : pthreadCancelableWait (*sem, msecs)
+ );
+
+} /* sem_wait */
+
+
+int
sem_post (sem_t * sem)
/*
* ------------------------------------------------------