Changeset e0f17fc in rtems


Ignore:
Timestamp:
Jul 15, 2016, 4:52:05 PM (4 years ago)
Author:
Gedare Bloom <gedare@…>
Branches:
master
Children:
f78a5f5
Parents:
b5bfaaf9
git-author:
Gedare Bloom <gedare@…> (07/15/16 16:52:05)
git-committer:
Gedare Bloom <gedare@…> (07/25/16 16:44:48)
Message:

posix: fix clock_nanosleep and nanosleep clock use

Sleeping with CLOCK_REALTIME should use the WATCHDOG_ABSOLUTE
clock discipline for the threadq so that the timeout interval
may change in case the clock source changes. Similarly,
CLOCK_MONOTONIC uses the WATCHDOG_RELATIVE threadq that will
only wakeup the thread after the requested count of ticks elapse.

updates #2732

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpukit/posix/src/nanosleep.c

    rb5bfaaf9 re0f17fc  
    3434
    3535static inline int nanosleep_helper(
    36   const struct timespec  *rqtp,
    37   struct timespec        *rmtp,
    38   Watchdog_Discipline     discipline
     36  uint64_t              ticks,
     37  struct timespec      *rmtp,
     38  Watchdog_Discipline   discipline
    3939)
    4040{
     
    4646  Per_CPU_Control *cpu_self;
    4747
    48   Watchdog_Interval  ticks;
    4948  Watchdog_Interval  start;
    5049  Watchdog_Interval  elapsed;
    51 
    52 
    53   /*
    54    *  Return EINVAL if the delay interval is negative.
    55    *
    56    *  NOTE:  This behavior is beyond the POSIX specification.
    57    *         FSU and GNU/Linux pthreads shares this behavior.
    58    */
    59   if ( !_Timespec_Is_valid( rqtp ) )
    60     return EINVAL;
    61 
    62   /*
    63    * Convert the timespec delay into the appropriate number of clock ticks.
    64    */
    65   ticks = _Timespec_To_ticks( rqtp );
    6650
    6751  executing = _Thread_Get_executing();
     
    11195   * If the user wants the time remaining, do the conversion.
    11296   */
    113   if ( rmtp && discipline == WATCHDOG_RELATIVE ) {
     97  if ( rmtp ) {
    11498    _Timespec_From_ticks( ticks, rmtp );
    11599  }
     
    136120)
    137121{
    138   int err = nanosleep_helper(rqtp, rmtp, WATCHDOG_RELATIVE);
    139   if (err) {
     122  int err;
     123  struct timespec timeout;
     124  uint64_t ticks;
     125
     126  /*
     127   *  Return EINVAL if the delay interval is negative.
     128   *
     129   *  NOTE:  This behavior is beyond the POSIX specification.
     130   *         FSU and GNU/Linux pthreads shares this behavior.
     131   */
     132  if ( !_Timespec_Is_valid( rqtp ) )
     133    return EINVAL;
     134
     135 /* CLOCK_REALTIME can be adjusted during the timeout,
     136  * so convert to an absolute timeout value and put the
     137  * thread on the WATCHDOG_ABSOLUTE threadq. */
     138  err = clock_gettime( CLOCK_REALTIME, &timeout );
     139  if ( err != 0 )
     140    return -1;
     141
     142  _Timespec_Add_to( &timeout, rqtp );
     143  ticks = _Watchdog_Ticks_from_timespec( &timeout );
     144  err = nanosleep_helper(ticks, rmtp, WATCHDOG_ABSOLUTE );
     145  if ( err != 0 ) {
    140146    rtems_set_errno_and_return_minus_one( err );
    141147  }
     
    154160{
    155161  int err = 0;
    156   if ( clock_id == CLOCK_REALTIME || clock_id == CLOCK_MONOTONIC ) {
     162  struct timespec absolute_timeout;
     163  uint64_t ticks;
     164  Watchdog_Interval relative_ticks;
     165  TOD_Absolute_timeout_conversion_results status;
     166
     167  /*
     168   *  Return EINVAL if the delay interval is negative.
     169   *
     170   *  NOTE:  This behavior is beyond the POSIX specification.
     171   *         FSU and GNU/Linux pthreads shares this behavior.
     172   */
     173  if ( !_Timespec_Is_valid( rqtp ) )
     174    return EINVAL;
     175
     176  if ( flags & TIMER_ABSTIME ) {
     177    /* See if absolute time already passed */
     178    status = _TOD_Absolute_timeout_to_ticks(rqtp, clock_id, &relative_ticks);
     179    if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
     180      return EINVAL;
     181    if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
     182        status == TOD_ABSOLUTE_TIMEOUT_IS_NOW ) {
     183      return 0;
     184    }
     185    rmtp = NULL; /* Do not touch rmtp when using absolute time */
     186  } else {
     187    relative_ticks = _Timespec_To_ticks(rqtp);
     188  }
     189
     190  if ( clock_id == CLOCK_REALTIME ) {
    157191    if ( flags & TIMER_ABSTIME ) {
    158       err = nanosleep_helper(rqtp, rmtp, WATCHDOG_ABSOLUTE);
     192      ticks = _Watchdog_Ticks_from_timespec(rqtp);
    159193    } else {
    160       err = nanosleep_helper(rqtp, rmtp, WATCHDOG_RELATIVE);
     194      err = clock_gettime( CLOCK_REALTIME, &absolute_timeout );
     195      if ( err != 0 ) {
     196        return EINVAL;
     197      }
     198      _Timespec_Add_to( &absolute_timeout, rqtp );
     199      ticks = _Watchdog_Ticks_from_timespec( &absolute_timeout );
    161200    }
     201    err = nanosleep_helper( ticks, rmtp, WATCHDOG_ABSOLUTE );
     202  } else if ( clock_id == CLOCK_MONOTONIC ) {
     203    /* use the WATCHDOG_RELATIVE to ignore changes in wall time */
     204    err = nanosleep_helper( relative_ticks, rmtp, WATCHDOG_RELATIVE );
    162205  } else {
    163206    err = ENOTSUP;
Note: See TracChangeset for help on using the changeset viewer.