diff options
author | rpj <rpj> | 1999-01-14 22:33:54 +0000 |
---|---|---|
committer | rpj <rpj> | 1999-01-14 22:33:54 +0000 |
commit | 677bfb0881c56dad767a07b31ac543db284e16c6 (patch) | |
tree | 1a25c36c4291cb435b1196ffad2ae80f31829ce7 | |
parent | d0b36781d64a52a93ffec89d7b89a243793ea835 (diff) |
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().
-rw-r--r-- | ChangeLog | 26 | ||||
-rw-r--r-- | condvar.c | 149 | ||||
-rw-r--r-- | implement.h | 2 | ||||
-rw-r--r-- | misc.c | 6 | ||||
-rw-r--r-- | pthread.h | 5 | ||||
-rw-r--r-- | semaphore.c | 61 |
6 files changed, 180 insertions, 69 deletions
@@ -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. @@ -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 */ @@ -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 @@ -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) /* * ------------------------------------------------------ |