Changeset 6e51c4c in rtems


Ignore:
Timestamp:
Nov 30, 2009, 9:08:35 AM (9 years ago)
Author:
Thomas Doerfler <Thomas.Doerfler@…>
Branches:
4.10, 4.11, master
Children:
1498a59
Parents:
6cc3dfb
Message:

Added timer server control block
Removed _Timer_Server thread pointer
Added _Timer_server pointer to the default timer server control block
Rework of the timer server implementation.

Files:
10 added
13 edited

Legend:

Unmodified
Added
Removed
  • cpukit/ChangeLog

    r6cc3dfb r6e51c4c  
     12009-11-30      Sebastian Huber <sebastian.huber@embedded-brains.de>
     2
     3        * rtems/include/rtems/rtems/timer.h: Added timer server control block
     4        Timer_server_Control.  Removed _Timer_Server thread pointer. Added
     5        _Timer_server pointer to the default timer server control block.
     6        * rtems/src/rtemstimer.c, rtems/src/timerreset.c,
     7        rtems/src/timerserverfireafter.c, rtems/src/timerserverfirewhen.c:
     8        Update for changes above.
     9        * rtems/src/timerserver.c: Rework of the timer server implementation.
     10        It is now possible to insert timers without the help of the timer
     11        server thread.  This reduces the need for a thread dispatch.  The
     12        timer server can now block on any resource type.  Timer callbacks can
     13        even wait for time.
     14
    1152009-11-23      Joel Sherrill <joel.sherrill@oarcorp.com>
    216
  • cpukit/rtems/include/rtems/rtems/timer.h

    r6cc3dfb r6e51c4c  
    2626 *  On-Line Applications Research Corporation (OAR).
    2727 *
     28 *  Copyright (c) 2009 embedded brains GmbH.
     29 *
    2830 *  The license and distribution terms for this file may be
    2931 *  found in the file LICENSE in this distribution or at
     
    5355#include <rtems/score/watchdog.h>
    5456#include <rtems/score/thread.h>
     57#include <rtems/score/chain.h>
    5558#include <rtems/rtems/clock.h>
    5659#include <rtems/rtems/attr.h>
     
    119122                 void *
    120123             );
    121 
    122 /**
    123  *  The following defines the information control block used to manage
    124  *  this class of objects.
    125  */
    126 RTEMS_TIMER_EXTERN Objects_Information  _Timer_Information;
    127 
    128 /**
    129  *  Pointer to TCB of the Timer Server.  This is NULL before the
    130  *  server is executing and task-based timers are not allowed to be
    131  *  initiated until the server is started.
    132  */
    133 RTEMS_TIMER_EXTERN Thread_Control *_Timer_Server;
    134124
    135125/**
     
    145135  Timer_Classes    the_class;
    146136}   Timer_Control;
     137
     138typedef struct Timer_server_Control Timer_server_Control;
     139
     140/**
     141 * @brief Method used to schedule the insertion of task based timers.
     142 */
     143typedef void (*Timer_server_Schedule_operation)(
     144  Timer_server_Control *timer_server,
     145  Timer_Control        *timer
     146);
     147
     148typedef struct {
     149  /**
     150   * @brief This watchdog that will be registered in the system tick mechanic
     151   * for timer server wake-up.
     152   */
     153  Watchdog_Control System_watchdog;
     154
     155  /**
     156   * @brief Chain for watchdogs which will be triggered by the timer server.
     157   */
     158  Chain_Control Chain;
     159
     160  /**
     161   * @brief Last known time snapshot of the timer server.
     162   *
     163   * The units may be ticks or seconds.
     164   */
     165  Watchdog_Interval volatile last_snapshot;
     166} Timer_server_Watchdogs;
     167
     168struct Timer_server_Control {
     169  /**
     170   * @brief Timer server thread.
     171   */
     172  Thread_Control *thread;
     173
     174  /**
     175   * @brief The schedule operation method of the timer server.
     176   */
     177  Timer_server_Schedule_operation schedule_operation;
     178
     179  /**
     180   * @brief Interval watchdogs triggered by the timer server.
     181   */
     182  Timer_server_Watchdogs Interval_watchdogs;
     183
     184  /**
     185   * @brief TOD watchdogs triggered by the timer server.
     186   */
     187  Timer_server_Watchdogs TOD_watchdogs;
     188
     189  /**
     190   * @brief Chain of timers scheduled for insert.
     191   *
     192   * This pointer is not @c NULL whenever the interval and TOD chains are
     193   * processed.  After the processing this list will be checked and if
     194   * necessary the processing will be restarted.  Processing of these chains
     195   * can be only interrupted through interrupts.
     196   */
     197  Chain_Control *volatile insert_chain;
     198
     199  /**
     200   * @brief Indicates that the timer server is active or not.
     201   *
     202   * The server is active after the delay on a system watchdog.  The activity
     203   * period of the server ends when no more watchdogs managed by the server
     204   * fire.  The system watchdogs must not be manipulated when the server is
     205   * active.
     206   */
     207  bool volatile active;
     208};
     209
     210/**
     211 * @brief Pointer to default timer server control block.
     212 *
     213 * This value is @c NULL when the default timer server is not initialized.
     214 */
     215RTEMS_TIMER_EXTERN Timer_server_Control *volatile _Timer_server;
     216
     217/**
     218 *  The following defines the information control block used to manage
     219 *  this class of objects.
     220 */
     221RTEMS_TIMER_EXTERN Objects_Information  _Timer_Information;
    147222
    148223/**
     
    320395);
    321396
    322 /**
    323  *  This type defines the method used to schedule the insertion of task
    324  *  based timers.
    325  */
    326 typedef void (*Timer_Server_schedule_operation_t)(
    327   Timer_Control     *the_timer
    328 );
    329 
    330 /**
    331  *  This variable will point to the schedule operation method once the
    332  *  timer server is initialized.
    333  */
    334 RTEMS_TIMER_EXTERN Timer_Server_schedule_operation_t
    335   _Timer_Server_schedule_operation;
    336 
    337397#ifndef __RTEMS_APPLICATION__
    338398#include <rtems/rtems/timer.inl>
  • cpukit/rtems/src/rtemstimer.c

    r6cc3dfb r6e51c4c  
    5757
    5858  /*
    59    *  Initialize the pointer to the Timer Server TCB to NULL indicating
    60    *  that task-based timer support is not initialized.
     59   *  Initialize the pointer to the default timer server control block to NULL
     60   *  indicating that task-based timer support is not initialized.
    6161   */
    6262
    63   _Timer_Server = NULL;
    64   _Timer_Server_schedule_operation = NULL;
     63  _Timer_server = NULL;
    6564}
  • cpukit/rtems/src/timerreset.c

    r6cc3dfb r6e51c4c  
    5656        _Watchdog_Insert( &_Watchdog_Ticks_chain, &the_timer->Ticker );
    5757      } else if ( the_timer->the_class == TIMER_INTERVAL_ON_TASK ) {
     58        Timer_server_Control *timer_server = _Timer_server;
     59
    5860        /*
    5961         *  There is no way for a timer to have this class unless
     
    6365         */
    6466        #if defined(RTEMS_DEBUG)
    65           if ( !_Timer_Server_schedule_operation ) {
     67          if ( !timer_server ) {
    6668            _Thread_Enable_dispatch();
    6769            return RTEMS_INCORRECT_STATE;
     
    6971        #endif
    7072        _Watchdog_Remove( &the_timer->Ticker );
    71         (*_Timer_Server_schedule_operation)( the_timer );
     73        (*timer_server->schedule_operation)( timer_server, the_timer );
    7274      } else {
    7375        /*
  • cpukit/rtems/src/timerserver.c

    r6cc3dfb r6e51c4c  
    1515/*  COPYRIGHT (c) 1989-2008.
    1616 *  On-Line Applications Research Corporation (OAR).
     17 *
     18 *  Copyright (c) 2009 embedded brains GmbH.
    1719 *
    1820 *  The license and distribution terms for this file may be
     
    4042#include <rtems/score/thread.h>
    4143
    42 /**
    43  *  This chain contains the list of interval timers that are
    44  *  executed in the context of the Timer Server.
    45  */
    46 Chain_Control _Timer_Ticks_chain;
    47 
    48 /**
    49  *  This chain contains the list of time of day timers that are
    50  *  executed in the context of the Timer Server.
    51  */
    52 Chain_Control _Timer_Seconds_chain;
    53 
    54 /**
    55  *  This chain holds the set of timers to be inserted when the
    56  *  server runs again.
    57  */
    58 Chain_Control _Timer_To_be_inserted;
    59 
    60 /**
    61  *  This variables keeps track of the last time the Timer Server actually
    62  *  processed the ticks chain.
    63  */
    64 Watchdog_Interval _Timer_Server_ticks_last_time;
    65 
    66 /**
    67  *  This variable keeps track of the last time the Timer Server actually
    68  *  processed the seconds chain.
    69  */
    70 Watchdog_Interval _Timer_Server_seconds_last_time;
    71 
    72 /**
    73  *  This is the timer used to control when the Timer Server wakes up to
    74  *  service "when" timers.
    75  *
    76  *  @note The timer in the Timer Server TCB is used for ticks timer.
    77  */
    78 Watchdog_Control _Timer_Seconds_timer;
    79 
    80 /**
    81  *  This method is used to temporarily disable updates to the
    82  *  Ticks Timer Chain managed by the Timer Server.
    83  */
    84 #define _Timer_Server_stop_ticks_timer() \
    85       _Watchdog_Remove( &_Timer_Server->Timer )
    86 
    87 /**
    88  *  This method is used to temporarily disable updates to the
    89  *  Seconds Timer Chain managed by the Timer Server.
    90  */
    91 #define _Timer_Server_stop_seconds_timer() \
    92       _Watchdog_Remove( &_Timer_Seconds_timer );
    93 
    94 /**
    95  *  This method resets a timer and places it on the Ticks chain.  It
    96  *  is assumed that the timer has already been canceled.
    97  */
    98 #define _Timer_Server_reset_ticks_timer() \
    99    do { \
    100       if ( !_Chain_Is_empty( &_Timer_Ticks_chain ) ) { \
    101         _Watchdog_Insert_ticks( &_Timer_Server->Timer, \
    102            ((Watchdog_Control *)_Timer_Ticks_chain.first)->delta_interval ); \
    103       } \
    104    } while (0)
    105 
    106 /**
    107  *  This method resets a timer and places it on the Seconds chain.  It
    108  *  is assumed that the timer has already been canceled.
    109  */
    110 #define _Timer_Server_reset_seconds_timer() \
    111    do { \
    112       if ( !_Chain_Is_empty( &_Timer_Seconds_chain ) ) { \
    113         _Watchdog_Insert_seconds( &_Timer_Seconds_timer, \
    114           ((Watchdog_Control *)_Timer_Seconds_chain.first)->delta_interval ); \
    115       } \
    116    } while (0)
    117 
    118 /**
    119  *  @brief _Timer_Server_process_insertions
    120  *
    121  *  This method processes the set of timers scheduled for insertion
    122  *  onto one of the Timer Server chains.
    123  *
    124  *  @note It is only to be called from the Timer Server task.
    125  */
    126 static void _Timer_Server_process_insertions(void)
    127 {
    128   Timer_Control *the_timer;
    129 
    130   while ( 1 ) {
    131     the_timer = (Timer_Control *) _Chain_Get( &_Timer_To_be_inserted );
    132     if ( the_timer == NULL )
    133       break;
    134 
    135     if ( the_timer->the_class == TIMER_INTERVAL_ON_TASK ) {
    136       _Watchdog_Insert( &_Timer_Ticks_chain, &the_timer->Ticker );
    137     } else if ( the_timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
    138       _Watchdog_Insert( &_Timer_Seconds_chain, &the_timer->Ticker );
    139     }
    140   }
    141 }
    142 
    143 /**
    144  *  @brief _Timer_Server_process_ticks_chain
    145  *
    146  *  This routine is responsible for adjusting the list of task-based
    147  *  interval timers to reflect the passage of time.
    148  *
    149  *  @param[in] to_fire will contain the set of timers that are to be fired.
    150  *
    151  *  @note It is only to be called from the Timer Server task.
    152  */
    153 static void _Timer_Server_process_ticks_chain(
    154   Chain_Control *to_fire
    155 )
    156 {
     44static Timer_server_Control _Timer_server_Default;
     45
     46static void _Timer_server_Stop_interval_system_watchdog(
     47  Timer_server_Control *ts
     48)
     49{
     50  _Watchdog_Remove( &ts->Interval_watchdogs.System_watchdog );
     51}
     52
     53static void _Timer_server_Reset_interval_system_watchdog(
     54  Timer_server_Control *ts
     55)
     56{
     57  ISR_Level level;
     58
     59  _Timer_server_Stop_interval_system_watchdog( ts );
     60
     61  _ISR_Disable( level );
     62  if ( !_Chain_Is_empty( &ts->Interval_watchdogs.Chain ) ) {
     63    Watchdog_Interval delta_interval =
     64      _Watchdog_First( &ts->Interval_watchdogs.Chain )->delta_interval;
     65    _ISR_Enable( level );
     66
     67    /*
     68     *  The unit is TICKS here.
     69     */
     70    _Watchdog_Insert_ticks(
     71      &ts->Interval_watchdogs.System_watchdog,
     72      delta_interval
     73    );
     74  } else {
     75    _ISR_Enable( level );
     76  }
     77}
     78
     79static void _Timer_server_Stop_tod_system_watchdog(
     80  Timer_server_Control *ts
     81)
     82{
     83  _Watchdog_Remove( &ts->TOD_watchdogs.System_watchdog );
     84}
     85
     86static void _Timer_server_Reset_tod_system_watchdog(
     87  Timer_server_Control *ts
     88)
     89{
     90  ISR_Level level;
     91
     92  _Timer_server_Stop_tod_system_watchdog( ts );
     93
     94  _ISR_Disable( level );
     95  if ( !_Chain_Is_empty( &ts->TOD_watchdogs.Chain ) ) {
     96    Watchdog_Interval delta_interval =
     97      _Watchdog_First( &ts->TOD_watchdogs.Chain )->delta_interval;
     98    _ISR_Enable( level );
     99
     100    /*
     101     *  The unit is SECONDS here.
     102     */
     103    _Watchdog_Insert_seconds(
     104      &ts->TOD_watchdogs.System_watchdog,
     105      delta_interval
     106    );
     107  } else {
     108    _ISR_Enable( level );
     109  }
     110}
     111
     112static void _Timer_server_Insert_timer(
     113  Timer_server_Control *ts,
     114  Timer_Control *timer
     115)
     116{
     117  if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) {
     118    _Watchdog_Insert( &ts->Interval_watchdogs.Chain, &timer->Ticker );
     119  } else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
     120    _Watchdog_Insert( &ts->TOD_watchdogs.Chain, &timer->Ticker );
     121  }
     122}
     123
     124static void _Timer_server_Insert_timer_and_make_snapshot(
     125  Timer_server_Control *ts,
     126  Timer_Control *timer
     127)
     128{
     129  Watchdog_Control *first_watchdog;
     130  Watchdog_Interval delta_interval;
     131  Watchdog_Interval last_snapshot;
    157132  Watchdog_Interval snapshot;
    158   Watchdog_Interval ticks;
    159 
    160   snapshot = _Watchdog_Ticks_since_boot;
    161   if ( snapshot >= _Timer_Server_ticks_last_time )
    162     ticks = snapshot - _Timer_Server_ticks_last_time;
    163   else
    164     ticks = (0xFFFFFFFF - _Timer_Server_ticks_last_time) + snapshot;
    165 
    166   _Timer_Server_ticks_last_time = snapshot;
    167   _Watchdog_Adjust_to_chain( &_Timer_Ticks_chain, ticks, to_fire );
    168 }
    169 
    170 /**
    171  *  @brief _Timer_Server_process_seconds_chain
    172  *
    173  *  This routine is responsible for adjusting the list of task-based
    174  *  time of day timers to reflect the passage of time.
    175  *
    176  *  @param[in] to_fire will contain the set of timers that are to be fired.
    177  *
    178  *  @note It is only to be called from the Timer Server task.
    179  */
    180 static void _Timer_Server_process_seconds_chain(
    181   Chain_Control *to_fire
    182 )
    183 {
    184   Watchdog_Interval snapshot;
    185   Watchdog_Interval ticks;
     133  Watchdog_Interval delta;
     134  ISR_Level level;
     135
     136  /*
     137   *  We have to update the time snapshots here, because otherwise we may have
     138   *  problems with the integer range of the delta values.  The time delta DT
     139   *  from the last snapshot to now may be arbitrarily long.  The last snapshot
     140   *  is the reference point for the delta chain.  Thus if we do not update the
     141   *  reference point we have to add DT to the initial delta of the watchdog
     142   *  being inserted.  This could result in an integer overflow.
     143   */
     144
     145  _Thread_Disable_dispatch();
     146
     147  if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) {
     148    /*
     149     *  We have to advance the last known ticks value of the server and update
     150     *  the watchdog chain accordingly.
     151     */
     152    _ISR_Disable( level );
     153    snapshot = _Watchdog_Ticks_since_boot;
     154    last_snapshot = ts->Interval_watchdogs.last_snapshot;
     155    if ( !_Chain_Is_empty( &ts->Interval_watchdogs.Chain ) ) {
     156      first_watchdog = _Watchdog_First( &ts->Interval_watchdogs.Chain );
     157
     158      /*
     159       *  We assume adequate unsigned arithmetic here.
     160       */
     161      delta = snapshot - last_snapshot;
     162
     163      delta_interval = first_watchdog->delta_interval;
     164      if (delta_interval > delta) {
     165        delta_interval -= delta;
     166      } else {
     167        delta_interval = 0;
     168      }
     169      first_watchdog->delta_interval = delta_interval;
     170    }
     171    ts->Interval_watchdogs.last_snapshot = snapshot;
     172    _ISR_Enable( level );
     173
     174    _Watchdog_Insert( &ts->Interval_watchdogs.Chain, &timer->Ticker );
     175
     176    if ( !ts->active ) {
     177      _Timer_server_Reset_interval_system_watchdog( ts );
     178    }
     179  } else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
     180    /*
     181     *  We have to advance the last known seconds value of the server and update
     182     *  the watchdog chain accordingly.
     183     */
     184    _ISR_Disable( level );
     185    snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch();
     186    last_snapshot = ts->TOD_watchdogs.last_snapshot;
     187    if ( !_Chain_Is_empty( &ts->TOD_watchdogs.Chain ) ) {
     188      first_watchdog = _Watchdog_First( &ts->TOD_watchdogs.Chain );
     189      delta_interval = first_watchdog->delta_interval;
     190      if ( snapshot > last_snapshot ) {
     191        /*
     192         *  We advanced in time.
     193         */
     194        delta = snapshot - last_snapshot;
     195        if (delta_interval > delta) {
     196          delta_interval -= delta;
     197        } else {
     198          delta_interval = 0;
     199        }
     200      } else {
     201        /*
     202         *  Someone put us in the past.
     203         */
     204        delta = last_snapshot - snapshot;
     205        delta_interval += delta;
     206      }
     207      first_watchdog->delta_interval = delta_interval;
     208    }
     209    ts->TOD_watchdogs.last_snapshot = snapshot;
     210    _ISR_Enable( level );
     211
     212    _Watchdog_Insert( &ts->TOD_watchdogs.Chain, &timer->Ticker );
     213
     214    if ( !ts->active ) {
     215      _Timer_server_Reset_tod_system_watchdog( ts );
     216    }
     217  }
     218
     219  _Thread_Enable_dispatch();
     220}
     221
     222static void _Timer_server_Schedule_operation_method(
     223  Timer_server_Control *ts,
     224  Timer_Control *timer
     225)
     226{
     227  if ( ts->insert_chain == NULL ) {
     228    _Timer_server_Insert_timer_and_make_snapshot( ts, timer );
     229  } else {
     230    /*
     231     *  We interrupted a critical section of the timer server.  The timer
     232     *  server is not preemptible, so we must be in interrupt context here.  No
     233     *  thread dispatch will happen until the timer server finishes its
     234     *  critical section.  We have to use the protected chain methods because
     235     *  we may be interrupted by a higher priority interrupt.
     236     */
     237    _Chain_Append( ts->insert_chain, &timer->Object.Node );
     238  }
     239}
     240
     241static void _Timer_server_Process_interval_watchdogs(
     242  Timer_server_Watchdogs *watchdogs,
     243  Chain_Control *fire_chain
     244)
     245{
     246  Watchdog_Interval snapshot = _Watchdog_Ticks_since_boot;
     247
     248  /*
     249   *  We assume adequate unsigned arithmetic here.
     250   */
     251  Watchdog_Interval delta = snapshot - watchdogs->last_snapshot;
     252
     253  watchdogs->last_snapshot = snapshot;
     254
     255  _Watchdog_Adjust_to_chain( &watchdogs->Chain, delta, fire_chain );
     256}
     257
     258static void _Timer_server_Process_tod_watchdogs(
     259  Timer_server_Watchdogs *watchdogs,
     260  Chain_Control *fire_chain
     261)
     262{
     263  Watchdog_Interval snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch();
     264  Watchdog_Interval last_snapshot = watchdogs->last_snapshot;
     265  Watchdog_Interval delta;
    186266
    187267  /*
    188268   *  Process the seconds chain.  Start by checking that the Time
    189269   *  of Day (TOD) has not been set backwards.  If it has then
    190    *  we want to adjust the _Timer_Seconds_chain to indicate this.
    191    */
    192   snapshot =  _TOD_Seconds_since_epoch();
    193   if ( snapshot > _Timer_Server_seconds_last_time ) {
     270   *  we want to adjust the watchdogs->Chain to indicate this.
     271   */
     272  if ( snapshot > last_snapshot ) {
    194273    /*
    195274     *  This path is for normal forward movement and cases where the
    196275     *  TOD has been set forward.
    197276     */
    198     ticks = snapshot - _Timer_Server_seconds_last_time;
    199     _Watchdog_Adjust_to_chain( &_Timer_Seconds_chain, ticks, to_fire );
    200 
    201   } else if ( snapshot < _Timer_Server_seconds_last_time ) {
     277    delta = snapshot - last_snapshot;
     278    _Watchdog_Adjust_to_chain( &watchdogs->Chain, delta, fire_chain );
     279
     280  } else if ( snapshot < last_snapshot ) {
    202281     /*
    203282      *  The current TOD is before the last TOD which indicates that
    204283      *  TOD has been set backwards.
    205284      */
    206      ticks = _Timer_Server_seconds_last_time - snapshot;
    207      _Watchdog_Adjust( &_Timer_Seconds_chain, WATCHDOG_BACKWARD, ticks );
    208   }
    209   _Timer_Server_seconds_last_time = snapshot;
     285     delta = last_snapshot - snapshot;
     286     _Watchdog_Adjust( &watchdogs->Chain, WATCHDOG_BACKWARD, delta );
     287  }
     288
     289  watchdogs->last_snapshot = snapshot;
     290}
     291
     292static void _Timer_server_Process_insertions( Timer_server_Control *ts )
     293{
     294  while ( true ) {
     295    Timer_Control *timer = (Timer_Control *) _Chain_Get( ts->insert_chain );
     296
     297    if ( timer == NULL ) {
     298      break;
     299    }
     300
     301    _Timer_server_Insert_timer( ts, timer );
     302  }
     303}
     304
     305static void _Timer_server_Get_watchdogs_that_fire_now(
     306  Timer_server_Control *ts,
     307  Chain_Control *insert_chain,
     308  Chain_Control *fire_chain
     309)
     310{
     311  /*
     312   *  Afterwards all timer inserts are directed to this chain and the interval
     313   *  and TOD chains will be no more modified by other parties.
     314   */
     315  ts->insert_chain = insert_chain;
     316
     317  while ( true ) {
     318    ISR_Level level;
     319
     320    /*
     321     *  Remove all the watchdogs that need to fire so we can invoke them.
     322     */
     323    _Timer_server_Process_interval_watchdogs(
     324      &ts->Interval_watchdogs,
     325      fire_chain
     326    );
     327    _Timer_server_Process_tod_watchdogs( &ts->TOD_watchdogs, fire_chain );
     328
     329    /*
     330     *  The insertions have to take place here, because they reference the
     331     *  current time.  The previous process methods take a snapshot of the
     332     *  current time.  In case someone inserts a watchdog with an initial value
     333     *  of zero it will be processed in the next iteration of the timer server
     334     *  body loop.
     335     */
     336    _Timer_server_Process_insertions( ts );
     337
     338    _ISR_Disable( level );
     339    if ( _Chain_Is_empty( insert_chain ) ) {
     340      ts->insert_chain = NULL;
     341      _ISR_Enable( level );
     342
     343      break;
     344    } else {
     345      _ISR_Enable( level );
     346    }
     347  }
    210348}
    211349
    212350/**
    213  *  @brief _Timer_Server_body
    214  *
    215  *  This is the server for task based timers.  This task executes whenever
    216  *  a task-based timer should fire.  It services both "after" and "when"
    217  *  timers.  It is not created automatically but must be created explicitly
    218  *  by the application before task-based timers may be initiated.
    219  *
    220  *  @param[in] ignored is the the task argument that is ignored
     351 *  @brief Timer server body.
     352 *
     353 *  This is the server for task based timers.  This task executes whenever a
     354 *  task-based timer should fire.  It services both "after" and "when" timers.
     355 *  It is not created automatically but must be created explicitly by the
     356 *  application before task-based timers may be initiated.  The parameter
     357 *  @a arg points to the corresponding timer server control block.
    221358 */
    222 rtems_task _Timer_Server_body(
    223   rtems_task_argument argument __attribute__((unused))
    224 )
    225 {
    226   Chain_Control to_fire;
    227 
    228   _Chain_Initialize_empty( &to_fire );
    229 
    230   /*
    231    *  Initialize the "last time" markers to indicate the timer that
    232    *  the server was initiated.
    233    */
    234   _Timer_Server_ticks_last_time   = _Watchdog_Ticks_since_boot;
    235   _Timer_Server_seconds_last_time = _TOD_Seconds_since_epoch();
    236 
    237   /*
    238    *  Insert the timers that were inserted before we got to run.
    239    *  This should be done with dispatching disabled.
    240    */
    241   _Thread_Disable_dispatch();
    242     _Timer_Server_process_insertions();
    243   _Thread_Enable_dispatch();
    244 
    245   while(1) {
    246 
    247     /*
    248      *  Block until there is something to do.
    249      */
    250     _Thread_Disable_dispatch();
    251       _Thread_Set_state( _Timer_Server, STATES_DELAYING );
    252       _Timer_Server_reset_ticks_timer();
    253       _Timer_Server_reset_seconds_timer();
    254     _Thread_Enable_dispatch();
    255 
    256     /********************************************************************
    257      ********************************************************************
    258      ****                TIMER SERVER BLOCKS HERE                    ****
    259      ********************************************************************
    260      ********************************************************************/
    261 
    262     /*
    263      *  Disable dispatching while processing the timers since we want
    264      *  the removal of the timers from the chain to be atomic.
    265      *
    266      *  NOTE: Dispatching is disabled for interrupt based TSRs.
    267      *        Dispatching is enabled for task based TSRs so they
    268      *          can temporarily malloc memory or block.
    269      *        _ISR_Nest_level is 0 for task-based TSRs and non-zero
    270      *          for the others.
    271      */
    272     _Thread_Disable_dispatch();
    273 
    274     /*
    275      *  At this point, at least one of the timers this task relies
    276      *  upon has fired.  Stop them both while we process any outstanding
    277      *  timers.  Before we block, we will restart them.
    278      */
    279     _Timer_Server_stop_ticks_timer();
    280     _Timer_Server_stop_seconds_timer();
    281 
    282     /*
    283      *  Remove all the timers that need to fire so we can invoke them
    284      *  outside the critical section.
    285      */
    286     _Timer_Server_process_ticks_chain( &to_fire );
    287     _Timer_Server_process_seconds_chain( &to_fire );
    288 
    289     /*
    290      *  Insert the timers that have been requested to be inserted.
    291      */
    292     _Timer_Server_process_insertions();
    293 
    294     /*
    295      * Enable dispatching to process the set that are ready "to fire."
    296      */
    297     _Thread_Enable_dispatch();
    298 
    299     /*
    300      *  Now we actually invoke the TSR for all the timers that fired.
    301      *  This is done with dispatching
    302      */
    303     while (1) {
    304       Watchdog_Control *watch;
    305       ISR_Level         level;
    306 
    307       _ISR_Disable( level );
    308       watch = (Watchdog_Control *) _Chain_Get_unprotected( &to_fire );
    309       if ( watch == NULL ) {
    310         _ISR_Enable( level );
    311         break;
     359static rtems_task _Timer_server_Body(
     360  rtems_task_argument arg
     361)
     362{
     363  Timer_server_Control *ts = (Timer_server_Control *) arg;
     364  Chain_Control insert_chain;
     365  Chain_Control fire_chain;
     366
     367  _Chain_Initialize_empty( &insert_chain );
     368  _Chain_Initialize_empty( &fire_chain );
     369
     370  while ( true ) {
     371    _Timer_server_Get_watchdogs_that_fire_now( ts, &insert_chain, &fire_chain );
     372
     373    if ( !_Chain_Is_empty( &fire_chain ) ) {
     374      /*
     375       *  Fire the watchdogs.
     376       */
     377      while ( true ) {
     378        Watchdog_Control *watchdog;
     379        ISR_Level level;
     380
     381        /*
     382         *  It is essential that interrupts are disable here since an interrupt
     383         *  service routine may remove a watchdog from the chain.
     384         */
     385        _ISR_Disable( level );
     386        watchdog = (Watchdog_Control *) _Chain_Get_unprotected( &fire_chain );
     387        if ( watchdog != NULL ) {
     388          watchdog->state = WATCHDOG_INACTIVE;
     389          _ISR_Enable( level );
     390        } else {
     391          _ISR_Enable( level );
     392
     393          break;
     394        }
     395
     396        /*
     397         *  The timer server may block here and wait for resources or time.
     398         *  The system watchdogs are inactive and will remain inactive since
     399         *  the active flag of the timer server is true.
     400         */
     401        (*watchdog->routine)( watchdog->id, watchdog->user_data );
    312402      }
    313 
    314       watch->state = WATCHDOG_INACTIVE;
    315       _ISR_Enable( level );
    316 
    317       (*watch->routine)( watch->id, watch->user_data );
    318     }
    319 
    320     /*
    321      *  Insert the timers that have been requested to be inserted.
    322      */
    323     _Timer_Server_process_insertions();
    324   }
    325 
    326 }
    327 
    328 /**
    329  *  This method schedules the insertion of timers on the proper list.  It
    330  *  wakes up the Timer Server task to process the insertion.
    331  *
    332  *  @param[in] the_timer is the timer to insert
    333  *
    334  *  @note It is highly likely the executing task will be preempted after
    335  *        the directive invoking this is executed.
    336  */
    337 static void _Timer_Server_schedule_operation_method(
    338   Timer_Control     *the_timer
    339 )
    340 {
    341   _Chain_Append( &_Timer_To_be_inserted, &the_timer->Object.Node );
    342   _Watchdog_Remove( &_Timer_Server->Timer );
    343   _Thread_Delay_ended( _Timer_Server->Object.id, NULL );
     403    } else {
     404      ts->active = false;
     405
     406      /*
     407       *  Block until there is something to do.
     408       */
     409      _Thread_Disable_dispatch();
     410        _Thread_Set_state( ts->thread, STATES_DELAYING );
     411        _Timer_server_Reset_interval_system_watchdog( ts );
     412        _Timer_server_Reset_tod_system_watchdog( ts );
     413      _Thread_Enable_dispatch();
     414
     415      ts->active = true;
     416
     417      /*
     418       *  Maybe an interrupt did reset the system timers, so we have to stop
     419       *  them here.  Since we are active now, there will be no more resets
     420       *  until we are inactive again.
     421       */
     422      _Timer_server_Stop_interval_system_watchdog( ts );
     423      _Timer_server_Stop_tod_system_watchdog( ts );
     424    }
     425  }
    344426}
    345427
     
    354436 *  @param[in] attribute_set is the timer server attributes
    355437 *
    356  *  @return This method returns RTEMS_SUCCESSFUL if successful and an 
     438 *  @return This method returns RTEMS_SUCCESSFUL if successful and an
    357439 *          error code otherwise.
    358440 */
     
    363445)
    364446{
    365   rtems_id            id;
    366   rtems_status_code   status;
    367   rtems_task_priority _priority;
    368   static bool         initialized = false;
    369   bool                tmpInitialized;
     447  rtems_id              id;
     448  rtems_status_code     status;
     449  rtems_task_priority   _priority;
     450  static bool           initialized = false;
     451  bool                  tmpInitialized;
     452  Timer_server_Control *ts = &_Timer_server_Default;
    370453
    371454  /*
     
    391474  if ( tmpInitialized )
    392475    return RTEMS_INCORRECT_STATE;
    393 
    394   /*
    395    *  Initialize the set of timers to be inserted by the server.
    396    */
    397   _Chain_Initialize_empty( &_Timer_To_be_inserted );
    398476
    399477  /*
     
    434512   *  We work with the TCB pointer, not the ID, so we need to convert
    435513   *  to a TCB pointer from here out.
    436    *
    437    *  NOTE: Setting the pointer to the Timer Server TCB to a value other than
    438    *        NULL indicates that task-based timer support is initialized.
    439    */
    440   _Timer_Server = (Thread_Control *)_Objects_Get_local_object(
     514   */
     515  ts->thread = (Thread_Control *)_Objects_Get_local_object(
    441516    &_RTEMS_tasks_Information,
    442517    _Objects_Get_index(id)
     
    446521   *  Initialize the timer lists that the server will manage.
    447522   */
    448   _Chain_Initialize_empty( &_Timer_Ticks_chain );
    449   _Chain_Initialize_empty( &_Timer_Seconds_chain );
     523  _Chain_Initialize_empty( &ts->Interval_watchdogs.Chain );
     524  _Chain_Initialize_empty( &ts->TOD_watchdogs.Chain );
    450525
    451526  /*
     
    453528   *  Timer Server wakes up and services the task-based timers.
    454529   */
    455   _Watchdog_Initialize( &_Timer_Server->Timer, _Thread_Delay_ended, id, NULL );
    456   _Watchdog_Initialize( &_Timer_Seconds_timer, _Thread_Delay_ended, id, NULL );
    457 
    458   /*
    459    *  Initialize the pointer to the timer reset method so applications
    460    *  that do not use the Timer Server do not have to pull it in.
    461    */
    462   _Timer_Server_schedule_operation = _Timer_Server_schedule_operation_method;
     530  _Watchdog_Initialize(
     531    &ts->Interval_watchdogs.System_watchdog,
     532    _Thread_Delay_ended,
     533    id,
     534    NULL
     535  );
     536  _Watchdog_Initialize(
     537    &ts->TOD_watchdogs.System_watchdog,
     538    _Thread_Delay_ended,
     539    id,
     540    NULL
     541  );
     542
     543  /*
     544   *  Initialize the pointer to the timer schedule method so applications that
     545   *  do not use the Timer Server do not have to pull it in.
     546   */
     547  ts->schedule_operation = _Timer_server_Schedule_operation_method;
     548
     549  ts->Interval_watchdogs.last_snapshot = _Watchdog_Ticks_since_boot;
     550  ts->TOD_watchdogs.last_snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch();
     551
     552  ts->insert_chain = NULL;
     553  ts->active = false;
     554
     555  /*
     556   * The default timer server is now available.
     557   */
     558  _Timer_server = ts;
    463559
    464560  /*
     
    466562   */
    467563  status = rtems_task_start(
    468     id,                                    /* the id from create */
    469     _Timer_Server_body,                    /* the timer server entry point */
    470     0                                      /* there is no argument */
     564    id,
     565    _Timer_server_Body,
     566    (rtems_task_argument) ts
    471567  );
    472  
     568
    473569  #if defined(RTEMS_DEBUG)
    474570    /*
  • cpukit/rtems/src/timerserverfireafter.c

    r6cc3dfb r6e51c4c  
    5454  Objects_Locations     location;
    5555  ISR_Level             level;
     56  Timer_server_Control *timer_server = _Timer_server;
    5657
    57   if ( !_Timer_Server )
     58  if ( !timer_server )
    5859    return RTEMS_INCORRECT_STATE;
    5960
     
    9394      _ISR_Enable( level );
    9495
    95       /*
    96        * _Timer_Server_schedule_operation != NULL because we checked that
    97        * _Timer_Server was != NULL above.  Both are set at the same time.
    98        */
    99 
    100       (*_Timer_Server_schedule_operation)( the_timer );
     96      (*timer_server->schedule_operation)( timer_server, the_timer );
    10197
    10298      _Thread_Enable_dispatch();
  • cpukit/rtems/src/timerserverfirewhen.c

    r6cc3dfb r6e51c4c  
    5454  Objects_Locations     location;
    5555  rtems_interval        seconds;
     56  Timer_server_Control *timer_server = _Timer_server;
    5657
    57   if ( !_Timer_Server )
     58  if ( !timer_server )
    5859    return RTEMS_INCORRECT_STATE;
    5960
     
    8081      the_timer->Ticker.initial = seconds - _TOD_Seconds_since_epoch();
    8182
    82       /*
    83        * _Timer_Server_schedule_operation != NULL because we checked that
    84        * _Timer_Server was != NULL above.  Both are set at the same time.
    85        */
    86 
    87       (*_Timer_Server_schedule_operation)( the_timer );
     83      (*timer_server->schedule_operation)( timer_server, the_timer );
    8884
    8985      _Thread_Enable_dispatch();
  • testsuites/sptests/ChangeLog

    r6cc3dfb r6e51c4c  
     12009-11-30      Sebastian Huber <Sebastian.Huber@embedded-brains.de>
     2
     3        * sp68/init.c, sp68/Makefile.am, sp68/sp68.doc, sp68/sp68.scn,
     4        spintrcritical17/init.c, spintrcritical17/Makefile.am,
     5        spintrcritical17/spintrcritical17.doc,
     6        spintrcritical17/spintrcritical17.scn: New files.
     7        * Makefile.am, configure.ac: Update for test sp68 and spintrcritical17.
     8        * sp31/task1.c, sp67/init.c: Changes for new timer server
     9        implementation.
     10        * sp52/init.c: The init task must be preemptible to let the timer
     11        server run.
     12
    1132009-11-23      Joel Sherrill <joel.sherrill@oarcorp.com>
    214
  • testsuites/sptests/Makefile.am

    r6cc3dfb r6e51c4c  
    1414    sp40 sp41 sp42 sp43 sp44 sp45 sp46 sp47 sp48 sp49 \
    1515    sp50 sp51 sp52 sp53 sp54 sp55 sp56 sp57 sp58 sp59 \
    16     sp60 sp61 sp62 sp63 sp64 sp65 sp66 sp67 \
     16    sp60 sp61 sp62 sp63 sp64 sp65 sp66 sp67 sp68 \
    1717    spchain spclockget spcoverage spobjgetnext spnotepad01 spprintk spsize \
    1818    spstkalloc spthreadq01 spwatchdog spwkspace \
     
    2222    spintrcritical05 spintrcritical06 spintrcritical07 spintrcritical08 \
    2323    spintrcritical09 spintrcritical10 spintrcritical11 spintrcritical12 \
    24     spintrcritical13 spintrcritical14 spintrcritical15 spintrcritical16
     24    spintrcritical13 spintrcritical14 spintrcritical15 spintrcritical16 \
     25    spintrcritical17
    2526 
    2627DIST_SUBDIRS = $(SUBDIRS) spfatal_support spintrcritical_support
  • testsuites/sptests/configure.ac

    r6cc3dfb r6e51c4c  
    9494sp66/Makefile
    9595sp67/Makefile
     96sp68/Makefile
    9697spchain/Makefile
    9798spclockget/Makefile
     
    125126spintrcritical15/Makefile
    126127spintrcritical16/Makefile
     128spintrcritical17/Makefile
    127129spnotepad01/Makefile
    128130spobjgetnext/Makefile
  • testsuites/sptests/sp31/task1.c

    r6cc3dfb r6e51c4c  
    3434{
    3535  TSR_fired = 1;
     36}
     37
     38static Watchdog_Interval schedule_time( void )
     39{
     40  const Watchdog_Control *watchdog =
     41    &_Timer_server->Interval_watchdogs.System_watchdog;
     42
     43  return watchdog->initial + watchdog->start_time;
    3644}
    3745
     
    106114    info.start_time + info.initial );
    107115  printf( "Timer Server scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
    108     _Timer_Server->Timer.initial + _Timer_Server->Timer.start_time );
     116    schedule_time() );
    109117
    110118  puts( "TA1 - rtems_task_wake_after - 1 second" );
     
    122130    info.start_time + info.initial );
    123131  printf( "Timer Server scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
    124     _Timer_Server->Timer.initial + _Timer_Server->Timer.start_time );
    125   assert(  (info.start_time + info.initial) ==
    126     (_Timer_Server->Timer.initial + _Timer_Server->Timer.start_time) );
     132    schedule_time() );
     133  assert(  (info.start_time + info.initial) == schedule_time() );
    127134
    128135  puts( "TA1 - rtems_task_wake_after - 1 second" );
     
    140147    info.start_time + info.initial );
    141148  printf( "Timer Server scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
    142     _Timer_Server->Timer.initial + _Timer_Server->Timer.start_time );
    143   assert(  (info.start_time + info.initial) ==
    144     (_Timer_Server->Timer.initial + _Timer_Server->Timer.start_time) );
     149    schedule_time() );
     150  assert(  (info.start_time + info.initial) == schedule_time() );
    145151
    146152  puts( "TA1 - rtems_timer_cancel - timer 1" );
  • testsuites/sptests/sp52/init.c

    r6cc3dfb r6e51c4c  
    113113#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
    114114
     115#define CONFIGURE_INIT_TASK_PRIORITY (RTEMS_MINIMUM_PRIORITY + 1)
     116#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
     117
    115118#define CONFIGURE_INIT
    116119#include <rtems/confdefs.h>
  • testsuites/sptests/sp67/init.c

    r6cc3dfb r6e51c4c  
    5555  directive_failed( status, "rtems_timer_create #1" );
    5656
     57  /* Manipulate the time */
     58  _Watchdog_Ticks_since_boot = (Watchdog_Interval) -15;
     59
    5760  /* initiate timer server */
    5861  puts( "Init - Initiate the timer server" );
     
    6467  directive_failed( status, "rtems_timer_initiate_server" );
    6568
     69  /* Give the timer server some time to initialize */
    6670  status = rtems_task_wake_after( 10 );
    6771  directive_failed( status, "task wake_after" );
     
    6973  status = rtems_timer_server_fire_after(
    7074    timer1,
    71     0xffff,
     75    10,
    7276    TIMER_service_routine,
    7377    (void*) &_timer_passage_1
     
    7579  directive_failed( status, "rtems_timer_server_fire_after" );
    7680
    77   /* Make the timer server think that the ticks has wrapped */
    78   _Timer_Server_ticks_last_time = 100;
    79 
    80   status = rtems_task_wake_after( 10 );
    81   directive_failed( status, "task wake_after" );
    82 
    83   /* Make the timer server think that the ticks has wrapped */
    84   _Timer_Server_ticks_last_time = 200;
    85 
    8681  status = rtems_timer_server_fire_after(
    8782    timer2,
    88     0xffff,
     83    20,
    8984    TIMER_service_routine,
    9085    (void*) &_timer_passage_2
     
    9287  directive_failed( status, "rtems_timer_server_fire_after" );
    9388
    94   status = rtems_task_wake_after( 10 );
     89  status = rtems_task_wake_after( 15 );
    9590  directive_failed( status, "task wake_after" );
    9691
Note: See TracChangeset for help on using the changeset viewer.