Changeset 39d97ab in rtems


Ignore:
Timestamp:
Jul 26, 2016, 6:13:36 PM (3 years ago)
Author:
Gedare Bloom <gedare@…>
Branches:
master
Children:
dfa2cdb
Parents:
f6fdf2e
Message:

cpukit: refactor nanosleep and use 64-bit timeout for threadq

  • Fixes a bug with elapsed time calculations misusing absolute time arguments in nanosleep_helper by passing the requested relative interval.
  • Fixes a bug with truncation of absolute timeouts by passing the full 64-bit value to Thread_queue_Enqueue.
  • Share yield logic between nanosleep and clock_nanosleep.

updates #2732

Location:
cpukit
Files:
2 edited

Legend:

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

    rf6fdf2e r39d97ab  
    3535static inline int nanosleep_helper(
    3636  uint64_t              ticks,
     37  Watchdog_Interval     relative_interval,
    3738  struct timespec      *rmtp,
    3839  Watchdog_Discipline   discipline
    3940)
    4041{
    41   /*
    42    * It is critical to obtain the executing thread after thread dispatching is
    43    * disabled on SMP configurations.
    44    */
    4542  Thread_Control  *executing;
    46   Per_CPU_Control *cpu_self;
    4743
    4844  Watchdog_Interval  start;
     
    5046
    5147  executing = _Thread_Get_executing();
    52 
    53   /*
    54    *  A nanosleep for zero time is implemented as a yield.
    55    *  This behavior is also beyond the POSIX specification but is
    56    *  consistent with the RTEMS API and yields desirable behavior.
    57    */
    58   if ( !ticks ) {
    59     cpu_self = _Thread_Dispatch_disable();
    60       _Thread_Yield( executing );
    61     _Thread_Dispatch_enable( cpu_self );
    62     if ( rmtp ) {
    63        rmtp->tv_sec = 0;
    64        rmtp->tv_nsec = 0;
    65     }
    66     return 0;
    67   }
    6848
    6949  start = _Watchdog_Ticks_since_boot;
     
    8767   */
    8868  elapsed = _Watchdog_Ticks_since_boot - start;
    89   if ( elapsed >= ticks )
    90     ticks = 0;
     69  if ( elapsed >= relative_interval )
     70    relative_interval = 0;
    9171  else
    92     ticks -= elapsed;
     72    relative_interval -= elapsed;
    9373
    9474  /*
     
    9676   */
    9777  if ( rmtp ) {
    98     _Timespec_From_ticks( ticks, rmtp );
     78    _Timespec_From_ticks( relative_interval, rmtp );
    9979  }
    10080
     
    10686     *  If there is time remaining, then we were interrupted by a signal.
    10787     */
    108     if ( ticks )
     88    if ( relative_interval )
    10989      return EINTR;
    11090  #endif
     
    11292  return 0;
    11393}
     94
     95/*
     96 * A nanosleep for zero time is implemented as a yield.
     97 * This behavior is also beyond the POSIX specification but is
     98 * consistent with the RTEMS API and yields desirable behavior.
     99 */
     100static inline int nanosleep_yield( struct timespec *rmtp )
     101{
     102  /*
     103   * It is critical to obtain the executing thread after thread dispatching is
     104   * disabled on SMP configurations.
     105   */
     106  Thread_Control  *executing;
     107  Per_CPU_Control *cpu_self;
     108
     109  executing = _Thread_Get_executing();
     110  cpu_self = _Thread_Dispatch_disable();
     111  _Thread_Yield( executing );
     112  _Thread_Dispatch_enable( cpu_self );
     113  if ( rmtp ) {
     114    rmtp->tv_sec = 0;
     115    rmtp->tv_nsec = 0;
     116  }
     117  return 0;
     118}
     119
    114120/*
    115121 *  14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
     
    121127{
    122128  int err;
    123   struct timespec timeout;
     129  struct timespec now;
    124130  uint64_t ticks;
     131  Watchdog_Interval relative_interval;
    125132
    126133  /*
     
    133140    return EINVAL;
    134141
     142  relative_interval = _Timespec_To_ticks( rqtp );
     143  if ( relative_interval == 0 )
     144    return nanosleep_yield( rmtp );
     145
    135146 /* CLOCK_REALTIME can be adjusted during the timeout,
    136147  * so convert to an absolute timeout value and put the
    137148  * thread on the WATCHDOG_ABSOLUTE threadq. */
    138   err = clock_gettime( CLOCK_REALTIME, &timeout );
     149  err = clock_gettime( CLOCK_REALTIME, &now );
    139150  if ( err != 0 )
    140151    return -1;
    141 
    142   _Timespec_Add_to( &timeout, rqtp );
    143   ticks = _Watchdog_Ticks_from_timespec( &timeout );
    144   err = nanosleep_helper(ticks, rmtp, WATCHDOG_ABSOLUTE );
     152  _Timespec_Add_to( &now, rqtp );
     153  ticks = _Watchdog_Ticks_from_timespec( &now );
     154  err = nanosleep_helper(ticks, relative_interval, rmtp, WATCHDOG_ABSOLUTE );
    145155  if ( err != 0 ) {
    146156    rtems_set_errno_and_return_minus_one( err );
     
    160170{
    161171  int err = 0;
    162   struct timespec absolute_timeout;
     172  struct timespec now;
    163173  uint64_t ticks;
    164   Watchdog_Interval relative_ticks;
     174  Watchdog_Interval relative_interval;
     175  struct timespec relative_ts;
    165176  TOD_Absolute_timeout_conversion_results status;
    166177
    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    */
    173178  if ( !_Timespec_Is_valid( rqtp ) )
    174179    return EINVAL;
    175180
     181  /* get relative ticks of the requested timeout */
    176182  if ( flags & TIMER_ABSTIME ) {
    177183    /* See if absolute time already passed */
    178     status = _TOD_Absolute_timeout_to_ticks(rqtp, clock_id, &relative_ticks);
     184    status = _TOD_Absolute_timeout_to_ticks(rqtp, clock_id, &relative_interval);
    179185    if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
    180186      return EINVAL;
    181     if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
    182         status == TOD_ABSOLUTE_TIMEOUT_IS_NOW ) {
     187    if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST )
    183188      return 0;
    184     }
     189    if ( status == TOD_ABSOLUTE_TIMEOUT_IS_NOW )
     190      return nanosleep_yield( NULL );
    185191    rmtp = NULL; /* Do not touch rmtp when using absolute time */
    186192  } else {
    187     relative_ticks = _Timespec_To_ticks(rqtp);
    188   }
     193    relative_interval = _Timespec_To_ticks( rqtp );
     194  }
     195  if ( relative_interval == 0 )
     196    return nanosleep_yield( rmtp );
    189197
    190198  if ( clock_id == CLOCK_REALTIME ) {
    191     if ( flags & TIMER_ABSTIME ) {
    192       ticks = _Watchdog_Ticks_from_timespec(rqtp);
    193     } else {
    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 );
    200     }
    201     err = nanosleep_helper( ticks, rmtp, WATCHDOG_ABSOLUTE );
     199    /* convert relative ticks to absolute timeout */
     200    err = clock_gettime( CLOCK_REALTIME, &now );
     201    if ( err != 0 )
     202      return EINVAL;
     203    _Timespec_From_ticks( relative_interval, &relative_ts );
     204    _Timespec_Add_to( &now, &relative_ts );
     205    ticks = _Watchdog_Ticks_from_timespec( &now );
     206    err = nanosleep_helper( ticks, relative_interval, rmtp, WATCHDOG_ABSOLUTE );
    202207  } else if ( clock_id == CLOCK_MONOTONIC ) {
    203208    /* use the WATCHDOG_RELATIVE to ignore changes in wall time */
    204     err = nanosleep_helper( relative_ticks, rmtp, WATCHDOG_RELATIVE );
     209    err = nanosleep_helper(
     210        relative_interval,
     211        relative_interval,
     212        rmtp,
     213        WATCHDOG_RELATIVE
     214    );
    205215  } else {
    206216    err = ENOTSUP;
  • cpukit/score/include/rtems/score/threadqimpl.h

    rf6fdf2e r39d97ab  
    433433  Thread_Control                *the_thread,
    434434  States_Control                 state,
    435   Watchdog_Interval              timeout,
     435  uint64_t                       timeout,
    436436  Watchdog_Discipline            discipline,
    437437  uint32_t                       expected_level
Note: See TracChangeset for help on using the changeset viewer.