diff options
Diffstat (limited to 'condvar.c')
| -rw-r--r-- | condvar.c | 62 | 
1 files changed, 34 insertions, 28 deletions
@@ -530,19 +530,23 @@ typedef struct {    pthread_mutex_t * mutexPtr;    pthread_cond_t cv;    int * resultPtr; -} cond_wait_cleanup_args_t; +} ptw32_cond_wait_cleanup_args_t;  static void -cond_wait_cleanup(void * args) +ptw32_cond_wait_cleanup(void * args)  { -  cond_wait_cleanup_args_t * cleanup_args = (cond_wait_cleanup_args_t *) args; +  ptw32_cond_wait_cleanup_args_t * cleanup_args = (ptw32_cond_wait_cleanup_args_t *) args;    pthread_mutex_t * mutexPtr = cleanup_args->mutexPtr;    pthread_cond_t cv = cleanup_args->cv;    int * resultPtr = cleanup_args->resultPtr; -  int lock_result;    int lastWaiter = FALSE; -  if ((lock_result = pthread_mutex_lock (&(cv->waitersLock))) == 0) +  /* +   * Whether we got here legitimately or because of an error we +   * indicate that we are no longer waiting. The alternative +   * will result in never signaling the broadcasting thread. +   */ +  if (pthread_mutex_lock (&(cv->waitersLock)) == 0)      {        /*         * The waiter is responsible for decrementing @@ -558,40 +562,42 @@ cond_wait_cleanup(void * args)            cv->wasBroadcast = FALSE;          } -      lock_result = pthread_mutex_unlock (&(cv->waitersLock)); +      (void) pthread_mutex_unlock (&(cv->waitersLock));      } -  if ((*resultPtr == 0 || *resultPtr == ETIMEDOUT) && lock_result == 0) +  /* +   * If we are the last waiter on this broadcast +   * let the thread doing the broadcast proceed +   */ +  if (lastWaiter && !SetEvent (cv->waitersDone))      { -      if (lastWaiter) -        { -          /* -           * If we are the last waiter on this broadcast -           * let the thread doing the broadcast proceed -           */ -          if (!SetEvent (cv->waitersDone)) -            { -              *resultPtr = EINVAL; -            } -        } +      *resultPtr = EINVAL;      }    /*     * We must always regain the external mutex, even when     * errors occur, because that's the guarantee that we give -   * to our callers +   * to our callers. +   * +   * Note that the broadcasting thread may already own the lock. +   * The standard actually requires that the signaling thread hold +   * the lock at the time that it signals if the developer wants +   * predictable scheduling behaviour. It's up to the developer. +   * In that case all waiting threads will block here until +   * the broadcasting thread releases the lock, having been +   * notified by the last waiting thread (SetEvent call above).     */    (void) pthread_mutex_lock (mutexPtr);  }  static int  ptw32_cond_timedwait (pthread_cond_t * cond,  -		pthread_mutex_t * mutex, -		const struct timespec *abstime) +                      pthread_mutex_t * mutex, +                      const struct timespec *abstime)  {    int result = 0;    pthread_cond_t cv; -  cond_wait_cleanup_args_t cleanup_args; +  ptw32_cond_wait_cleanup_args_t cleanup_args;    if (cond == NULL || *cond == NULL)      { @@ -644,15 +650,15 @@ ptw32_cond_timedwait (pthread_cond_t * cond,    cleanup_args.cv = cv;    cleanup_args.resultPtr = &result; -  pthread_cleanup_push (cond_wait_cleanup, (void *) &cleanup_args); +  pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *) &cleanup_args);    if ((result = pthread_mutex_unlock (mutex)) == 0)      {        /*         * Wait to be awakened by         *              pthread_cond_signal, or -       *              pthread_cond_broadcast -       *              timeout +       *              pthread_cond_broadcast, or +       *              a timeout         *         * Note:          *      ptw32_sem_timedwait is a cancelation point, @@ -668,7 +674,7 @@ ptw32_cond_timedwait (pthread_cond_t * cond,  	}      } -  pthread_cleanup_pop (1); +  pthread_cleanup_pop (1);  /* Always cleanup */    /*     * "result" can be modified by the cleanup handler. @@ -737,8 +743,8 @@ pthread_cond_wait (pthread_cond_t * cond,  int  pthread_cond_timedwait (pthread_cond_t * cond,  -		pthread_mutex_t * mutex, -		const struct timespec *abstime) +                        pthread_mutex_t * mutex, +                        const struct timespec *abstime)       /*        * ------------------------------------------------------        * DOCPUBLIC  | 
