Changeset a2cf229 in rtems


Ignore:
Timestamp:
Jul 22, 2008, 5:17:12 PM (11 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.8
Children:
e5c0540
Parents:
a570a14
Message:

2008-07-18 Joel Sherrill <joel.sherrill@…>

PR 1291/cpukit

  • itron/inline/rtems/itron/semaphore.inl, itron/src/twai_sem.c, posix/include/mqueue.h, posix/include/rtems/posix/mqueue.h, posix/include/rtems/posix/semaphore.h, posix/include/rtems/posix/time.h, posix/src/condtimedwait.c, posix/src/mqueuereceive.c, posix/src/mqueuerecvsupp.c, posix/src/mqueuesend.c, posix/src/mqueuesendsupp.c, posix/src/mqueuetimedreceive.c, posix/src/mqueuetimedsend.c, posix/src/mutextimedlock.c, posix/src/mutextranslatereturncode.c, posix/src/posixtimespecabsolutetimeout.c, posix/src/prwlocktimedrdlock.c, posix/src/prwlocktimedwrlock.c, posix/src/semaphoretranslatereturncode.c, posix/src/semaphorewaitsupp.c, posix/src/semtimedwait.c, posix/src/semtrywait.c, posix/src/semwait.c, posix/src/sigtimedwait.c, posix/src/timersettime.c, posix/src/ualarm.c, rtems/src/semobtain.c, rtems/src/semtranslatereturncode.c, score/include/rtems/score/coremutex.h, score/include/rtems/score/coresem.h, score/src/coresemseize.c: This patch addresses issues on implementation of the timeout on the following POSIX services. Some of these services incorrectly took a timeout as a relative time. Others would compute a 0 delta to timeout if the absolute time and the current time were equal and thus incorrectly block the caller forever. The root of the confusion is that POSIX specifies that if the timeout is incorrect (e.g. in the past, is now, or is numerically invalid), that it does not matter if the call would succeed without blocking. This is in contrast to RTEMS programming style where all errors are checked before any critical sections are entered. This fix implemented a more uniform way of handling POSIX absolute time timeouts.

+ pthread_cond_timedwait - could block forever
+ mq_timedreceive - used relative not absolute time
+ mq_timedsend - used relative not absolute time
+ pthread_mutex_timedlock - used relative not absolute time
+ pthread_rwlock_timedrdlock- used relative not absolute time
+ pthread_rwlock_timedwrlock- used relative not absolute time
+ sem_timedwait - could block forever

Location:
cpukit
Files:
28 edited

Legend:

Unmodified
Added
Removed
  • cpukit/ChangeLog

    ra570a14 ra2cf229  
     12008-07-18      Joel Sherrill <joel.sherrill@oarcorp.com>
     2
     3        PR 1291/cpukit
     4        * itron/inline/rtems/itron/semaphore.inl, itron/src/twai_sem.c,
     5        posix/include/mqueue.h, posix/include/rtems/posix/mqueue.h,
     6        posix/include/rtems/posix/semaphore.h,
     7        posix/include/rtems/posix/time.h, posix/src/condtimedwait.c,
     8        posix/src/mqueuereceive.c, posix/src/mqueuerecvsupp.c,
     9        posix/src/mqueuesend.c, posix/src/mqueuesendsupp.c,
     10        posix/src/mqueuetimedreceive.c, posix/src/mqueuetimedsend.c,
     11        posix/src/mutextimedlock.c, posix/src/mutextranslatereturncode.c,
     12        posix/src/posixtimespecabsolutetimeout.c,
     13        posix/src/prwlocktimedrdlock.c, posix/src/prwlocktimedwrlock.c,
     14        posix/src/semaphoretranslatereturncode.c,
     15        posix/src/semaphorewaitsupp.c, posix/src/semtimedwait.c,
     16        posix/src/semtrywait.c, posix/src/semwait.c,
     17        posix/src/sigtimedwait.c, posix/src/timersettime.c,
     18        posix/src/ualarm.c, rtems/src/semobtain.c,
     19        rtems/src/semtranslatereturncode.c,
     20        score/include/rtems/score/coremutex.h,
     21        score/include/rtems/score/coresem.h, score/src/coresemseize.c: This
     22        patch addresses issues on implementation of the timeout on the
     23        following POSIX services. Some of these services incorrectly took a
     24        timeout as a relative time. Others would compute a 0 delta to timeout
     25        if the absolute time and the current time were equal and thus
     26        incorrectly block the caller forever. The root of the confusion is
     27        that POSIX specifies that if the timeout is incorrect (e.g. in the
     28        past, is now, or is numerically invalid), that it does not matter if
     29        the call would succeed without blocking. This is in contrast to RTEMS
     30        programming style where all errors are checked before any critical
     31        sections are entered. This fix implemented a more uniform way of
     32        handling POSIX absolute time timeouts.
     33            + pthread_cond_timedwait - could block forever
     34            + mq_timedreceive - used relative not absolute time
     35            + mq_timedsend - used relative not absolute time
     36            + pthread_mutex_timedlock - used relative not absolute time
     37            + pthread_rwlock_timedrdlock- used relative not absolute time
     38            + pthread_rwlock_timedwrlock- used relative not absolute time
     39            + sem_timedwait - could block forever
     40
    1412008-05-06      Joel Sherrill <joel.sherrill@OARcorp.com>
    242
  • cpukit/itron/inline/rtems/itron/semaphore.inl

    ra570a14 ra2cf229  
    173173    case CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED:
    174174      return E_QOVR;
    175     case CORE_SEMAPHORE_BAD_TIMEOUT_VALUE:
    176       return E_PAR;
    177175    case THREAD_STATUS_PROXY_BLOCKING:
    178176      return THREAD_STATUS_PROXY_BLOCKING;
  • cpukit/itron/src/twai_sem.c

    ra570a14 ra2cf229  
    3131)
    3232{
    33   ITRON_Semaphore_Control        *the_semaphore;
    34   Objects_Locations               location;
    35   Watchdog_Interval               interval;
    36   Core_semaphore_Blocking_option  blocking;
     33  ITRON_Semaphore_Control  *the_semaphore;
     34  Objects_Locations         location;
     35  Watchdog_Interval         interval;
     36  boolean                   blocking;
    3737
    3838  interval = 0;
    3939  if ( tmout == TMO_POL ) {
    40     blocking = CORE_SEMAPHORE_NO_WAIT;
     40    blocking = FALSE;
    4141  } else {
    42     blocking = CORE_SEMAPHORE_BLOCK_FOREVER;
     42    blocking = TRUE;
    4343
    4444    if ( tmout != TMO_FEVR )
  • cpukit/posix/include/mqueue.h

    ra570a14 ra2cf229  
    2727 */
    2828
     29/**
     30 *  Message queue id type
     31 */
    2932typedef Objects_Id  mqd_t;
    3033
     34/**
     35 *  This is the message queue attributes structure.
     36 */
    3137struct mq_attr {
    32   long  mq_flags;     /* Message queue flags */
    33   long  mq_maxmsg;    /* Maximum number of messages */
    34   long  mq_msgsize;   /* Maximum message size */
    35   long  mq_curmsgs;   /* Number of messages currently queued */
     38  /** This is the message queue flags */
     39  long  mq_flags;
     40  /** This is the maximum number of messages */
     41  long  mq_maxmsg;
     42  /** This is the maximum message size */
     43  long  mq_msgsize;
     44  /** This is the mumber of messages currently queued */
     45  long  mq_curmsgs;
    3646};
    3747
    38 /*
     48/**
    3949 *  15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
    4050 */
    41 
    4251mqd_t mq_open(
    4352  const char *name,
     
    4655);
    4756
    48 /*
     57/**
    4958 *  15.2.2 Close a Message Queue, P1003.1b-1993, p. 275
    5059 */
    51 
    5260int mq_close(
    5361  mqd_t  mqdes
    5462);
    5563
    56 /*
     64/**
    5765 *  15.2.2 Remove a Message Queue, P1003.1b-1993, p. 276
    5866 */
    59 
    6067int mq_unlink(
    6168  const char *name
    6269);
    6370
    64 /*
     71/**
    6572 *  15.2.4 Send a Message to a Message Queue, P1003.1b-1993, p. 277
    6673 *
    67  *  NOTE: P1003.4b/D8, p. 45 adds mq_timedsend().
     74 *  @note P1003.4b/D8, p. 45 adds mq_timedsend().
    6875 */
    69 
    7076int mq_send(
    7177  mqd_t         mqdes,
     
    8490  size_t                 msg_len,
    8591  unsigned int           msg_prio,
    86   const struct timespec *timeout
     92  const struct timespec *abstime
    8793);
    8894
     
    109115  size_t                 msg_len,
    110116  unsigned int          *msg_prio,
    111   const struct timespec *timeout
     117  const struct timespec *abstime
    112118);
    113119
  • cpukit/posix/include/rtems/posix/mqueue.h

    ra570a14 ra2cf229  
    113113  size_t              msg_len,
    114114  unsigned int       *msg_prio,
     115  boolean             wait,
    115116  Watchdog_Interval   timeout
    116117);
     
    129130  size_t              msg_len,
    130131  uint32_t            msg_prio,
     132  boolean             wait,
    131133  Watchdog_Interval   timeout
    132134);
  • cpukit/posix/include/rtems/posix/semaphore.h

    ra570a14 ra2cf229  
    154154
    155155int _POSIX_Semaphore_Wait_support(
    156   sem_t                          *sem,
    157   Core_semaphore_Blocking_option  blocking,
    158   Watchdog_Interval               timeout
     156  sem_t               *sem,
     157  boolean              blocking,
     158  Watchdog_Interval    timeout
    159159);
    160160
  • cpukit/posix/include/rtems/posix/time.h

    ra570a14 ra2cf229  
    1919#include <rtems/score/timespec.h>
    2020
    21 /*
    22  *  _POSIX_Absolute_timeout_to_ticks
     21/** @brief Absolute Timeout Conversion Results
     22 *
     23 *  This enumeration defines the possible results of converting
     24 *  an absolute time used for timeouts to POSIX blocking calls to
     25 *  a number of ticks.
    2326 */
    24 int _POSIX_Absolute_timeout_to_ticks(
     27typedef enum {
     28  /** The timeout is invalid. */
     29  POSIX_ABSOLUTE_TIMEOUT_INVALID,
     30  /** The timeout represents a time that is in the past. */
     31  POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST,
     32  /** The timeout represents a time that is equal to the current time. */
     33  POSIX_ABSOLUTE_TIMEOUT_IS_NOW,
     34  /** The timeout represents a time that is in the future. */
     35  POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE,
     36} POSIX_Absolute_timeout_conversion_results_t;
     37
     38/**
     39 *  @brief Convert Absolute Timeout to Ticks
     40 *
     41 *  This method takes an absolute time being used as a timeout
     42 *  to a blocking directive, validates it and returns the number
     43 *  of corresponding clock ticks for use by the SuperCore.
     44 *
     45 *  @param[in] abstime is the timeout
     46 *  @param[in] ticks_out will contain the number of ticks
     47 *
     48 *  @return This method returns the number of ticks in @a ticks_out
     49 *          and a status value indicating whether the absolute time
     50 *          is valid, in the past, equal to the current time or in
     51 *          the future as it should be.
     52 */
     53POSIX_Absolute_timeout_conversion_results_t _POSIX_Absolute_timeout_to_ticks(
    2554  const struct timespec *abstime,
    2655  Watchdog_Interval     *ticks_out
  • cpukit/posix/src/condtimedwait.c

    ra570a14 ra2cf229  
    4040)
    4141{
    42   Watchdog_Interval timeout;
    43   struct timespec   current_time;
    44   struct timespec   difference;
    45   boolean           already_timedout = FALSE;
    46 
    47   if ( !_Timespec_Is_valid(abstime) )
    48     return EINVAL;
     42  Watchdog_Interval ticks;
     43  boolean           already_timedout = TRUE;
    4944
    5045  /*
    51    *  The abstime is a walltime.  We turn it into an interval.
     46   *  POSIX requires that blocking calls with timeouts that take
     47   *  an absolute timeout must ignore issues with the absolute
     48   *  time provided if the operation would otherwise succeed.
     49   *  So we check the abstime provided, and hold on to whether it
     50   *  is valid or not.  If it isn't correct and in the future,
     51   *  then we do a polling operation and convert the UNSATISFIED
     52   *  status into the appropriate error.
    5253   */
    53 
    54   _TOD_Get( &current_time );
    55 
    56   /*
    57    * Make sure the timeout is in the future
    58    */
    59   if ( _Timespec_Less_than( abstime, &current_time ) ) {
    60     already_timedout = TRUE;
    61     difference.tv_sec  = 0;
    62     difference.tv_nsec = 0;
    63     timeout = 0;
    64   } else {
    65     _Timespec_Subtract( &current_time, abstime, &difference );
    66     timeout = _Timespec_To_ticks( &difference );
     54  switch ( _POSIX_Absolute_timeout_to_ticks(abstime, &ticks) ) {
     55    case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     56      return EINVAL;
     57    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     58    case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     59      already_timedout = TRUE;
     60      break;
     61    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     62      already_timedout = FALSE;
     63      break;
    6764  }
    6865
     
    7067    cond,
    7168    mutex,
    72     timeout,
     69    ticks,
    7370    already_timedout
    7471  );
  • cpukit/posix/src/mqueuereceive.c

    ra570a14 ra2cf229  
    5252    msg_len,
    5353    msg_prio,
     54    TRUE,
    5455    THREAD_QUEUE_WAIT_FOREVER
    5556  );
  • cpukit/posix/src/mqueuerecvsupp.c

    ra570a14 ra2cf229  
    3333#include <rtems/posix/time.h>
    3434
    35 /*PAGE
    36  *
     35/*
    3736 *  _POSIX_Message_queue_Receive_support
    3837 *
     
    4645  size_t              msg_len,
    4746  unsigned int       *msg_prio,
     47  boolean             wait,
    4848  Watchdog_Interval   timeout
    4949)
     
    5353  Objects_Locations                location;
    5454  size_t                           length_out;
     55  boolean                          do_wait;
    5556
    5657  the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location );
     
    8283      length_out = -1;
    8384
     85      /*
     86       *  A timed receive with a bad time will do a poll regardless.
     87       */
     88      if ( wait )
     89        do_wait = (the_mq_fd->oflag & O_NONBLOCK) ? FALSE : TRUE;
     90      else
     91        do_wait = wait;
     92
     93      /*
     94       *  Now perform the actual message receive
     95       */
    8496      _CORE_message_queue_Seize(
    8597        &the_mq->Message_queue,
     
    8799        msg_ptr,
    88100        &length_out,
    89         (the_mq_fd->oflag & O_NONBLOCK) ? FALSE : TRUE,
     101        do_wait,
    90102        timeout
    91103      );
  • cpukit/posix/src/mqueuesend.c

    ra570a14 ra2cf229  
    5252    msg_len,
    5353    msg_prio,
     54    TRUE,
    5455    THREAD_QUEUE_WAIT_FOREVER
    5556  );
  • cpukit/posix/src/mqueuesendsupp.c

    ra570a14 ra2cf229  
    4444  size_t              msg_len,
    4545  uint32_t            msg_prio,
     46  boolean             wait,
    4647  Watchdog_Interval   timeout
    4748)
     
    5152  Objects_Locations               location;
    5253  CORE_message_queue_Status       msg_status;
     54  boolean                         do_wait;
    5355
    5456  /*
     
    7880      the_mq = the_mq_fd->Queue;
    7981
     82      /*
     83       *  A timed receive with a bad time will do a poll regardless.
     84       */
     85      if ( wait )
     86        do_wait = (the_mq_fd->oflag & O_NONBLOCK) ? FALSE : TRUE;
     87      else
     88        do_wait = wait;
     89
     90      /*
     91       *  Now perform the actual message receive
     92       */
    8093      msg_status = _CORE_message_queue_Submit(
    8194        &the_mq->Message_queue,
     
    89102#endif
    90103        _POSIX_Message_queue_Priority_to_core( msg_prio ),
    91          (the_mq_fd->oflag & O_NONBLOCK) ? FALSE : TRUE,
     104        do_wait,
    92105        timeout    /* no timeout */
    93106      );
  • cpukit/posix/src/mqueuetimedreceive.c

    ra570a14 ra2cf229  
    5454  size_t                 msg_len,
    5555  unsigned int          *msg_prio,
    56   const struct timespec *timeout
     56  const struct timespec *abstime
    5757)
    5858{
     59  Watchdog_Interval ticks;
     60  boolean           do_wait;
     61
     62  /*
     63   *  POSIX requires that blocking calls with timeouts that take
     64   *  an absolute timeout must ignore issues with the absolute
     65   *  time provided if the operation would otherwise succeed.
     66   *  So we check the abstime provided, and hold on to whether it
     67   *  is valid or not.  If it isn't correct and in the future,
     68   *  then we do a polling operation and convert the UNSATISFIED
     69   *  status into the appropriate error.
     70   */
     71  switch ( _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ) ) {
     72    case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     73    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     74    case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     75      do_wait = FALSE;
     76      break;
     77    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     78      do_wait = TRUE;
     79      break;
     80  }
     81
    5982  return _POSIX_Message_queue_Receive_support(
    6083    mqdes,
     
    6285    msg_len,
    6386    msg_prio,
    64     _Timespec_To_ticks( timeout )
     87    do_wait,
     88    ticks
    6589  );
    6690}
  • cpukit/posix/src/mqueuetimedsend.c

    ra570a14 ra2cf229  
    5454  size_t                 msg_len,
    5555  unsigned int           msg_prio,
    56   const struct timespec *timeout
     56  const struct timespec *abstime
    5757)
    5858{
     59  Watchdog_Interval ticks;
     60  boolean           do_wait;
     61
     62  /*
     63   *  POSIX requires that blocking calls with timeouts that take
     64   *  an absolute timeout must ignore issues with the absolute
     65   *  time provided if the operation would otherwise succeed.
     66   *  So we check the abstime provided, and hold on to whether it
     67   *  is valid or not.  If it isn't correct and in the future,
     68   *  then we do a polling operation and convert the UNSATISFIED
     69   *  status into the appropriate error.
     70   */
     71  switch ( _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ) ) {
     72    case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     73    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     74    case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     75      do_wait = FALSE;
     76      break;
     77    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     78      do_wait = TRUE;
     79      break;
     80  }
     81
    5982  return _POSIX_Message_queue_Send_support(
    6083    mqdes,
     
    6285    msg_len,
    6386    msg_prio,
    64     _Timespec_To_ticks( timeout )
     87    do_wait,
     88    ticks
    6589  );
    6690}
  • cpukit/posix/src/mutexfromcorestatus.c

    ra570a14 ra2cf229  
    4242      return EINVAL;
    4343    case CORE_MUTEX_TIMEOUT:
    44       return EAGAIN;
     44      return ETIMEDOUT;
    4545    case CORE_MUTEX_STATUS_CEILING_VIOLATED:
    4646      return EINVAL;
  • cpukit/posix/src/mutextimedlock.c

    ra570a14 ra2cf229  
    4040int pthread_mutex_timedlock(
    4141  pthread_mutex_t       *mutex,
    42   const struct timespec *timeout
     42  const struct timespec *abstime
    4343)
    4444{
    45   /* XXX does timeout need to be based on CLOCK_REALTIME and be TOD? */
    46   return _POSIX_Mutex_Lock_support(
     45  Watchdog_Interval                            ticks;
     46  boolean                                      do_wait;
     47  POSIX_Absolute_timeout_conversion_results_t  status;
     48  int                                          lock_status;
     49
     50  /*
     51   *  POSIX requires that blocking calls with timeouts that take
     52   *  an absolute timeout must ignore issues with the absolute
     53   *  time provided if the operation would otherwise succeed.
     54   *  So we check the abstime provided, and hold on to whether it
     55   *  is valid or not.  If it isn't correct and in the future,
     56   *  then we do a polling operation and convert the UNSATISFIED
     57   *  status into the appropriate error.
     58   */
     59  status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks );
     60  switch ( status ) {
     61    case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     62    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     63    case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     64      do_wait = FALSE;
     65      break;
     66    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     67      do_wait = TRUE;
     68      break;
     69  }
     70
     71  lock_status = _POSIX_Mutex_Lock_support(
    4772    mutex,
    48     TRUE,
    49     _Timespec_To_ticks( timeout )
     73    do_wait,
     74    ticks
    5075  );
     76
     77  /*
     78   *  This service only gives us the option to block.  We used a polling
     79   *  attempt to lock if the abstime was not in the future.  If we did
     80   *  not obtain the mutex, then not look at the status immediately,
     81   *  make sure the right reason is returned.
     82   */
     83  if ( !do_wait && (lock_status == EBUSY) ) {
     84    switch (lock_status) {
     85      case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     86        return EINVAL;
     87      case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     88      case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     89        return ETIMEDOUT;
     90      case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     91        break;
     92    }
     93  }
     94
     95  return lock_status;
    5196}
  • cpukit/posix/src/posixtimespecabsolutetimeout.c

    ra570a14 ra2cf229  
    3535 *  The abstime is a walltime.  We turn it into an interval.
    3636 */
    37 int _POSIX_Absolute_timeout_to_ticks(
     37POSIX_Absolute_timeout_conversion_results_t _POSIX_Absolute_timeout_to_ticks(
    3838  const struct timespec *abstime,
    3939  Watchdog_Interval     *ticks_out
     
    4343  struct timespec difference;
    4444
     45 
     46  /*
     47   *  Make sure there is always a value returned.
     48   */
     49  *ticks_out = 0;
     50
     51  /*
     52   *  Is the absolute time even valid?
     53   */
    4554  if ( !_Timespec_Is_valid(abstime) )
    46     return EINVAL;
     55    return POSIX_ABSOLUTE_TIMEOUT_INVALID;
    4756
     57  /*
     58   *  Is the absolute time in the past?
     59   */
    4860  _TOD_Get( &current_time );
    4961
     62  if ( _Timespec_Less_than( abstime, &current_time ) )
     63    return POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST;
     64
    5065  /*
    51    *  Make sure the abstime is in the future
     66   *  How long until the requested absolute time?
    5267   */
    53   if ( _Timespec_Less_than( abstime, &current_time ) )
    54     return EINVAL;
    55 
    5668  _Timespec_Subtract( &current_time, abstime, &difference );
    5769
     70  /*
     71   *  Internally the SuperCore uses ticks, so convert to them.
     72   */
    5873  *ticks_out = _Timespec_To_ticks( &difference );
    5974
    60   return 0;
     75  /*
     76   *  If the difference was 0, then the future is now.  It is so bright
     77   *  we better wear shades.
     78   */
     79  if ( !*ticks_out )
     80    return POSIX_ABSOLUTE_TIMEOUT_IS_NOW;
     81
     82  /*
     83   *  This is the case we were expecting and it took this long to
     84   *  get here.
     85   */
     86  return POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE;
    6187}
    6288
  • cpukit/posix/src/prwlocktimedrdlock.c

    ra570a14 ra2cf229  
    4141)
    4242{
    43   POSIX_RWLock_Control  *the_rwlock;
    44   Objects_Locations      location;
    45   Watchdog_Interval      ticks;
    46   int                    status;
     43  POSIX_RWLock_Control                        *the_rwlock;
     44  Objects_Locations                            location;
     45  Watchdog_Interval                            ticks;
     46  boolean                                      do_wait;
     47  POSIX_Absolute_timeout_conversion_results_t  status;
    4748 
    4849  if ( !rwlock )
    4950    return EINVAL;
    5051
     52  /*
     53   *  POSIX requires that blocking calls with timeouts that take
     54   *  an absolute timeout must ignore issues with the absolute
     55   *  time provided if the operation would otherwise succeed.
     56   *  So we check the abstime provided, and hold on to whether it
     57   *  is valid or not.  If it isn't correct and in the future,
     58   *  then we do a polling operation and convert the UNSATISFIED
     59   *  status into the appropriate error.
     60   */
    5161  status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks );
    52   if ( status )
    53     return status;
     62  switch (status) {
     63    case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     64    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     65    case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     66      do_wait = FALSE;
     67      break;
     68    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     69      do_wait = TRUE;
     70      break;
     71  }
    5472
    5573  the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
     
    6583        &the_rwlock->RWLock,
    6684        *rwlock,
    67         TRUE,                   // we are willing to wait up to ticks
     85        do_wait,
    6886        ticks,
    6987        NULL
     
    7189
    7290      _Thread_Enable_dispatch();
     91      if ( !do_wait &&
     92           (_Thread_Executing->Wait.return_code == CORE_RWLOCK_UNAVAILABLE) ) {
     93        switch (status) {
     94          case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     95            return EINVAL;
     96          case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     97          case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     98            return ETIMEDOUT;
     99          case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     100            break;
     101        }
     102      }
     103
    73104      return _POSIX_RWLock_Translate_core_RWLock_return_code(
    74105        (CORE_RWLock_Status) _Thread_Executing->Wait.return_code
  • cpukit/posix/src/prwlocktimedwrlock.c

    ra570a14 ra2cf229  
    4141)
    4242{
    43   POSIX_RWLock_Control  *the_rwlock;
    44   Objects_Locations      location;
    45   int                    status;
    46   Watchdog_Interval      ticks;
    47 
     43  POSIX_RWLock_Control                        *the_rwlock;
     44  Objects_Locations                            location;
     45  Watchdog_Interval                            ticks;
     46  boolean                                      do_wait;
     47  POSIX_Absolute_timeout_conversion_results_t  status;
     48 
    4849  if ( !rwlock )
    4950    return EINVAL;
    5051
     52  /*
     53   *  POSIX requires that blocking calls with timeouts that take
     54   *  an absolute timeout must ignore issues with the absolute
     55   *  time provided if the operation would otherwise succeed.
     56   *  So we check the abstime provided, and hold on to whether it
     57   *  is valid or not.  If it isn't correct and in the future,
     58   *  then we do a polling operation and convert the UNSATISFIED
     59   *  status into the appropriate error.
     60   */
    5161  status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks );
    52   if ( status )
    53     return status;
     62  switch (status) {
     63    case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     64    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     65    case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     66      do_wait = FALSE;
     67      break;
     68    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     69      do_wait = TRUE;
     70      break;
     71  }
    5472
    5573  the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
     
    6583        &the_rwlock->RWLock,
    6684        *rwlock,
    67         TRUE,                 // we are willing to wait up to ticks
     85        do_wait,
    6886        ticks,
    6987        NULL
     
    7189
    7290      _Thread_Enable_dispatch();
     91      if ( !do_wait &&
     92           (_Thread_Executing->Wait.return_code == CORE_RWLOCK_UNAVAILABLE) ) {
     93        switch (status) {
     94          case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     95            return EINVAL;
     96          case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     97          case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     98            return ETIMEDOUT;
     99          case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     100            break;
     101        }
     102      }
     103
    73104      return _POSIX_RWLock_Translate_core_RWLock_return_code(
    74105        (CORE_RWLock_Status) _Thread_Executing->Wait.return_code
  • cpukit/posix/src/semaphorewaitsupp.c

    ra570a14 ra2cf229  
    2727
    2828int _POSIX_Semaphore_Wait_support(
    29   sem_t                          *sem,
    30   Core_semaphore_Blocking_option  blocking,
    31   Watchdog_Interval               timeout
     29  sem_t             *sem,
     30  boolean            blocking,
     31  Watchdog_Interval  timeout
    3232)
    3333{
     
    6666           */
    6767          break;
    68         case CORE_SEMAPHORE_BAD_TIMEOUT_VALUE:
    69           rtems_set_errno_and_return_minus_one( EINVAL );
    70           break;
    7168      }
    7269  }
  • cpukit/posix/src/semtimedwait.c

    ra570a14 ra2cf229  
    4040)
    4141{
    42   /*
    43    *  The abstime is a walltime.  We turn it into an interval.
    44    */
    45   Watchdog_Interval              ticks = 0;
    46   struct timespec                current_time;
    47   struct timespec                difference;
    48   Core_semaphore_Blocking_option blocking = CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT;
     42  Watchdog_Interval                            ticks;
     43  boolean                                      do_wait = TRUE;
     44  POSIX_Absolute_timeout_conversion_results_t  status;
     45  int                                          lock_status;
    4946
    5047  /*
    51    *  Error check the absolute time to timeout
     48   *  POSIX requires that blocking calls with timeouts that take
     49   *  an absolute timeout must ignore issues with the absolute
     50   *  time provided if the operation would otherwise succeed.
     51   *  So we check the abstime provided, and hold on to whether it
     52   *  is valid or not.  If it isn't correct and in the future,
     53   *  then we do a polling operation and convert the UNSATISFIED
     54   *  status into the appropriate error.
    5255   */
    53   if ( !_Timespec_Is_valid( abstime ) ) {
    54     blocking = CORE_SEMAPHORE_BAD_TIMEOUT_VALUE;
    55   } else {
    56     _TOD_Get( &current_time );
    57     /*
    58      *  Make sure the abstime is in the future
    59      */
    60     if ( _Timespec_Less_than( abstime, &current_time ) ) {
    61       blocking = CORE_SEMAPHORE_BAD_TIMEOUT;
    62     } else {
    63       _Timespec_Subtract( &current_time, abstime, &difference );
    64       ticks = _Timespec_To_ticks( &difference );
    65       blocking = CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT;
     56  status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks );
     57  switch ( status ) {
     58    case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     59    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     60    case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     61      do_wait = FALSE;
     62      break;
     63    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     64      do_wait = TRUE;
     65      break;
     66  }
     67
     68  lock_status = _POSIX_Semaphore_Wait_support( sem, do_wait, ticks );
     69
     70  /*
     71   *  This service only gives us the option to block.  We used a polling
     72   *  attempt to obtain if the abstime was not in the future.  If we did
     73   *  not obtain the semaphore, then not look at the status immediately,
     74   *  make sure the right reason is returned.
     75   */
     76  if ( !do_wait && (lock_status == EBUSY) ) {
     77    switch (lock_status) {
     78      case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     79        return EINVAL;
     80      case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     81      case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     82        return ETIMEDOUT;
     83      case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     84        break;
    6685    }
    67    }
     86  }
    6887
    69    return _POSIX_Semaphore_Wait_support( sem, blocking, ticks );
     88  return lock_status;
    7089}
  • cpukit/posix/src/semtrywait.c

    ra570a14 ra2cf229  
    3232)
    3333{
    34   return _POSIX_Semaphore_Wait_support( sem, FALSE, THREAD_QUEUE_WAIT_FOREVER );
     34  return _POSIX_Semaphore_Wait_support(sem, FALSE, THREAD_QUEUE_WAIT_FOREVER);
    3535}
  • cpukit/posix/src/semwait.c

    ra570a14 ra2cf229  
    3232)
    3333{
    34   return _POSIX_Semaphore_Wait_support(
    35            sem,
    36            CORE_SEMAPHORE_BLOCK_FOREVER,
    37            THREAD_QUEUE_WAIT_FOREVER
    38          );
     34  return _POSIX_Semaphore_Wait_support( sem, TRUE, THREAD_QUEUE_WAIT_FOREVER );
    3935}
  • cpukit/posix/src/sigtimedwait.c

    ra570a14 ra2cf229  
    6464  /*
    6565   *  Error check parameters before disabling interrupts.
     66   *
     67   *  NOTE: This is very specifically a RELATIVE not ABSOLUTE time
     68   *        in the Open Group specification.
    6669   */
    6770
     
    6972  if ( timeout ) {
    7073
    71     if ( !_Timespec_Is_valid( timeout ) ) {
     74    if ( !_Timespec_Is_valid( timeout ) )
    7275      rtems_set_errno_and_return_minus_one( EINVAL );
    73     }
    7476
    7577    interval = _Timespec_To_ticks( timeout );
     78
     79    if ( !interval )
     80      rtems_set_errno_and_return_minus_one( EINVAL );
    7681  }
    7782
  • cpukit/rtems/src/semobtain.c

    ra570a14 ra2cf229  
    108108        &the_semaphore->Core_control.semaphore,
    109109        id,
    110         ((_Options_Is_no_wait( option_set )) ?
    111           CORE_SEMAPHORE_NO_WAIT : CORE_SEMAPHORE_BLOCK_FOREVER),
     110        ((_Options_Is_no_wait( option_set )) ? FALSE : TRUE),
    112111        timeout,
    113112        &level
  • cpukit/rtems/src/semtranslatereturncode.c

    ra570a14 ra2cf229  
    104104  RTEMS_TIMEOUT,            /* CORE_SEMAPHORE_TIMEOUT  */
    105105  RTEMS_INTERNAL_ERROR,     /* CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED */
    106   RTEMS_INTERNAL_ERROR      /* CORE_SEMAPHORE_BAD_TIMEOUT_VALUE */
    107106};
    108107
     
    115114    return RTEMS_PROXY_BLOCKING;
    116115#endif
    117   if ( status > CORE_SEMAPHORE_BAD_TIMEOUT_VALUE )
     116  if ( status > CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED )
    118117    return RTEMS_INTERNAL_ERROR;
    119118  return _Semaphore_Translate_core_semaphore_return_code_[status];
  • cpukit/score/include/rtems/score/coresem.h

    ra570a14 ra2cf229  
    8383   *  and this would have made its count greater than that allowed.
    8484   */
    85   CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED,
    86   /** This status indicates that the semaphore was not immediately
    87    *  available and the caller passed a bad timeout value to the API
    88    *  routine.  In this case, the API required that the validity check
    89    *  for the timeout occur after the check that the semaphore was immediately
    90    *  available.
    91    */
    92   CORE_SEMAPHORE_BAD_TIMEOUT_VALUE
     85  CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED
    9386}   CORE_semaphore_Status;
    9487
     
    124117
    125118/**
    126  *  The following enumerated type is the set of blocking options
    127  *  available to seize operation.
    128  */
    129 typedef enum {
    130   /** This value indicates that the caller does not wish to block. */
    131   CORE_SEMAPHORE_NO_WAIT,
    132   /** This value indicates that the caller is willing to block forever. */
    133   CORE_SEMAPHORE_BLOCK_FOREVER,
    134   /** This value indicates that the caller is blocking with a timeout. */
    135   CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT,
    136   /** This value indicates that the caller wanted to block but passed in
    137    *  a bad timeout value to the API. Unfortunately, this is a weird case
    138    *  where the timeout bad error is required to be generated only if
    139    *  the semaphore is not available.
    140    */
    141   CORE_SEMAPHORE_BAD_TIMEOUT
    142 } Core_semaphore_Blocking_option;
    143 
    144 /**
    145119 *  This routine initializes the semaphore based on the parameters passed.
    146120 *
     
    164138 *  @param[in] id is the Id of the API level Semaphore object associated
    165139 *         with this instance of a SuperCore Semaphore
    166  *  @param[in] wait is the blocking mode
     140 *  @param[in] wait indicates if the caller is willing to block
    167141 *  @param[in] timeout is the number of ticks the calling thread is willing
    168142 *         to wait if @a wait is TRUE.
    169143 */
    170144void _CORE_semaphore_Seize(
    171   CORE_semaphore_Control         *the_semaphore,
    172   Objects_Id                      id,
    173   Core_semaphore_Blocking_option  wait,
    174   Watchdog_Interval               timeout
     145  CORE_semaphore_Control  *the_semaphore,
     146  Objects_Id               id,
     147  boolean                  wait,
     148  Watchdog_Interval        timeout
    175149);
    176150
  • cpukit/score/src/coresemseize.c

    ra570a14 ra2cf229  
    5252
    5353void _CORE_semaphore_Seize(
    54   CORE_semaphore_Control         *the_semaphore,
    55   Objects_Id                      id,
    56   Core_semaphore_Blocking_option  wait,
    57   Watchdog_Interval               timeout
     54  CORE_semaphore_Control *the_semaphore,
     55  Objects_Id              id,
     56  boolean                 wait,
     57  Watchdog_Interval       timeout
    5858)
    5959{
     
    7070  }
    7171
    72   switch ( wait ) {
    73     case CORE_SEMAPHORE_NO_WAIT:
    74       _ISR_Enable( level );
    75       executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
    76       return;
    77     case CORE_SEMAPHORE_BAD_TIMEOUT:
    78       _ISR_Enable( level );
    79       executing->Wait.return_code = CORE_SEMAPHORE_BAD_TIMEOUT_VALUE;
    80       return;
    81     case CORE_SEMAPHORE_BLOCK_FOREVER:
    82     case CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT:
    83       _Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
    84       executing->Wait.queue          = &the_semaphore->Wait_queue;
    85       executing->Wait.id             = id;
    86       _ISR_Enable( level );
    87       _Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
    88       break;
     72  if ( !wait ) {
     73    _ISR_Enable( level );
     74    executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
     75    return;
    8976  }
    9077
     78   /*
     79    *  If the semaphore is not available and the caller is willing to
     80    *  block, then we now block the caller with optional timeout.
     81    */
     82  _Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
     83  executing->Wait.queue = &the_semaphore->Wait_queue;
     84  executing->Wait.id    = id;
     85  _ISR_Enable( level );
     86  _Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
     87
    9188}
Note: See TracChangeset for help on using the changeset viewer.