diff options
| -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)       /*        * ------------------------------------------------------  | 
