Changeset 9093c3c in rtems


Ignore:
Timestamp:
09/17/96 21:29:51 (27 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
aa48536
Parents:
ded66f8
Message:

Corrected implementation of timed wait on condition variables. First
the timeout is given as a wall-time not an interval as was previously
implemented. Second, the interpretation of ETIMEDOUT behavior was
incorrect as all possible error cases needed to be checked before
this error was returned. This caused problems when the wall-time
specified was in the past.

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/exec/posix/src/cond.c

    rded66f8 r9093c3c  
    364364  pthread_cond_t            *cond,
    365365  pthread_mutex_t           *mutex,
    366   Watchdog_Interval          timeout
     366  Watchdog_Interval          timeout,
     367  boolean                    already_timedout
    367368)
    368369{
     
    370371  Objects_Locations                           location;
    371372  int                                         status;
     373  int                                         mutex_status;
    372374 
    373375  if ( !_POSIX_Mutex_Get( mutex, &location ) ) {
     
    392394      }
    393395 
    394       the_cond->Mutex = *mutex;
    395  
    396       status = pthread_mutex_unlock( mutex );
    397 /* XXX ignore this for now
    398       if ( status ) {
     396      (void) pthread_mutex_unlock( mutex );
     397/* XXX ignore this for now  since behavior is undefined
     398      if ( mutex_status ) {
    399399        _Thread_Enable_dispatch();
    400400        return EINVAL;
    401401      }
    402402*/
    403  
    404       _Thread_queue_Enter_critical_section( &the_cond->Wait_queue );
    405       _Thread_Executing->Wait.return_code = 0;
    406       _Thread_Executing->Wait.queue       = &the_cond->Wait_queue;
    407       _Thread_Executing->Wait.id          = *cond;
    408 
    409       _Thread_queue_Enqueue( &the_cond->Wait_queue, timeout );
    410 
    411       _Thread_Enable_dispatch();
    412 
    413       /*
    414        *  Switch ourself out because we blocked as a result of the
    415        *  _Thread_queue_Enqueue.
    416        */
    417 
    418       if ( _Thread_Executing->Wait.return_code )
    419         return _Thread_Executing->Wait.return_code;
    420 
    421       status = pthread_mutex_lock( mutex );
    422       if ( status )
     403
     404      if ( !already_timedout ) {
     405        the_cond->Mutex = *mutex;
     406 
     407        _Thread_queue_Enter_critical_section( &the_cond->Wait_queue );
     408        _Thread_Executing->Wait.return_code = 0;
     409        _Thread_Executing->Wait.queue       = &the_cond->Wait_queue;
     410        _Thread_Executing->Wait.id          = *cond;
     411
     412        _Thread_queue_Enqueue( &the_cond->Wait_queue, timeout );
     413
     414        _Thread_Enable_dispatch();
     415
     416        /*
     417         *  Switch ourself out because we blocked as a result of the
     418         *  _Thread_queue_Enqueue.
     419         */
     420
     421        status = _Thread_Executing->Wait.return_code;
     422        if ( status && status != ETIMEDOUT )
     423          return status;
     424
     425      }
     426      else
     427        status = ETIMEDOUT;
     428
     429      mutex_status = pthread_mutex_lock( mutex );
     430      if ( mutex_status )
    423431        return EINVAL;
    424432   
    425       return _Thread_Executing->Wait.return_code;
     433      return status;
    426434  }
    427435  return POSIX_BOTTOM_REACHED();
     
    441449    cond,
    442450    mutex,
    443     THREAD_QUEUE_WAIT_FOREVER
     451    THREAD_QUEUE_WAIT_FOREVER,
     452    FALSE
    444453  );
    445454}
     
    456465)
    457466{
     467  Watchdog_Interval timeout;
     468  struct timespec   current_time;
     469  struct timespec   difference;
     470  boolean           already_timedout = FALSE;
     471
    458472  if ( !abstime )
    459473    return EINVAL;
    460474
    461 /* XXX need to fully address an error occuring in the total timespec */
    462 
    463   if ( abstime->tv_sec < 0 || abstime->tv_nsec < 0 )
    464     return EINVAL;
    465 
    466   if ( abstime->tv_nsec >= TOD_NANOSECONDS_PER_SECOND )
    467     return EINVAL;
    468  
     475  /*
     476   *  The abstime is a walltime.  We turn it into an interval.
     477   */
     478
     479  (void) clock_gettime( CLOCK_REALTIME, &current_time );
     480
     481  /* XXX probably some error checking should go here */
     482
     483  _POSIX_Timespec_subtract( &current_time, abstime, &difference );
     484
     485  if ( ( difference.tv_sec < 0 ) || ( ( difference.tv_sec == 0 ) &&
     486       ( difference.tv_nsec < 0 ) ) )
     487    already_timedout = TRUE;   
     488
     489  timeout = _POSIX_Timespec_to_interval( &difference );
     490
    469491  return _POSIX_Condition_variables_Wait_support(
    470492    cond,
    471493    mutex,
    472     _POSIX_Timespec_to_interval( abstime )
     494    timeout,
     495    already_timedout
    473496  );
    474497}
  • cpukit/posix/src/cond.c

    rded66f8 r9093c3c  
    364364  pthread_cond_t            *cond,
    365365  pthread_mutex_t           *mutex,
    366   Watchdog_Interval          timeout
     366  Watchdog_Interval          timeout,
     367  boolean                    already_timedout
    367368)
    368369{
     
    370371  Objects_Locations                           location;
    371372  int                                         status;
     373  int                                         mutex_status;
    372374 
    373375  if ( !_POSIX_Mutex_Get( mutex, &location ) ) {
     
    392394      }
    393395 
    394       the_cond->Mutex = *mutex;
    395  
    396       status = pthread_mutex_unlock( mutex );
    397 /* XXX ignore this for now
    398       if ( status ) {
     396      (void) pthread_mutex_unlock( mutex );
     397/* XXX ignore this for now  since behavior is undefined
     398      if ( mutex_status ) {
    399399        _Thread_Enable_dispatch();
    400400        return EINVAL;
    401401      }
    402402*/
    403  
    404       _Thread_queue_Enter_critical_section( &the_cond->Wait_queue );
    405       _Thread_Executing->Wait.return_code = 0;
    406       _Thread_Executing->Wait.queue       = &the_cond->Wait_queue;
    407       _Thread_Executing->Wait.id          = *cond;
    408 
    409       _Thread_queue_Enqueue( &the_cond->Wait_queue, timeout );
    410 
    411       _Thread_Enable_dispatch();
    412 
    413       /*
    414        *  Switch ourself out because we blocked as a result of the
    415        *  _Thread_queue_Enqueue.
    416        */
    417 
    418       if ( _Thread_Executing->Wait.return_code )
    419         return _Thread_Executing->Wait.return_code;
    420 
    421       status = pthread_mutex_lock( mutex );
    422       if ( status )
     403
     404      if ( !already_timedout ) {
     405        the_cond->Mutex = *mutex;
     406 
     407        _Thread_queue_Enter_critical_section( &the_cond->Wait_queue );
     408        _Thread_Executing->Wait.return_code = 0;
     409        _Thread_Executing->Wait.queue       = &the_cond->Wait_queue;
     410        _Thread_Executing->Wait.id          = *cond;
     411
     412        _Thread_queue_Enqueue( &the_cond->Wait_queue, timeout );
     413
     414        _Thread_Enable_dispatch();
     415
     416        /*
     417         *  Switch ourself out because we blocked as a result of the
     418         *  _Thread_queue_Enqueue.
     419         */
     420
     421        status = _Thread_Executing->Wait.return_code;
     422        if ( status && status != ETIMEDOUT )
     423          return status;
     424
     425      }
     426      else
     427        status = ETIMEDOUT;
     428
     429      mutex_status = pthread_mutex_lock( mutex );
     430      if ( mutex_status )
    423431        return EINVAL;
    424432   
    425       return _Thread_Executing->Wait.return_code;
     433      return status;
    426434  }
    427435  return POSIX_BOTTOM_REACHED();
     
    441449    cond,
    442450    mutex,
    443     THREAD_QUEUE_WAIT_FOREVER
     451    THREAD_QUEUE_WAIT_FOREVER,
     452    FALSE
    444453  );
    445454}
     
    456465)
    457466{
     467  Watchdog_Interval timeout;
     468  struct timespec   current_time;
     469  struct timespec   difference;
     470  boolean           already_timedout = FALSE;
     471
    458472  if ( !abstime )
    459473    return EINVAL;
    460474
    461 /* XXX need to fully address an error occuring in the total timespec */
    462 
    463   if ( abstime->tv_sec < 0 || abstime->tv_nsec < 0 )
    464     return EINVAL;
    465 
    466   if ( abstime->tv_nsec >= TOD_NANOSECONDS_PER_SECOND )
    467     return EINVAL;
    468  
     475  /*
     476   *  The abstime is a walltime.  We turn it into an interval.
     477   */
     478
     479  (void) clock_gettime( CLOCK_REALTIME, &current_time );
     480
     481  /* XXX probably some error checking should go here */
     482
     483  _POSIX_Timespec_subtract( &current_time, abstime, &difference );
     484
     485  if ( ( difference.tv_sec < 0 ) || ( ( difference.tv_sec == 0 ) &&
     486       ( difference.tv_nsec < 0 ) ) )
     487    already_timedout = TRUE;   
     488
     489  timeout = _POSIX_Timespec_to_interval( &difference );
     490
    469491  return _POSIX_Condition_variables_Wait_support(
    470492    cond,
    471493    mutex,
    472     _POSIX_Timespec_to_interval( abstime )
     494    timeout,
     495    already_timedout
    473496  );
    474497}
Note: See TracChangeset for help on using the changeset viewer.