Changeset d17c114 in rtems


Ignore:
Timestamp:
Jul 24, 2008, 8:43:24 PM (11 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Children:
1750f5a6
Parents:
5e60f15
Message:

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

PR 1291/cpukit

  • posix/src/posixtimespecabsolutetimeout.c: New file.
  • itron/inline/rtems/itron/semaphore.inl, itron/src/twai_sem.c, posix/Makefile.am, 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/mutexfromcorestatus.c, posix/src/mutextimedlock.c, posix/src/semaphorewaitsupp.c, posix/src/semtimedwait.c, posix/src/semtrywait.c, posix/src/semwait.c, rtems/src/semobtain.c, rtems/src/semtranslatereturncode.c, score/include/rtems/score/coresem.h, score/src/coremsgseize.c, 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:
1 added
26 edited

Legend:

Unmodified
Added
Removed
  • cpukit/ChangeLog

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

    r5e60f15 rd17c114  
    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

    r5e60f15 rd17c114  
    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/Makefile.am

    r5e60f15 rd17c114  
    133133## TIME_C_FILES
    134134libposix_a_SOURCES += src/adjtime.c src/time.c src/posixtimespecsubtract.c \
    135     src/posixtimespectointerval.c src/posixintervaltotimespec.c \
    136     src/clockgetcpuclockid.c src/clockgetenableattr.c src/clockgetres.c \
    137     src/clockgettime.c src/clocksetenableattr.c src/clocksettime.c \
    138     src/nanosleep.c src/sleep.c src/usleep.c
     135    src/posixtimespecabsolutetimeout.c src/posixtimespectointerval.c \
     136    src/posixintervaltotimespec.c src/clockgetcpuclockid.c \
     137    src/clockgetenableattr.c src/clockgetres.c src/clockgettime.c \
     138    src/clocksetenableattr.c src/clocksettime.c src/nanosleep.c src/sleep.c \
     139    src/usleep.c
    139140
    140141# the timer manager needs to be split further but only after its
  • cpukit/posix/include/mqueue.h

    r5e60f15 rd17c114  
    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

    r5e60f15 rd17c114  
    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

    r5e60f15 rd17c114  
    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

    r5e60f15 rd17c114  
    1313
    1414#include <rtems/score/tod.h>
     15
     16/*  Absolute Timeout Conversion Results
     17 *
     18 *  This enumeration defines the possible results of converting
     19 *  an absolute time used for timeouts to POSIX blocking calls to
     20 *  a number of ticks.
     21 */
     22typedef enum {
     23  /* The timeout is invalid. */
     24  POSIX_ABSOLUTE_TIMEOUT_INVALID,
     25  /* The timeout represents a time that is in the past. */
     26  POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST,
     27  /* The timeout represents a time that is equal to the current time. */
     28  POSIX_ABSOLUTE_TIMEOUT_IS_NOW,
     29  /* The timeout represents a time that is in the future. */
     30  POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE,
     31} POSIX_Absolute_timeout_conversion_results_t;
    1532
    1633/*
     
    5269);
    5370
     71/*
     72 *  Convert Absolute Timeout to Ticks
     73 *
     74 *  This method takes an absolute time being used as a timeout
     75 *  to a blocking directive, validates it and returns the number
     76 *  of corresponding clock ticks for use by the SuperCore.
     77 *
     78 *  abstime   - is the timeout
     79 *  ticks_out -  will contain the number of ticks
     80 *
     81 *  This method returns the number of ticks in @a ticks_out
     82 *  and a status value indicating whether the absolute time
     83 *  is valid, in the past, equal to the current time or in
     84 *  the future as it should be.
     85 */
     86POSIX_Absolute_timeout_conversion_results_t _POSIX_Absolute_timeout_to_ticks(
     87  const struct timespec *abstime,
     88  Watchdog_Interval     *ticks_out
     89);
     90
    5491#endif
  • cpukit/posix/src/condtimedwait.c

    r5e60f15 rd17c114  
    2929)
    3030{
    31   Watchdog_Interval timeout;
    32   struct timespec   current_time;
    33   struct timespec   difference;
    34   boolean           already_timedout = FALSE;
    35 
    36   if ( !abstime )
    37     return EINVAL;
     31  Watchdog_Interval ticks;
     32  boolean           already_timedout;
    3833
    3934  /*
    40    *  The abstime is a walltime.  We turn it into an interval.
     35   *  POSIX requires that blocking calls with timeouts that take
     36   *  an absolute timeout must ignore issues with the absolute
     37   *  time provided if the operation would otherwise succeed.
     38   *  So we check the abstime provided, and hold on to whether it
     39   *  is valid or not.  If it isn't correct and in the future,
     40   *  then we do a polling operation and convert the UNSATISFIED
     41   *  status into the appropriate error.
    4142   */
    42 
    43   (void) clock_gettime( CLOCK_REALTIME, &current_time );
    44 
    45   /* XXX probably some error checking should go here */
    46 
    47   _POSIX_Timespec_subtract( &current_time, abstime, &difference );
    48 
    49   if ( ( difference.tv_sec < 0 ) || ( ( difference.tv_sec == 0 ) &&
    50        ( difference.tv_nsec < 0 ) ) )
    51     already_timedout = TRUE;
    52 
    53   timeout = _POSIX_Timespec_to_interval( &difference );
     43  switch ( _POSIX_Absolute_timeout_to_ticks(abstime, &ticks) ) {
     44    case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     45      return EINVAL;
     46    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     47    case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     48      already_timedout = TRUE;
     49      break;
     50    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     51      already_timedout = FALSE;
     52      break;
     53  }
    5454
    5555  return _POSIX_Condition_variables_Wait_support(
    5656    cond,
    5757    mutex,
    58     timeout,
     58    ticks,
    5959    already_timedout
    6060  );
  • cpukit/posix/src/mqueuereceive.c

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

    r5e60f15 rd17c114  
    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

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

    r5e60f15 rd17c114  
    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

    r5e60f15 rd17c114  
    4545  size_t                 msg_len,
    4646  unsigned int          *msg_prio,
    47   const struct timespec *timeout
     47  const struct timespec *abstime
    4848)
    4949{
     50  Watchdog_Interval ticks;
     51  boolean           do_wait;
     52
     53  /*
     54   *  POSIX requires that blocking calls with timeouts that take
     55   *  an absolute timeout must ignore issues with the absolute
     56   *  time provided if the operation would otherwise succeed.
     57   *  So we check the abstime provided, and hold on to whether it
     58   *  is valid or not.  If it isn't correct and in the future,
     59   *  then we do a polling operation and convert the UNSATISFIED
     60   *  status into the appropriate error.
     61   */
     62  switch ( _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ) ) {
     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  }
     72
    5073  return _POSIX_Message_queue_Receive_support(
    5174    mqdes,
     
    5376    msg_len,
    5477    msg_prio,
    55     _POSIX_Timespec_to_interval( timeout )
     78    do_wait,
     79    ticks
    5680  );
    5781}
  • cpukit/posix/src/mqueuetimedsend.c

    r5e60f15 rd17c114  
    4545  size_t                 msg_len,
    4646  unsigned int           msg_prio,
    47   const struct timespec *timeout
     47  const struct timespec *abstime
    4848)
    4949{
     50  Watchdog_Interval ticks;
     51  boolean           do_wait;
     52
     53  /*
     54   *  POSIX requires that blocking calls with timeouts that take
     55   *  an absolute timeout must ignore issues with the absolute
     56   *  time provided if the operation would otherwise succeed.
     57   *  So we check the abstime provided, and hold on to whether it
     58   *  is valid or not.  If it isn't correct and in the future,
     59   *  then we do a polling operation and convert the UNSATISFIED
     60   *  status into the appropriate error.
     61   */
     62  switch ( _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ) ) {
     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  }
     72
    5073  return _POSIX_Message_queue_Send_support(
    5174    mqdes,
     
    5376    msg_len,
    5477    msg_prio,
    55     _POSIX_Timespec_to_interval( timeout )
     78    do_wait,
     79    ticks
    5680  );
    5781}
  • cpukit/posix/src/mutexfromcorestatus.c

    r5e60f15 rd17c114  
    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

    r5e60f15 rd17c114  
    2929int pthread_mutex_timedlock(
    3030  pthread_mutex_t       *mutex,
    31   const struct timespec *timeout
     31  const struct timespec *abstime
    3232)
    3333{
    34   return _POSIX_Mutex_Lock_support(
     34  Watchdog_Interval                            ticks;
     35  boolean                                      do_wait;
     36  POSIX_Absolute_timeout_conversion_results_t  status;
     37  int                                          lock_status;
     38
     39  /*
     40   *  POSIX requires that blocking calls with timeouts that take
     41   *  an absolute timeout must ignore issues with the absolute
     42   *  time provided if the operation would otherwise succeed.
     43   *  So we check the abstime provided, and hold on to whether it
     44   *  is valid or not.  If it isn't correct and in the future,
     45   *  then we do a polling operation and convert the UNSATISFIED
     46   *  status into the appropriate error.
     47   */
     48  status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks );
     49  switch ( status ) {
     50    case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     51    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     52    case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     53      do_wait = FALSE;
     54      break;
     55    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     56      do_wait = TRUE;
     57      break;
     58  }
     59
     60  lock_status = _POSIX_Mutex_Lock_support(
    3561    mutex,
    36     TRUE,
    37     _POSIX_Timespec_to_interval( timeout )
     62    do_wait,
     63    ticks
    3864  );
     65
     66  /*
     67   *  This service only gives us the option to block.  We used a polling
     68   *  attempt to lock if the abstime was not in the future.  If we did
     69   *  not obtain the mutex, then not look at the status immediately,
     70   *  make sure the right reason is returned.
     71   */
     72  if ( !do_wait && (lock_status == EBUSY) ) {
     73    switch (lock_status) {
     74      case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     75        return EINVAL;
     76      case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     77      case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     78        return ETIMEDOUT;
     79      case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     80        break;
     81    }
     82  }
     83
     84  return lock_status;
    3985}
  • cpukit/posix/src/semaphorewaitsupp.c

    r5e60f15 rd17c114  
    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

    r5e60f15 rd17c114  
    3333)
    3434{
    35   /*
    36    *  The abstime is a walltime.  We turn it into an interval.
    37    */
    38   Watchdog_Interval              ticks = 0;
    39   struct timespec                current_time;
    40   struct timespec                difference;
    41   Core_semaphore_Blocking_option blocking = CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT;
     35  Watchdog_Interval                            ticks;
     36  boolean                                      do_wait = TRUE;
     37  POSIX_Absolute_timeout_conversion_results_t  status;
     38  int                                          lock_status;
    4239
    4340  /*
    44    *  Error check the absolute time to timeout
     41   *  POSIX requires that blocking calls with timeouts that take
     42   *  an absolute timeout must ignore issues with the absolute
     43   *  time provided if the operation would otherwise succeed.
     44   *  So we check the abstime provided, and hold on to whether it
     45   *  is valid or not.  If it isn't correct and in the future,
     46   *  then we do a polling operation and convert the UNSATISFIED
     47   *  status into the appropriate error.
    4548   */
    46 #if 0
    47   if ( /* abstime->tv_sec < 0 || */ abstime->tv_nsec ) /* tv_sec is unsigned */
    48     blocking = CORE_SEMAPHORE_BAD_TIMEOUT_VALUE;
    49   else
    50 #endif
    51   if ( abstime->tv_nsec >= TOD_NANOSECONDS_PER_SECOND ) {
    52     blocking = CORE_SEMAPHORE_BAD_TIMEOUT;
    53   } else {
    54     clock_gettime( CLOCK_REALTIME, &current_time );
    55     /*
    56      *  Make sure the abstime is in the future
    57      */
    58     if ( abstime->tv_sec < current_time.tv_sec )
    59       blocking = CORE_SEMAPHORE_BAD_TIMEOUT;
    60     else if ( (abstime->tv_sec == current_time.tv_sec) &&
    61          (abstime->tv_nsec <= current_time.tv_nsec) )
    62       blocking = CORE_SEMAPHORE_BAD_TIMEOUT;
    63     else {
    64       _POSIX_Timespec_subtract( &current_time, abstime, &difference );
    65       ticks = _POSIX_Timespec_to_interval( &difference );
    66       blocking = CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT;
     49  status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks );
     50  switch ( status ) {
     51    case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     52    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     53    case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     54      do_wait = FALSE;
     55      break;
     56    case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     57      do_wait = TRUE;
     58      break;
     59  }
     60
     61  lock_status = _POSIX_Semaphore_Wait_support( sem, do_wait, ticks );
     62
     63  /*
     64   *  This service only gives us the option to block.  We used a polling
     65   *  attempt to obtain if the abstime was not in the future.  If we did
     66   *  not obtain the semaphore, then not look at the status immediately,
     67   *  make sure the right reason is returned.
     68   */
     69  if ( !do_wait && (lock_status == EBUSY) ) {
     70    switch (lock_status) {
     71      case POSIX_ABSOLUTE_TIMEOUT_INVALID:
     72        return EINVAL;
     73      case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST:
     74      case POSIX_ABSOLUTE_TIMEOUT_IS_NOW:
     75        return ETIMEDOUT;
     76      case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE:
     77        break;
    6778    }
    68    }
     79  }
    6980
    70    return _POSIX_Semaphore_Wait_support( sem, blocking, ticks );
     81  return lock_status;
    7182}
  • cpukit/posix/src/semtrywait.c

    r5e60f15 rd17c114  
    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

    r5e60f15 rd17c114  
    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/rtems/src/semobtain.c

    r5e60f15 rd17c114  
    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

    r5e60f15 rd17c114  
    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_MUTEX_STATUS_CEILING_VIOLATED )
     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

    r5e60f15 rd17c114  
    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/coremsgseize.c

    r5e60f15 rd17c114  
    8585    *size = the_message->Contents.size;
    8686    _Thread_Executing->Wait.count = the_message->priority;
    87     _CORE_message_queue_Copy_buffer(the_message->Contents.buffer,buffer,*size);
     87    _CORE_message_queue_Copy_buffer(the_message->Contents.buffer, buffer,*size);
    8888
    8989    /*
     
    108108
    109109    the_message->priority  = the_thread->Wait.count;
    110     the_message->Contents.size = (uint32_t  )the_thread->Wait.return_argument_1;
     110    the_message->Contents.size = (uint32_t)the_thread->Wait.option;
    111111    _CORE_message_queue_Copy_buffer(
    112112      the_thread->Wait.return_argument,
  • cpukit/score/src/coresemseize.c

    r5e60f15 rd17c114  
    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.