Changeset 03b900d in rtems


Ignore:
Timestamp:
Feb 18, 2016, 7:36:26 AM (3 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
0a5aa2d
Parents:
90d8567
git-author:
Sebastian Huber <sebastian.huber@…> (02/18/16 07:36:26)
git-committer:
Sebastian Huber <sebastian.huber@…> (03/04/16 12:36:10)
Message:

score: Replace watchdog handler implementation

Use a red-black tree instead of delta chains.

Close #2344.
Update #2554.
Update #2555.
Close #2606.

Files:
8 added
9 deleted
75 edited

Legend:

Unmodified
Added
Removed
  • cpukit/posix/Makefile.am

    r90d8567 r03b900d  
    197197## TIMER_C_FILES
    198198libposix_a_SOURCES += src/ptimer.c src/timercreate.c src/timerdelete.c \
    199     src/timergetoverrun.c src/timergettime.c src/timersettime.c \
    200     src/timertsr.c src/timerinserthelper.c
     199    src/timergetoverrun.c src/timergettime.c src/timersettime.c
    201200
    202201## ITIMER_C_FILES
  • cpukit/posix/include/rtems/posix/pthreadimpl.h

    r90d8567 r03b900d  
    115115 *            for the thread being replenished.
    116116 */
    117 void _POSIX_Threads_Sporadic_budget_TSR(
    118   Objects_Id      id,
    119   void           *argument
    120 );
     117void _POSIX_Threads_Sporadic_budget_TSR( Watchdog_Control *watchdog );
    121118
    122119/**
  • cpukit/posix/include/rtems/posix/threadsup.h

    r90d8567 r03b900d  
    4343 */
    4444typedef struct {
     45  /** Back pointer to thread of this POSIX API control. */
     46  Thread_Control         *thread;
    4547  /** This is the POSIX threads attribute set. */
    4648  pthread_attr_t          Attributes;
  • cpukit/posix/include/rtems/posix/timerimpl.h

    r90d8567 r03b900d  
    2222#include <rtems/posix/timer.h>
    2323#include <rtems/score/objectimpl.h>
     24#include <rtems/score/watchdogimpl.h>
    2425
    2526#ifdef __cplusplus
     
    5051#error "POSIX_TIMER_RELATIVE == TIMER_ABSTIME"
    5152#endif
    52 
    53 /**
    54  *  @brief POSIX Timer Manager Timer Service Routine Helper
    55  *
    56  *  This is the operation that is run when a timer expires.
    57  */
    58 void _POSIX_Timer_TSR(Objects_Id timer, void *data);
    59 
    60 /**
    61  *  @brief POSIX Timer Watchdog Insertion Helper
    62  */
    63 bool _POSIX_Timer_Insert_helper(
    64   Watchdog_Control               *timer,
    65   Watchdog_Interval               ticks,
    66   Objects_Id                      id,
    67   Watchdog_Service_routine_entry  TSR,
    68   void                           *arg
    69 );
    7053
    7154/**
     
    9982}
    10083
     84void _POSIX_Timer_TSR( Watchdog_Control *the_watchdog );
     85
    10186/**
    10287 *  @brief POSIX Timer Get
     
    11095RTEMS_INLINE_ROUTINE POSIX_Timer_Control *_POSIX_Timer_Get (
    11196  timer_t            id,
    112   Objects_Locations *location
     97  Objects_Locations *location,
     98  ISR_lock_Context  *lock_context
    11399)
    114100{
    115   return (POSIX_Timer_Control *)
    116     _Objects_Get( &_POSIX_Timer_Information, (Objects_Id) id, location );
     101  return (POSIX_Timer_Control *) _Objects_Get_isr_disable(
     102    &_POSIX_Timer_Information,
     103    (Objects_Id) id,
     104    location,
     105    lock_context
     106  );
     107}
     108
     109RTEMS_INLINE_ROUTINE Per_CPU_Control *_POSIX_Timer_Acquire_critical(
     110  POSIX_Timer_Control *ptimer,
     111  ISR_lock_Context    *lock_context
     112)
     113{
     114  Per_CPU_Control *cpu;
     115
     116  cpu = _Watchdog_Get_CPU( &ptimer->Timer );
     117  _Watchdog_Per_CPU_acquire_critical( cpu, lock_context );
     118
     119  return cpu;
     120}
     121
     122RTEMS_INLINE_ROUTINE void _POSIX_Timer_Release(
     123  Per_CPU_Control  *cpu,
     124  ISR_lock_Context *lock_context
     125)
     126{
     127  _Watchdog_Per_CPU_release_critical( cpu, lock_context );
     128  _ISR_lock_ISR_enable( lock_context );
    117129}
    118130
  • cpukit/posix/src/alarm.c

    r90d8567 r03b900d  
    2323
    2424#include <unistd.h>
     25#include <signal.h>
    2526
    26 #include <rtems/posix/pthreadimpl.h>
    27 #include <rtems/posix/psignalimpl.h>
    28 #include <rtems/score/threaddispatch.h>
    2927#include <rtems/score/todimpl.h>
    3028#include <rtems/score/watchdogimpl.h>
    3129
    32 /*
    33  *  _POSIX_signals_Alarm_TSR
    34  */
    35 static void _POSIX_signals_Alarm_TSR(
    36   Objects_Id      id RTEMS_UNUSED,
    37   void           *argument RTEMS_UNUSED
    38 )
     30ISR_LOCK_DEFINE( static, _POSIX_signals_Alarm_lock, "POSIX Alarm" )
     31
     32static void _POSIX_signals_Alarm_TSR( Watchdog_Control *the_watchdog )
    3933{
    40   #if defined(RTEMS_DEBUG)
    41     int status;
    42     #define KILL_STATUS status =
    43   #else
    44     #define KILL_STATUS (void)
    45   #endif
     34  int status;
    4635
    47   KILL_STATUS kill( getpid(), SIGALRM );
     36  status = kill( getpid(), SIGALRM );
    4837
    4938  #if defined(RTEMS_DEBUG)
     
    5342     */
    5443    _Assert(status == 0);
     44  #else
     45    (void) status;
    5546  #endif
    5647}
    5748
    58 static Watchdog_Control _POSIX_signals_Alarm_timer = WATCHDOG_INITIALIZER(
    59   _POSIX_signals_Alarm_TSR,
    60   0,
    61   NULL
     49static Watchdog_Control _POSIX_signals_Alarm_watchdog = WATCHDOG_INITIALIZER(
     50  _POSIX_signals_Alarm_TSR
    6251);
    6352
     
    6655)
    6756{
    68   unsigned int      remaining = 0;
    69   Watchdog_Control *the_timer;
    70   Watchdog_States   state;
     57  unsigned int      remaining;
     58  Watchdog_Control *the_watchdog;
     59  ISR_lock_Context  lock_context;
     60  ISR_lock_Context  lock_context2;
     61  Per_CPU_Control  *cpu;
     62  uint64_t          now;
     63  uint32_t          ticks_per_second;
     64  uint32_t          ticks;
    7165
    72   the_timer = &_POSIX_signals_Alarm_timer;
     66  the_watchdog = &_POSIX_signals_Alarm_watchdog;
     67  ticks_per_second = TOD_TICKS_PER_SECOND;
     68  ticks = seconds * ticks_per_second;
    7369
    74   _Thread_Disable_dispatch();
     70  _ISR_lock_ISR_disable_and_acquire(
     71    &_POSIX_signals_Alarm_lock,
     72    &lock_context
     73  );
    7574
    76   state = _Watchdog_Remove_seconds( the_timer );
    77   if ( state == WATCHDOG_ACTIVE ) {
    78     /*
    79      *  The stop_time and start_time fields are snapshots of ticks since
    80      *  boot.  Since alarm() is dealing in seconds, we must account for
    81      *  this.
    82      */
     75  cpu = _Watchdog_Get_CPU( the_watchdog );
     76  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context2 );
     77  now = cpu->Watchdog.ticks;
    8378
    84     remaining = the_timer->initial -
    85       ((the_timer->stop_time - the_timer->start_time) / TOD_TICKS_PER_SECOND);
     79  remaining = (unsigned long) _Watchdog_Cancel(
     80    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
     81    the_watchdog,
     82    now
     83  );
     84
     85  if ( ticks != 0 ) {
     86    cpu = _Per_CPU_Get();
     87    _Watchdog_Set_CPU( the_watchdog, cpu );
     88    _Watchdog_Insert(
     89      &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
     90      the_watchdog,
     91      now + ticks
     92    );
    8693  }
    8794
    88   if ( seconds )
    89     _Watchdog_Insert_seconds( the_timer, seconds );
     95  _Watchdog_Per_CPU_release_critical( cpu, &lock_context2 );
     96  _ISR_lock_Release_and_ISR_enable(
     97    &_POSIX_signals_Alarm_lock,
     98    &lock_context
     99  );
    90100
    91   _Thread_Enable_dispatch();
    92 
    93   return remaining;
     101  return ( remaining + ticks_per_second - 1 ) / ticks_per_second;
    94102}
  • cpukit/posix/src/nanosleep.c

    r90d8567 r03b900d  
    4747
    4848  Watchdog_Interval  ticks;
     49  Watchdog_Interval  start;
    4950  Watchdog_Interval  elapsed;
    5051
     
    8283  }
    8384
     85  start = _Watchdog_Ticks_since_boot;
     86
    8487  /*
    8588   *  Block for the desired amount of time
     
    97100   * much remains from what we requested.
    98101   */
    99   elapsed = executing->Timer.stop_time - executing->Timer.start_time;
     102  elapsed = _Watchdog_Ticks_since_boot - start;
    100103  if ( elapsed >= ticks )
    101104    ticks = 0;
  • cpukit/posix/src/pthread.c

    r90d8567 r03b900d  
    105105 *  _POSIX_Threads_Sporadic_budget_TSR
    106106 */
    107 void _POSIX_Threads_Sporadic_budget_TSR(
    108   Objects_Id      id RTEMS_UNUSED,
    109   void           *argument
    110 )
     107void _POSIX_Threads_Sporadic_budget_TSR( Watchdog_Control *watchdog )
    111108{
    112109  uint32_t            ticks;
     110  POSIX_API_Control  *api;
    113111  Thread_Control     *the_thread;
    114   POSIX_API_Control  *api;
    115 
    116   the_thread = argument;
    117 
    118   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
     112  ISR_Level           level;
     113
     114  api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic_timer );
     115  the_thread = api->thread;
    119116
    120117  /* ticks is guaranteed to be at least one */
     
    134131  ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period );
    135132
    136   _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks );
     133  _Thread_Disable_dispatch();
     134  _ISR_Disable( level );
     135  _Watchdog_Per_CPU_insert_relative(
     136    &api->Sporadic_timer,
     137    _Per_CPU_Get(),
     138    ticks
     139  );
     140  _ISR_Enable( level );
     141  _Thread_Unnest_dispatch();
    137142}
    138143
     
    199204
    200205  /* XXX check all fields are touched */
     206  api->thread = created;
    201207  _POSIX_Threads_Initialize_attributes( &api->Attributes );
    202208  api->detachstate = _POSIX_Threads_Default_attributes.detachstate;
     
    230236  _Thread_queue_Initialize( &api->Join_List, THREAD_QUEUE_DISCIPLINE_FIFO );
    231237
     238  _Watchdog_Preinitialize( &api->Sporadic_timer, _Per_CPU_Get_by_index( 0 ) );
    232239  _Watchdog_Initialize(
    233240    &api->Sporadic_timer,
    234     _POSIX_Threads_Sporadic_budget_TSR,
    235     created->Object.id,
    236     created
     241    _POSIX_Threads_Sporadic_budget_TSR
    237242  );
    238243
     
    261266
    262267  if ( api->schedpolicy == SCHED_SPORADIC )
    263     _Watchdog_Remove_ticks( &api->Sporadic_timer );
     268    _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
    264269
    265270  _Thread_queue_Destroy( &api->Join_List );
  • cpukit/posix/src/pthreadcreate.c

    r90d8567 r03b900d  
    7575  Objects_Name                        name;
    7676  int                                 rc;
     77  ISR_Level                           level;
    7778
    7879  if ( !start_routine )
     
    247248
    248249  if ( schedpolicy == SCHED_SPORADIC ) {
    249     _Watchdog_Insert_ticks(
     250    _ISR_Disable( level );
     251    _Watchdog_Per_CPU_insert_relative(
    250252      &api->Sporadic_timer,
     253      _Per_CPU_Get(),
    251254      _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period )
    252255    );
     256    _ISR_Enable( level );
    253257  }
    254258
  • cpukit/posix/src/pthreadsetschedparam.c

    r90d8567 r03b900d  
    4545  int                                  rc;
    4646  Priority_Control                     unused;
     47  ISR_Level                            level;
    4748
    4849  /*
     
    7071      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    7172
    72       if ( api->schedpolicy == SCHED_SPORADIC )
    73         _Watchdog_Remove_ticks( &api->Sporadic_timer );
     73      if ( api->schedpolicy == SCHED_SPORADIC ) {
     74        _ISR_Disable( level );
     75        _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
     76        _ISR_Enable( level );
     77      }
    7478
    7579      api->schedpolicy = policy;
     
    98102        case SCHED_SPORADIC:
    99103          api->ss_high_priority = api->schedparam.sched_priority;
    100           _Watchdog_Remove_ticks( &api->Sporadic_timer );
    101           _POSIX_Threads_Sporadic_budget_TSR( 0, the_thread );
     104          _ISR_Disable( level );
     105          _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
     106          _ISR_Enable( level );
     107          _POSIX_Threads_Sporadic_budget_TSR( &api->Sporadic_timer );
    102108          break;
    103109      }
  • cpukit/posix/src/timercreate.c

    r90d8567 r03b900d  
    9292  ptimer->timer_data.it_interval.tv_nsec = 0;
    9393
    94   _Watchdog_Preinitialize( &ptimer->Timer );
     94  _Watchdog_Preinitialize( &ptimer->Timer, _Per_CPU_Get_snapshot() );
     95  _Watchdog_Initialize( &ptimer->Timer, _POSIX_Timer_TSR );
    9596  _Objects_Open_u32(&_POSIX_Timer_Information, &ptimer->Object, 0);
    9697
  • cpukit/posix/src/timerdelete.c

    r90d8567 r03b900d  
    4646  POSIX_Timer_Control *ptimer;
    4747  Objects_Locations    location;
     48  ISR_lock_Context     lock_context;
     49  Per_CPU_Control     *cpu;
    4850
    4951  _Objects_Allocator_lock();
    50   ptimer = _POSIX_Timer_Get( timerid, &location );
     52  ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
    5153  switch ( location ) {
    5254
    5355    case OBJECTS_LOCAL:
    5456      _Objects_Close( &_POSIX_Timer_Information, &ptimer->Object );
     57      cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
    5558      ptimer->state = POSIX_TIMER_STATE_FREE;
    56       _Watchdog_Remove_ticks( &ptimer->Timer );
    57       _Objects_Put( &ptimer->Object );
     59      _Watchdog_Remove(
     60        &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
     61        &ptimer->Timer
     62      );
     63      _POSIX_Timer_Release( cpu, &lock_context );
    5864      _POSIX_Timer_Free( ptimer );
    5965      _Objects_Allocator_unlock();
  • cpukit/posix/src/timergetoverrun.c

    r90d8567 r03b900d  
    3434  POSIX_Timer_Control *ptimer;
    3535  Objects_Locations    location;
     36  ISR_lock_Context     lock_context;
     37  Per_CPU_Control     *cpu;
    3638
    37   ptimer = _POSIX_Timer_Get( timerid, &location );
     39  ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
    3840  switch ( location ) {
    3941
    4042    case OBJECTS_LOCAL:
     43      cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
    4144      overrun = ptimer->overrun;
    4245      ptimer->overrun = 0;
    43       _Objects_Put( &ptimer->Object );
     46      _POSIX_Timer_Release( cpu, &lock_context );
    4447      return overrun;
    4548
  • cpukit/posix/src/timergettime.c

    r90d8567 r03b900d  
    4343  POSIX_Timer_Control *ptimer;
    4444  Objects_Locations    location;
    45   struct timespec      current_time;
    46   Watchdog_Interval    left;
     45  ISR_lock_Context     lock_context;
     46  Per_CPU_Control     *cpu;
     47  uint64_t             now;
     48  uint32_t             remaining;
    4749
    4850  if ( !value )
    4951    rtems_set_errno_and_return_minus_one( EINVAL );
    5052
    51   /* Reads the current time */
    52   _TOD_Get_as_timespec( &current_time );
    53 
    54   ptimer = _POSIX_Timer_Get( timerid, &location );
     53  ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
    5554  switch ( location ) {
    5655
    5756    case OBJECTS_LOCAL:
    5857
    59       /* Calculates the time left before the timer finishes */
     58      cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
     59      now = cpu->Watchdog.ticks;
    6060
    61       left =
    62         (ptimer->Timer.start_time + ptimer->Timer.initial) - /* expire */
    63         _Watchdog_Ticks_since_boot;                          /* now */
     61      if ( now < ptimer->Timer.expire ) {
     62        remaining = (uint32_t) ( ptimer->Timer.expire - now );
     63      } else {
     64        remaining = 0;
     65      }
    6466
    65       _Timespec_From_ticks( left, &value->it_value );
     67      _Timespec_From_ticks( remaining, &value->it_value );
     68      value->it_interval = ptimer->timer_data.it_interval;
    6669
    67       value->it_interval  = ptimer->timer_data.it_interval;
    68 
    69       _Objects_Put( &ptimer->Object );
     70      _POSIX_Timer_Release( cpu, &lock_context );
    7071      return 0;
    7172
  • cpukit/posix/src/timersettime.c

    r90d8567 r03b900d  
    3030#include <rtems/seterr.h>
    3131
     32static void _POSIX_Timer_Insert(
     33  POSIX_Timer_Control *ptimer,
     34  Per_CPU_Control     *cpu,
     35  Watchdog_Interval    ticks
     36)
     37{
     38  ptimer->ticks = ticks;
     39
     40  /* The state really did not change but just to be safe */
     41  ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
     42
     43  /* Store the time when the timer was started again */
     44  _TOD_Get_as_timespec( &ptimer->time );
     45
     46  _Watchdog_Insert(
     47    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
     48    &ptimer->Timer,
     49    cpu->Watchdog.ticks + ticks
     50  );
     51}
     52
     53/*
     54 *  This is the operation that is run when a timer expires
     55 */
     56void _POSIX_Timer_TSR( Watchdog_Control *the_watchdog )
     57{
     58  POSIX_Timer_Control *ptimer;
     59  ISR_lock_Context     lock_context;
     60  Per_CPU_Control     *cpu;
     61
     62  ptimer = RTEMS_CONTAINER_OF( the_watchdog, POSIX_Timer_Control, Timer );
     63  _ISR_lock_ISR_disable( &lock_context );
     64  cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
     65
     66  /* Increment the number of expirations. */
     67  ptimer->overrun = ptimer->overrun + 1;
     68
     69  /* The timer must be reprogrammed */
     70  if ( ( ptimer->timer_data.it_interval.tv_sec  != 0 ) ||
     71       ( ptimer->timer_data.it_interval.tv_nsec != 0 ) ) {
     72    _POSIX_Timer_Insert( ptimer, cpu, ptimer->ticks );
     73  } else {
     74   /* Indicates that the timer is stopped */
     75   ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
     76  }
     77
     78  _POSIX_Timer_Release( cpu, &lock_context );
     79
     80  /*
     81   * The sending of the signal to the process running the handling function
     82   * specified for that signal is simulated
     83   */
     84
     85  if ( pthread_kill ( ptimer->thread_id, ptimer->inf.sigev_signo ) ) {
     86    _Assert( FALSE );
     87    /*
     88     * TODO: What if an error happens at run-time? This should never
     89     *       occur because the timer should be canceled if the thread
     90     *       is deleted. This method is being invoked from the Clock
     91     *       Tick ISR so even if we decide to take action on an error,
     92     *       we don't have many options. We shouldn't shut the system down.
     93     */
     94  }
     95
     96  /* After the signal handler returns, the count of expirations of the
     97   * timer must be set to 0.
     98   */
     99  ptimer->overrun = 0;
     100}
     101
    32102int timer_settime(
    33103  timer_t                  timerid,
     
    39109  POSIX_Timer_Control *ptimer;
    40110  Objects_Locations    location;
    41   bool                 activated;
     111  ISR_lock_Context     lock_context;
     112  Per_CPU_Control     *cpu;
    42113  uint32_t             initial_period;
    43114  struct itimerspec    normalize;
     
    78149   */
    79150
    80   ptimer = _POSIX_Timer_Get( timerid, &location );
     151  ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
    81152  switch ( location ) {
    82153
    83154    case OBJECTS_LOCAL:
     155      cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
     156
     157      /* Stop the timer */
     158      _Watchdog_Remove(
     159        &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
     160        &ptimer->Timer
     161      );
     162
    84163      /* First, it verifies if the timer must be stopped */
    85164      if ( normalize.it_value.tv_sec == 0 && normalize.it_value.tv_nsec == 0 ) {
    86          /* Stop the timer */
    87          _Watchdog_Remove_ticks( &ptimer->Timer );
    88          /* The old data of the timer are returned */
    89          if ( ovalue )
    90            *ovalue = ptimer->timer_data;
    91          /* The new data are set */
    92          ptimer->timer_data = normalize;
    93          /* Indicates that the timer is created and stopped */
    94          ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
    95          /* Returns with success */
    96         _Objects_Put( &ptimer->Object );
     165        /* The old data of the timer are returned */
     166        if ( ovalue )
     167          *ovalue = ptimer->timer_data;
     168        /* The new data are set */
     169        ptimer->timer_data = normalize;
     170        /* Indicates that the timer is created and stopped */
     171        ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
     172        /* Returns with success */
     173        _POSIX_Timer_Release( cpu, &lock_context );
    97174        return 0;
    98        }
    99 
    100        /* Convert from seconds and nanoseconds to ticks */
    101        ptimer->ticks  = _Timespec_To_ticks( &value->it_interval );
    102        initial_period = _Timespec_To_ticks( &normalize.it_value );
    103 
    104 
    105        activated = _POSIX_Timer_Insert_helper(
    106          &ptimer->Timer,
    107          initial_period,
    108          ptimer->Object.id,
    109          _POSIX_Timer_TSR,
    110          ptimer
    111        );
    112        if ( !activated ) {
    113          _Objects_Put( &ptimer->Object );
    114          return 0;
    115        }
    116 
    117        /*
    118         * The timer has been started and is running.  So we return the
    119         * old ones in "ovalue"
    120         */
    121        if ( ovalue )
    122          *ovalue = ptimer->timer_data;
    123        ptimer->timer_data = normalize;
    124 
    125        /* Indicate that the time is running */
    126        ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
    127        _TOD_Get_as_timespec( &ptimer->time );
    128       _Objects_Put( &ptimer->Object );
    129        return 0;
     175      }
     176
     177      /* Convert from seconds and nanoseconds to ticks */
     178      ptimer->ticks  = _Timespec_To_ticks( &value->it_interval );
     179      initial_period = _Timespec_To_ticks( &normalize.it_value );
     180
     181      _POSIX_Timer_Insert( ptimer, cpu, initial_period );
     182
     183      /*
     184       * The timer has been started and is running.  So we return the
     185       * old ones in "ovalue"
     186       */
     187      if ( ovalue )
     188        *ovalue = ptimer->timer_data;
     189      ptimer->timer_data = normalize;
     190      _POSIX_Timer_Release( cpu, &lock_context );
     191      return 0;
    130192
    131193#if defined(RTEMS_MULTIPROCESSING)
  • cpukit/posix/src/ualarm.c

    r90d8567 r03b900d  
    2222#include <unistd.h>
    2323
    24 #include <rtems/posix/pthreadimpl.h>
    25 #include <rtems/posix/psignalimpl.h>
    26 #include <rtems/score/threaddispatch.h>
    2724#include <rtems/score/todimpl.h>
    2825#include <rtems/score/watchdogimpl.h>
     26#include <rtems/config.h>
    2927
    30 static void _POSIX_signals_Ualarm_TSR( Objects_Id id, void *argument );
     28ISR_LOCK_DEFINE( static, _POSIX_signals_Ualarm_lock, "POSIX Ualarm" )
    3129
    32 static Watchdog_Control _POSIX_signals_Ualarm_timer = WATCHDOG_INITIALIZER(
    33   _POSIX_signals_Ualarm_TSR,
    34   0,
    35   NULL
    36 );
     30static uint32_t _POSIX_signals_Ualarm_interval;
    3731
    38 /*
    39  *  _POSIX_signals_Ualarm_TSR
    40  */
     32static void _POSIX_signals_Ualarm_TSR( Watchdog_Control *the_watchdog )
     33{
     34  int              status;
     35  ISR_lock_Context lock_context;
    4136
    42 static void _POSIX_signals_Ualarm_TSR(
    43   Objects_Id      id RTEMS_UNUSED,
    44   void           *argument RTEMS_UNUSED
    45 )
    46 {
    47   /*
    48    * Send a SIGALRM but if there is a problem, ignore it.
    49    * It's OK, there isn't a way this should fail.
    50    */
    51   (void) kill( getpid(), SIGALRM );
     37  status = kill( getpid(), SIGALRM );
     38
     39  #if defined(RTEMS_DEBUG)
     40    /*
     41     *  There is no reason to think this might fail but we should be
     42     *  cautious.
     43     */
     44    _Assert(status == 0);
     45  #else
     46    (void) status;
     47  #endif
     48
     49  _ISR_lock_ISR_disable_and_acquire(
     50    &_POSIX_signals_Ualarm_lock,
     51    &lock_context
     52  );
    5253
    5354  /*
    5455   * If the reset interval is non-zero, reschedule ourselves.
    5556   */
    56   _Watchdog_Reset_ticks( &_POSIX_signals_Ualarm_timer );
     57  if ( _POSIX_signals_Ualarm_interval != 0 ) {
     58    _Watchdog_Per_CPU_insert_relative(
     59      the_watchdog,
     60      _Per_CPU_Get(),
     61      _POSIX_signals_Ualarm_interval
     62    );
     63  }
     64
     65  _ISR_lock_Release_and_ISR_enable(
     66    &_POSIX_signals_Ualarm_lock,
     67    &lock_context
     68  );
     69}
     70
     71static Watchdog_Control _POSIX_signals_Ualarm_watchdog = WATCHDOG_INITIALIZER(
     72  _POSIX_signals_Ualarm_TSR
     73);
     74
     75static uint32_t _POSIX_signals_Ualarm_us_to_ticks( useconds_t us )
     76{
     77  uint32_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
     78
     79  return ( us + us_per_tick - 1 ) / us_per_tick;
    5780}
    5881
     
    6285)
    6386{
    64   useconds_t        remaining = 0;
    65   Watchdog_Control *the_timer;
    66   Watchdog_Interval ticks;
    67   Watchdog_States   state;
    68   struct timespec   tp;
     87  useconds_t        remaining;
     88  Watchdog_Control *the_watchdog;
     89  ISR_lock_Context  lock_context;
     90  ISR_lock_Context  lock_context2;
     91  Per_CPU_Control  *cpu;
     92  uint64_t          now;
     93  uint32_t          ticks_initial;
     94  uint32_t          ticks_interval;
    6995
    70   the_timer = &_POSIX_signals_Ualarm_timer;
     96  the_watchdog = &_POSIX_signals_Ualarm_watchdog;
     97  ticks_initial = _POSIX_signals_Ualarm_us_to_ticks( useconds );
     98  ticks_interval = _POSIX_signals_Ualarm_us_to_ticks( interval );
    7199
    72   _Thread_Disable_dispatch();
     100  _ISR_lock_ISR_disable_and_acquire(
     101    &_POSIX_signals_Ualarm_lock,
     102    &lock_context
     103  );
    73104
    74   state = _Watchdog_Remove_ticks( the_timer );
    75   if ( state == WATCHDOG_ACTIVE ) {
    76     /*
    77      *  The stop_time and start_time fields are snapshots of ticks since
    78      *  boot.  Since alarm() is dealing in seconds, we must account for
    79      *  this.
    80      */
     105  cpu = _Watchdog_Get_CPU( the_watchdog );
     106  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context2 );
     107  now = cpu->Watchdog.ticks;
    81108
    82     ticks = the_timer->initial;
    83     ticks -= (the_timer->stop_time - the_timer->start_time);
    84     /* remaining is now in ticks */
     109  remaining = (useconds_t) _Watchdog_Cancel(
     110    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
     111    the_watchdog,
     112    now
     113  );
    85114
    86     _Timespec_From_ticks( ticks, &tp );
    87     remaining  = tp.tv_sec * TOD_MICROSECONDS_PER_SECOND;
    88     remaining += tp.tv_nsec / 1000;
     115  if ( ticks_initial != 0 ) {
     116    _POSIX_signals_Ualarm_interval = ticks_interval;
     117
     118    cpu = _Per_CPU_Get();
     119    _Watchdog_Set_CPU( the_watchdog, cpu );
     120    _Watchdog_Insert(
     121      &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
     122      the_watchdog,
     123      now + ticks_initial
     124    );
    89125  }
    90126
    91   /*
    92    *  If useconds is non-zero, then the caller wants to schedule
    93    *  the alarm repeatedly at that interval.  If the interval is
    94    *  less than a single clock tick, then fudge it to a clock tick.
    95    */
    96   if ( useconds ) {
    97     Watchdog_Interval ticks;
     127  _Watchdog_Per_CPU_release_critical( cpu, &lock_context2 );
     128  _ISR_lock_Release_and_ISR_enable(
     129    &_POSIX_signals_Ualarm_lock,
     130    &lock_context
     131  );
    98132
    99     tp.tv_sec = useconds / TOD_MICROSECONDS_PER_SECOND;
    100     tp.tv_nsec = (useconds % TOD_MICROSECONDS_PER_SECOND) * 1000;
    101     ticks = _Timespec_To_ticks( &tp );
    102     if ( ticks == 0 )
    103       ticks = 1;
    104 
    105     _Watchdog_Insert_ticks( the_timer, _Timespec_To_ticks( &tp ) );
    106   }
    107 
    108   _Thread_Enable_dispatch();
     133  remaining *= rtems_configuration_get_microseconds_per_tick();
    109134
    110135  return remaining;
  • cpukit/rtems/include/rtems/rtems/ratemonimpl.h

    r90d8567 r03b900d  
    130130 * @brief Rate Monotonic Timeout
    131131 *
    132  * This routine is invoked when the period represented
    133  * by ID expires. If the thread which owns this period is blocked
    134  * waiting for the period to expire, then it is readied and the
    135  * period is restarted. If the owning thread is not waiting for the
    136  * period to expire, then the period is placed in the EXPIRED
    137  * state and not restarted.
    138  *
    139  * @param[in] id is the period id
    140  */
    141 void _Rate_monotonic_Timeout(
    142   rtems_id    id,
    143   void       *ignored
    144 );
     132 * This routine is invoked when the period represented by the watchdog expires.
     133 * If the thread which owns this period is blocked waiting for the period to
     134 * expire, then it is readied and the period is restarted. If the owning thread
     135 * is not waiting for the period to expire, then the period is placed in the
     136 * EXPIRED state and not restarted.
     137 */
     138void _Rate_monotonic_Timeout( Watchdog_Control *watchdog );
    145139
    146140/**
     
    166160
    167161/**
    168  *  @brief Initiate Rate Monotonic Statistics
     162 *  @brief Restart Rate Monotonic Period
    169163 *
    170164 *  This routine is invoked when a period is initiated via an explicit
     
    174168 *  @param[in] the_period points to the period being operated upon.
    175169 */
    176 void _Rate_monotonic_Initiate_statistics(
     170void _Rate_monotonic_Restart(
    177171  Rate_monotonic_Control *the_period
    178172);
  • cpukit/rtems/include/rtems/rtems/timer.h

    r90d8567 r03b900d  
    3232 * On-Line Applications Research Corporation (OAR).
    3333 *
    34  * Copyright (c) 2009 embedded brains GmbH.
     34 * Copyright (c) 2009, 2016 embedded brains GmbH.
    3535 *
    3636 * The license and distribution terms for this file may be
     
    4444#include <rtems/rtems/attr.h>
    4545#include <rtems/rtems/status.h>
     46#include <rtems/rtems/tasks.h>
    4647#include <rtems/rtems/types.h>
    4748
     
    6465/**@{*/
    6566
     67#define TIMER_CLASS_BIT_TIME_OF_DAY 0x1
     68
     69#define TIMER_CLASS_BIT_ON_TASK 0x2
     70
     71#define TIMER_CLASS_BIT_NOT_DORMANT 0x4
     72
    6673/**
    6774 *  The following enumerated type details the classes to which a timer
     
    7077typedef enum {
    7178  /**
     79   * This value indicates the timer is currently not in use.
     80   */
     81  TIMER_DORMANT,
     82
     83  /**
    7284   * This value indicates the timer is currently in use as an interval
    7385   * timer which will fire in the clock tick ISR.
    7486   */
    75   TIMER_INTERVAL,
     87  TIMER_INTERVAL = TIMER_CLASS_BIT_NOT_DORMANT,
    7688
    7789  /**
     
    7991   * timer which will fire in the timer server task.
    8092   */
    81   TIMER_INTERVAL_ON_TASK,
     93  TIMER_INTERVAL_ON_TASK =
     94    TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_ON_TASK,
    8295
    8396  /**
     
    8598   * timer which will fire in the clock tick ISR.
    8699   */
    87   TIMER_TIME_OF_DAY,
     100  TIMER_TIME_OF_DAY =
     101    TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_TIME_OF_DAY,
    88102
    89103  /**
     
    91105   * timer which will fire in the timer server task.
    92106   */
    93   TIMER_TIME_OF_DAY_ON_TASK,
    94 
    95   /**
    96    * This value indicates the timer is currently not in use.
    97    */
    98   TIMER_DORMANT
     107  TIMER_TIME_OF_DAY_ON_TASK =
     108    TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_TIME_OF_DAY |
     109    TIMER_CLASS_BIT_ON_TASK
    99110} Timer_Classes;
    100111
     
    125136  /** This field indicates what type of timer this currently is. */
    126137  Timer_Classes    the_class;
     138  /** This field is the timer service routine. */
     139  rtems_timer_service_routine_entry routine;
     140  /** This field is the timer service routine user data. */
     141  void *user_data;
     142  /** This field is the timer interval in ticks or seconds. */
     143  Watchdog_Interval initial;
     144  /** This field is the timer start time point in ticks. */
     145  Watchdog_Interval start_time;
     146  /** This field is the timer stop time point in ticks. */
     147  Watchdog_Interval stop_time;
    127148}   Timer_Control;
    128149
     
    297318
    298319/**
    299  *  @brief rtems_timer_initiate_server
    300  *
    301  *  This routine implements the rtems_timer_initiate_server directive.
    302  *  It creates and starts the server that executes task-based timers.
     320 *  @brief Initiates the timer server.
     321 *
     322 *  This directive creates and starts the server for task-based timers.
    303323 *  It must be invoked before any task-based timers can be initiated.
     324 *
     325 *  @param priority The timer server task priority.
     326 *  @param stack_size The stack size in bytes for the timer server task.
     327 *  @param attribute_set The timer server task attributes.
     328 *
     329 *  @return This method returns RTEMS_SUCCESSFUL if successful and an
     330 *          error code otherwise.
    304331 */
    305332rtems_status_code rtems_timer_initiate_server(
    306   uint32_t            priority,
    307   uint32_t             stack_size,
    308   rtems_attribute      attribute_set
     333  rtems_task_priority priority,
     334  size_t              stack_size,
     335  rtems_attribute     attribute_set
    309336);
    310337
  • cpukit/rtems/include/rtems/rtems/timerimpl.h

    r90d8567 r03b900d  
    1010 * COPYRIGHT (c) 1989-2011.
    1111 * On-Line Applications Research Corporation (OAR).
     12 *
     13 * Copyright (c) 2016 embedded brains GmbH.
    1214 *
    1315 * The license and distribution terms for this file may be
     
    3638 */
    3739
    38 typedef struct Timer_server_Control Timer_server_Control;
    39 
    40 /**
    41  * @brief Method used for task based timers.
    42  */
    43 typedef void (*Timer_server_Method)(
    44   Timer_server_Control *timer_server,
    45   Timer_Control        *timer
    46 );
    47 
    48 typedef struct {
    49   /**
    50    * @brief This watchdog that will be registered in the system tick mechanic
    51    * for timer server wake-up.
    52    */
    53   Watchdog_Control System_watchdog;
    54 
    55   /**
    56    * @brief Remaining delta of the system watchdog.
    57    */
    58   Watchdog_Interval system_watchdog_delta;
    59 
    60   /**
    61    * @brief Unique identifier of the context which deals currently with the
    62    * system watchdog.
    63    */
    64   Thread_Control *system_watchdog_helper;
    65 
    66   /**
    67    * @brief Each insert and tickle operation increases the generation count so
    68    * that the system watchdog dealer notices updates of the watchdog chain.
    69    */
    70   uint32_t generation;
    71 
    72   /**
    73    * @brief Watchdog header managed by the timer server.
    74    */
    75   Watchdog_Header Header;
    76 
    77   /**
    78    * @brief Last time snapshot of the timer server.
    79    *
    80    * The units may be ticks or seconds.
    81    */
    82   Watchdog_Interval last_snapshot;
    83 
    84   /**
    85    * @brief Current time snapshot of the timer server.
    86    *
    87    * The units may be ticks or seconds.
    88    */
    89   Watchdog_Interval current_snapshot;
    90 } Timer_server_Watchdogs;
    91 
    92 struct Timer_server_Control {
    93   /**
    94    * @brief The cancel method of the timer server.
    95    */
    96   Timer_server_Method cancel;
    97 
    98   /**
    99    * @brief The schedule operation method of the timer server.
    100    */
    101   Timer_server_Method schedule_operation;
    102 
    103   /**
    104    * @brief Interval watchdogs triggered by the timer server.
    105    */
    106   Timer_server_Watchdogs Interval_watchdogs;
    107 
    108   /**
    109    * @brief TOD watchdogs triggered by the timer server.
    110    */
    111   Timer_server_Watchdogs TOD_watchdogs;
    112 };
     40typedef struct Timer_server_Control {
     41  ISR_LOCK_MEMBER( Lock )
     42
     43  Chain_Control Pending;
     44
     45  Objects_Id server_id;
     46} Timer_server_Control;
    11347
    11448/**
     
    14983}
    15084
    151 /**
    152  *  @brief Timer_Get
    153  *
    154  *  This function maps timer IDs to timer control blocks.
    155  *  If ID corresponds to a local timer, then it returns
    156  *  the timer control pointer which maps to ID and location
    157  *  is set to OBJECTS_LOCAL.  Otherwise, location is set
    158  *  to OBJECTS_ERROR and the returned value is undefined.
    159  */
    160 RTEMS_INLINE_ROUTINE Timer_Control *_Timer_Get (
     85RTEMS_INLINE_ROUTINE Timer_Control *_Timer_Get(
    16186  Objects_Id         id,
    162   Objects_Locations *location
    163 )
    164 {
    165   return (Timer_Control *)
    166     _Objects_Get( &_Timer_Information, id, location );
    167 }
    168 
    169 /**
    170  *  @brief Timer_Is_interval_class
    171  *
    172  *  This function returns TRUE if the class is that of an INTERVAL
    173  *  timer, and FALSE otherwise.
    174  */
    175 RTEMS_INLINE_ROUTINE bool _Timer_Is_interval_class (
     87  Objects_Locations *location,
     88  ISR_lock_Context  *lock_context
     89)
     90{
     91  return (Timer_Control *) _Objects_Get_isr_disable(
     92    &_Timer_Information,
     93    id,
     94    location,
     95    lock_context
     96  );
     97}
     98
     99RTEMS_INLINE_ROUTINE Per_CPU_Control *_Timer_Acquire_critical(
     100  Timer_Control    *the_timer,
     101  ISR_lock_Context *lock_context
     102)
     103{
     104  Per_CPU_Control *cpu;
     105
     106  cpu = _Watchdog_Get_CPU( &the_timer->Ticker );
     107  _Watchdog_Per_CPU_acquire_critical( cpu, lock_context );
     108
     109  return cpu;
     110}
     111
     112RTEMS_INLINE_ROUTINE void _Timer_Release(
     113  Per_CPU_Control  *cpu,
     114  ISR_lock_Context *lock_context
     115)
     116{
     117  _Watchdog_Per_CPU_release_critical( cpu, lock_context );
     118  _ISR_lock_ISR_enable( lock_context );
     119}
     120
     121RTEMS_INLINE_ROUTINE bool _Timer_Is_interval_class(
    176122  Timer_Classes the_class
    177123)
    178124{
    179   return (the_class == TIMER_INTERVAL) || (the_class == TIMER_INTERVAL_ON_TASK);
    180 }
    181 
    182 /**
    183  *  @brief Timer_Is_time_of_day_class
    184  *
    185  *  This function returns TRUE if the class is that of an INTERVAL
    186  *  timer, and FALSE otherwise.
    187  */
    188 RTEMS_INLINE_ROUTINE bool _Timer_Is_timer_of_day_class (
     125  Timer_Classes mask =
     126    TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_TIME_OF_DAY;
     127
     128  return ( the_class & mask ) == TIMER_CLASS_BIT_NOT_DORMANT;
     129}
     130
     131RTEMS_INLINE_ROUTINE bool _Timer_Is_on_task_class(
    189132  Timer_Classes the_class
    190133)
    191134{
    192   return ( the_class == TIMER_TIME_OF_DAY );
    193 }
    194 
    195 /**
    196  *  @brief Timer_Is_dormant_class
    197  *
    198  *  This function returns TRUE if the class is that of a DORMANT
    199  *  timer, and FALSE otherwise.
    200  */
    201 RTEMS_INLINE_ROUTINE bool _Timer_Is_dormant_class (
     135  Timer_Classes mask =
     136    TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_ON_TASK;
     137
     138  return ( the_class & mask ) == mask;
     139}
     140
     141RTEMS_INLINE_ROUTINE Per_CPU_Watchdog_index _Timer_Watchdog_header_index(
    202142  Timer_Classes the_class
    203143)
    204144{
    205   return ( the_class == TIMER_DORMANT );
    206 }
    207 
    208 void _Timer_Cancel( Timer_Control *the_timer );
     145  return ( the_class & TIMER_CLASS_BIT_TIME_OF_DAY );
     146}
     147
     148RTEMS_INLINE_ROUTINE Watchdog_Interval _Timer_Get_CPU_ticks(
     149  const Per_CPU_Control *cpu
     150)
     151{
     152  return (Watchdog_Interval) cpu->Watchdog.ticks;
     153}
     154
     155rtems_status_code _Timer_Fire(
     156  rtems_id                           id,
     157  rtems_interval                     interval,
     158  rtems_timer_service_routine_entry  routine,
     159  void                              *user_data,
     160  Timer_Classes                      the_class,
     161  Watchdog_Service_routine_entry     adaptor
     162);
     163
     164rtems_status_code _Timer_Fire_after(
     165  rtems_id                           id,
     166  rtems_interval                     ticks,
     167  rtems_timer_service_routine_entry  routine,
     168  void                              *user_data,
     169  Timer_Classes                      the_class,
     170  Watchdog_Service_routine_entry     adaptor
     171);
     172
     173rtems_status_code _Timer_Fire_when(
     174  rtems_id                           id,
     175  const rtems_time_of_day           *wall_time,
     176  rtems_timer_service_routine_entry  routine,
     177  void                              *user_data,
     178  Timer_Classes                      the_class,
     179  Watchdog_Service_routine_entry     adaptor
     180);
     181
     182void _Timer_Cancel( Per_CPU_Control *cpu, Timer_Control *the_timer );
     183
     184void _Timer_Routine_adaptor( Watchdog_Control *the_watchdog );
     185
     186void _Timer_server_Routine_adaptor( Watchdog_Control *the_watchdog );
     187
     188RTEMS_INLINE_ROUTINE void _Timer_server_Acquire_critical(
     189  Timer_server_Control *timer_server,
     190  ISR_lock_Context     *lock_context
     191)
     192{
     193  _ISR_lock_Acquire( &timer_server->Lock, lock_context );
     194}
     195
     196RTEMS_INLINE_ROUTINE void _Timer_server_Release_critical(
     197  Timer_server_Control *timer_server,
     198  ISR_lock_Context     *lock_context
     199)
     200{
     201  _ISR_lock_Release( &timer_server->Lock, lock_context );
     202}
    209203
    210204/**@}*/
  • cpukit/rtems/src/eventseize.c

    r90d8567 r03b900d  
    9191  if ( ticks ) {
    9292    _Thread_Wait_set_timeout_code( executing, RTEMS_TIMEOUT );
    93     _Watchdog_Initialize(
    94       &executing->Timer,
     93    _Thread_Timer_insert_relative(
     94      executing,
     95      cpu_self,
    9596      _Thread_Timeout,
    96       0,
    97       executing
     97      ticks
    9898    );
    99     _Watchdog_Insert_ticks( &executing->Timer, ticks );
    10099  }
    101100
     
    114113  );
    115114  if ( !success ) {
    116     _Watchdog_Remove_ticks( &executing->Timer );
     115    _Thread_Timer_remove( executing );
    117116    _Thread_Unblock( executing );
    118117  }
  • cpukit/rtems/src/eventsurrender.c

    r90d8567 r03b900d  
    122122    _Thread_Lock_release_default( the_thread, lock_context );
    123123
    124     _Watchdog_Remove_ticks( &the_thread->Timer );
     124    _Thread_Timer_remove( the_thread );
    125125    _Thread_Unblock( the_thread );
    126126
  • cpukit/rtems/src/ratemoncancel.c

    r90d8567 r03b900d  
    3030  Rate_monotonic_Control *the_period;
    3131  Objects_Locations       location;
     32  ISR_Level               level;
    3233
    3334  the_period = _Rate_monotonic_Get( id, &location );
     
    3940        return RTEMS_NOT_OWNER_OF_RESOURCE;
    4041      }
    41       _Watchdog_Remove_ticks( &the_period->Timer );
     42      _ISR_Disable( level );
     43      _Watchdog_Per_CPU_remove_relative( &the_period->Timer );
     44      _ISR_Enable( level );
    4245      the_period->state = RATE_MONOTONIC_INACTIVE;
    4346      _Scheduler_Release_job( the_period->owner, 0 );
  • cpukit/rtems/src/ratemoncreate.c

    r90d8567 r03b900d  
    6666  the_period->state = RATE_MONOTONIC_INACTIVE;
    6767
    68   _Watchdog_Preinitialize( &the_period->Timer );
     68  _Watchdog_Preinitialize( &the_period->Timer, _Per_CPU_Get_by_index( 0 ) );
     69  _Watchdog_Initialize( &the_period->Timer, _Rate_monotonic_Timeout );
    6970
    7071  _Rate_monotonic_Reset_statistics( the_period );
  • cpukit/rtems/src/ratemondelete.c

    r90d8567 r03b900d  
    3030  Rate_monotonic_Control *the_period;
    3131  Objects_Locations       location;
     32  ISR_Level               level;
    3233
    3334  _Objects_Allocator_lock();
     
    3839      _Scheduler_Release_job( the_period->owner, 0 );
    3940      _Objects_Close( &_Rate_monotonic_Information, &the_period->Object );
    40       _Watchdog_Remove_ticks( &the_period->Timer );
     41      _ISR_Disable( level );
     42      _Watchdog_Per_CPU_remove_relative( &the_period->Timer );
     43      _ISR_Enable( level );
    4144      the_period->state = RATE_MONOTONIC_INACTIVE;
    4245      _Objects_Put( &the_period->Object );
  • cpukit/rtems/src/ratemonperiod.c

    r90d8567 r03b900d  
    7878}
    7979
    80 void _Rate_monotonic_Initiate_statistics(
    81   Rate_monotonic_Control *the_period
    82 )
     80void _Rate_monotonic_Restart( Rate_monotonic_Control *the_period )
    8381{
    8482  Thread_Control    *owning_thread = the_period->owner;
    8583  Timestamp_Control  uptime;
     84  ISR_Level          level;
    8685
    8786  _TOD_Get_uptime( &uptime );
     
    114113  }
    115114
    116   _Scheduler_Release_job( the_period->owner, the_period->next_length );
     115  _Scheduler_Release_job( owning_thread, the_period->next_length );
     116
     117  _ISR_Disable( level );
     118  _Watchdog_Per_CPU_insert_relative(
     119    &the_period->Timer,
     120    _Per_CPU_Get(),
     121    the_period->next_length
     122  );
     123  _ISR_Enable( level );
    117124}
    118125
     
    239246        _ISR_Enable( level );
    240247
     248        the_period->state = RATE_MONOTONIC_ACTIVE;
    241249        the_period->next_length = length;
    242 
    243         /*
    244          *  Baseline statistics information for the beginning of a period.
    245          */
    246         _Rate_monotonic_Initiate_statistics( the_period );
    247 
    248         the_period->state = RATE_MONOTONIC_ACTIVE;
    249         _Watchdog_Initialize(
    250           &the_period->Timer,
    251           _Rate_monotonic_Timeout,
    252           id,
    253           NULL
    254         );
    255 
    256         _Watchdog_Insert_ticks( &the_period->Timer, length );
     250        _Rate_monotonic_Restart( the_period );
    257251        _Objects_Put( &the_period->Object );
    258252        return RTEMS_SUCCESSFUL;
     
    309303        the_period->next_length = length;
    310304
    311         _Watchdog_Insert_ticks( &the_period->Timer, length );
     305        _Watchdog_Per_CPU_insert_relative(
     306          &the_period->Timer,
     307          _Per_CPU_Get(),
     308          length
     309        );
    312310        _Scheduler_Release_job( the_period->owner, the_period->next_length );
    313311        _Objects_Put( &the_period->Object );
  • cpukit/rtems/src/ratemontimeout.c

    r90d8567 r03b900d  
    2323#include <rtems/score/watchdogimpl.h>
    2424
    25 void _Rate_monotonic_Timeout(
    26   Objects_Id  id,
    27   void       *ignored
    28 )
     25void _Rate_monotonic_Timeout( Watchdog_Control *watchdog )
    2926{
    3027  Rate_monotonic_Control *the_period;
    31   Objects_Locations       location;
    3228  Thread_Control         *the_thread;
    3329
     
    3632   *  have to worry about that -- hence no _Watchdog_Remove().
    3733   */
    38   the_period = _Rate_monotonic_Get( id, &location );
    39   switch ( location ) {
     34  the_period = RTEMS_CONTAINER_OF( watchdog, Rate_monotonic_Control, Timer );
     35  the_thread = the_period->owner;
    4036
    41     case OBJECTS_LOCAL:
    42       the_thread = the_period->owner;
    43       if ( _States_Is_waiting_for_period( the_thread->current_state ) &&
    44             the_thread->Wait.id == the_period->Object.id ) {
    45         _Thread_Unblock( the_thread );
     37  _Thread_Disable_dispatch();
    4638
    47         _Rate_monotonic_Initiate_statistics( the_period );
     39  if ( _States_Is_waiting_for_period( the_thread->current_state ) &&
     40        the_thread->Wait.id == the_period->Object.id ) {
     41    _Thread_Unblock( the_thread );
     42    _Rate_monotonic_Restart( the_period );
     43  } else if ( the_period->state == RATE_MONOTONIC_OWNER_IS_BLOCKING ) {
     44    the_period->state = RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING;
     45    _Rate_monotonic_Restart( the_period );
     46  } else {
     47    the_period->state = RATE_MONOTONIC_EXPIRED;
     48  }
    4849
    49         _Watchdog_Insert_ticks( &the_period->Timer, the_period->next_length );
    50       } else if ( the_period->state == RATE_MONOTONIC_OWNER_IS_BLOCKING ) {
    51         the_period->state = RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING;
    52 
    53         _Rate_monotonic_Initiate_statistics( the_period );
    54 
    55         _Watchdog_Insert_ticks( &the_period->Timer, the_period->next_length );
    56       } else
    57         the_period->state = RATE_MONOTONIC_EXPIRED;
    58       _Objects_Put_without_thread_dispatch( &the_period->Object );
    59       break;
    60 
    61 #if defined(RTEMS_MULTIPROCESSING)
    62     case OBJECTS_REMOTE:  /* impossible */
    63 #endif
    64     case OBJECTS_ERROR:
    65       break;
    66   }
     50  _Thread_Unnest_dispatch();
    6751}
  • cpukit/rtems/src/taskwakeafter.c

    r90d8567 r03b900d  
    4242      _Thread_Set_state( executing, STATES_DELAYING );
    4343      _Thread_Wait_flags_set( executing, THREAD_WAIT_STATE_BLOCKED );
    44       _Watchdog_Initialize(
    45         &executing->Timer,
     44      _Thread_Timer_insert_relative(
     45        executing,
     46        cpu_self,
    4647        _Thread_Timeout,
    47         0,
    48         executing
     48        ticks
    4949      );
    50       _Watchdog_Insert_ticks( &executing->Timer, ticks );
    5150    }
    5251  _Thread_Dispatch_enable( cpu_self );
  • cpukit/rtems/src/taskwakewhen.c

    r90d8567 r03b900d  
    2929)
    3030{
    31   Watchdog_Interval   seconds;
    32   Thread_Control     *executing;
    33   Per_CPU_Control    *cpu_self;
     31  uint32_t         seconds;
     32  Thread_Control  *executing;
     33  Per_CPU_Control *cpu_self;
    3434
    3535  if ( !_TOD_Is_set() )
     
    5353    _Thread_Set_state( executing, STATES_WAITING_FOR_TIME );
    5454    _Thread_Wait_flags_set( executing, THREAD_WAIT_STATE_BLOCKED );
    55     _Watchdog_Initialize(
    56       &executing->Timer,
     55    _Thread_Timer_insert_absolute(
     56      executing,
     57      cpu_self,
    5758      _Thread_Timeout,
    58       0,
    59       executing
    60     );
    61     _Watchdog_Insert_seconds(
    62       &executing->Timer,
    63       seconds - _TOD_Seconds_since_epoch()
     59      _Watchdog_Ticks_from_seconds( seconds )
    6460    );
    6561  _Thread_Dispatch_enable( cpu_self );
  • cpukit/rtems/src/timercancel.c

    r90d8567 r03b900d  
    1515#endif
    1616
    17 #include <rtems/system.h>
    18 #include <rtems/rtems/status.h>
    19 #include <rtems/rtems/support.h>
    20 #include <rtems/score/thread.h>
    2117#include <rtems/rtems/timerimpl.h>
    22 #include <rtems/score/watchdogimpl.h>
    23 
    24 /*
    25  *  rtems_timer_cancel
    26  *
    27  *  This directive allows a thread to cancel a timer.
    28  *
    29  *  Input parameters:
    30  *    id - timer id
    31  *
    32  *  Output parameters:
    33  *    RTEMS_SUCCESSFUL - if successful
    34  *    error code       - if unsuccessful
    35  */
    3618
    3719rtems_status_code rtems_timer_cancel(
     
    3921)
    4022{
    41   Timer_Control   *the_timer;
    42   Objects_Locations       location;
     23  Timer_Control     *the_timer;
     24  Objects_Locations  location;
     25  ISR_lock_Context   lock_context;
     26  Per_CPU_Control   *cpu;
    4327
    44   the_timer = _Timer_Get( id, &location );
     28  the_timer = _Timer_Get( id, &location, &lock_context );
    4529  switch ( location ) {
    4630
    4731    case OBJECTS_LOCAL:
    48       _Timer_Cancel( the_timer );
    49       _Objects_Put( &the_timer->Object );
     32      cpu = _Timer_Acquire_critical( the_timer, &lock_context );
     33      _Timer_Cancel( cpu, the_timer );
     34      _Timer_Release( cpu, &lock_context );
    5035      return RTEMS_SUCCESSFUL;
    5136
  • cpukit/rtems/src/timercreate.c

    r90d8567 r03b900d  
    1919#endif
    2020
    21 #include <rtems/system.h>
     21#include <rtems/rtems/timerimpl.h>
     22#include <rtems/rtems/clock.h>
    2223#include <rtems/rtems/status.h>
    2324#include <rtems/rtems/support.h>
    2425#include <rtems/score/assert.h>
     26#include <rtems/score/chainimpl.h>
    2527#include <rtems/score/thread.h>
    26 #include <rtems/rtems/timerimpl.h>
     28#include <rtems/score/todimpl.h>
    2729#include <rtems/score/watchdogimpl.h>
    2830
    29 void _Timer_Cancel( Timer_Control *the_timer )
    30 {
    31   Timer_server_Control *timer_server;
    32   ISR_Level level;
    33 
    34   /* The timer class must not change during the cancel operation */
    35   _ISR_Disable( level );
    36 
    37   switch ( the_timer->the_class ) {
    38     case TIMER_INTERVAL:
    39       _Watchdog_Remove_ticks( &the_timer->Ticker );
    40       break;
    41     case TIMER_TIME_OF_DAY:
    42       _Watchdog_Remove_seconds( &the_timer->Ticker );
    43       break;
    44     case TIMER_INTERVAL_ON_TASK:
    45     case TIMER_TIME_OF_DAY_ON_TASK:
    46       timer_server = _Timer_server;
    47       (*timer_server->cancel)( timer_server, the_timer );
    48       break;
    49     default:
    50       _Assert( the_timer->the_class == TIMER_DORMANT );
     31RTEMS_STATIC_ASSERT(
     32  PER_CPU_WATCHDOG_ABSOLUTE == TIMER_CLASS_BIT_TIME_OF_DAY,
     33  TIMER_CLASS_BIT_TIME_OF_DAY
     34);
     35
     36void _Timer_Routine_adaptor( Watchdog_Control *the_watchdog )
     37{
     38  Timer_Control   *the_timer;
     39  Per_CPU_Control *cpu;
     40
     41  the_timer = RTEMS_CONTAINER_OF( the_watchdog, Timer_Control, Ticker );
     42  cpu = _Watchdog_Get_CPU( &the_timer->Ticker );
     43  the_timer->stop_time = _Timer_Get_CPU_ticks( cpu );
     44
     45  ( *the_timer->routine )( the_timer->Object.id, the_timer->user_data );
     46}
     47
     48rtems_status_code _Timer_Fire(
     49  rtems_id                           id,
     50  rtems_interval                     interval,
     51  rtems_timer_service_routine_entry  routine,
     52  void                              *user_data,
     53  Timer_Classes                      the_class,
     54  Watchdog_Service_routine_entry     adaptor
     55)
     56{
     57  Timer_Control        *the_timer;
     58  Objects_Locations     location;
     59  ISR_lock_Context      lock_context;
     60  Per_CPU_Control      *cpu;
     61
     62  the_timer = _Timer_Get( id, &location, &lock_context );
     63  switch ( location ) {
     64
     65    case OBJECTS_LOCAL:
     66      cpu = _Timer_Acquire_critical( the_timer, &lock_context );
     67      _Timer_Cancel( cpu, the_timer );
     68      _Watchdog_Initialize( &the_timer->Ticker, adaptor );
     69      the_timer->the_class = the_class;
     70      the_timer->routine = routine;
     71      the_timer->user_data = user_data;
     72      the_timer->initial = interval;
     73      the_timer->start_time = _Timer_Get_CPU_ticks( cpu );
     74
     75      if ( _Timer_Is_interval_class( the_class ) ) {
     76        _Watchdog_Insert(
     77          &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
     78          &the_timer->Ticker,
     79          cpu->Watchdog.ticks + interval
     80        );
     81      } else {
     82        _Watchdog_Insert(
     83          &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ],
     84          &the_timer->Ticker,
     85          _Watchdog_Ticks_from_seconds( interval )
     86        );
     87      }
     88
     89      _Timer_Release( cpu, &lock_context );
     90      return RTEMS_SUCCESSFUL;
     91
     92#if defined(RTEMS_MULTIPROCESSING)
     93    case OBJECTS_REMOTE:            /* should never return this */
     94#endif
     95    case OBJECTS_ERROR:
    5196      break;
    5297  }
    5398
    54   _ISR_Enable( level );
     99  return RTEMS_INVALID_ID;
     100}
     101
     102rtems_status_code _Timer_Fire_after(
     103  rtems_id                           id,
     104  rtems_interval                     ticks,
     105  rtems_timer_service_routine_entry  routine,
     106  void                              *user_data,
     107  Timer_Classes                      the_class,
     108  Watchdog_Service_routine_entry     adaptor
     109)
     110{
     111  if ( ticks == 0 )
     112    return RTEMS_INVALID_NUMBER;
     113
     114  if ( !routine )
     115    return RTEMS_INVALID_ADDRESS;
     116
     117  return _Timer_Fire(
     118    id,
     119    ticks,
     120    routine,
     121    user_data,
     122    the_class,
     123    adaptor
     124  );
     125}
     126
     127rtems_status_code _Timer_Fire_when(
     128  rtems_id                           id,
     129  const rtems_time_of_day           *wall_time,
     130  rtems_timer_service_routine_entry  routine,
     131  void                              *user_data,
     132  Timer_Classes                      the_class,
     133  Watchdog_Service_routine_entry     adaptor
     134)
     135{
     136  rtems_interval seconds;
     137
     138  if ( !_TOD_Is_set() )
     139    return RTEMS_NOT_DEFINED;
     140
     141  if ( !routine )
     142    return RTEMS_INVALID_ADDRESS;
     143
     144  if ( !_TOD_Validate( wall_time ) )
     145    return RTEMS_INVALID_CLOCK;
     146
     147  seconds = _TOD_To_seconds( wall_time );
     148  if ( seconds <= _TOD_Seconds_since_epoch() )
     149    return RTEMS_INVALID_CLOCK;
     150
     151  return _Timer_Fire(
     152    id,
     153    seconds,
     154    routine,
     155    user_data,
     156    the_class,
     157    adaptor
     158  );
     159}
     160
     161void _Timer_Cancel( Per_CPU_Control *cpu, Timer_Control *the_timer )
     162{
     163  Timer_Classes the_class;
     164
     165  the_class = the_timer->the_class;
     166
     167  if ( _Watchdog_Is_scheduled( &the_timer->Ticker ) ) {
     168    the_timer->stop_time = _Timer_Get_CPU_ticks( cpu );
     169    _Watchdog_Remove(
     170      &cpu->Watchdog.Header[ _Timer_Watchdog_header_index( the_class ) ],
     171      &the_timer->Ticker
     172    );
     173  } else if ( _Timer_Is_on_task_class( the_class ) ) {
     174    Timer_server_Control *timer_server;
     175    ISR_lock_Context      lock_context;
     176
     177    timer_server = _Timer_server;
     178    _Assert( timer_server != NULL );
     179    _Timer_server_Acquire_critical( timer_server, &lock_context );
     180
     181    if ( _Watchdog_Get_state( &the_timer->Ticker ) == WATCHDOG_PENDING ) {
     182      _Watchdog_Set_state( &the_timer->Ticker, WATCHDOG_INACTIVE );
     183      _Chain_Extract_unprotected( &the_timer->Ticker.Node.Chain );
     184    }
     185
     186    _Timer_server_Release_critical( timer_server, &lock_context );
     187  }
    55188}
    56189
     
    76209
    77210  the_timer->the_class = TIMER_DORMANT;
    78   _Watchdog_Preinitialize( &the_timer->Ticker );
     211  _Watchdog_Preinitialize( &the_timer->Ticker, _Per_CPU_Get_snapshot() );
    79212
    80213  _Objects_Open(
  • cpukit/rtems/src/timerdelete.c

    r90d8567 r03b900d  
    1919#endif
    2020
    21 #include <rtems/system.h>
    22 #include <rtems/rtems/status.h>
    23 #include <rtems/rtems/support.h>
    24 #include <rtems/score/thread.h>
    2521#include <rtems/rtems/timerimpl.h>
    26 #include <rtems/score/watchdogimpl.h>
    2722
    2823rtems_status_code rtems_timer_delete(
     
    3227  Timer_Control     *the_timer;
    3328  Objects_Locations  location;
     29  ISR_lock_Context   lock_context;
     30  Per_CPU_Control   *cpu;
    3431
    3532  _Objects_Allocator_lock();
    36   the_timer = _Timer_Get( id, &location );
     33  the_timer = _Timer_Get( id, &location, &lock_context );
    3734  switch ( location ) {
    3835
    3936    case OBJECTS_LOCAL:
    4037      _Objects_Close( &_Timer_Information, &the_timer->Object );
    41       _Timer_Cancel( the_timer );
    42       _Objects_Put( &the_timer->Object );
     38      cpu = _Timer_Acquire_critical( the_timer, &lock_context );
     39      _Timer_Cancel( cpu, the_timer );
     40      _Timer_Release( cpu, &lock_context );
    4341      _Timer_Free( the_timer );
    4442      _Objects_Allocator_unlock();
  • cpukit/rtems/src/timerfireafter.c

    r90d8567 r03b900d  
    1919#endif
    2020
    21 #include <rtems/system.h>
    22 #include <rtems/rtems/status.h>
    23 #include <rtems/rtems/support.h>
    24 #include <rtems/score/thread.h>
    2521#include <rtems/rtems/timerimpl.h>
    26 #include <rtems/score/watchdogimpl.h>
    2722
    2823rtems_status_code rtems_timer_fire_after(
     
    3328)
    3429{
    35   Timer_Control      *the_timer;
    36   Objects_Locations   location;
    37   ISR_Level           level;
    38 
    39   if ( ticks == 0 )
    40     return RTEMS_INVALID_NUMBER;
    41 
    42   if ( !routine )
    43     return RTEMS_INVALID_ADDRESS;
    44 
    45   the_timer = _Timer_Get( id, &location );
    46   switch ( location ) {
    47 
    48     case OBJECTS_LOCAL:
    49       _Timer_Cancel( the_timer );
    50 
    51       _ISR_Disable( level );
    52 
    53         /*
    54          *  Check to see if the watchdog has just been inserted by a
    55          *  higher priority interrupt.  If so, abandon this insert.
    56          */
    57 
    58         if ( the_timer->Ticker.state != WATCHDOG_INACTIVE ) {
    59           _ISR_Enable( level );
    60           _Objects_Put( &the_timer->Object );
    61           return RTEMS_SUCCESSFUL;
    62         }
    63 
    64         /*
    65          *  OK.  Now we now the timer was not rescheduled by an interrupt
    66          *  so we can atomically initialize it as in use.
    67          */
    68 
    69         the_timer->the_class = TIMER_INTERVAL;
    70         _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
    71       _ISR_Enable( level );
    72 
    73 
    74       _Watchdog_Insert_ticks( &the_timer->Ticker, ticks );
    75       _Objects_Put( &the_timer->Object );
    76       return RTEMS_SUCCESSFUL;
    77 
    78 #if defined(RTEMS_MULTIPROCESSING)
    79     case OBJECTS_REMOTE:            /* should never return this */
    80 #endif
    81     case OBJECTS_ERROR:
    82       break;
    83   }
    84 
    85   return RTEMS_INVALID_ID;
     30  return _Timer_Fire_after(
     31    id,
     32    ticks,
     33    routine,
     34    user_data,
     35    TIMER_INTERVAL,
     36    _Timer_Routine_adaptor
     37  );
    8638}
  • cpukit/rtems/src/timerfirewhen.c

    r90d8567 r03b900d  
    2020
    2121#include <rtems/rtems/timerimpl.h>
    22 #include <rtems/rtems/clock.h>
    23 #include <rtems/score/todimpl.h>
    24 #include <rtems/score/watchdogimpl.h>
    2522
    2623rtems_status_code rtems_timer_fire_when(
     
    3128)
    3229{
    33   Timer_Control       *the_timer;
    34   Objects_Locations    location;
    35   rtems_interval       seconds;
    36 
    37   if ( !_TOD_Is_set() )
    38     return RTEMS_NOT_DEFINED;
    39 
    40   if ( !_TOD_Validate( wall_time ) )
    41     return RTEMS_INVALID_CLOCK;
    42 
    43   if ( !routine )
    44     return RTEMS_INVALID_ADDRESS;
    45 
    46   seconds = _TOD_To_seconds( wall_time );
    47   if ( seconds <= _TOD_Seconds_since_epoch() )
    48     return RTEMS_INVALID_CLOCK;
    49 
    50   the_timer = _Timer_Get( id, &location );
    51   switch ( location ) {
    52 
    53     case OBJECTS_LOCAL:
    54       _Timer_Cancel( the_timer );
    55       the_timer->the_class = TIMER_TIME_OF_DAY;
    56       _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
    57       _Watchdog_Insert_seconds(
    58          &the_timer->Ticker,
    59          seconds - _TOD_Seconds_since_epoch()
    60        );
    61       _Objects_Put( &the_timer->Object );
    62       return RTEMS_SUCCESSFUL;
    63 
    64 #if defined(RTEMS_MULTIPROCESSING)
    65     case OBJECTS_REMOTE:            /* should never return this */
    66 #endif
    67     case OBJECTS_ERROR:
    68       break;
    69   }
    70 
    71   return RTEMS_INVALID_ID;
     30  return _Timer_Fire_when(
     31    id,
     32    wall_time,
     33    routine,
     34    user_data,
     35    TIMER_TIME_OF_DAY,
     36    _Timer_Routine_adaptor
     37  );
    7238}
  • cpukit/rtems/src/timergetinfo.c

    r90d8567 r03b900d  
    3333  Timer_Control     *the_timer;
    3434  Objects_Locations  location;
     35  ISR_lock_Context   lock_context;
     36  Per_CPU_Control   *cpu;
    3537
    3638  if ( !the_info )
    3739    return RTEMS_INVALID_ADDRESS;
    3840
    39   the_timer = _Timer_Get( id, &location );
     41  the_timer = _Timer_Get( id, &location, &lock_context );
    4042  switch ( location ) {
    4143
    4244    case OBJECTS_LOCAL:
     45      cpu = _Timer_Acquire_critical( the_timer, &lock_context );
    4346      the_info->the_class  = the_timer->the_class;
    44       the_info->initial    = the_timer->Ticker.initial;
    45       the_info->start_time = the_timer->Ticker.start_time;
    46       the_info->stop_time  = the_timer->Ticker.stop_time;
    47       _Objects_Put( &the_timer->Object );
     47      the_info->initial    = the_timer->initial;
     48      the_info->start_time = the_timer->start_time;
     49      the_info->stop_time  = the_timer->stop_time;
     50      _Timer_Release( cpu, &lock_context );
    4851      return RTEMS_SUCCESSFUL;
    4952
  • cpukit/rtems/src/timerreset.c

    r90d8567 r03b900d  
    4545  Timer_Control     *the_timer;
    4646  Objects_Locations  location;
    47   rtems_status_code  status = RTEMS_SUCCESSFUL;
     47  ISR_lock_Context   lock_context;
     48  Per_CPU_Control   *cpu;
     49  rtems_status_code  status;
    4850
    49   the_timer = _Timer_Get( id, &location );
     51  the_timer = _Timer_Get( id, &location, &lock_context );
    5052  switch ( location ) {
    5153
    5254    case OBJECTS_LOCAL:
    53       if ( the_timer->the_class == TIMER_INTERVAL ) {
    54         _Watchdog_Reset_ticks( &the_timer->Ticker );
    55       } else if ( the_timer->the_class == TIMER_INTERVAL_ON_TASK ) {
    56         Timer_server_Control *timer_server = _Timer_server;
     55      cpu = _Timer_Acquire_critical( the_timer, &lock_context );
    5756
    58         /*
    59          *  There is no way for a timer to have this class unless
    60          *  it was scheduled as a server fire.  That requires that
    61          *  the Timer Server be initiated.  So this error cannot
    62          *  occur unless something is internally wrong.
    63          */
    64         #if defined(RTEMS_DEBUG)
    65           if ( !timer_server ) {
    66             _Objects_Put( &the_timer->Object );
    67             return RTEMS_INCORRECT_STATE;
    68           }
    69         #endif
    70         (*timer_server->cancel)( timer_server, the_timer );
    71         (*timer_server->schedule_operation)( timer_server, the_timer );
     57      if ( _Timer_Is_interval_class( the_timer->the_class ) ) {
     58        _Timer_Cancel( cpu, the_timer );
     59        _Watchdog_Insert(
     60          &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
     61          &the_timer->Ticker,
     62          cpu->Watchdog.ticks + the_timer->initial
     63        );
     64        status = RTEMS_SUCCESSFUL;
    7265      } else {
    73         /*
    74          *  Must be dormant or time of day timer (e.g. TIMER_DORMANT,
    75          *  TIMER_TIME_OF_DAY, or TIMER_TIME_OF_DAY_ON_TASK).  We
    76          *  can only reset active interval timers.
    77          */
    7866        status = RTEMS_NOT_DEFINED;
    7967      }
    80       _Objects_Put( &the_timer->Object );
     68
     69      _Timer_Release( cpu, &lock_context );
    8170      return status;
    8271
  • cpukit/rtems/src/timerserver.c

    r90d8567 r03b900d  
    1616 *  On-Line Applications Research Corporation (OAR).
    1717 *
    18  *  Copyright (c) 2009-2015 embedded brains GmbH.
     18 *  Copyright (c) 2009, 2016 embedded brains GmbH.
    1919 *
    2020 *  The license and distribution terms for this file may be
     
    3535static Timer_server_Control _Timer_server_Default;
    3636
    37 static void _Timer_server_Cancel_method(
     37static void _Timer_server_Acquire(
    3838  Timer_server_Control *ts,
    39   Timer_Control *timer
    40 )
    41 {
    42   if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) {
    43     _Watchdog_Remove( &ts->Interval_watchdogs.Header, &timer->Ticker );
    44   } else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
    45     _Watchdog_Remove( &ts->TOD_watchdogs.Header, &timer->Ticker );
    46   }
    47 }
    48 
    49 static Watchdog_Interval _Timer_server_Get_ticks( void )
    50 {
    51   return _Watchdog_Ticks_since_boot;
    52 }
    53 
    54 static Watchdog_Interval _Timer_server_Get_seconds( void )
    55 {
    56   return _TOD_Seconds_since_epoch();
    57 }
    58 
    59 static void _Timer_server_Update_system_watchdog(
    60   Timer_server_Watchdogs *watchdogs,
    61   Watchdog_Header *system_header
    62 )
    63 {
    64   ISR_lock_Context lock_context;
    65 
    66   _Watchdog_Acquire( &watchdogs->Header, &lock_context );
    67 
    68   if ( watchdogs->system_watchdog_helper == NULL ) {
    69     Thread_Control *executing;
    70     uint32_t my_generation;
    71 
    72     executing = _Thread_Executing;
    73     watchdogs->system_watchdog_helper = executing;
    74 
    75     do {
    76       my_generation = watchdogs->generation;
    77 
    78       if ( !_Watchdog_Is_empty( &watchdogs->Header ) ) {
    79         Watchdog_Control *first;
    80         Watchdog_Interval delta;
    81 
    82         first = _Watchdog_First( &watchdogs->Header );
    83         delta = first->delta_interval;
    84 
    85         if (
    86           watchdogs->System_watchdog.state == WATCHDOG_INACTIVE
    87             || delta != watchdogs->system_watchdog_delta
    88         ) {
    89           watchdogs->system_watchdog_delta = delta;
    90           _Watchdog_Release( &watchdogs->Header, &lock_context );
    91 
    92           _Watchdog_Remove( system_header, &watchdogs->System_watchdog );
    93           watchdogs->System_watchdog.initial = delta;
    94           _Watchdog_Insert( system_header, &watchdogs->System_watchdog );
    95 
    96           _Watchdog_Acquire( &watchdogs->Header, &lock_context );
    97         }
    98       }
    99     } while ( watchdogs->generation != my_generation );
    100 
    101     watchdogs->system_watchdog_helper = NULL;
    102   }
    103 
    104   _Watchdog_Release( &watchdogs->Header, &lock_context );
    105 }
    106 
    107 static void _Timer_server_Insert_timer(
    108   Timer_server_Watchdogs *watchdogs,
    109   Timer_Control *timer,
    110   Watchdog_Header *system_header,
    111   Watchdog_Interval (*get_ticks)( void )
    112 )
    113 {
    114   ISR_lock_Context lock_context;
    115   Watchdog_Interval now;
    116   Watchdog_Interval delta;
    117 
    118   _Watchdog_Acquire( &watchdogs->Header, &lock_context );
    119 
    120   now = (*get_ticks)();
    121   delta = now - watchdogs->last_snapshot;
    122   watchdogs->last_snapshot = now;
    123   watchdogs->current_snapshot = now;
    124 
    125   if ( watchdogs->system_watchdog_delta > delta ) {
    126     watchdogs->system_watchdog_delta -= delta;
    127   } else {
    128     watchdogs->system_watchdog_delta = 0;
    129   }
    130 
    131   if ( !_Watchdog_Is_empty( &watchdogs->Header ) ) {
    132     Watchdog_Control *first = _Watchdog_First( &watchdogs->Header );
    133 
    134     if ( first->delta_interval > delta ) {
    135       first->delta_interval -= delta;
    136     } else {
    137       first->delta_interval = 0;
    138     }
    139   }
    140 
    141   _Watchdog_Insert_locked(
    142     &watchdogs->Header,
    143     &timer->Ticker,
    144     &lock_context
    145   );
    146 
    147   ++watchdogs->generation;
    148 
    149   _Watchdog_Release( &watchdogs->Header, &lock_context );
    150 
    151   _Timer_server_Update_system_watchdog( watchdogs, system_header );
    152 }
    153 
    154 static void _Timer_server_Schedule_operation_method(
     39  ISR_lock_Context     *lock_context
     40)
     41{
     42  _ISR_lock_ISR_disable_and_acquire( &ts->Lock, lock_context );
     43}
     44
     45static void _Timer_server_Release(
    15546  Timer_server_Control *ts,
    156   Timer_Control *timer
    157 )
    158 {
    159   if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) {
    160     _Timer_server_Insert_timer(
    161       &ts->Interval_watchdogs,
    162       timer,
    163       &_Watchdog_Ticks_header,
    164       _Timer_server_Get_ticks
    165     );
    166   } else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
    167     _Timer_server_Insert_timer(
    168       &ts->TOD_watchdogs,
    169       timer,
    170       &_Watchdog_Seconds_header,
    171       _Timer_server_Get_seconds
    172     );
    173   }
    174 }
    175 
    176 static void _Timer_server_Update_current_snapshot(
    177   Timer_server_Watchdogs *watchdogs,
    178   Watchdog_Interval (*get_ticks)( void )
    179 )
    180 {
    181   ISR_lock_Context lock_context;
    182 
    183   _Watchdog_Acquire( &watchdogs->Header, &lock_context );
    184   watchdogs->current_snapshot = (*get_ticks)();
    185   watchdogs->system_watchdog_delta = 0;
    186   _Watchdog_Release( &watchdogs->Header, &lock_context );
    187 }
    188 
    189 static void _Timer_server_Tickle(
    190   Timer_server_Watchdogs *watchdogs,
    191   Watchdog_Header *system_header,
    192   Watchdog_Interval (*get_ticks)( void ),
    193   bool ticks
    194 )
    195 {
    196   ISR_lock_Context lock_context;
    197   Watchdog_Interval now;
    198   Watchdog_Interval last;
    199 
    200   _Watchdog_Acquire( &watchdogs->Header, &lock_context );
    201 
    202   now = watchdogs->current_snapshot;
    203   last = watchdogs->last_snapshot;
    204   watchdogs->last_snapshot = now;
    205 
    206   if ( ticks || now >= last ) {
    207     _Watchdog_Adjust_forward_locked(
    208       &watchdogs->Header,
    209       now - last,
    210       &lock_context
    211     );
    212   } else {
    213     _Watchdog_Adjust_backward_locked(
    214       &watchdogs->Header,
    215       last - now
    216     );
    217   }
    218 
    219   ++watchdogs->generation;
    220 
    221   _Watchdog_Release( &watchdogs->Header, &lock_context );
    222 
    223   _Timer_server_Update_system_watchdog( watchdogs, system_header );
     47  ISR_lock_Context     *lock_context
     48)
     49{
     50  _ISR_lock_Release_and_ISR_enable( &ts->Lock, lock_context );
     51}
     52
     53void _Timer_server_Routine_adaptor( Watchdog_Control *the_watchdog )
     54{
     55  Timer_Control        *the_timer;
     56  ISR_lock_Context      lock_context;
     57  Per_CPU_Control      *cpu;
     58  Timer_server_Control *ts;
     59  bool                  wakeup;
     60
     61  ts = _Timer_server;
     62  _Assert( ts != NULL );
     63  the_timer = RTEMS_CONTAINER_OF( the_watchdog, Timer_Control, Ticker );
     64
     65  _Timer_server_Acquire( ts, &lock_context );
     66
     67  _Assert( _Watchdog_Get_state( &the_timer->Ticker ) == WATCHDOG_INACTIVE );
     68  _Watchdog_Set_state( &the_timer->Ticker, WATCHDOG_PENDING );
     69  cpu = _Watchdog_Get_CPU( &the_timer->Ticker );
     70  the_timer->stop_time = _Timer_Get_CPU_ticks( cpu );
     71  wakeup = _Chain_Is_empty( &ts->Pending );
     72  _Chain_Append_unprotected( &ts->Pending, &the_timer->Ticker.Node.Chain );
     73
     74  _Timer_server_Release( ts, &lock_context );
     75
     76  if ( wakeup ) {
     77    (void) rtems_event_system_send( ts->server_id, RTEMS_EVENT_SYSTEM_SERVER );
     78  }
    22479}
    22580
     
    24095
    24196  while ( true ) {
    242     rtems_event_set events;
    243 
    244     _Timer_server_Tickle(
    245       &ts->Interval_watchdogs,
    246       &_Watchdog_Ticks_header,
    247       _Timer_server_Get_ticks,
    248       true
    249     );
    250 
    251     _Timer_server_Tickle(
    252       &ts->TOD_watchdogs,
    253       &_Watchdog_Seconds_header,
    254       _Timer_server_Get_seconds,
    255       false
    256     );
     97    ISR_lock_Context  lock_context;
     98    rtems_event_set   events;
     99
     100    _Timer_server_Acquire( ts, &lock_context );
     101
     102    while ( true ) {
     103      Watchdog_Control                  *the_watchdog;
     104      Timer_Control                     *the_timer;
     105      rtems_timer_service_routine_entry  routine;
     106      Objects_Id                         id;
     107      void                              *user_data;
     108
     109      the_watchdog = (Watchdog_Control *) _Chain_Get_unprotected( &ts->Pending );
     110      if ( the_watchdog == NULL ) {
     111        break;
     112      }
     113
     114      _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_PENDING );
     115      _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
     116      the_timer = RTEMS_CONTAINER_OF( the_watchdog, Timer_Control, Ticker );
     117      routine = the_timer->routine;
     118      id = the_timer->Object.id;
     119      user_data = the_timer->user_data;
     120
     121      _Timer_server_Release( ts, &lock_context );
     122
     123      ( *routine )( id, user_data );
     124
     125      _Timer_server_Acquire( ts, &lock_context );
     126    }
     127
     128    _Timer_server_Release( ts, &lock_context );
    257129
    258130    (void) rtems_event_system_receive(
     
    265137}
    266138
    267 static void _Timer_server_Wakeup(
    268   Objects_Id  id,
    269   void       *arg
    270 )
    271 {
    272   Timer_server_Control *ts = arg;
    273 
    274   _Timer_server_Update_current_snapshot(
    275     &ts->Interval_watchdogs,
    276     _Timer_server_Get_ticks
    277   );
    278 
    279   _Timer_server_Update_current_snapshot(
    280     &ts->TOD_watchdogs,
    281     _Timer_server_Get_seconds
    282   );
    283 
    284   (void) rtems_event_system_send( id, RTEMS_EVENT_SYSTEM_SERVER );
    285 }
    286 
    287 static void _Timer_server_Initialize_watchdogs(
    288   Timer_server_Control *ts,
    289   rtems_id id,
    290   Timer_server_Watchdogs *watchdogs,
    291   Watchdog_Interval (*get_ticks)( void )
    292 )
    293 {
    294   Watchdog_Interval now;
    295 
    296   now = (*get_ticks)();
    297   watchdogs->last_snapshot = now;
    298   watchdogs->current_snapshot = now;
    299 
    300   _Watchdog_Header_initialize( &watchdogs->Header );
    301   _Watchdog_Preinitialize( &watchdogs->System_watchdog );
    302   _Watchdog_Initialize(
    303     &watchdogs->System_watchdog,
    304     _Timer_server_Wakeup,
    305     id,
    306     ts
    307   );
    308 }
    309 
    310 /**
    311  *  @brief rtems_timer_initiate_server
    312  *
    313  *  This directive creates and starts the server for task-based timers.
    314  *  It must be invoked before any task-based timers can be initiated.
    315  *
    316  *  @param[in] priority is the timer server priority
    317  *  @param[in] stack_size is the stack size in bytes
    318  *  @param[in] attribute_set is the timer server attributes
    319  *
    320  *  @return This method returns RTEMS_SUCCESSFUL if successful and an
    321  *          error code otherwise.
    322  */
    323 rtems_status_code rtems_timer_initiate_server(
    324   uint32_t             priority,
    325   uint32_t             stack_size,
    326   rtems_attribute      attribute_set
    327 )
    328 {
     139static rtems_status_code _Timer_server_Initiate(
     140  rtems_task_priority priority,
     141  size_t              stack_size,
     142  rtems_attribute     attribute_set
     143)
     144{
     145  rtems_status_code     status;
    329146  rtems_id              id;
    330   rtems_status_code     status;
    331   rtems_task_priority   _priority;
    332   static bool           initialized = false;
    333   bool                  tmpInitialized;
    334   Timer_server_Control *ts = &_Timer_server_Default;
     147  Timer_server_Control *ts;
     148
     149  /*
     150   *  Just to make sure this is only called once.
     151   */
     152  if ( _Timer_server != NULL ) {
     153    return RTEMS_INCORRECT_STATE;
     154  }
    335155
    336156  /*
     
    339159   *  a specific invalid value as the default.
    340160   */
    341   _priority = priority;
    342161  if ( !_RTEMS_tasks_Priority_is_valid( priority ) ) {
    343162    if ( priority != RTEMS_TIMER_SERVER_DEFAULT_PRIORITY )
    344163      return RTEMS_INVALID_PRIORITY;
    345     _priority = PRIORITY_PSEUDO_ISR;
    346   }
    347 
    348   /*
    349    *  Just to make sure this is only called once.
    350    */
    351   _Once_Lock();
    352     tmpInitialized  = initialized;
    353     initialized = true;
    354   _Once_Unlock();
    355 
    356   if ( tmpInitialized )
    357     return RTEMS_INCORRECT_STATE;
     164    priority = PRIORITY_PSEUDO_ISR;
     165  }
    358166
    359167  /*
     
    372180   */
    373181  status = rtems_task_create(
    374     _Objects_Build_name('T','I','M','E'),           /* "TIME" */
    375     _priority,            /* create with priority 1 since 0 is illegal */
    376     stack_size,           /* let user specify stack size */
     182    rtems_build_name('T','I','M','E'),
     183    priority,
     184    stack_size,
    377185    rtems_configuration_is_smp_enabled() ?
    378186      RTEMS_DEFAULT_MODES : /* no preempt is not supported for SMP */
     
    381189                          /*   system task specified for 0 priority */
    382190    attribute_set | RTEMS_SYSTEM_TASK,
    383     &id                   /* get the id back */
     191    &id
    384192  );
    385   if (status) {
    386     initialized = false;
     193  if (status != RTEMS_SUCCESSFUL) {
    387194    return status;
    388195  }
     
    393200   */
    394201
    395   _Timer_server_Initialize_watchdogs(
    396     ts,
    397     id,
    398     &ts->Interval_watchdogs,
    399     _Timer_server_Get_ticks
    400   );
    401 
    402   _Timer_server_Initialize_watchdogs(
    403     ts,
    404     id,
    405     &ts->TOD_watchdogs,
    406     _Timer_server_Get_seconds
    407   );
    408 
    409   /*
    410    *  Initialize the pointer to the timer server methods so applications that
    411    *  do not use the Timer Server do not have to pull it in.
    412    */
    413   ts->cancel = _Timer_server_Cancel_method;
    414   ts->schedule_operation = _Timer_server_Schedule_operation_method;
     202  ts = &_Timer_server_Default;
     203  _ISR_lock_Initialize( &ts->Lock, "Timer Server" );
     204  _Chain_Initialize_empty( &ts->Pending );
     205  ts->server_id = id;
    415206
    416207  /*
     
    427218    (rtems_task_argument) ts
    428219  );
    429 
    430   #if defined(RTEMS_DEBUG)
    431     /*
    432      *  One would expect a call to rtems_task_delete() here to clean up
    433      *  but there is actually no way (in normal circumstances) that the
    434      *  start can fail.  The id and starting address are known to be
    435      *  be good.  If this service fails, something is weirdly wrong on the
    436      *  target such as a stray write in an ISR or incorrect memory layout.
    437      */
    438     if (status) {
    439       initialized = false;
    440     }
    441   #endif
     220  _Assert( status == RTEMS_SUCCESSFUL );
    442221
    443222  return status;
    444223}
     224
     225rtems_status_code rtems_timer_initiate_server(
     226  rtems_task_priority priority,
     227  size_t              stack_size,
     228  rtems_attribute     attribute_set
     229)
     230{
     231  rtems_status_code status;
     232
     233  _Once_Lock();
     234  status = _Timer_server_Initiate( priority, stack_size, attribute_set );
     235  _Once_Unlock();
     236
     237  return status;
     238}
  • cpukit/rtems/src/timerserverfireafter.c

    r90d8567 r03b900d  
    1919#endif
    2020
    21 #include <rtems/system.h>
    22 #include <rtems/rtems/status.h>
    23 #include <rtems/rtems/support.h>
    24 #include <rtems/score/thread.h>
    2521#include <rtems/rtems/timerimpl.h>
    26 #include <rtems/score/watchdogimpl.h>
    2722
    2823rtems_status_code rtems_timer_server_fire_after(
     
    3328)
    3429{
    35   Timer_Control        *the_timer;
    36   Objects_Locations     location;
    37   ISR_Level             level;
    38   Timer_server_Control *timer_server = _Timer_server;
     30  Timer_server_Control *timer_server;
     31
     32  timer_server = _Timer_server;
    3933
    4034  if ( !timer_server )
    4135    return RTEMS_INCORRECT_STATE;
    4236
    43   if ( !routine )
    44     return RTEMS_INVALID_ADDRESS;
    45 
    46   if ( ticks == 0 )
    47     return RTEMS_INVALID_NUMBER;
    48 
    49   the_timer = _Timer_Get( id, &location );
    50   switch ( location ) {
    51 
    52     case OBJECTS_LOCAL:
    53       _Timer_Cancel( the_timer );
    54 
    55       _ISR_Disable( level );
    56 
    57         /*
    58          *  Check to see if the watchdog has just been inserted by a
    59          *  higher priority interrupt.  If so, abandon this insert.
    60          */
    61 
    62         if ( the_timer->Ticker.state != WATCHDOG_INACTIVE ) {
    63           _ISR_Enable( level );
    64           _Objects_Put( &the_timer->Object );
    65           return RTEMS_SUCCESSFUL;
    66         }
    67 
    68         /*
    69          *  OK.  Now we now the timer was not rescheduled by an interrupt
    70          *  so we can atomically initialize it as in use.
    71          */
    72 
    73         the_timer->the_class = TIMER_INTERVAL_ON_TASK;
    74         _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
    75         the_timer->Ticker.initial = ticks;
    76       _ISR_Enable( level );
    77 
    78       (*timer_server->schedule_operation)( timer_server, the_timer );
    79 
    80       _Objects_Put( &the_timer->Object );
    81       return RTEMS_SUCCESSFUL;
    82 
    83 #if defined(RTEMS_MULTIPROCESSING)
    84     case OBJECTS_REMOTE:            /* should never return this */
    85 #endif
    86     case OBJECTS_ERROR:
    87       break;
    88   }
    89 
    90   return RTEMS_INVALID_ID;
     37  return _Timer_Fire_after(
     38    id,
     39    ticks,
     40    routine,
     41    user_data,
     42    TIMER_INTERVAL_ON_TASK,
     43    _Timer_server_Routine_adaptor
     44  );
    9145}
  • cpukit/rtems/src/timerserverfirewhen.c

    r90d8567 r03b900d  
    2020
    2121#include <rtems/rtems/timerimpl.h>
    22 #include <rtems/rtems/clock.h>
    23 #include <rtems/score/todimpl.h>
    24 #include <rtems/score/watchdogimpl.h>
    25 
    26 /*
    27  *  rtems_timer_server_fire_when
    28  *
    29  *  This directive allows a thread to start a timer which will by
    30  *  executed by the Timer Server when it fires.
    31  *
    32  *  Input parameters:
    33  *    id        - timer id
    34  *    wall_time - time of day to fire timer
    35  *    routine   - routine to schedule
    36  *    user_data - passed as argument to routine when it is fired
    37  *
    38  *  Output parameters:
    39  *    RTEMS_SUCCESSFUL - if successful
    40  *    error code       - if unsuccessful
    41  */
    4222
    4323rtems_status_code rtems_timer_server_fire_when(
     
    4828)
    4929{
    50   Timer_Control        *the_timer;
    51   Objects_Locations     location;
    52   rtems_interval        seconds;
    53   Timer_server_Control *timer_server = _Timer_server;
     30  Timer_server_Control *timer_server;
     31
     32  timer_server = _Timer_server;
    5433
    5534  if ( !timer_server )
    5635    return RTEMS_INCORRECT_STATE;
    5736
    58   if ( !_TOD_Is_set() )
    59     return RTEMS_NOT_DEFINED;
    60 
    61   if ( !routine )
    62     return RTEMS_INVALID_ADDRESS;
    63 
    64   if ( !_TOD_Validate( wall_time ) )
    65     return RTEMS_INVALID_CLOCK;
    66 
    67   seconds = _TOD_To_seconds( wall_time );
    68   if ( seconds <= _TOD_Seconds_since_epoch() )
    69     return RTEMS_INVALID_CLOCK;
    70 
    71   the_timer = _Timer_Get( id, &location );
    72   switch ( location ) {
    73 
    74     case OBJECTS_LOCAL:
    75       _Timer_Cancel( the_timer );
    76       the_timer->the_class = TIMER_TIME_OF_DAY_ON_TASK;
    77       _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
    78       the_timer->Ticker.initial = seconds - _TOD_Seconds_since_epoch();
    79 
    80       (*timer_server->schedule_operation)( timer_server, the_timer );
    81 
    82       _Objects_Put( &the_timer->Object );
    83       return RTEMS_SUCCESSFUL;
    84 
    85 #if defined(RTEMS_MULTIPROCESSING)
    86     case OBJECTS_REMOTE:            /* should never return this */
    87 #endif
    88     case OBJECTS_ERROR:
    89       break;
    90   }
    91 
    92   return RTEMS_INVALID_ID;
     37  return _Timer_Fire_when(
     38    id,
     39    wall_time,
     40    routine,
     41    user_data,
     42    TIMER_TIME_OF_DAY_ON_TASK,
     43    _Timer_server_Routine_adaptor
     44  );
    9345}
  • cpukit/sapi/src/exinit.c

    r90d8567 r03b900d  
    3939#include <rtems/score/threadimpl.h>
    4040#include <rtems/score/todimpl.h>
    41 #include <rtems/score/watchdogimpl.h>
    4241#include <rtems/score/wkspace.h>
    4342
     
    8786  _API_Mutex_Allocate( &_RTEMS_Allocator_Mutex );
    8887  _API_Mutex_Allocate( &_Once_Mutex );
    89 
    90   _Watchdog_Handler_initialization();
    9188
    9289  _Thread_Handler_initialization();
  • cpukit/score/Makefile.am

    r90d8567 r03b900d  
    328328## TOD_C_FILES
    329329libscore_a_SOURCES += src/coretod.c src/coretodset.c \
    330     src/coretodtickle.c \
    331330    src/coretodtickspersec.c \
    332331    src/coretodadjust.c
     
    334333
    335334## WATCHDOG_C_FILES
    336 libscore_a_SOURCES += src/watchdog.c src/watchdogadjust.c \
    337     src/watchdoginsert.c src/watchdogremove.c
     335libscore_a_SOURCES += src/watchdoginsert.c
     336libscore_a_SOURCES += src/watchdogremove.c
    338337libscore_a_SOURCES += src/watchdogtick.c
    339338libscore_a_SOURCES += src/watchdogtickssinceboot.c
  • cpukit/score/include/rtems/score/mrsp.h

    r90d8567 r03b900d  
    11/*
    2  * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
     2 * Copyright (c) 2014, 2016 embedded brains GmbH.  All rights reserved.
    33 *
    44 *  embedded brains GmbH
     
    129129   */
    130130  volatile MRSP_Status status;
     131
     132  /**
     133   * @brief Watchdog for timeouts.
     134   */
     135  Watchdog_Control Watchdog;
    131136} MRSP_Rival;
    132137
  • cpukit/score/include/rtems/score/mrspimpl.h

    r90d8567 r03b900d  
    11/*
    2  * Copyright (c) 2014-2015 embedded brains GmbH.  All rights reserved.
     2 * Copyright (c) 2014, 2016 embedded brains GmbH.  All rights reserved.
    33 *
    44 *  embedded brains GmbH
     
    160160}
    161161
    162 RTEMS_INLINE_ROUTINE void _MRSP_Timeout(
    163   Objects_Id  id,
    164   void       *arg
    165 )
    166 {
    167   MRSP_Rival *rival = arg;
     162RTEMS_INLINE_ROUTINE void _MRSP_Timeout( Watchdog_Control *watchdog )
     163{
     164  MRSP_Rival *rival = RTEMS_CONTAINER_OF( watchdog, MRSP_Rival, Watchdog );
    168165  MRSP_Control *mrsp = rival->resource;
    169166  Thread_Control *thread = rival->thread;
    170167  ISR_lock_Context lock_context;
    171 
    172   (void) id;
    173168
    174169  _ISR_lock_ISR_disable_and_acquire( &mrsp->Lock, &lock_context );
     
    210205  Per_CPU_Control *cpu_self;
    211206  ISR_lock_Context giant_lock_context;
     207  ISR_Level level;
    212208
    213209  rival.thread = executing;
     
    237233
    238234  if ( timeout > 0 ) {
    239     _Watchdog_Initialize(
    240       &executing->Timer,
    241       _MRSP_Timeout,
    242       0,
    243       &rival
    244     );
    245     _Watchdog_Insert_ticks( &executing->Timer, timeout );
     235    _Watchdog_Preinitialize( &rival.Watchdog, cpu_self );
     236    _Watchdog_Initialize( &rival.Watchdog, _MRSP_Timeout );
     237    _ISR_Disable_without_giant( level );
     238    _Watchdog_Per_CPU_insert_relative( &rival.Watchdog, cpu_self, timeout );
     239    _ISR_Enable_without_giant( level );
    246240  }
    247241
     
    259253
    260254  if ( timeout > 0 ) {
    261     _Watchdog_Remove_ticks( &executing->Timer );
     255    _ISR_Disable_without_giant( level );
     256    _Watchdog_Per_CPU_remove(
     257      &rival.Watchdog,
     258      cpu_self,
     259      &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ]
     260    );
     261    _ISR_Enable_without_giant( level );
    262262
    263263    if ( status == MRSP_TIMEOUT ) {
  • cpukit/score/include/rtems/score/percpu.h

    r90d8567 r03b900d  
    2424#else
    2525  #include <rtems/score/assert.h>
    26   #include <rtems/score/isrlevel.h>
     26  #include <rtems/score/isrlock.h>
    2727  #include <rtems/score/smp.h>
    2828  #include <rtems/score/smplock.h>
    2929  #include <rtems/score/timestamp.h>
     30  #include <rtems/score/watchdog.h>
    3031#endif
    3132
     
    4243   */
    4344  #if defined( RTEMS_PROFILING )
    44     #define PER_CPU_CONTROL_SIZE_LOG2 8
     45    #define PER_CPU_CONTROL_SIZE_LOG2 9
    4546  #else
    4647    #define PER_CPU_CONTROL_SIZE_LOG2 7
     
    227228
    228229/**
     230 * @brief Per-CPU watchdog header index.
     231 */
     232typedef enum {
     233  /**
     234   * @brief Index for relative per-CPU watchdog header.
     235   *
     236   * The reference time point for this header is current ticks value
     237   * during insert.  Time is measured in clock ticks.
     238   */
     239  PER_CPU_WATCHDOG_RELATIVE,
     240
     241  /**
     242   * @brief Index for absolute per-CPU watchdog header.
     243   *
     244   * The reference time point for this header is the POSIX Epoch.  Time is
     245   * measured in nanoseconds since POSIX Epoch.
     246   */
     247  PER_CPU_WATCHDOG_ABSOLUTE,
     248
     249  /**
     250   * @brief Count of per-CPU watchdog headers.
     251   */
     252  PER_CPU_WATCHDOG_COUNT
     253} Per_CPU_Watchdog_index;
     254
     255/**
    229256 *  @brief Per CPU Core Structure
    230257 *
     
    309336  /** This is the time of the last context switch on this CPU. */
    310337  Timestamp_Control time_of_last_context_switch;
     338
     339  /**
     340   * @brief Watchdog state for this processor.
     341   */
     342  struct {
     343    /**
     344     * @brief Protects all watchdog operations on this processor.
     345     */
     346    ISR_LOCK_MEMBER( Lock )
     347
     348    /**
     349     * @brief Watchdog ticks on this processor used for relative watchdogs.
     350     */
     351    uint64_t ticks;
     352
     353    /**
     354     * @brief Header for watchdogs.
     355     *
     356     * @see Per_CPU_Watchdog_index.
     357     */
     358    Watchdog_Header Header[ PER_CPU_WATCHDOG_COUNT ];
     359  } Watchdog;
    311360
    312361  #if defined( RTEMS_SMP )
  • cpukit/score/include/rtems/score/schedulerimpl.h

    r90d8567 r03b900d  
    453453 * time-slicing management.
    454454 */
    455 RTEMS_INLINE_ROUTINE void _Scheduler_Tick( void )
    456 {
    457   uint32_t cpu_count = _SMP_Get_processor_count();
    458   uint32_t cpu_index;
    459 
    460   for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
    461     const Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
    462     const Scheduler_Control *scheduler = _Scheduler_Get_by_CPU( cpu );
    463     Thread_Control *executing = cpu->executing;
    464 
    465     if ( scheduler != NULL && executing != NULL ) {
    466       ( *scheduler->Operations.tick )( scheduler, executing );
    467     }
     455RTEMS_INLINE_ROUTINE void _Scheduler_Tick( const Per_CPU_Control *cpu )
     456{
     457  const Scheduler_Control *scheduler = _Scheduler_Get_by_CPU( cpu );
     458  Thread_Control *executing = cpu->executing;
     459
     460  if ( scheduler != NULL && executing != NULL ) {
     461    ( *scheduler->Operations.tick )( scheduler, executing );
    468462  }
    469463}
  • cpukit/score/include/rtems/score/thread.h

    r90d8567 r03b900d  
    348348
    349349/**
     350 * @brief Information required to manage a thread timer.
     351 */
     352typedef struct {
     353  ISR_LOCK_MEMBER( Lock )
     354  Watchdog_Header *header;
     355  Watchdog_Control Watchdog;
     356} Thread_Timer_information;
     357
     358/**
    350359 *  The following defines the control block used to manage
    351360 *  each thread proxy.
     
    401410  Thread_Wait_information  Wait;
    402411  /** This field is the Watchdog used to manage proxy delays and timeouts. */
    403   Watchdog_Control        Timer;
     412  Thread_Timer_information Timer;
    404413#if defined(RTEMS_MULTIPROCESSING)
    405414  /** This field is the received response packet in an MP system. */
     
    729738  Thread_Wait_information  Wait;
    730739  /** This field is the Watchdog used to manage thread delays and timeouts. */
    731   Watchdog_Control        Timer;
     740  Thread_Timer_information Timer;
    732741#if defined(RTEMS_MULTIPROCESSING)
    733742  /** This field is the received response packet in an MP system. */
  • cpukit/score/include/rtems/score/threadimpl.h

    r90d8567 r03b900d  
    3434#include <rtems/score/todimpl.h>
    3535#include <rtems/score/freechain.h>
     36#include <rtems/score/watchdogimpl.h>
    3637#include <rtems/config.h>
    3738
     
    14731474 * @brief General purpose thread wait timeout.
    14741475 *
    1475  * @param[in] id Unused.
    1476  * @param[in] arg The thread.
    1477  */
    1478 void _Thread_Timeout( Objects_Id id, void *arg );
     1476 * @param[in] watchdog The thread timer watchdog.
     1477 */
     1478void _Thread_Timeout( Watchdog_Control *watchdog );
     1479
     1480RTEMS_INLINE_ROUTINE void _Thread_Timer_insert_relative(
     1481  Thread_Control                 *the_thread,
     1482  Per_CPU_Control                *cpu,
     1483  Watchdog_Service_routine_entry  routine,
     1484  Watchdog_Interval               ticks
     1485)
     1486{
     1487  ISR_lock_Context lock_context;
     1488
     1489  _ISR_lock_ISR_disable_and_acquire( &the_thread->Timer.Lock, &lock_context );
     1490
     1491  the_thread->Timer.header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ];
     1492  the_thread->Timer.Watchdog.routine = routine;
     1493  _Watchdog_Per_CPU_insert_relative( &the_thread->Timer.Watchdog, cpu, ticks );
     1494
     1495  _ISR_lock_Release_and_ISR_enable( &the_thread->Timer.Lock, &lock_context );
     1496}
     1497
     1498RTEMS_INLINE_ROUTINE void _Thread_Timer_insert_absolute(
     1499  Thread_Control                 *the_thread,
     1500  Per_CPU_Control                *cpu,
     1501  Watchdog_Service_routine_entry  routine,
     1502  uint64_t                        expire
     1503)
     1504{
     1505  ISR_lock_Context lock_context;
     1506
     1507  _ISR_lock_ISR_disable_and_acquire( &the_thread->Timer.Lock, &lock_context );
     1508
     1509  the_thread->Timer.header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ];
     1510  the_thread->Timer.Watchdog.routine = routine;
     1511  _Watchdog_Per_CPU_insert_absolute( &the_thread->Timer.Watchdog, cpu, expire );
     1512
     1513  _ISR_lock_Release_and_ISR_enable( &the_thread->Timer.Lock, &lock_context );
     1514}
     1515
     1516RTEMS_INLINE_ROUTINE void _Thread_Timer_remove( Thread_Control *the_thread )
     1517{
     1518  ISR_lock_Context lock_context;
     1519
     1520  _ISR_lock_ISR_disable_and_acquire( &the_thread->Timer.Lock, &lock_context );
     1521
     1522  _Watchdog_Per_CPU_remove(
     1523    &the_thread->Timer.Watchdog,
     1524#if defined(RTEMS_SMP)
     1525    the_thread->Timer.Watchdog.cpu,
     1526#else
     1527    _Per_CPU_Get(),
     1528#endif
     1529    the_thread->Timer.header
     1530  );
     1531
     1532  _ISR_lock_Release_and_ISR_enable( &the_thread->Timer.Lock, &lock_context );
     1533}
    14791534
    14801535RTEMS_INLINE_ROUTINE void _Thread_Debug_set_real_processor(
  • cpukit/score/include/rtems/score/todimpl.h

    r90d8567 r03b900d  
    132132 */
    133133typedef struct {
    134   /**
    135    * @brief Time of day seconds trigger.
    136    *
    137    * This value specifies the nanoseconds since the last time of day second.
    138    * It is updated and evaluated in _TOD_Tickle_ticks().  It is set in
    139    * _TOD_Set_with_timestamp().
    140    */
    141   uint32_t seconds_trigger;
    142 
    143134  /**
    144135   *  @brief Indicates if the time of day is set.
     
    272263  return (uint32_t) _Timecounter_Time_second;
    273264}
    274 
    275 /**
    276  *  @brief Increments time of day at each clock tick.
    277  *
    278  *  This routine increments the ticks field of the current time of
    279  *  day at each clock tick.
    280  */
    281 void _TOD_Tickle_ticks( void );
    282265
    283266/**
  • cpukit/score/include/rtems/score/watchdog.h

    r90d8567 r03b900d  
    2121#define _RTEMS_SCORE_WATCHDOG_H
    2222
    23 #include <rtems/score/object.h>
     23#include <rtems/score/basedefs.h>
     24#include <rtems/score/chain.h>
     25#include <rtems/score/rbtree.h>
     26
     27struct Per_CPU_Control;
    2428
    2529#ifdef __cplusplus
     
    3943 */
    4044/**@{*/
     45
     46typedef struct Watchdog_Control Watchdog_Control;
    4147
    4248/**
     
    5965 *  This type define a pointer to a watchdog service routine.
    6066 */
    61 typedef Watchdog_Service_routine ( *Watchdog_Service_routine_entry )(
    62                  Objects_Id,
    63                  void *
    64              );
     67typedef Watchdog_Service_routine
     68  ( *Watchdog_Service_routine_entry )( Watchdog_Control * );
    6569
    6670/**
     
    7377
    7478/**
    75  *  @brief Set of the states which a watchdog timer may be at any given time.
    76  *
    77  *  This enumerated type is the set of the states in which a
    78  *  watchdog timer may be at any given time.
     79 * @brief The watchdog header to manage scheduled watchdogs.
    7980 */
     81typedef struct {
     82  /**
     83   * @brief Red-black tree of scheduled watchdogs sorted by expiration time.
     84   */
     85  RBTree_Control Watchdogs;
    8086
    81 typedef enum {
    82   /** This is the state when the watchdog is off all chains */
    83   WATCHDOG_INACTIVE,
    84   /** This is the state when the watchdog is off all chains, but we are
    85    *  currently searching for the insertion point.
     87  /**
     88   * @brief The scheduled watchdog with the earliest expiration time or NULL in
     89   * case no watchdog is scheduled.
    8690   */
    87   WATCHDOG_BEING_INSERTED,
    88   /** This is the state when the watchdog is on a chain, and allowed to fire. */
    89   WATCHDOG_ACTIVE
    90 } Watchdog_States;
     91  RBTree_Node *first;
     92} Watchdog_Header;
    9193
    9294/**
     
    9698 *  to manage each watchdog timer.
    9799 */
    98 typedef struct {
    99   /** This field is a Chain Node structure and allows this to be placed on
    100    *  chains for set management.
     100struct Watchdog_Control {
     101  /**
     102   * @brief Nodes for the watchdog.
    101103   */
    102   Chain_Node                      Node;
    103   /** This field is the state of the watchdog. */
    104   Watchdog_States                 state;
    105   /** This field is the initially requested interval. */
    106   Watchdog_Interval               initial;
    107   /** This field is the remaining portion of the interval. */
    108   Watchdog_Interval               delta_interval;
    109   /** This field is the number of system clock ticks when this was scheduled. */
    110   Watchdog_Interval               start_time;
    111   /** This field is the number of system clock ticks when this was suspended. */
    112   Watchdog_Interval               stop_time;
    113   /** This field is the function to invoke. */
    114   Watchdog_Service_routine_entry  routine;
    115   /** This field is the Id to pass as an argument to the routine. */
    116   Objects_Id                      id;
    117   /** This field is an untyped pointer to user data that is passed to the
    118    *  watchdog handler routine.
    119    */
    120   void                           *user_data;
    121 }   Watchdog_Control;
     104  union {
     105    /**
     106     * @brief this field is a red-black tree node structure and allows this to
     107     * be placed on a red-black tree used to manage the scheduled watchdogs.
     108     */
     109    RBTree_Node RBTree;
     110
     111    /**
     112     * @brief this field is a chain node structure and allows this to be placed
     113     * on a chain used to manage pending watchdogs by the timer server.
     114     */
     115    Chain_Node Chain;
     116  } Node;
     117
     118#if defined(RTEMS_SMP)
     119  /** @brief This field references the processor of this watchdog control. */
     120  struct Per_CPU_Control *cpu;
     121#endif
     122
     123  /** @brief This field is the function to invoke. */
     124  Watchdog_Service_routine_entry routine;
     125
     126  /** @brief This field is the expiration time point. */
     127  uint64_t expire;
     128};
    122129
    123130/**
  • cpukit/score/include/rtems/score/watchdogimpl.h

    r90d8567 r03b900d  
    2222#include <rtems/score/watchdog.h>
    2323#include <rtems/score/assert.h>
    24 #include <rtems/score/chainimpl.h>
    2524#include <rtems/score/isrlock.h>
    2625#include <rtems/score/percpu.h>
     26#include <rtems/score/rbtreeimpl.h>
     27
     28#include <sys/timespec.h>
    2729
    2830#ifdef __cplusplus
     
    3638
    3739/**
     40 * @brief Watchdog states.
     41 */
     42typedef enum {
     43  /**
     44   * @brief The watchdog is scheduled and a black node in the red-black tree.
     45   */
     46  WATCHDOG_SCHEDULED_BLACK,
     47
     48  /**
     49   * @brief The watchdog is scheduled and a red node in the red-black tree.
     50   */
     51  WATCHDOG_SCHEDULED_RED,
     52
     53  /**
     54   * @brief The watchdog is inactive.
     55   */
     56  WATCHDOG_INACTIVE,
     57
     58  /**
     59   * @brief The watchdog is on a chain of pending watchdogs.
     60   *
     61   * This state is used by the timer server for example.
     62   */
     63  WATCHDOG_PENDING
     64} Watchdog_State;
     65
     66/**
    3867 * @brief Watchdog initializer for static initialization.
    3968 *
    40  * @see _Watchdog_Initialize().
    41  */
    42 #define WATCHDOG_INITIALIZER( routine, id, user_data ) \
    43   { \
    44     { NULL, NULL }, \
    45     WATCHDOG_INACTIVE, \
    46     0, 0, 0, 0, \
    47     ( routine ), ( id ), ( user_data ) \
    48   }
    49 
    50 /**
    51  * @brief Iterator item to synchronize concurrent insert, remove and tickle
    52  * operations.
    53  */
    54 typedef struct {
    55   /**
    56    * @brief A node for a Watchdog_Header::Iterators chain.
    57    */
    58   Chain_Node Node;
    59 
    60   /**
    61    * @brief The current delta interval of the new watchdog to insert.
    62    */
    63   Watchdog_Interval delta_interval;
    64 
    65   /**
    66    * @brief The current watchdog of the chain on the way to insert the new
    67    * watchdog.
    68    */
    69   Chain_Node *current;
    70 } Watchdog_Iterator;
    71 
    72 /**
    73  * @brief Watchdog header.
    74  */
    75 typedef struct {
    76   /**
    77    * @brief ISR lock to protect this watchdog chain.
    78    */
    79   ISR_LOCK_MEMBER( Lock )
    80 
    81   /**
    82    * @brief The chain of active or transient watchdogs.
    83    */
    84   Chain_Control Watchdogs;
    85 
    86   /**
    87    * @brief Currently active iterators.
    88    *
    89    * The iterators are registered in _Watchdog_Insert() and updated in case the
    90    * watchdog chain changes.
    91    */
    92   Chain_Control Iterators;
    93 } Watchdog_Header;
    94 
    95 /**
    96  *  @brief Watchdog chain which is managed at ticks.
    97  *
    98  *  This is the watchdog chain which is managed at ticks.
    99  */
    100 extern Watchdog_Header _Watchdog_Ticks_header;
    101 
    102 /**
    103  *  @brief Watchdog chain which is managed at second boundaries.
    104  *
    105  *  This is the watchdog chain which is managed at second boundaries.
    106  */
    107 extern Watchdog_Header _Watchdog_Seconds_header;
    108 
    109 RTEMS_INLINE_ROUTINE void _Watchdog_Acquire(
     69 * The processor of this watchdog is set to processor with index zero.
     70 *
     71 * @see _Watchdog_Preinitialize().
     72 */
     73#if defined(RTEMS_SMP)
     74  #define WATCHDOG_INITIALIZER( routine ) \
     75    { \
     76      { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \
     77      &_Per_CPU_Information[ 0 ].per_cpu, \
     78      ( routine ), \
     79      0 \
     80    }
     81#else
     82  #define WATCHDOG_INITIALIZER( routine ) \
     83    { \
     84      { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \
     85      ( routine ), \
     86      0 \
     87    }
     88#endif
     89
     90RTEMS_INLINE_ROUTINE void _Watchdog_Header_initialize(
     91  Watchdog_Header *header
     92)
     93{
     94  _RBTree_Initialize_empty( &header->Watchdogs );
     95  header->first = NULL;
     96}
     97
     98RTEMS_INLINE_ROUTINE void _Watchdog_Header_destroy(
     99  Watchdog_Header *header
     100)
     101{
     102  /* Do nothing */
     103  (void) header;
     104}
     105
     106/**
     107 *  @brief Performs a watchdog tick.
     108 *
     109 *  @param cpu The processor for this watchdog tick.
     110 */
     111void _Watchdog_Tick( struct Per_CPU_Control *cpu );
     112
     113RTEMS_INLINE_ROUTINE Watchdog_State _Watchdog_Get_state(
     114  const Watchdog_Control *the_watchdog
     115)
     116{
     117  return RB_COLOR( &the_watchdog->Node.RBTree, Node );
     118}
     119
     120RTEMS_INLINE_ROUTINE void _Watchdog_Set_state(
     121  Watchdog_Control *the_watchdog,
     122  Watchdog_State    state
     123)
     124{
     125  RB_COLOR( &the_watchdog->Node.RBTree, Node ) = state;
     126}
     127
     128RTEMS_INLINE_ROUTINE Per_CPU_Control *_Watchdog_Get_CPU(
     129  const Watchdog_Control *the_watchdog
     130)
     131{
     132#if defined(RTEMS_SMP)
     133  return the_watchdog->cpu;
     134#else
     135  return _Per_CPU_Get_by_index( 0 );
     136#endif
     137}
     138
     139RTEMS_INLINE_ROUTINE void _Watchdog_Set_CPU(
     140  Watchdog_Control *the_watchdog,
     141  Per_CPU_Control  *cpu
     142)
     143{
     144#if defined(RTEMS_SMP)
     145  the_watchdog->cpu = cpu;
     146#else
     147  (void) cpu;
     148#endif
     149}
     150
     151/**
     152 * @brief Pre-initializes a watchdog.
     153 *
     154 * This routine must be called before a watchdog is used in any way.  The
     155 * exception are statically initialized watchdogs via WATCHDOG_INITIALIZER().
     156 *
     157 * @param[in] the_watchdog The uninitialized watchdog.
     158 */
     159RTEMS_INLINE_ROUTINE void _Watchdog_Preinitialize(
     160  Watchdog_Control *the_watchdog,
     161  Per_CPU_Control  *cpu
     162)
     163{
     164  _Watchdog_Set_CPU( the_watchdog, cpu );
     165  _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
     166
     167#if defined(RTEMS_DEBUG)
     168  the_watchdog->routine = NULL;
     169  the_watchdog->expire = 0;
     170#endif
     171}
     172
     173/**
     174 * @brief Initializes a watchdog with a new service routine.
     175 *
     176 * The watchdog must be inactive.
     177 */
     178RTEMS_INLINE_ROUTINE void _Watchdog_Initialize(
     179  Watchdog_Control               *the_watchdog,
     180  Watchdog_Service_routine_entry  routine
     181)
     182{
     183  _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE );
     184  the_watchdog->routine = routine;
     185}
     186
     187void _Watchdog_Do_tickle(
    110188  Watchdog_Header  *header,
     189  uint64_t          now,
     190#if defined(RTEMS_SMP)
     191  ISR_lock_Control *lock,
     192#endif
    111193  ISR_lock_Context *lock_context
    112 )
    113 {
    114   _ISR_lock_ISR_disable_and_acquire( &header->Lock, lock_context );
    115 }
    116 
    117 RTEMS_INLINE_ROUTINE void _Watchdog_Release(
     194);
     195
     196#if defined(RTEMS_SMP)
     197  #define _Watchdog_Tickle( header, now, lock, lock_context ) \
     198    _Watchdog_Do_tickle( header, now, lock, lock_context )
     199#else
     200  #define _Watchdog_Tickle( header, now, lock, lock_context ) \
     201    _Watchdog_Do_tickle( header, now, lock_context )
     202#endif
     203
     204/**
     205 * @brief Inserts a watchdog into the set of scheduled watchdogs according to
     206 * the specified expiration time.
     207 *
     208 * The watchdog must be inactive.
     209 */
     210void _Watchdog_Insert(
    118211  Watchdog_Header  *header,
    119   ISR_lock_Context *lock_context
    120 )
    121 {
    122   _ISR_lock_Release_and_ISR_enable( &header->Lock, lock_context );
    123 }
    124 
    125 RTEMS_INLINE_ROUTINE void _Watchdog_Flash(
    126   Watchdog_Header  *header,
    127   ISR_lock_Context *lock_context
    128 )
    129 {
    130   _ISR_lock_Flash( &header->Lock, lock_context );
    131 }
    132 
    133 /**
    134  *  @brief Initialize the watchdog handler.
    135  *
    136  *  This routine initializes the watchdog handler.  The watchdog
    137  *  synchronization flag is initialized and the watchdog chains are
    138  *  initialized and emptied.
    139  */
    140 void _Watchdog_Handler_initialization( void );
    141 
    142 /**
    143  *  @brief Performs a watchdog tick.
    144  *
    145  *  @param cpu The processor for this watchdog tick.
    146  */
    147 void _Watchdog_Tick( Per_CPU_Control *cpu );
    148 
    149 /**
    150  *  @brief Removes @a the_watchdog from the watchdog chain.
    151  *
    152  *  This routine removes @a the_watchdog from the watchdog chain on which
    153  *  it resides and returns the state @a the_watchdog timer was in.
    154  *
    155  *  @param[in] header The watchdog chain.
    156  *  @param[in] the_watchdog will be removed
    157  *  @retval the state in which @a the_watchdog was in when removed
    158  */
    159 Watchdog_States _Watchdog_Remove (
     212  Watchdog_Control *the_watchdog,
     213  uint64_t          expire
     214);
     215
     216/**
     217 * @brief In case the watchdog is scheduled, then it is removed from the set of
     218 * scheduled watchdogs.
     219 *
     220 * The watchdog must be initialized before this call.
     221 */
     222void _Watchdog_Remove(
    160223  Watchdog_Header  *header,
    161224  Watchdog_Control *the_watchdog
     
    163226
    164227/**
    165  *  @brief Adjusts the header watchdog chain in the backward direction for
    166  *  units ticks.
    167  *
    168  *  @param[in] header The watchdog chain.
    169  *  @param[in] units The units of ticks to adjust.
    170  */
    171 void _Watchdog_Adjust_backward(
    172   Watchdog_Header   *header,
    173   Watchdog_Interval  units
    174 );
    175 
    176 /**
    177  * @brief Adjusts the watchdogs in backward direction in a locked context.
    178  *
    179  * The caller must be the owner of the watchdog lock and will be the owner
    180  * after the call.
    181  *
    182  * @param[in] header The watchdog header.
    183  * @param[in] units The units of ticks to adjust.
    184  *
    185  * @see _Watchdog_Adjust_forward().
    186  */
    187 void _Watchdog_Adjust_backward_locked(
    188   Watchdog_Header   *header,
    189   Watchdog_Interval  units
    190 );
    191 
    192 /**
    193  *  @brief Adjusts the header watchdog chain in the forward direction for units
    194  *  ticks.
    195  *
    196  *  This may lead to several _Watchdog_Tickle() invocations.
    197  *
    198  *  @param[in] header The watchdog chain.
    199  *  @param[in] units The units of ticks to adjust.
    200  */
    201 void _Watchdog_Adjust_forward(
    202   Watchdog_Header   *header,
    203   Watchdog_Interval  units
    204 );
    205 
    206 /**
    207  * @brief Adjusts the watchdogs in forward direction in a locked context.
    208  *
    209  * The caller must be the owner of the watchdog lock and will be the owner
    210  * after the call.  This function may release and acquire the watchdog lock
    211  * internally.
    212  *
    213  * @param[in] header The watchdog header.
    214  * @param[in] units The units of ticks to adjust.
    215  * @param[in] lock_context The lock context.
    216  *
    217  * @see _Watchdog_Adjust_forward().
    218  */
    219 void _Watchdog_Adjust_forward_locked(
    220   Watchdog_Header   *header,
    221   Watchdog_Interval  units,
    222   ISR_lock_Context  *lock_context
    223 );
    224 
    225 /**
    226  *  @brief Inserts @a the_watchdog into the @a header watchdog chain
    227  *  for a time of @a units.
    228  *
    229  *  This routine inserts @a the_watchdog into the @a header watchdog chain
    230  *  for a time of @a units.
    231  *  Update the delta interval counters.
    232  *
    233  *  @param[in] header is @a the_watchdog list to insert @a the_watchdog on
    234  *  @param[in] the_watchdog is the watchdog to insert
    235  */
    236 void _Watchdog_Insert (
     228 * @brief In case the watchdog is scheduled, then it is removed from the set of
     229 * scheduled watchdogs.
     230 *
     231 * The watchdog must be initialized before this call.
     232 *
     233 * @retval 0 The now time is greater than or equal to the expiration time of
     234 * the watchdog.
     235 * @retval other The difference of the now and expiration time.
     236 */
     237RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Cancel(
     238  Watchdog_Header  *header,
     239  Watchdog_Control *the_watchdog,
     240  uint64_t          now
     241)
     242{
     243  uint64_t expire;
     244  uint64_t remaining;
     245
     246  expire = the_watchdog->expire;
     247
     248  if ( now < expire ) {
     249    remaining = expire - now;
     250  } else {
     251    remaining = 0;
     252  }
     253
     254  _Watchdog_Remove( header, the_watchdog );
     255
     256  return remaining;
     257}
     258
     259RTEMS_INLINE_ROUTINE bool _Watchdog_Is_scheduled(
     260  const Watchdog_Control *the_watchdog
     261)
     262{
     263  return _Watchdog_Get_state( the_watchdog ) < WATCHDOG_INACTIVE;
     264}
     265
     266RTEMS_INLINE_ROUTINE void _Watchdog_Next_first(
    237267  Watchdog_Header  *header,
    238268  Watchdog_Control *the_watchdog
    239 );
    240 
    241 /**
    242  * @brief Inserts the watchdog in a locked context.
    243  *
    244  * The caller must be the owner of the watchdog lock and will be the owner
    245  * after the call.  This function may release and acquire the watchdog lock
    246  * internally.
    247  *
    248  * @param[in] header The watchdog header.
    249  * @param[in] the_watchdog The watchdog.
    250  * @param[in] lock_context The lock context.
    251  *
    252  * @see _Watchdog_Insert().
    253  */
    254 void _Watchdog_Insert_locked(
    255   Watchdog_Header  *header,
    256   Watchdog_Control *the_watchdog,
     269)
     270{
     271  RBTree_Node *node = _RBTree_Right( &the_watchdog->Node.RBTree );
     272
     273  if ( node != NULL ) {
     274    RBTree_Node *left;
     275
     276    while ( ( left = _RBTree_Left( node ) ) != NULL ) {
     277      node = left;
     278    }
     279
     280    header->first = node;
     281  } else {
     282    header->first = _RBTree_Parent( &the_watchdog->Node.RBTree );
     283  }
     284}
     285
     286/**
     287 * @brief The bits necessary to store 1000000000 nanoseconds.
     288 *
     289 * The expiration time is an unsigned 64-bit integer.  To store absolute
     290 * timeouts we use 30 bits (2**30 == 1073741824) for the nanoseconds and 34
     291 * bits for the seconds since UNIX Epoch.  This leads to a year 2514 problem.
     292 */
     293#define WATCHDOG_BITS_FOR_1E9_NANOSECONDS 30
     294
     295RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_seconds(
     296  uint32_t seconds
     297)
     298{
     299  uint64_t ticks = seconds;
     300
     301  ticks <<= WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
     302
     303  return ticks;
     304}
     305
     306RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_timespec(
     307  const struct timespec *ts
     308)
     309{
     310  /*
     311   * The seconds are in time_t which is a signed integer.  Thus this cast is
     312   * subject to the year 2038 problem in case time_t is a 32-bit integer.
     313   */
     314  uint64_t ticks = (uint64_t) ts->tv_sec;
     315
     316  _Assert( ticks < 0x400000000 );
     317  _Assert( ts->tv_nsec >= 0 );
     318  _Assert( ts->tv_nsec < 1000000000 );
     319
     320  ticks <<= WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
     321  ticks |= ts->tv_nsec;
     322
     323  return ticks;
     324}
     325
     326RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_acquire_critical(
     327  Per_CPU_Control  *cpu,
    257328  ISR_lock_Context *lock_context
    258 );
    259 
    260 /**
    261  *  @brief This routine is invoked at appropriate intervals to update
    262  *  the @a header watchdog chain.
    263  *
    264  *  This routine is invoked at appropriate intervals to update
    265  *  the @a header watchdog chain.
    266  *  This routine decrements the delta counter in response to a tick.
    267  *
    268  *  @param[in] header is the watchdog chain to tickle
    269  */
    270 void _Watchdog_Tickle (
    271   Watchdog_Header *header
    272 );
    273 
    274 /**
    275  * @brief Pre-initializes a watchdog.
    276  *
    277  * This routine must be called before a watchdog is used in any way.  The
    278  * exception are statically initialized watchdogs via WATCHDOG_INITIALIZER().
    279  *
    280  * @param[in] the_watchdog The uninitialized watchdog.
    281  */
    282 RTEMS_INLINE_ROUTINE void _Watchdog_Preinitialize(
     329)
     330{
     331  _ISR_lock_Acquire( &cpu->Watchdog.Lock, lock_context );
     332}
     333
     334RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_release_critical(
     335  Per_CPU_Control  *cpu,
     336  ISR_lock_Context *lock_context
     337)
     338{
     339  _ISR_lock_Release( &cpu->Watchdog.Lock, lock_context );
     340}
     341
     342RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_insert_relative(
     343  Watchdog_Control *the_watchdog,
     344  Per_CPU_Control  *cpu,
     345  uint32_t          ticks
     346)
     347{
     348  ISR_lock_Context lock_context;
     349
     350  _Watchdog_Set_CPU( the_watchdog, cpu );
     351
     352  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
     353  _Watchdog_Insert(
     354    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
     355    the_watchdog,
     356    cpu->Watchdog.ticks + ticks
     357  );
     358  _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
     359}
     360
     361RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_insert_absolute(
     362  Watchdog_Control *the_watchdog,
     363  Per_CPU_Control  *cpu,
     364  uint64_t          expire
     365)
     366{
     367  ISR_lock_Context lock_context;
     368
     369  _Watchdog_Set_CPU( the_watchdog, cpu );
     370
     371  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
     372  _Watchdog_Insert(
     373    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ],
     374    the_watchdog,
     375    expire
     376  );
     377  _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
     378}
     379
     380RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove(
     381  Watchdog_Control *the_watchdog,
     382  Per_CPU_Control  *cpu,
     383  Watchdog_Header  *header
     384)
     385{
     386  ISR_lock_Context lock_context;
     387
     388  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
     389  _Watchdog_Remove(
     390    header,
     391    the_watchdog
     392  );
     393  _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
     394}
     395
     396RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove_relative(
    283397  Watchdog_Control *the_watchdog
    284398)
    285399{
    286   the_watchdog->state = WATCHDOG_INACTIVE;
    287 #if defined(RTEMS_DEBUG)
    288   the_watchdog->routine = NULL;
    289   the_watchdog->id = 0;
    290   the_watchdog->user_data = NULL;
    291 #endif
    292 }
    293 
    294 /**
    295  * This routine initializes the specified watchdog.  The watchdog is
    296  * made inactive, the watchdog id and handler routine are set to the
    297  * specified values.
    298  */
    299 
    300 RTEMS_INLINE_ROUTINE void _Watchdog_Initialize(
    301   Watchdog_Control               *the_watchdog,
    302   Watchdog_Service_routine_entry  routine,
    303   Objects_Id                      id,
    304   void                           *user_data
    305 )
    306 {
    307   _Assert( the_watchdog->state == WATCHDOG_INACTIVE );
    308   the_watchdog->routine   = routine;
    309   the_watchdog->id        = id;
    310   the_watchdog->user_data = user_data;
    311 }
    312 
    313 /**
    314  * This routine returns true if the watchdog timer is in the ACTIVE
    315  * state, and false otherwise.
    316  */
    317 
    318 RTEMS_INLINE_ROUTINE bool _Watchdog_Is_active(
     400  Per_CPU_Control *cpu;
     401
     402  cpu = _Watchdog_Get_CPU( the_watchdog );
     403  _Watchdog_Per_CPU_remove(
     404    the_watchdog,
     405    cpu,
     406    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ]
     407  );
     408}
     409
     410RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove_absolute(
    319411  Watchdog_Control *the_watchdog
    320412)
    321413{
    322 
    323   return ( the_watchdog->state == WATCHDOG_ACTIVE );
    324 
    325 }
    326 
    327 /**
    328  * This routine activates THE_WATCHDOG timer which is already
    329  * on a watchdog chain.
    330  */
    331 
    332 RTEMS_INLINE_ROUTINE void _Watchdog_Activate(
    333   Watchdog_Control *the_watchdog
    334 )
    335 {
    336 
    337   the_watchdog->state = WATCHDOG_ACTIVE;
    338 
    339 }
    340 
    341 /**
    342  * This routine is invoked at each clock tick to update the ticks
    343  * watchdog chain.
    344  */
    345 
    346 RTEMS_INLINE_ROUTINE void _Watchdog_Tickle_ticks( void )
    347 {
    348 
    349   _Watchdog_Tickle( &_Watchdog_Ticks_header );
    350 
    351 }
    352 
    353 /**
    354  * This routine is invoked at each clock tick to update the seconds
    355  * watchdog chain.
    356  */
    357 
    358 RTEMS_INLINE_ROUTINE void _Watchdog_Tickle_seconds( void )
    359 {
    360 
    361   _Watchdog_Tickle( &_Watchdog_Seconds_header );
    362 
    363 }
    364 
    365 /**
    366  * This routine inserts THE_WATCHDOG into the ticks watchdog chain
    367  * for a time of UNITS ticks.  The INSERT_MODE indicates whether
    368  * THE_WATCHDOG is to be activated automatically or later, explicitly
    369  * by the caller.
    370  */
    371 
    372 RTEMS_INLINE_ROUTINE void _Watchdog_Insert_ticks(
    373   Watchdog_Control      *the_watchdog,
    374   Watchdog_Interval      units
    375 )
    376 {
    377 
    378   the_watchdog->initial = units;
    379 
    380   _Watchdog_Insert( &_Watchdog_Ticks_header, the_watchdog );
    381 
    382 }
    383 
    384 /**
    385  * This routine inserts THE_WATCHDOG into the seconds watchdog chain
    386  * for a time of UNITS seconds.  The INSERT_MODE indicates whether
    387  * THE_WATCHDOG is to be activated automatically or later, explicitly
    388  * by the caller.
    389  */
    390 
    391 RTEMS_INLINE_ROUTINE void _Watchdog_Insert_seconds(
    392   Watchdog_Control      *the_watchdog,
    393   Watchdog_Interval      units
    394 )
    395 {
    396 
    397   the_watchdog->initial = units;
    398 
    399   _Watchdog_Insert( &_Watchdog_Seconds_header, the_watchdog );
    400 
    401 }
    402 
    403 RTEMS_INLINE_ROUTINE Watchdog_States _Watchdog_Remove_ticks(
    404   Watchdog_Control *the_watchdog
    405 )
    406 {
    407   return _Watchdog_Remove( &_Watchdog_Ticks_header, the_watchdog );
    408 }
    409 
    410 RTEMS_INLINE_ROUTINE Watchdog_States _Watchdog_Remove_seconds(
    411   Watchdog_Control *the_watchdog
    412 )
    413 {
    414   return _Watchdog_Remove( &_Watchdog_Seconds_header, the_watchdog );
    415 }
    416 
    417 /**
    418  * This routine resets THE_WATCHDOG timer to its state at INSERT
    419  * time.  This routine is valid only on interval watchdog timers
    420  * and is used to make an interval watchdog timer fire "every" so
    421  * many ticks.
    422  */
    423 
    424 RTEMS_INLINE_ROUTINE void _Watchdog_Reset_ticks(
    425   Watchdog_Control *the_watchdog
    426 )
    427 {
    428 
    429   _Watchdog_Remove_ticks( the_watchdog );
    430 
    431   _Watchdog_Insert( &_Watchdog_Ticks_header, the_watchdog );
    432 
    433 }
    434 
    435 /**
    436  * This routine returns a pointer to the watchdog timer following
    437  * THE_WATCHDOG on the watchdog chain.
    438  */
    439 
    440 RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Next(
    441   Watchdog_Control *the_watchdog
    442 )
    443 {
    444 
    445   return ( (Watchdog_Control *) the_watchdog->Node.next );
    446 
    447 }
    448 
    449 /**
    450  * This routine returns a pointer to the watchdog timer preceding
    451  * THE_WATCHDOG on the watchdog chain.
    452  */
    453 
    454 RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Previous(
    455   Watchdog_Control *the_watchdog
    456 )
    457 {
    458 
    459   return ( (Watchdog_Control *) the_watchdog->Node.previous );
    460 
    461 }
    462 
    463 /**
    464  * This routine returns a pointer to the first watchdog timer
    465  * on the watchdog chain HEADER.
    466  */
    467 
    468 RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_First(
    469   Watchdog_Header *header
    470 )
    471 {
    472 
    473   return ( (Watchdog_Control *) _Chain_First( &header->Watchdogs ) );
    474 
    475 }
    476 
    477 /**
    478  * This routine returns a pointer to the last watchdog timer
    479  * on the watchdog chain HEADER.
    480  */
    481 
    482 RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Last(
    483   Watchdog_Header *header
    484 )
    485 {
    486 
    487   return ( (Watchdog_Control *) _Chain_Last( &header->Watchdogs ) );
    488 
    489 }
    490 
    491 RTEMS_INLINE_ROUTINE bool _Watchdog_Is_empty(
    492   const Watchdog_Header *header
    493 )
    494 {
    495   return _Chain_Is_empty( &header->Watchdogs );
    496 }
    497 
    498 RTEMS_INLINE_ROUTINE void _Watchdog_Header_initialize(
    499   Watchdog_Header *header
    500 )
    501 {
    502   _ISR_lock_Initialize( &header->Lock, "Watchdog" );
    503   _Chain_Initialize_empty( &header->Watchdogs );
    504   _Chain_Initialize_empty( &header->Iterators );
     414  Per_CPU_Control *cpu;
     415
     416  cpu = _Watchdog_Get_CPU( the_watchdog );
     417  _Watchdog_Per_CPU_remove(
     418    the_watchdog,
     419    cpu,
     420    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ]
     421  );
     422}
     423
     424RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_tickle_absolute(
     425  Per_CPU_Control *cpu,
     426  uint64_t         now
     427)
     428{
     429  ISR_lock_Context lock_context;
     430
     431  _ISR_lock_ISR_disable_and_acquire( &cpu->Watchdog.Lock, &lock_context );
     432  _Watchdog_Tickle(
     433    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ],
     434    now,
     435    &cpu->Watchdog.Lock,
     436    &lock_context
     437  );
    505438}
    506439
  • cpukit/score/src/condition.c

    r90d8567 r03b900d  
    283283      next = _Chain_Next( node );
    284284      thread = THREAD_CHAIN_NODE_TO_THREAD( node );
    285       _Watchdog_Remove_ticks( &thread->Timer );
     285      _Thread_Timer_remove( thread );
    286286      _Thread_Unblock( thread );
    287287
  • cpukit/score/src/coretodset.c

    r90d8567 r03b900d  
    2727)
    2828{
    29   struct timespec ts;
    30   uint32_t nanoseconds;
    31   Watchdog_Interval seconds_next;
    32   Watchdog_Interval seconds_now;
    33   Watchdog_Header *header;
     29  struct timespec tod_as_timespec;
     30  uint64_t        tod_as_ticks;
     31  uint32_t        cpu_count;
     32  uint32_t        cpu_index;
    3433
    35   _Timestamp_To_timespec( tod_as_timestamp, &ts );
    36   nanoseconds = ts.tv_nsec;
    37   seconds_next = ts.tv_sec;
     34  _Timestamp_To_timespec( tod_as_timestamp, &tod_as_timespec );
    3835
    3936  _Thread_Disable_dispatch();
    4037
    41   seconds_now = _TOD_Seconds_since_epoch();
     38  _Timecounter_Set_clock( &tod_as_timespec );
    4239
    43   _Timecounter_Set_clock( &ts );
     40  tod_as_ticks = _Watchdog_Ticks_from_timespec( &tod_as_timespec );
     41  cpu_count = _SMP_Get_processor_count();
    4442
    45   header = &_Watchdog_Seconds_header;
     43  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
     44    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
    4645
    47   if ( seconds_next < seconds_now )
    48     _Watchdog_Adjust_backward( header, seconds_now - seconds_next );
    49   else
    50     _Watchdog_Adjust_forward( header, seconds_next - seconds_now );
     46    _Watchdog_Per_CPU_tickle_absolute( cpu, tod_as_ticks );
     47  }
    5148
    52   _TOD.seconds_trigger = nanoseconds;
    5349  _TOD.is_set = true;
    5450
  • cpukit/score/src/kern_tc.c

    r90d8567 r03b900d  
    19721972        count = 0;
    19731973#else /* __rtems__ */
     1974#include <rtems/score/smp.h>
    19741975void
    19751976_Timecounter_Tick(void)
     
    20222023        _Timecounter_Release(lock_context);
    20232024
    2024         _Watchdog_Tick(_Per_CPU_Get());
     2025        _Watchdog_Tick(_Per_CPU_Get_snapshot());
    20252026}
    20262027#endif /* __rtems__ */
  • cpukit/score/src/smp.c

    r90d8567 r03b900d  
    8888    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
    8989
     90    _ISR_lock_Initialize( &cpu->Watchdog.Lock, "Watchdog" );
    9091    _SMP_ticket_lock_Initialize( &cpu->Lock );
    9192    _SMP_lock_Stats_initialize( &cpu->Lock_stats, "Per-CPU" );
  • cpukit/score/src/threadinitialize.c

    r90d8567 r03b900d  
    161161  the_thread->Start.budget_callout   = budget_callout;
    162162
     163  _ISR_lock_Initialize( &the_thread->Timer.Lock, "Thread Timer" );
     164  the_thread->Timer.header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ];
     165  _Watchdog_Preinitialize( &the_thread->Timer.Watchdog, cpu );
     166
    163167  switch ( budget_algorithm ) {
    164168    case THREAD_CPU_BUDGET_ALGORITHM_NONE:
  • cpukit/score/src/threadqenqueue.c

    r90d8567 r03b900d  
    3636static void _Thread_queue_Unblock( Thread_Control *the_thread )
    3737{
    38   _Watchdog_Remove_ticks( &the_thread->Timer );
     38  _Thread_Timer_remove( the_thread );
    3939  _Thread_Unblock( the_thread );
    4040
     
    8585  if ( timeout != WATCHDOG_NO_TIMEOUT ) {
    8686    _Thread_Wait_set_timeout_code( the_thread, timeout_code );
    87     _Watchdog_Initialize( &the_thread->Timer, _Thread_Timeout, 0, the_thread );
    88     _Watchdog_Insert_ticks( &the_thread->Timer, timeout );
     87    _Thread_Timer_insert_relative(
     88      the_thread,
     89      cpu_self,
     90      _Thread_Timeout,
     91      timeout
     92    );
    8993  }
    9094
  • cpukit/score/src/threadrestart.c

    r90d8567 r03b900d  
    8585  _Thread_Set_state( the_thread, STATES_ZOMBIE );
    8686  _Thread_queue_Extract_with_proxy( the_thread );
    87   _Watchdog_Remove_ticks( &the_thread->Timer );
     87  _Thread_Timer_remove( the_thread );
    8888
    8989  _ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context );
     
    192192)
    193193{
    194   _Assert( executing->Timer.state == WATCHDOG_INACTIVE );
     194  _Assert(
     195    _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
     196  );
    195197  _Assert(
    196198    executing->current_state == STATES_READY
     
    247249      _Thread_Start_life_change_for_executing( executing );
    248250    } else {
    249       _Assert( executing->Timer.state == WATCHDOG_INACTIVE );
     251      _Assert(
     252        _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
     253      );
    250254      _Assert(
    251255        executing->current_state == STATES_READY
     
    275279  _Thread_Set_state( the_thread, STATES_RESTARTING );
    276280  _Thread_queue_Extract_with_proxy( the_thread );
    277   _Watchdog_Remove_ticks( &the_thread->Timer );
     281  _Thread_Timer_remove( the_thread );
    278282  _Thread_Change_priority(
    279283    the_thread,
  • cpukit/score/src/threadtimeout.c

    r90d8567 r03b900d  
    3434}
    3535
    36 void _Thread_Timeout( Objects_Id id, void *arg )
     36void _Thread_Timeout( Watchdog_Control *watchdog )
    3737{
    3838  Thread_Control    *the_thread;
     
    4242  bool               unblock;
    4343
    44   the_thread = arg;
     44  the_thread = RTEMS_CONTAINER_OF( watchdog, Thread_Control, Timer.Watchdog );
    4545  thread_lock = _Thread_Lock_acquire( the_thread, &lock_context );
    4646
  • cpukit/score/src/watchdoginsert.c

    r90d8567 r03b900d  
    11/**
    2  * @file 
     2 * @file
    33 *
    44 * @brief Watchdog Insert
    55 * @ingroup ScoreWatchdog
    66 */
    7  
     7
    88/*
    9  *  COPYRIGHT (c) 1989-1999.
    10  *  On-Line Applications Research Corporation (OAR).
     9 * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
    1110 *
    12  *  The license and distribution terms for this file may be
    13  *  found in the file LICENSE in this distribution or at
    14  *  http://www.rtems.org/license/LICENSE.
     11 *  embedded brains GmbH
     12 *  Dornierstr. 4
     13 *  82178 Puchheim
     14 *  Germany
     15 *  <rtems@embedded-brains.de>
     16 *
     17 * The license and distribution terms for this file may be
     18 * found in the file LICENSE in this distribution or at
     19 * http://www.rtems.org/license/LICENSE.
    1520 */
    1621
     
    2126#include <rtems/score/watchdogimpl.h>
    2227
    23 static void _Watchdog_Insert_fixup(
    24   Watchdog_Header   *header,
    25   Watchdog_Control  *the_watchdog,
    26   Watchdog_Interval  delta,
    27   Watchdog_Control  *next_watchdog,
    28   Watchdog_Interval  delta_next
     28void _Watchdog_Insert(
     29  Watchdog_Header  *header,
     30  Watchdog_Control *the_watchdog,
     31  uint64_t          expire
    2932)
    3033{
    31   const Chain_Node *iterator_tail;
    32   Chain_Node       *iterator_node;
     34  RBTree_Node **link;
     35  RBTree_Node  *parent;
     36  RBTree_Node  *old_first;
     37  RBTree_Node  *new_first;
    3338
    34   next_watchdog->delta_interval = delta_next - delta;
     39  _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE );
    3540
    36   iterator_node = _Chain_First( &header->Iterators );
    37   iterator_tail = _Chain_Immutable_tail( &header->Iterators );
     41  link = _RBTree_Root_reference( &header->Watchdogs );
     42  parent = NULL;
     43  old_first = header->first;
     44  new_first = &the_watchdog->Node.RBTree;
    3845
    39   while ( iterator_node != iterator_tail ) {
    40     Watchdog_Iterator *iterator;
     46  the_watchdog->expire = expire;
    4147
    42     iterator = (Watchdog_Iterator *) iterator_node;
     48  while ( *link != NULL ) {
     49    Watchdog_Control *parent_watchdog;
    4350
    44     if ( iterator->current == &next_watchdog->Node ) {
    45       iterator->current = &the_watchdog->Node;
     51    parent = *link;
     52    parent_watchdog = (Watchdog_Control *) parent;
     53
     54    if ( expire < parent_watchdog->expire ) {
     55      link = _RBTree_Left_reference( parent );
     56    } else {
     57      link = _RBTree_Right_reference( parent );
     58      new_first = old_first;
    4659    }
     60  }
    4761
    48     iterator_node = _Chain_Next( iterator_node );
    49   }
     62  header->first = new_first;
     63  _RBTree_Add_child( &the_watchdog->Node.RBTree, parent, link );
     64  _RBTree_Insert_color( &header->Watchdogs, &the_watchdog->Node.RBTree );
    5065}
    51 
    52 void _Watchdog_Insert_locked(
    53   Watchdog_Header  *header,
    54   Watchdog_Control *the_watchdog,
    55   ISR_lock_Context *lock_context
    56 )
    57 {
    58   if ( the_watchdog->state == WATCHDOG_INACTIVE ) {
    59     Watchdog_Iterator  iterator;
    60     Chain_Node        *current;
    61     Chain_Node        *next;
    62     Watchdog_Interval  delta;
    63 
    64     the_watchdog->state = WATCHDOG_BEING_INSERTED;
    65 
    66     _Chain_Append_unprotected( &header->Iterators, &iterator.Node );
    67 
    68     delta = the_watchdog->initial;
    69     current = _Chain_Head( &header->Watchdogs );
    70 
    71     while (
    72       ( next = _Chain_Next( current ) ) != _Chain_Tail( &header->Watchdogs )
    73     ) {
    74       Watchdog_Control  *next_watchdog;
    75       Watchdog_Interval  delta_next;
    76 
    77       next_watchdog = (Watchdog_Control *) next;
    78       delta_next = next_watchdog->delta_interval;
    79 
    80       if ( delta < delta_next ) {
    81         _Watchdog_Insert_fixup(
    82           header,
    83           the_watchdog,
    84           delta,
    85           next_watchdog,
    86           delta_next
    87         );
    88         break;
    89       }
    90 
    91       iterator.delta_interval = delta - delta_next;
    92       iterator.current = next;
    93 
    94       _Watchdog_Flash( header, lock_context );
    95 
    96       if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
    97         goto abort_insert;
    98       }
    99 
    100       delta = iterator.delta_interval;
    101       current = iterator.current;
    102     }
    103 
    104     the_watchdog->delta_interval = delta;
    105     the_watchdog->start_time = _Watchdog_Ticks_since_boot;
    106     _Watchdog_Activate( the_watchdog );
    107     _Chain_Insert_unprotected( current, &the_watchdog->Node );
    108 
    109 abort_insert:
    110 
    111     _Chain_Extract_unprotected( &iterator.Node );
    112   }
    113 }
    114 
    115 void _Watchdog_Insert(
    116   Watchdog_Header  *header,
    117   Watchdog_Control *the_watchdog
    118 )
    119 {
    120   ISR_lock_Context lock_context;
    121 
    122   _Watchdog_Acquire( header, &lock_context );
    123   _Watchdog_Insert_locked( header, the_watchdog, &lock_context );
    124   _Watchdog_Release( header, &lock_context );
    125 }
  • cpukit/score/src/watchdogremove.c

    r90d8567 r03b900d  
    22 * @file
    33 *
    4  * @brief Remove Watchdog from List
     4 * @brief Remove Watchdog
    55 * @ingroup ScoreWatchdog
    66 */
    77
    88/*
    9  *  COPYRIGHT (c) 1989-1999.
    10  *  On-Line Applications Research Corporation (OAR).
     9 * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
    1110 *
    12  *  The license and distribution terms for this file may be
    13  *  found in the file LICENSE in this distribution or at
    14  *  http://www.rtems.org/license/LICENSE.
     11 *  embedded brains GmbH
     12 *  Dornierstr. 4
     13 *  82178 Puchheim
     14 *  Germany
     15 *  <rtems@embedded-brains.de>
     16 *
     17 * The license and distribution terms for this file may be
     18 * found in the file LICENSE in this distribution or at
     19 * http://www.rtems.org/license/LICENSE.
    1520 */
    1621
     
    2025
    2126#include <rtems/score/watchdogimpl.h>
    22 #include <rtems/score/assert.h>
    2327
    24 static void _Watchdog_Remove_it(
    25   Watchdog_Header   *header,
    26   Watchdog_Control  *the_watchdog
    27 )
    28 {
    29   Chain_Node        *next;
    30   Watchdog_Interval  delta;
    31   const Chain_Node  *iterator_tail;
    32   Chain_Node        *iterator_node;
    33 
    34   _Assert( the_watchdog->state == WATCHDOG_ACTIVE );
    35 
    36   the_watchdog->state = WATCHDOG_INACTIVE;
    37   the_watchdog->stop_time = _Watchdog_Ticks_since_boot;
    38 
    39   next = _Chain_Next( &the_watchdog->Node );
    40   delta = the_watchdog->delta_interval;
    41 
    42   if ( next != _Chain_Tail( &header->Watchdogs ) ) {
    43     Watchdog_Control *next_watchdog;
    44 
    45     next_watchdog = (Watchdog_Control *) next;
    46     next_watchdog->delta_interval += delta;
    47   }
    48 
    49   _Chain_Extract_unprotected( &the_watchdog->Node );
    50 
    51   iterator_node = _Chain_First( &header->Iterators );
    52   iterator_tail = _Chain_Immutable_tail( &header->Iterators );
    53 
    54   while ( iterator_node != iterator_tail ) {
    55     Watchdog_Iterator *iterator;
    56 
    57     iterator = (Watchdog_Iterator *) iterator_node;
    58 
    59     if ( iterator->current == next ) {
    60       iterator->delta_interval += delta;
    61     }
    62 
    63     if ( iterator->current == &the_watchdog->Node ) {
    64       Chain_Node *previous = _Chain_Previous( &the_watchdog->Node );
    65 
    66       iterator->current = previous;
    67 
    68       if ( previous != _Chain_Head( &header->Watchdogs ) ) {
    69         Watchdog_Control *previous_watchdog;
    70 
    71         previous_watchdog = (Watchdog_Control *) previous;
    72         iterator->delta_interval += previous_watchdog->delta_interval;
    73       }
    74     }
    75 
    76     iterator_node = _Chain_Next( iterator_node );
    77   }
    78 }
    79 
    80 Watchdog_States _Watchdog_Remove(
     28void _Watchdog_Remove(
    8129  Watchdog_Header  *header,
    8230  Watchdog_Control *the_watchdog
    8331)
    8432{
    85   ISR_lock_Context  lock_context;
    86   Watchdog_States   previous_state;
    87   Watchdog_Interval now;
    88 
    89   _Watchdog_Acquire( header, &lock_context );
    90   previous_state = the_watchdog->state;
    91   switch ( previous_state ) {
    92     case WATCHDOG_INACTIVE:
    93       break;
    94 
    95     case WATCHDOG_BEING_INSERTED:
    96 
    97       /*
    98        *  It is not actually on the chain so just change the state and
    99        *  the Insert operation we interrupted will be aborted.
    100        */
    101       the_watchdog->state = WATCHDOG_INACTIVE;
    102       now = _Watchdog_Ticks_since_boot;
    103       the_watchdog->start_time = now;
    104       the_watchdog->stop_time = now;
    105       break;
    106 
    107     case WATCHDOG_ACTIVE:
    108       _Watchdog_Remove_it( header, the_watchdog );
    109       break;
    110   }
    111 
    112   _Watchdog_Release( header, &lock_context );
    113   return( previous_state );
    114 }
    115 
    116 void _Watchdog_Tickle(
    117   Watchdog_Header *header
    118 )
    119 {
    120   ISR_lock_Context lock_context;
    121 
    122   _Watchdog_Acquire( header, &lock_context );
    123 
    124   if ( !_Watchdog_Is_empty( header ) ) {
    125     Watchdog_Control  *first;
    126     Watchdog_Interval  delta;
    127 
    128     first = _Watchdog_First( header );
    129     delta = first->delta_interval;
    130 
    131     /*
    132      * Although it is forbidden to insert watchdogs with a delta interval of
    133      * zero it is possible to observe watchdogs with a delta interval of zero
    134      * at this point.  For example lets have a watchdog chain of one watchdog
    135      * with a delta interval of one and insert a new one with an initial value
    136      * of one.  At the start of the insert procedure it will advance one step
    137      * and reduce its delta interval by one yielding zero.  Now a tick happens.
    138      * This will remove the watchdog on the chain and update the insert
    139      * iterator.  Now the insert operation continues and will insert the new
    140      * watchdog with a delta interval of zero.
    141      */
    142     if ( delta > 0 ) {
    143       --delta;
    144       first->delta_interval = delta;
     33  if ( _Watchdog_Is_scheduled( the_watchdog ) ) {
     34    if ( header->first == &the_watchdog->Node.RBTree ) {
     35      _Watchdog_Next_first( header, the_watchdog );
    14536    }
    14637
    147     while ( delta == 0 ) {
    148       bool                            run;
    149       Watchdog_Service_routine_entry  routine;
    150       Objects_Id                      id;
    151       void                           *user_data;
    152 
    153       run = ( first->state == WATCHDOG_ACTIVE );
    154 
    155       _Watchdog_Remove_it( header, first );
    156 
    157       routine = first->routine;
    158       id = first->id;
    159       user_data = first->user_data;
    160 
    161       _Watchdog_Release( header, &lock_context );
    162 
    163       if ( run ) {
    164         (*routine)( id, user_data );
    165       }
    166 
    167       _Watchdog_Acquire( header, &lock_context );
    168 
    169       if ( _Watchdog_Is_empty( header ) ) {
    170         break;
    171       }
    172 
    173       first = _Watchdog_First( header );
    174       delta = first->delta_interval;
    175     }
     38    _RBTree_Extract( &header->Watchdogs, &the_watchdog->Node.RBTree );
     39    _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
    17640  }
    177 
    178   _Watchdog_Release( header, &lock_context );
    17941}
  • cpukit/score/src/watchdogtick.c

    r90d8567 r03b900d  
    11/*
    2  * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
     2 * Copyright (c) 2015, 2016 embedded brains GmbH.  All rights reserved.
    33 *
    44 *  embedded brains GmbH
     
    1313 */
    1414
    15 #include <rtems/score/assert.h>
    16 #include <rtems/score/schedulerimpl.h>
    17 #include <rtems/score/threaddispatch.h>
    18 #include <rtems/score/todimpl.h>
    19 #include <rtems/score/watchdogimpl.h>
    20 
    2115#if HAVE_CONFIG_H
    2216#include "config.h"
    2317#endif
    2418
     19#include <rtems/score/watchdogimpl.h>
     20#include <rtems/score/schedulerimpl.h>
     21#include <rtems/score/threaddispatch.h>
     22#include <rtems/score/timecounter.h>
     23
     24void _Watchdog_Do_tickle(
     25  Watchdog_Header  *header,
     26  uint64_t          now,
     27#ifdef RTEMS_SMP
     28  ISR_lock_Control *lock,
     29#endif
     30  ISR_lock_Context *lock_context
     31)
     32{
     33  while ( true ) {
     34    Watchdog_Control *the_watchdog;
     35
     36    the_watchdog = (Watchdog_Control *) header->first;
     37
     38    if ( the_watchdog == NULL ) {
     39      break;
     40    }
     41
     42    if ( the_watchdog->expire <= now ) {
     43      Watchdog_Service_routine_entry routine;
     44
     45      _Watchdog_Next_first( header, the_watchdog );
     46      _RBTree_Extract( &header->Watchdogs, &the_watchdog->Node.RBTree );
     47      _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
     48      routine = the_watchdog->routine;
     49
     50      _ISR_lock_Release_and_ISR_enable( lock, lock_context );
     51      ( *routine )( the_watchdog );
     52      _ISR_lock_ISR_disable_and_acquire( lock, lock_context );
     53    } else {
     54      break;
     55    }
     56  }
     57
     58  _ISR_lock_Release_and_ISR_enable( lock, lock_context );
     59}
     60
    2561void _Watchdog_Tick( Per_CPU_Control *cpu )
    2662{
    27   _Assert( !_Thread_Dispatch_is_enabled() );
     63  ISR_lock_Context lock_context;
     64  uint64_t         ticks;
     65  struct timespec  now;
    2866
    2967  if ( _Per_CPU_Is_boot_processor( cpu ) ) {
    30     _TOD_Tickle_ticks();
     68    ++_Watchdog_Ticks_since_boot;
     69  }
    3170
    32     _Watchdog_Tickle_ticks();
     71  _ISR_lock_ISR_disable_and_acquire( &cpu->Watchdog.Lock, &lock_context );
    3372
    34     _Scheduler_Tick();
    35   }
     73  ticks = cpu->Watchdog.ticks;
     74  _Assert( ticks < UINT64_MAX );
     75  ++ticks;
     76  cpu->Watchdog.ticks = ticks;
     77
     78  _Watchdog_Tickle(
     79    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
     80    ticks,
     81    &cpu->Watchdog.Lock,
     82    &lock_context
     83  );
     84
     85  _Timecounter_Getnanotime( &now );
     86  _Watchdog_Per_CPU_tickle_absolute(
     87    cpu,
     88    _Watchdog_Ticks_from_timespec( &now )
     89  );
     90
     91  _Scheduler_Tick( cpu );
    3692}
  • testsuites/psxtests/psx04/init.c

    r90d8567 r03b900d  
    282282  remaining = sleep( 4 );
    283283  printf( "Init: %d seconds left in sleep\n", remaining );
    284   rtems_test_assert( remaining == 2 );
     284
     285  /*
     286   * sleep() uses nanosleep() internally which discards the nanoseconds part,
     287   * e.g. 1.99s -> 1s
     288   */
     289  rtems_test_assert( remaining == 1 || remaining == 2 );
    285290
    286291  /* test SIG_SETMASK case and returning oset of pthread_sigmask */
  • testsuites/smptests/Makefile.am

    r90d8567 r03b900d  
    1515SUBDIRS += smpcapture01
    1616SUBDIRS += smpcapture02
     17SUBDIRS += smpclock01
    1718SUBDIRS += smpfatal01
    1819SUBDIRS += smpfatal02
  • testsuites/smptests/configure.ac

    r90d8567 r03b900d  
    7070smpcapture01/Makefile
    7171smpcapture02/Makefile
     72smpclock01/Makefile
    7273smpfatal01/Makefile
    7374smpfatal02/Makefile
  • testsuites/smptests/smpwakeafter01/smpwakeafter01.scn

    r90d8567 r03b900d  
    10102 seconds remaining
    11111 seconds remaining
    12 counts[0][0] = 15479
    13 counts[0][1] = 17039
    14 counts[0][2] = 12389
    15 counts[0][3] = 8077
    16 counts[0][4] = 3
    17 counts[0][5] = 2431
    18 counts[0][6] = 2630
    19 counts[0][7] = 2128
    20 counts[1][0] = 15461
    21 counts[1][1] = 16813
    22 counts[1][2] = 12248
    23 counts[1][3] = 7483
    24 counts[1][4] = 5499
    25 counts[1][5] = 3170
    26 counts[1][6] = 2549
    27 counts[1][7] = 1748
    28 counts[2][0] = 71
    29 counts[2][1] = 17068
    30 counts[2][2] = 7661
    31 counts[2][3] = 8190
    32 counts[2][4] = 5513
    33 counts[2][5] = 3864
    34 counts[2][6] = 1454
    35 counts[2][7] = 1993
    36 counts[3][0] = 14511
    37 counts[3][1] = 16115
    38 counts[3][2] = 12561
    39 counts[3][3] = 7281
    40 counts[3][4] = 5507
    41 counts[3][5] = 3828
    42 counts[3][6] = 2687
    43 counts[3][7] = 1278
     12counts[0][0] = 10013
     13counts[0][1] = 5007
     14counts[0][2] = 3339
     15counts[0][3] = 2004
     16counts[0][4] = 1432
     17counts[0][5] = 912
     18counts[0][6] = 771
     19counts[0][7] = 590
     20counts[1][0] = 10027
     21counts[1][1] = 5015
     22counts[1][2] = 3344
     23counts[1][3] = 2007
     24counts[1][4] = 1434
     25counts[1][5] = 913
     26counts[1][6] = 773
     27counts[1][7] = 591
     28counts[2][0] = 10041
     29counts[2][1] = 5022
     30counts[2][2] = 3349
     31counts[2][3] = 2010
     32counts[2][4] = 1436
     33counts[2][5] = 914
     34counts[2][6] = 774
     35counts[2][7] = 592
     36counts[3][0] = 10055
     37counts[3][1] = 5029
     38counts[3][2] = 3353
     39counts[3][3] = 2013
     40counts[3][4] = 1438
     41counts[3][5] = 915
     42counts[3][6] = 775
     43counts[3][7] = 593
     44counts[4][0] = 10070
     45counts[4][1] = 5036
     46counts[4][2] = 3358
     47counts[4][3] = 2015
     48counts[4][4] = 1440
     49counts[4][5] = 917
     50counts[4][6] = 776
     51counts[4][7] = 594
     52counts[5][0] = 10084
     53counts[5][1] = 5043
     54counts[5][2] = 3363
     55counts[5][3] = 2018
     56counts[5][4] = 1442
     57counts[5][5] = 918
     58counts[5][6] = 777
     59counts[5][7] = 594
     60counts[6][0] = 10098
     61counts[6][1] = 5050
     62counts[6][2] = 3368
     63counts[6][3] = 2021
     64counts[6][4] = 1444
     65counts[6][5] = 919
     66counts[6][6] = 778
     67counts[6][7] = 595
     68counts[7][0] = 10113
     69counts[7][1] = 5058
     70counts[7][2] = 3373
     71counts[7][3] = 2024
     72counts[7][4] = 1446
     73counts[7][5] = 921
     74counts[7][6] = 779
     75counts[7][7] = 596
     76counts[8][0] = 10127
     77counts[8][1] = 5065
     78counts[8][2] = 3377
     79counts[8][3] = 2027
     80counts[8][4] = 1448
     81counts[8][5] = 922
     82counts[8][6] = 780
     83counts[8][7] = 597
     84counts[9][0] = 10142
     85counts[9][1] = 5072
     86counts[9][2] = 3382
     87counts[9][3] = 2030
     88counts[9][4] = 1450
     89counts[9][5] = 923
     90counts[9][6] = 781
     91counts[9][7] = 598
     92counts[10][0] = 10156
     93counts[10][1] = 5079
     94counts[10][2] = 3387
     95counts[10][3] = 2033
     96counts[10][4] = 1452
     97counts[10][5] = 925
     98counts[10][6] = 783
     99counts[10][7] = 599
     100counts[11][0] = 10170
     101counts[11][1] = 5086
     102counts[11][2] = 3392
     103counts[11][3] = 2036
     104counts[11][4] = 1454
     105counts[11][5] = 926
     106counts[11][6] = 784
     107counts[11][7] = 599
     108counts[12][0] = 10185
     109counts[12][1] = 5094
     110counts[12][2] = 3397
     111counts[12][3] = 2039
     112counts[12][4] = 1457
     113counts[12][5] = 927
     114counts[12][6] = 785
     115counts[12][7] = 600
     116counts[13][0] = 10200
     117counts[13][1] = 5101
     118counts[13][2] = 3402
     119counts[13][3] = 2042
     120counts[13][4] = 1459
     121counts[13][5] = 929
     122counts[13][6] = 786
     123counts[13][7] = 601
     124counts[14][0] = 10215
     125counts[14][1] = 5109
     126counts[14][2] = 3407
     127counts[14][3] = 2045
     128counts[14][4] = 1461
     129counts[14][5] = 930
     130counts[14][6] = 787
     131counts[14][7] = 602
     132counts[15][0] = 10230
     133counts[15][1] = 5116
     134counts[15][2] = 3412
     135counts[15][3] = 2048
     136counts[15][4] = 1463
     137counts[15][5] = 931
     138counts[15][6] = 788
     139counts[15][7] = 603
     140counts[16][0] = 10245
     141counts[16][1] = 5124
     142counts[16][2] = 3417
     143counts[16][3] = 2051
     144counts[16][4] = 1465
     145counts[16][5] = 933
     146counts[16][6] = 789
     147counts[16][7] = 604
     148counts[17][0] = 10260
     149counts[17][1] = 5131
     150counts[17][2] = 3422
     151counts[17][3] = 2054
     152counts[17][4] = 1467
     153counts[17][5] = 934
     154counts[17][6] = 791
     155counts[17][7] = 605
     156counts[18][0] = 10275
     157counts[18][1] = 5139
     158counts[18][2] = 3427
     159counts[18][3] = 2057
     160counts[18][4] = 1469
     161counts[18][5] = 935
     162counts[18][6] = 792
     163counts[18][7] = 606
     164counts[19][0] = 10290
     165counts[19][1] = 5146
     166counts[19][2] = 3432
     167counts[19][3] = 2060
     168counts[19][4] = 1472
     169counts[19][5] = 937
     170counts[19][6] = 793
     171counts[19][7] = 607
     172counts[20][0] = 10305
     173counts[20][1] = 5154
     174counts[20][2] = 3437
     175counts[20][3] = 2063
     176counts[20][4] = 1474
     177counts[20][5] = 938
     178counts[20][6] = 794
     179counts[20][7] = 607
     180counts[21][0] = 10320
     181counts[21][1] = 5161
     182counts[21][2] = 3442
     183counts[21][3] = 2066
     184counts[21][4] = 1476
     185counts[21][5] = 940
     186counts[21][6] = 795
     187counts[21][7] = 608
     188counts[22][0] = 10335
     189counts[22][1] = 5169
     190counts[22][2] = 3447
     191counts[22][3] = 2069
     192counts[22][4] = 1478
     193counts[22][5] = 941
     194counts[22][6] = 796
     195counts[22][7] = 609
     196counts[23][0] = 10350
     197counts[23][1] = 5176
     198counts[23][2] = 3452
     199counts[23][3] = 2072
     200counts[23][4] = 1480
     201counts[23][5] = 942
     202counts[23][6] = 798
     203counts[23][7] = 610
    44204*** END OF TEST SMPWAKEAFTER 1 ***
  • testsuites/sptests/Makefile.am

    r90d8567 r03b900d  
    2626    spintrcritical09 spintrcritical10 spintrcritical11 spintrcritical12 \
    2727    spintrcritical13 spintrcritical14 spintrcritical15 spintrcritical16 \
    28     spintrcritical17 spintrcritical18 spmkdir spmountmgr01 spheapprot \
     28    spintrcritical18 spmkdir spmountmgr01 spheapprot \
    2929    sppagesize spsem01 spsem02 spsimplesched01 spsimplesched02 \
    3030    spsimplesched03 spnsext01 spedfsched01 spedfsched02 spedfsched03 \
     
    7878_SUBDIRS += spinternalerror02
    7979_SUBDIRS += sptimer_err01 sptimer_err02
     80_SUBDIRS += sptimerserver01
    8081_SUBDIRS += spclock_err02
    8182
  • testsuites/sptests/configure.ac

    r90d8567 r03b900d  
    4747# Explicitly list all Makefiles here
    4848AC_CONFIG_FILES([Makefile
     49sptimerserver01/Makefile
    4950spsysinit01/Makefile
    5051splinkersets01/Makefile
     
    217218spintrcritical15/Makefile
    218219spintrcritical16/Makefile
    219 spintrcritical17/Makefile
    220220spheapprot/Makefile
    221221spmkdir/Makefile
  • testsuites/sptests/sp31/task1.c

    r90d8567 r03b900d  
    4141}
    4242
    43 static Watchdog_Interval schedule_time( void )
    44 {
    45   const Watchdog_Control *watchdog =
    46     &_Timer_server->Interval_watchdogs.System_watchdog;
    47 
    48   return watchdog->initial + watchdog->start_time;
    49 }
    50 
    5143rtems_task Task_1(
    5244  rtems_task_argument argument
     
    120112    info.start_time + info.initial
    121113  );
    122   printf(
    123     "Timer Server scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
    124     schedule_time()
    125   );
    126114
    127115  puts( "TA1 - rtems_task_wake_after - 1 second" );
     
    140128    info.start_time + info.initial
    141129  );
    142   printf(
    143     "Timer Server scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
    144     schedule_time()
    145   );
    146   rtems_test_assert( (info.start_time + info.initial) == schedule_time() );
    147130
    148131  puts( "TA1 - rtems_task_wake_after - 1 second" );
     
    161144     info.start_time + info.initial
    162145  );
    163   printf(
    164     "Timer Server scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
    165      schedule_time()
    166   );
    167   rtems_test_assert( (info.start_time + info.initial) == schedule_time() );
    168146
    169147  puts( "TA1 - rtems_timer_cancel - timer 1" );
  • testsuites/sptests/spintrcritical08/init.c

    r90d8567 r03b900d  
    4747)
    4848{
    49   Watchdog_Header *header = &_Watchdog_Ticks_header;
     49  Per_CPU_Control *cpu = _Per_CPU_Get();
     50  Watchdog_Header *header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ];
     51  Watchdog_Control *watchdog = (Watchdog_Control *) header->first;
    5052
    51   if ( !_Watchdog_Is_empty( header ) ) {
    52     Watchdog_Control *watchdog = _Watchdog_First( header );
     53  if (
     54    watchdog != NULL
     55      && watchdog->expire == cpu->Watchdog.ticks
     56      && watchdog->routine == _Rate_monotonic_Timeout
     57  ) {
     58    _Watchdog_Per_CPU_remove_relative( watchdog );
    5359
    54     if (
    55       watchdog->delta_interval == 0
    56         && watchdog->routine == _Rate_monotonic_Timeout
    57     ) {
    58       Watchdog_States state = _Watchdog_Remove_ticks( watchdog );
     60    (*watchdog->routine)( watchdog );
    5961
    60       rtems_test_assert( state == WATCHDOG_ACTIVE );
    61       (*watchdog->routine)( watchdog->id, watchdog->user_data );
    62 
    63       if ( getState() == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) {
    64         case_hit = true;
    65       }
     62    if ( getState() == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) {
     63      case_hit = true;
    6664    }
    6765  }
  • testsuites/sptests/spintrcritical09/init.c

    r90d8567 r03b900d  
    1515#include <intrcritical.h>
    1616
     17#include <rtems/score/threadimpl.h>
    1718#include <rtems/score/threadimpl.h>
    1819#include <rtems/score/watchdogimpl.h>
     
    3839)
    3940{
    40   Watchdog_Header *header = &_Watchdog_Ticks_header;
     41  Per_CPU_Control *cpu_self = _Per_CPU_Get();
     42  Watchdog_Header *header = &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ];
     43  Watchdog_Control *watchdog = (Watchdog_Control *) header->first;
    4144
    42   if ( !_Watchdog_Is_empty( header ) ) {
    43     Watchdog_Control *watchdog = _Watchdog_First( header );
     45  if (
     46    watchdog != NULL
     47      && watchdog->expire == cpu_self->Watchdog.ticks
     48      && watchdog->routine == _Thread_Timeout
     49  ) {
     50    _Watchdog_Per_CPU_remove( watchdog, cpu_self, header );
    4451
    45     if (
    46       watchdog->delta_interval == 0
    47         && watchdog->routine == _Thread_Timeout
    48     ) {
    49       Watchdog_States state = _Watchdog_Remove_ticks( watchdog );
     52    (*watchdog->routine)( watchdog );
    5053
    51       rtems_test_assert( state == WATCHDOG_ACTIVE );
    52       (*watchdog->routine)( watchdog->id, watchdog->user_data );
    53 
    54       if ( is_interrupt_timeout() ) {
    55         case_hit = true;
    56       }
     54    if ( is_interrupt_timeout() ) {
     55      case_hit = true;
    5756    }
    5857  }
  • testsuites/sptests/spintrcritical10/init.c

    r90d8567 r03b900d  
    7979    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
    8080
    81     _Thread_Timeout(0, thread);
     81    _Thread_Timeout(&thread->Timer.Watchdog);
    8282
    8383    rtems_test_assert(
     
    176176    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
    177177
    178     _Thread_Timeout(0, thread);
     178    _Thread_Timeout(&thread->Timer.Watchdog);
    179179
    180180    rtems_test_assert(
     
    252252    rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
    253253
    254     _Thread_Timeout(0, thread);
     254    _Thread_Timeout(&thread->Timer.Watchdog);
    255255
    256256    rtems_test_assert(
  • testsuites/sptests/spintrcritical16/init.c

    r90d8567 r03b900d  
    4444
    4545  if ( Main_TCB->Wait.queue != NULL ) {
    46     _Thread_Timeout( 0, Main_TCB );
     46    _Thread_Timeout( &Main_TCB->Timer.Watchdog );
    4747  }
    4848}
  • testsuites/sptests/spintrcritical20/init.c

    r90d8567 r03b900d  
    9292  }
    9393
    94   _Thread_Timeout(0, ctx->semaphore_task_tcb);
     94  _Thread_Timeout(&ctx->semaphore_task_tcb->Timer.Watchdog);
    9595
    9696  switch (ctx->semaphore_task_tcb->Wait.return_code) {
  • testsuites/sptests/spsize/size.c

    r90d8567 r03b900d  
    392392
    393393/*watchdog.h*/  (sizeof _Watchdog_Ticks_since_boot)       +
    394                 (sizeof _Watchdog_Ticks_header)           +
    395                 (sizeof _Watchdog_Seconds_header)         +
    396394
    397395/*wkspace.h*/   (sizeof _Workspace_Area);
  • testsuites/sptests/sptimecounter01/init.c

    r90d8567 r03b900d  
    2525#include <rtems/score/timecounterimpl.h>
    2626#include <rtems/score/todimpl.h>
    27 #include <rtems/score/watchdogimpl.h>
    2827#include <rtems/timecounter.h>
    2928#include <rtems/bsd.h>
     
    5756
    5857  rtems_test_begink();
    59 
    60   _Watchdog_Handler_initialization();
    6158
    6259  assert(time(NULL) == TOD_SECONDS_1970_THROUGH_1988);
  • testsuites/sptests/spwatchdog/init.c

    r90d8567 r03b900d  
    2727const char rtems_test_name[] = "SPWATCHDOG";
    2828
    29 static void test_watchdog_routine( Objects_Id id, void *arg )
    30 {
    31   (void) id;
    32   (void) arg;
    33 
    34   rtems_test_assert( 0 );
    35 }
    36 
    37 static void init_watchdogs(
    38   Watchdog_Header *header,
    39   Watchdog_Control watchdogs[4]
    40 )
    41 {
    42   Watchdog_Control *a = &watchdogs[0];
    43   Watchdog_Control *b = &watchdogs[1];
    44   Watchdog_Control *c = &watchdogs[2];
    45   Watchdog_Control *d = &watchdogs[3];
    46 
    47   _Watchdog_Header_initialize( header );
    48   rtems_test_assert( _Watchdog_Is_empty( header ) );
    49   rtems_test_assert( _Chain_Is_empty( &header->Iterators ) );
    50 
    51   _Watchdog_Preinitialize( c );
    52   c->initial = 6;
    53   _Watchdog_Insert( header, c );
    54   rtems_test_assert( c->delta_interval == 6 );
    55 
    56   rtems_test_assert( !_Watchdog_Is_empty( header ) );
    57   rtems_test_assert( _Chain_Is_empty( &header->Iterators ) );
    58 
    59   _Watchdog_Preinitialize( a );
    60   a->initial = 2;
    61   _Watchdog_Insert( header, a );
    62   rtems_test_assert( a->delta_interval == 2 );
    63   rtems_test_assert( c->delta_interval == 4 );
    64 
    65   _Watchdog_Preinitialize( b );
    66   b->initial = 4;
    67   _Watchdog_Insert( header, b );
    68   rtems_test_assert( a->delta_interval == 2 );
    69   rtems_test_assert( b->delta_interval == 2 );
    70   rtems_test_assert( c->delta_interval == 2 );
    71 
    72   _Watchdog_Preinitialize( d );
    73 }
    74 
    75 static void destroy_watchdogs(
    76   Watchdog_Header *header
    77 )
    78 {
    79   _ISR_lock_Destroy( &header->Lock );
    80 }
    81 
    82 static void add_iterator(
    83   Watchdog_Header *header,
    84   Watchdog_Iterator *i,
    85   Watchdog_Control *w
    86 )
    87 {
    88   _Chain_Append_unprotected( &header->Iterators, &i->Node );
    89   i->delta_interval = 2;
    90   i->current = &w->Node;
    91 }
    92 
    93 static void test_watchdog_insert_and_remove( void )
    94 {
    95   Watchdog_Header header;
    96   Watchdog_Control watchdogs[4];
    97   Watchdog_Control *a = &watchdogs[0];
    98   Watchdog_Control *b = &watchdogs[1];
    99   Watchdog_Control *c = &watchdogs[2];
    100   Watchdog_Control *d = &watchdogs[3];
    101   Watchdog_Iterator i;
    102 
    103   init_watchdogs( &header, watchdogs );
    104   add_iterator( &header, &i, c );
    105 
    106   /* Remove next watchdog of iterator */
    107   _Watchdog_Remove( &header, c );
    108   rtems_test_assert( i.delta_interval == 4 );
    109   rtems_test_assert( i.current == &b->Node );
    110 
    111   /* Remove watchdog before the current watchdog of iterator */
    112   _Watchdog_Remove( &header, a );
    113   rtems_test_assert( i.delta_interval == 6 );
    114   rtems_test_assert( i.current == &b->Node );
    115 
    116   /* Remove current (= last) watchdog of iterator */
    117   _Watchdog_Remove( &header, b );
    118   rtems_test_assert( i.delta_interval == 6 );
    119   rtems_test_assert( i.current == _Chain_Head( &header.Watchdogs ) );
    120 
    121   /* Insert first watchdog */
    122   a->initial = 1;
    123   _Watchdog_Insert( &header, a );
    124   rtems_test_assert( i.delta_interval == 6 );
    125   rtems_test_assert( i.current == _Chain_Head( &header.Watchdogs ) );
    126 
    127   destroy_watchdogs( &header );
    128   init_watchdogs( &header, watchdogs );
    129   add_iterator( &header, &i, b );
    130 
    131   /* Insert right before current watchdog of iterator */
    132   d->initial = 3;
    133   _Watchdog_Insert( &header, d );
    134   rtems_test_assert( i.delta_interval == 2 );
    135   rtems_test_assert( i.current == &d->Node );
    136 
    137   destroy_watchdogs( &header );
    138   init_watchdogs( &header, watchdogs );
    139   add_iterator( &header, &i, b );
    140 
    141   /* Insert right after current watchdog of iterator */
    142   d->initial = 5;
    143   _Watchdog_Insert( &header, d );
    144   rtems_test_assert( i.delta_interval == 2 );
    145   rtems_test_assert( i.current == &b->Node );
    146 
    147   destroy_watchdogs( &header );
    148 }
    149 
    150 static void init_watchdogs_remove_second_and_insert_first(
    151   Watchdog_Header *header,
    152   Watchdog_Control watchdogs[3]
    153 )
    154 {
    155   Watchdog_Control *a = &watchdogs[0];
    156   Watchdog_Control *b = &watchdogs[1];
    157   Watchdog_Control *c = &watchdogs[2];
    158 
    159   _Watchdog_Preinitialize( a );
    160   _Watchdog_Preinitialize( b );
    161   _Watchdog_Preinitialize( c );
    162 
    163   _Watchdog_Header_initialize( header );
    164 
    165   a->initial = 6;
    166   _Watchdog_Insert( header, a );
    167   rtems_test_assert( a->delta_interval == 6 );
    168 
    169   b->initial = 8;
    170   _Watchdog_Insert( header, b );
    171   rtems_test_assert( a->delta_interval == 6 );
    172   rtems_test_assert( b->delta_interval == 2 );
    173 }
    174 
    175 static void test_watchdog_remove_second_and_insert_first( void )
    176 {
    177   Watchdog_Header header;
    178   Watchdog_Control watchdogs[3];
    179   Watchdog_Control *a = &watchdogs[0];
    180   Watchdog_Control *b = &watchdogs[1];
    181   Watchdog_Control *c = &watchdogs[2];
    182   Watchdog_Iterator i;
    183 
    184   init_watchdogs_remove_second_and_insert_first( &header, watchdogs );
    185   add_iterator( &header, &i, b );
    186 
    187   _Watchdog_Remove( &header, b );
    188   rtems_test_assert( i.delta_interval == 8 );
    189   rtems_test_assert( i.current == &a->Node );
    190 
    191   c->initial = 4;
    192   _Watchdog_Insert( &header, c );
    193   rtems_test_assert( a->delta_interval == 2 );
    194   rtems_test_assert( c->delta_interval == 4 );
    195   rtems_test_assert( i.delta_interval == 8 );
    196   rtems_test_assert( i.current == &c->Node );
    197 
    198   destroy_watchdogs( &header );
    199 }
    200 
    201 static void init_watchdogs_insert_with_iterator(
    202   Watchdog_Header *header,
    203   Watchdog_Control watchdogs[2]
    204 )
    205 {
    206   Watchdog_Control *a = &watchdogs[0];
    207   Watchdog_Control *b = &watchdogs[1];
    208 
    209   _Watchdog_Preinitialize( a );
    210   _Watchdog_Preinitialize( b );
    211 
    212   _Watchdog_Header_initialize( header );
    213 
    214   a->initial = 6;
    215   _Watchdog_Insert( header, a );
    216   rtems_test_assert( a->delta_interval == 6 );
    217 }
    218 
    219 static void test_watchdog_insert_with_iterator( void )
    220 {
    221   Watchdog_Header header;
    222   Watchdog_Control watchdogs[2];
    223   Watchdog_Control *a = &watchdogs[0];
    224   Watchdog_Control *b = &watchdogs[1];
    225   Watchdog_Iterator i;
    226 
    227   init_watchdogs_insert_with_iterator( &header, watchdogs );
    228   add_iterator( &header, &i, a );
    229 
    230   b->initial = 4;
    231   _Watchdog_Insert( &header, b );
    232   rtems_test_assert( a->delta_interval == 2 );
    233   rtems_test_assert( b->delta_interval == 4 );
    234   rtems_test_assert( i.delta_interval == 2 );
    235   rtems_test_assert( i.current == &b->Node );
    236 
    237   destroy_watchdogs( &header );
     29typedef struct {
     30  Watchdog_Control Base;
     31  int counter;
     32} test_watchdog;
     33
     34static void test_watchdog_routine( Watchdog_Control *base )
     35{
     36  test_watchdog *watchdog = (test_watchdog *) base;
     37
     38  ++watchdog->counter;
    23839}
    23940
    24041static void test_watchdog_static_init( void )
    24142{
    242   #if defined(RTEMS_USE_16_BIT_OBJECT)
    243     #define JUNK_ID 0x1234
    244   #else
    245     #define JUNK_ID 0x12345678
    246   #endif
    247 
    24843  static Watchdog_Control a = WATCHDOG_INITIALIZER(
    249     test_watchdog_routine,
    250     JUNK_ID,
    251     (void *) 0xdeadbeef
     44    test_watchdog_routine
    25245  );
    25346  Watchdog_Control b;
    25447
    25548  memset( &b, 0, sizeof( b ) );
     49  _Watchdog_Preinitialize( &b, _Per_CPU_Get_by_index( 0 ) );
    25650  _Watchdog_Initialize(
    25751    &b,
    258     test_watchdog_routine,
    259     JUNK_ID,
    260     (void *) 0xdeadbeef
     52    test_watchdog_routine
    26153  );
    26254
    26355  rtems_test_assert( memcmp( &a, &b, sizeof( a ) ) == 0 );
     56}
     57
     58static bool test_watchdog_is_inactive( test_watchdog *watchdog )
     59{
     60  return _Watchdog_Get_state( &watchdog->Base ) == WATCHDOG_INACTIVE;
     61}
     62
     63static void test_watchdog_init( test_watchdog *watchdog, int counter )
     64{
     65  _Watchdog_Preinitialize( &watchdog->Base, _Per_CPU_Get_snapshot() );
     66  _Watchdog_Initialize( &watchdog->Base, test_watchdog_routine );
     67  rtems_test_assert( test_watchdog_is_inactive( watchdog ) ) ;
     68  watchdog->counter = counter;
     69}
     70
     71static uint64_t test_watchdog_tick( Watchdog_Header *header, uint64_t now )
     72{
     73  ISR_LOCK_DEFINE( , lock, "Test" )
     74  ISR_lock_Context lock_context;
     75
     76  _ISR_lock_ISR_disable_and_acquire( &lock, &lock_context );
     77  ++now;
     78  _Watchdog_Tickle( header, now, &lock, &lock_context );
     79  _ISR_lock_Destroy( &lock );
     80
     81  return now;
     82}
     83
     84static void test_watchdog_operations( void )
     85{
     86  Watchdog_Header header;
     87  uint64_t now;
     88  test_watchdog a;
     89  test_watchdog b;
     90  test_watchdog c;
     91
     92  _Watchdog_Header_initialize( &header );
     93  rtems_test_assert( _RBTree_Is_empty( &header.Watchdogs ) );
     94  rtems_test_assert( header.first == NULL );
     95
     96  test_watchdog_init( &a, 10 );
     97  test_watchdog_init( &b, 20 );
     98  test_watchdog_init( &c, 30 );
     99
     100  now = 0;
     101  now = test_watchdog_tick( &header, now );
     102
     103  _Watchdog_Insert( &header, &a.Base, now + 1 );
     104  rtems_test_assert( header.first == &a.Base.Node.RBTree );
     105  rtems_test_assert( !test_watchdog_is_inactive( &a ) ) ;
     106  rtems_test_assert( a.Base.expire == 2 );
     107  rtems_test_assert( a.counter == 10 );
     108
     109  _Watchdog_Remove( &header, &a.Base );
     110  rtems_test_assert( header.first == NULL );
     111  rtems_test_assert( test_watchdog_is_inactive( &a ) ) ;
     112  rtems_test_assert( a.Base.expire == 2 );
     113  rtems_test_assert( a.counter == 10 );
     114
     115  _Watchdog_Remove( &header, &a.Base );
     116  rtems_test_assert( header.first == NULL );
     117  rtems_test_assert( test_watchdog_is_inactive( &a ) ) ;
     118  rtems_test_assert( a.Base.expire == 2 );
     119  rtems_test_assert( a.counter == 10 );
     120
     121  _Watchdog_Insert( &header, &a.Base, now + 1 );
     122  rtems_test_assert( header.first == &a.Base.Node.RBTree );
     123  rtems_test_assert( !test_watchdog_is_inactive( &a ) ) ;
     124  rtems_test_assert( a.Base.expire == 2 );
     125  rtems_test_assert( a.counter == 10 );
     126
     127  _Watchdog_Insert( &header, &b.Base, now + 1 );
     128  rtems_test_assert( header.first == &a.Base.Node.RBTree );
     129  rtems_test_assert( !test_watchdog_is_inactive( &b ) ) ;
     130  rtems_test_assert( b.Base.expire == 2 );
     131  rtems_test_assert( b.counter == 20 );
     132
     133  _Watchdog_Insert( &header, &c.Base, now + 2 );
     134  rtems_test_assert( header.first == &a.Base.Node.RBTree );
     135  rtems_test_assert( !test_watchdog_is_inactive( &c ) ) ;
     136  rtems_test_assert( c.Base.expire == 3 );
     137  rtems_test_assert( c.counter == 30 );
     138
     139  _Watchdog_Remove( &header, &a.Base );
     140  rtems_test_assert( header.first == &b.Base.Node.RBTree );
     141  rtems_test_assert( test_watchdog_is_inactive( &a ) ) ;
     142  rtems_test_assert( a.Base.expire == 2 );
     143  rtems_test_assert( a.counter == 10 );
     144
     145  _Watchdog_Remove( &header, &b.Base );
     146  rtems_test_assert( header.first == &c.Base.Node.RBTree );
     147  rtems_test_assert( test_watchdog_is_inactive( &b ) ) ;
     148  rtems_test_assert( b.Base.expire == 2 );
     149  rtems_test_assert( b.counter == 20 );
     150
     151  _Watchdog_Remove( &header, &c.Base );
     152  rtems_test_assert( header.first == NULL );
     153  rtems_test_assert( test_watchdog_is_inactive( &c ) ) ;
     154  rtems_test_assert( c.Base.expire == 3 );
     155  rtems_test_assert( c.counter == 30 );
     156
     157  _Watchdog_Insert( &header, &a.Base, now + 2 );
     158  rtems_test_assert( header.first == &a.Base.Node.RBTree );
     159  rtems_test_assert( !test_watchdog_is_inactive( &a ) ) ;
     160  rtems_test_assert( a.Base.expire == 3 );
     161  rtems_test_assert( a.counter == 10 );
     162
     163  _Watchdog_Insert( &header, &b.Base, now + 2 );
     164  rtems_test_assert( header.first == &a.Base.Node.RBTree );
     165  rtems_test_assert( !test_watchdog_is_inactive( &b ) ) ;
     166  rtems_test_assert( b.Base.expire == 3 );
     167  rtems_test_assert( b.counter == 20 );
     168
     169  _Watchdog_Insert( &header, &c.Base, now + 3 );
     170  rtems_test_assert( header.first == &a.Base.Node.RBTree );
     171  rtems_test_assert( !test_watchdog_is_inactive( &c ) ) ;
     172  rtems_test_assert( c.Base.expire == 4 );
     173  rtems_test_assert( c.counter == 30 );
     174
     175  now = test_watchdog_tick( &header, now );
     176  rtems_test_assert( !_RBTree_Is_empty( &header.Watchdogs ) );
     177  rtems_test_assert( header.first == &a.Base.Node.RBTree );
     178  rtems_test_assert( !test_watchdog_is_inactive( &a ) ) ;
     179  rtems_test_assert( a.Base.expire == 3 );
     180  rtems_test_assert( a.counter == 10 );
     181  rtems_test_assert( !test_watchdog_is_inactive( &b ) ) ;
     182  rtems_test_assert( b.Base.expire == 3 );
     183  rtems_test_assert( b.counter == 20 );
     184  rtems_test_assert( !test_watchdog_is_inactive( &c ) ) ;
     185  rtems_test_assert( c.Base.expire == 4 );
     186  rtems_test_assert( c.counter == 30 );
     187
     188  now = test_watchdog_tick( &header, now );
     189  rtems_test_assert( !_RBTree_Is_empty( &header.Watchdogs ) );
     190  rtems_test_assert( header.first == &c.Base.Node.RBTree );
     191  rtems_test_assert( test_watchdog_is_inactive( &a ) ) ;
     192  rtems_test_assert( a.Base.expire == 3 );
     193  rtems_test_assert( a.counter == 11 );
     194  rtems_test_assert( test_watchdog_is_inactive( &b ) ) ;
     195  rtems_test_assert( b.Base.expire == 3 );
     196  rtems_test_assert( b.counter == 21 );
     197  rtems_test_assert( !test_watchdog_is_inactive( &c ) ) ;
     198  rtems_test_assert( c.Base.expire == 4 );
     199  rtems_test_assert( c.counter == 30 );
     200
     201  now = test_watchdog_tick( &header, now );
     202  rtems_test_assert( _RBTree_Is_empty( &header.Watchdogs ) );
     203  rtems_test_assert( header.first == NULL );
     204  rtems_test_assert( test_watchdog_is_inactive( &a ) ) ;
     205  rtems_test_assert( a.Base.expire == 3 );
     206  rtems_test_assert( a.counter == 11 );
     207  rtems_test_assert( test_watchdog_is_inactive( &b ) ) ;
     208  rtems_test_assert( b.Base.expire == 3 );
     209  rtems_test_assert( b.counter == 21 );
     210  rtems_test_assert( test_watchdog_is_inactive( &c ) ) ;
     211  rtems_test_assert( c.Base.expire == 4 );
     212  rtems_test_assert( c.counter == 31 );
     213
     214  _Watchdog_Header_destroy( &header );
    264215}
    265216
     
    273224  TEST_BEGIN();
    274225
     226  test_watchdog_operations();
    275227  test_watchdog_static_init();
    276   test_watchdog_insert_and_remove();
    277   test_watchdog_remove_second_and_insert_first();
    278   test_watchdog_insert_with_iterator();
    279228
    280229  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
  • testsuites/tmtests/tmtimer01/tmtimer01.scn

    r90d8567 r03b900d  
    11<TMTimer01 timerCount="65504">
    22  <Sample>
    3     <ActiveTimers>0</ActiveTimers><First unit="ns">6397</First><Middle unit="ns">3290</Middle><Last unit="ns">1527</Last>
     3    <ActiveTimers>0</ActiveTimers><First unit="ns">8812</First><Middle unit="ns">1412</Middle><Last unit="ns">917</Last>
    44  </Sample>
    55  <Sample>
    6     <ActiveTimers>2</ActiveTimers><First unit="ns">1986</First><Middle unit="ns">1550</Middle><Last unit="ns">1314</Last>
     6    <ActiveTimers>2</ActiveTimers><First unit="ns">1602</First><Middle unit="ns">1010</Middle><Last unit="ns">1367</Last>
    77  </Sample>
    88  <Sample>
    9     <ActiveTimers>4</ActiveTimers><First unit="ns">1551</First><Middle unit="ns">2134</Middle><Last unit="ns">3072</Last>
     9    <ActiveTimers>4</ActiveTimers><First unit="ns">1524</First><Middle unit="ns">1089</Middle><Last unit="ns">1086</Last>
    1010  </Sample>
    1111  <Sample>
    12     <ActiveTimers>7</ActiveTimers><First unit="ns">2545</First><Middle unit="ns">3511</Middle><Last unit="ns">3404</Last>
     12    <ActiveTimers>7</ActiveTimers><First unit="ns">1791</First><Middle unit="ns">1121</Middle><Last unit="ns">1838</Last>
    1313  </Sample>
    1414  <Sample>
    15     <ActiveTimers>10</ActiveTimers><First unit="ns">1595</First><Middle unit="ns">2363</Middle><Last unit="ns">4287</Last>
     15    <ActiveTimers>10</ActiveTimers><First unit="ns">1488</First><Middle unit="ns">1016</Middle><Last unit="ns">2134</Last>
    1616  </Sample>
    1717  <Sample>
    18     <ActiveTimers>14</ActiveTimers><First unit="ns">1473</First><Middle unit="ns">2740</Middle><Last unit="ns">6069</Last>
     18    <ActiveTimers>14</ActiveTimers><First unit="ns">1527</First><Middle unit="ns">1698</Middle><Last unit="ns">3186</Last>
    1919  </Sample>
    2020  <Sample>
    21     <ActiveTimers>19</ActiveTimers><First unit="ns">1566</First><Middle unit="ns">3195</Middle><Last unit="ns">5993</Last>
     21    <ActiveTimers>19</ActiveTimers><First unit="ns">2078</First><Middle unit="ns">1665</Middle><Last unit="ns">3397</Last>
    2222  </Sample>
    2323  <Sample>
    24     <ActiveTimers>25</ActiveTimers><First unit="ns">1251</First><Middle unit="ns">2718</Middle><Last unit="ns">7307</Last>
     24    <ActiveTimers>25</ActiveTimers><First unit="ns">1519</First><Middle unit="ns">2368</Middle><Last unit="ns">4464</Last>
    2525  </Sample>
    2626  <Sample>
    27     <ActiveTimers>32</ActiveTimers><First unit="ns">2302</First><Middle unit="ns">5690</Middle><Last unit="ns">10269</Last>
     27    <ActiveTimers>32</ActiveTimers><First unit="ns">1243</First><Middle unit="ns">2623</Middle><Last unit="ns">3549</Last>
    2828  </Sample>
    2929  <Sample>
    30     <ActiveTimers>41</ActiveTimers><First unit="ns">1522</First><Middle unit="ns">8221</Middle><Last unit="ns">13424</Last>
     30    <ActiveTimers>41</ActiveTimers><First unit="ns">2368</First><Middle unit="ns">2578</Middle><Last unit="ns">4105</Last>
    3131  </Sample>
    3232  <Sample>
    33     <ActiveTimers>52</ActiveTimers><First unit="ns">1799</First><Middle unit="ns">8455</Middle><Last unit="ns">14820</Last>
     33    <ActiveTimers>52</ActiveTimers><First unit="ns">2322</First><Middle unit="ns">2563</Middle><Last unit="ns">4126</Last>
    3434  </Sample>
    3535  <Sample>
    36     <ActiveTimers>66</ActiveTimers><First unit="ns">1062</First><Middle unit="ns">12480</Middle><Last unit="ns">16590</Last>
     36    <ActiveTimers>66</ActiveTimers><First unit="ns">2499</First><Middle unit="ns">1855</Middle><Last unit="ns">4919</Last>
    3737  </Sample>
    3838  <Sample>
    39     <ActiveTimers>83</ActiveTimers><First unit="ns">1384</First><Middle unit="ns">11710</Middle><Last unit="ns">21854</Last>
     39    <ActiveTimers>83</ActiveTimers><First unit="ns">1689</First><Middle unit="ns">3128</Middle><Last unit="ns">5894</Last>
    4040  </Sample>
    4141  <Sample>
    42     <ActiveTimers>104</ActiveTimers><First unit="ns">1666</First><Middle unit="ns">15200</Middle><Last unit="ns">30951</Last>
     42    <ActiveTimers>104</ActiveTimers><First unit="ns">2301</First><Middle unit="ns">2647</Middle><Last unit="ns">4595</Last>
    4343  </Sample>
    4444  <Sample>
    45     <ActiveTimers>130</ActiveTimers><First unit="ns">1345</First><Middle unit="ns">17154</Middle><Last unit="ns">37942</Last>
     45    <ActiveTimers>130</ActiveTimers><First unit="ns">2880</First><Middle unit="ns">3183</Middle><Last unit="ns">6222</Last>
    4646  </Sample>
    4747  <Sample>
    48     <ActiveTimers>162</ActiveTimers><First unit="ns">1369</First><Middle unit="ns">22381</Middle><Last unit="ns">46929</Last>
     48    <ActiveTimers>162</ActiveTimers><First unit="ns">2597</First><Middle unit="ns">2376</Middle><Last unit="ns">7118</Last>
    4949  </Sample>
    5050  <Sample>
    51     <ActiveTimers>201</ActiveTimers><First unit="ns">2271</First><Middle unit="ns">35625</Middle><Last unit="ns">59972</Last>
     51    <ActiveTimers>201</ActiveTimers><First unit="ns">3519</First><Middle unit="ns">3466</Middle><Last unit="ns">6673</Last>
    5252  </Sample>
    5353  <Sample>
    54     <ActiveTimers>249</ActiveTimers><First unit="ns">1279</First><Middle unit="ns">37271</Middle><Last unit="ns">69662</Last>
     54    <ActiveTimers>249</ActiveTimers><First unit="ns">2829</First><Middle unit="ns">3177</Middle><Last unit="ns">7784</Last>
    5555  </Sample>
    5656  <Sample>
    57     <ActiveTimers>308</ActiveTimers><First unit="ns">864</First><Middle unit="ns">44580</Middle><Last unit="ns">87633</Last>
     57    <ActiveTimers>308</ActiveTimers><First unit="ns">2614</First><Middle unit="ns">3396</Middle><Last unit="ns">7338</Last>
    5858  </Sample>
    5959  <Sample>
    60     <ActiveTimers>381</ActiveTimers><First unit="ns">1078</First><Middle unit="ns">53821</Middle><Last unit="ns">106376</Last>
     60    <ActiveTimers>381</ActiveTimers><First unit="ns">3454</First><Middle unit="ns">4888</Middle><Last unit="ns">9114</Last>
    6161  </Sample>
    6262  <Sample>
    63     <ActiveTimers>470</ActiveTimers><First unit="ns">913</First><Middle unit="ns">67021</Middle><Last unit="ns">133201</Last>
     63    <ActiveTimers>470</ActiveTimers><First unit="ns">3397</First><Middle unit="ns">2443</Middle><Last unit="ns">7689</Last>
    6464  </Sample>
    6565  <Sample>
    66     <ActiveTimers>580</ActiveTimers><First unit="ns">1870</First><Middle unit="ns">79863</Middle><Last unit="ns">169394</Last>
     66    <ActiveTimers>580</ActiveTimers><First unit="ns">2233</First><Middle unit="ns">4410</Middle><Last unit="ns">9355</Last>
    6767  </Sample>
    6868  <Sample>
    69     <ActiveTimers>715</ActiveTimers><First unit="ns">1732</First><Middle unit="ns">99965</Middle><Last unit="ns">208901</Last>
     69    <ActiveTimers>715</ActiveTimers><First unit="ns">3787</First><Middle unit="ns">5891</Middle><Last unit="ns">6833</Last>
    7070  </Sample>
    7171  <Sample>
    72     <ActiveTimers>881</ActiveTimers><First unit="ns">1503</First><Middle unit="ns">138820</Middle><Last unit="ns">259314</Last>
     72    <ActiveTimers>881</ActiveTimers><First unit="ns">3839</First><Middle unit="ns">5089</Middle><Last unit="ns">9232</Last>
    7373  </Sample>
    7474  <Sample>
    75     <ActiveTimers>1085</ActiveTimers><First unit="ns">1096</First><Middle unit="ns">166404</Middle><Last unit="ns">337461</Last>
     75    <ActiveTimers>1085</ActiveTimers><First unit="ns">2838</First><Middle unit="ns">2739</Middle><Last unit="ns">11575</Last>
    7676  </Sample>
    7777  <Sample>
    78     <ActiveTimers>1336</ActiveTimers><First unit="ns">1383</First><Middle unit="ns">209434</Middle><Last unit="ns">445806</Last>
     78    <ActiveTimers>1336</ActiveTimers><First unit="ns">3256</First><Middle unit="ns">5011</Middle><Last unit="ns">9684</Last>
    7979  </Sample>
    8080  <Sample>
    81     <ActiveTimers>1645</ActiveTimers><First unit="ns">1787</First><Middle unit="ns">253904</Middle><Last unit="ns">533644</Last>
     81    <ActiveTimers>1645</ActiveTimers><First unit="ns">2293</First><Middle unit="ns">5262</Middle><Last unit="ns">10183</Last>
    8282  </Sample>
    8383  <Sample>
    84     <ActiveTimers>2025</ActiveTimers><First unit="ns">2082</First><Middle unit="ns">327384</Middle><Last unit="ns">657141</Last>
     84    <ActiveTimers>2025</ActiveTimers><First unit="ns">4436</First><Middle unit="ns">5934</Middle><Last unit="ns">8804</Last>
    8585  </Sample>
    8686  <Sample>
    87     <ActiveTimers>2492</ActiveTimers><First unit="ns">1843</First><Middle unit="ns">417457</Middle><Last unit="ns">814380</Last>
     87    <ActiveTimers>2492</ActiveTimers><First unit="ns">4506</First><Middle unit="ns">7284</Middle><Last unit="ns">10389</Last>
    8888  </Sample>
    8989  <Sample>
    90     <ActiveTimers>3067</ActiveTimers><First unit="ns">1980</First><Middle unit="ns">493511</Middle><Last unit="ns">977427</Last>
     90    <ActiveTimers>3067</ActiveTimers><First unit="ns">3832</First><Middle unit="ns">4990</Middle><Last unit="ns">9536</Last>
    9191  </Sample>
    9292  <Sample>
    93     <ActiveTimers>3774</ActiveTimers><First unit="ns">2695</First><Middle unit="ns">622065</Middle><Last unit="ns">1237577</Last>
     93    <ActiveTimers>3774</ActiveTimers><First unit="ns">5088</First><Middle unit="ns">4888</Middle><Last unit="ns">9633</Last>
    9494  </Sample>
    9595  <Sample>
    96     <ActiveTimers>4644</ActiveTimers><First unit="ns">1463</First><Middle unit="ns">827565</Middle><Last unit="ns">1565553</Last>
     96    <ActiveTimers>4644</ActiveTimers><First unit="ns">5590</First><Middle unit="ns">5749</Middle><Last unit="ns">8975</Last>
    9797  </Sample>
    9898  <Sample>
    99     <ActiveTimers>5714</ActiveTimers><First unit="ns">1866</First><Middle unit="ns">1053458</Middle><Last unit="ns">1914932</Last>
     99    <ActiveTimers>5714</ActiveTimers><First unit="ns">4854</First><Middle unit="ns">6813</Middle><Last unit="ns">11603</Last>
    100100  </Sample>
    101101  <Sample>
    102     <ActiveTimers>7030</ActiveTimers><First unit="ns">3481</First><Middle unit="ns">1266198</Middle><Last unit="ns">2450199</Last>
     102    <ActiveTimers>7030</ActiveTimers><First unit="ns">6139</First><Middle unit="ns">6132</Middle><Last unit="ns">12630</Last>
    103103  </Sample>
    104104  <Sample>
    105     <ActiveTimers>8649</ActiveTimers><First unit="ns">2773</First><Middle unit="ns">1558351</Middle><Last unit="ns">2967472</Last>
     105    <ActiveTimers>8649</ActiveTimers><First unit="ns">6877</First><Middle unit="ns">3852</Middle><Last unit="ns">10973</Last>
    106106  </Sample>
    107107  <Sample>
    108     <ActiveTimers>10640</ActiveTimers><First unit="ns">2086</First><Middle unit="ns">2003884</Middle><Last unit="ns">3766161</Last>
     108    <ActiveTimers>10640</ActiveTimers><First unit="ns">6532</First><Middle unit="ns">6097</Middle><Last unit="ns">11725</Last>
    109109  </Sample>
    110110  <Sample>
    111     <ActiveTimers>13089</ActiveTimers><First unit="ns">3911</First><Middle unit="ns">2501427</Middle><Last unit="ns">4619553</Last>
     111    <ActiveTimers>13089</ActiveTimers><First unit="ns">5284</First><Middle unit="ns">5392</Middle><Last unit="ns">13246</Last>
    112112  </Sample>
    113113  <Sample>
    114     <ActiveTimers>16101</ActiveTimers><First unit="ns">3276</First><Middle unit="ns">3189159</Middle><Last unit="ns">5886373</Last>
     114    <ActiveTimers>16101</ActiveTimers><First unit="ns">7077</First><Middle unit="ns">7572</Middle><Last unit="ns">14820</Last>
    115115  </Sample>
    116116  <Sample>
    117     <ActiveTimers>19806</ActiveTimers><First unit="ns">3801</First><Middle unit="ns">4005049</Middle><Last unit="ns">7394938</Last>
     117    <ActiveTimers>19806</ActiveTimers><First unit="ns">7132</First><Middle unit="ns">8335</Middle><Last unit="ns">11668</Last>
    118118  </Sample>
    119119  <Sample>
    120     <ActiveTimers>24363</ActiveTimers><First unit="ns">3088</First><Middle unit="ns">4977788</Middle><Last unit="ns">9138839</Last>
     120    <ActiveTimers>24363</ActiveTimers><First unit="ns">8676</First><Middle unit="ns">7919</Middle><Last unit="ns">13937</Last>
    121121  </Sample>
    122122  <Sample>
    123     <ActiveTimers>29968</ActiveTimers><First unit="ns">4089</First><Middle unit="ns">6133462</Middle><Last unit="ns">11361012</Last>
     123    <ActiveTimers>29968</ActiveTimers><First unit="ns">5970</First><Middle unit="ns">10978</Middle><Last unit="ns">16035</Last>
    124124  </Sample>
    125125  <Sample>
    126     <ActiveTimers>36862</ActiveTimers><First unit="ns">2059</First><Middle unit="ns">7870138</Middle><Last unit="ns">14319206</Last>
     126    <ActiveTimers>36862</ActiveTimers><First unit="ns">8804</First><Middle unit="ns">8767</Middle><Last unit="ns">13089</Last>
    127127  </Sample>
    128128  <Sample>
    129     <ActiveTimers>45342</ActiveTimers><First unit="ns">2224</First><Middle unit="ns">9917100</Middle><Last unit="ns">17754441</Last>
     129    <ActiveTimers>45342</ActiveTimers><First unit="ns">8608</First><Middle unit="ns">10305</Middle><Last unit="ns">15709</Last>
    130130  </Sample>
    131131  <Sample>
    132     <ActiveTimers>55772</ActiveTimers><First unit="ns">1979</First><Middle unit="ns">11815557</Middle><Last unit="ns">21907509</Last>
     132    <ActiveTimers>55772</ActiveTimers><First unit="ns">8949</First><Middle unit="ns">10031</Middle><Last unit="ns">16262</Last>
    133133  </Sample>
    134134  <Sample>
    135     <ActiveTimers>65503</ActiveTimers><First unit="ns">2404</First><Middle unit="ns">13694591</Middle><Last unit="ns">26215885</Last>
     135    <ActiveTimers>65503</ActiveTimers><First unit="ns">9199</First><Middle unit="ns">10309</Middle><Last unit="ns">19090</Last>
    136136  </Sample>
    137137</TMTimer01>
Note: See TracChangeset for help on using the changeset viewer.