Ticket #147: pr147.diff

File pr147.diff, 14.4 KB (added by Joel Sherrill, on 12/03/06 at 13:31:13)

pr147.diff

  • new file c/src/exec/rtems/changes

    - +  
     12001-03-29      Joel Sherrill <joel@OARcorp.com>
     2
     3        * Per PR147 addressed problems when reseting and inserting a timer
     4        into a timer chain that did not honor time passage since the last
     5        time the timer server was scheduled and the new insertion.
     6        * include/rtems/rtems/timer.h, src/timerreset.c, src/timerserver.c,
     7        src/timerserverfireafter.c, src/timerserverfirewhen.c: Broke up
     8        the "reset server" routine into a set of very specific routines
     9        that allowed the server to be unscheduled, timer chains to be
     10        "synchronized" with the current time before inserting a new timer.
     11
  • new file c/src/tests/sptests/changes

    - +  
     12001-03-29      Joel Sherrill <joel@OARcorp.com>
     2
     3        * Per PR147 addressed problems when reseting and inserting a timer
     4        into a timer chain that did not honor time passage since the last
     5        time the timer server was scheduled and the new insertion.
     6        * sp31/sp31.scn, sp31/task1.c: Added test code to detect this case.
     7
  • c/src/exec/rtems/include/rtems/rtems/timer.h

    RCS file: /usr1/CVS/rtems/c/src/exec/rtems/include/rtems/rtems/timer.h,v
    retrieving revision 1.11.4.3
    diff -u -r1.11.4.3 timer.h
     
    135135);
    136136
    137137/*
    138  *  _Timer_Server_reset
    139  *
    140  *  DESCRIPTION:
    141  *
    142  *  This routine resets the timers which determine when the Timer Server
    143  *  will wake up next to service task-based timers.
    144  */
    145 
    146 typedef enum {
    147   TIMER_SERVER_RESET_TICKS,
    148   TIMER_SERVER_RESET_SECONDS
    149 } Timer_Server_reset_mode;
    150 
    151 void _Timer_Server_reset(
    152   Timer_Server_reset_mode  reset_mode
    153 );
    154 
    155 /*
    156138 *  rtems_timer_create
    157139 *
    158140 *  DESCRIPTION:
     
    338320  Objects_Id               id,
    339321  rtems_timer_information *the_info
    340322);
     323
     324/*
     325 *  Macros and routines that expose the mechanisms required to service
     326 *  the Timer Server timer.  These stop the timer, synchronize it with
     327 *  the current time, and restart it.
     328 */
     329
     330extern Watchdog_Control _Timer_Seconds_timer;
     331
     332#define _Timer_Server_stop_ticks_timer() \
     333      _Watchdog_Remove( &_Timer_Server->Timer )
     334
     335#define _Timer_Server_stop_seconds_timer() \
     336      _Watchdog_Remove( &_Timer_Seconds_timer );
     337
     338void _Timer_Server_process_ticks_chain(void);
     339void _Timer_Server_process_seconds_chain(void);
     340
     341#define _Timer_Server_reset_ticks_timer() \
     342   do { \
     343      if ( !_Chain_Is_empty( &_Timer_Ticks_chain ) ) { \
     344        _Watchdog_Insert_ticks( &_Timer_Server->Timer, \
     345           ((Watchdog_Control *)_Timer_Ticks_chain.first)->delta_interval ); \
     346      } \
     347   } while (0)
     348
     349#define _Timer_Server_reset_seconds_timer() \
     350   do { \
     351      if ( !_Chain_Is_empty( &_Timer_Seconds_chain ) ) { \
     352        _Watchdog_Insert_seconds( &_Timer_Seconds_timer, \
     353          ((Watchdog_Control *)_Timer_Seconds_chain.first)->delta_interval ); \
     354      } \
     355   } while (0)
    341356
    342357#ifndef __RTEMS_APPLICATION__
    343358#include <rtems/rtems/timer.inl>
  • c/src/exec/rtems/src/timerreset.c

    RCS file: /usr1/CVS/rtems/c/src/exec/rtems/src/timerreset.c,v
    retrieving revision 1.2.4.1
    diff -u -r1.2.4.1 timerreset.c
     
    5757          _Watchdog_Insert( &_Watchdog_Ticks_chain, &the_timer->Ticker );
    5858          break;
    5959        case TIMER_INTERVAL_ON_TASK:
     60          _Timer_Server_stop_ticks_timer();
    6061          _Watchdog_Remove( &the_timer->Ticker );
     62          _Timer_Server_process_ticks_chain();
    6163          _Watchdog_Insert( &_Timer_Ticks_chain, &the_timer->Ticker );
     64          _Timer_Server_reset_ticks_timer();
    6265          break;
    6366        case TIMER_TIME_OF_DAY:
    6467        case TIMER_TIME_OF_DAY_ON_TASK:
  • c/src/exec/rtems/src/timerserver.c

    RCS file: /usr1/CVS/rtems/c/src/exec/rtems/src/timerserver.c,v
    retrieving revision 1.1.2.3
    diff -u -r1.1.2.3 timerserver.c
     
    4949/*
    5050 *  The timer used to control when the Timer Server wakes up to service
    5151 *  "when" timers.
    52  *
    53  *  NOTE: This should NOT be used outside this file.
    5452 */
    5553
    5654Watchdog_Control _Timer_Seconds_timer;
    5755
    58 /*
    59  *  prototypes for support routines to process the chains
    60  */
    61 
    62 void _Timer_Process_ticks_chain(void);
    63 void _Timer_Process_seconds_chain(void);
    64 
    6556/*PAGE
    6657 *
    6758 *  _Timer_Server_body
     
    9788     */
    9889
    9990      _Thread_Set_state( _Timer_Server, STATES_DELAYING );
    100       _Timer_Server_reset( TIMER_SERVER_RESET_TICKS );
    101       _Timer_Server_reset( TIMER_SERVER_RESET_SECONDS );
     91      _Timer_Server_reset_ticks_timer();
     92      _Timer_Server_reset_seconds_timer();
    10293    _Thread_Enable_dispatch();
    10394
     95    /*
     96     *  At this point, at least one of the timers this task relies
     97     *  upon has fired.  Stop them both while we process any outstanding
     98     *  timers.  Before we block, we will restart them.
     99     */
     100 
     101      _Timer_Server_stop_ticks_timer();
     102      _Timer_Server_stop_seconds_timer();
    104103
    105104    /*
    106105     *  Disable dispatching while processing the timers since we want
     
    110109     */
    111110
    112111    _Thread_Disable_dispatch();
    113       _Timer_Process_ticks_chain();
    114       _Timer_Process_seconds_chain();
     112      _Timer_Server_process_ticks_chain();
     113      _Timer_Server_process_seconds_chain();
    115114  }
    116115}
    117116
     
    244243}
    245244
    246245/*PAGE
    247  *
    248  *  _Timer_Server_reset
    249  *
    250  *  This routine resets the timers which determine when the Timer Server
    251  *  will wake up next to service task-based timers.
    252  *
    253  *  Input parameters:
    254  *    do_ticks - TRUE indicates to process the ticks list
    255  *               FALSE indicates to process the seconds list
    256  *
    257  *  Output parameters:  NONE
    258  */
    259 
    260 void _Timer_Server_reset(
    261   Timer_Server_reset_mode reset_mode
    262 )
    263 {
    264   Watchdog_Interval  units;
    265 
    266   switch ( reset_mode ) {
    267     case TIMER_SERVER_RESET_TICKS:
    268       _Watchdog_Remove( &_Timer_Server->Timer );
    269       _Timer_Process_ticks_chain();
    270       if ( !_Chain_Is_empty( &_Timer_Ticks_chain ) ) {
    271         units = ((Watchdog_Control *)_Timer_Ticks_chain.first)->delta_interval;
    272         _Watchdog_Insert_ticks( &_Timer_Server->Timer, units );
    273       }
    274       break;
    275     case TIMER_SERVER_RESET_SECONDS:
    276       _Watchdog_Remove(  &_Timer_Seconds_timer );
    277       _Timer_Process_seconds_chain();
    278       if ( !_Chain_Is_empty( &_Timer_Seconds_chain ) ) {
    279         units = ((Watchdog_Control *)_Timer_Seconds_chain.first)->delta_interval;
    280         _Watchdog_Insert_seconds( &_Timer_Seconds_timer, units );
    281       }
    282       break;
    283   }
    284 }
    285 
    286 /*PAGE
    287246 *
    288  *  _Timer_Server_Process_ticks_chain
     247 *  _Timer_Server_process_ticks_chain
    289248 *
    290249 *  This routine is responsible for adjusting the list of task-based
    291250 *  interval timers to reflect the passage of time.
     
    295254 *  Output parameters:  NONE
    296255 */
    297256
    298 void _Timer_Process_ticks_chain(void)
     257void _Timer_Server_process_ticks_chain(void)
    299258{
    300259  Watchdog_Interval snapshot;
    301260  Watchdog_Interval ticks;
     
    312271
    313272/*PAGE
    314273 *
    315  *  _Timer_Server_Process_seconds_chain
     274 *  _Timer_Server_process_seconds_chain
    316275 *
    317276 *  This routine is responsible for adjusting the list of task-based
    318277 *  time of day timers to reflect the passage of time.
     
    322281 *  Output parameters:  NONE
    323282 */
    324283
    325 void _Timer_Process_seconds_chain(void)
     284void _Timer_Server_process_seconds_chain(void)
    326285{
    327286  Watchdog_Interval snapshot;
    328287  Watchdog_Interval ticks;
  • c/src/exec/rtems/src/timerserverfireafter.c

    RCS file: /usr1/CVS/rtems/c/src/exec/rtems/src/timerserverfireafter.c,v
    retrieving revision 1.1.2.1
    diff -u -r1.1.2.1 timerserverfireafter.c
     
    6969      the_timer->the_class = TIMER_INTERVAL_ON_TASK;
    7070      _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
    7171      the_timer->Ticker.initial = ticks;
     72
     73      _Timer_Server_stop_ticks_timer();
     74      _Timer_Server_process_ticks_chain();
    7275      _Watchdog_Insert( &_Timer_Ticks_chain, &the_timer->Ticker );
    73       _Timer_Server_reset( TIMER_SERVER_RESET_TICKS );
     76       _Timer_Server_reset_ticks_timer();
     77
    7478      _Thread_Enable_dispatch();
    7579      return RTEMS_SUCCESSFUL;
    7680  }
  • c/src/exec/rtems/src/timerserverfirewhen.c

    RCS file: /usr1/CVS/rtems/c/src/exec/rtems/src/timerserverfirewhen.c,v
    retrieving revision 1.1.2.1
    diff -u -r1.1.2.1 timerserverfirewhen.c
     
    7777      the_timer->the_class = TIMER_TIME_OF_DAY_ON_TASK;
    7878      _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
    7979      the_timer->Ticker.initial = seconds - _TOD_Seconds_since_epoch;
     80
     81      _Timer_Server_stop_seconds_timer();
     82      _Timer_Server_process_seconds_chain();
    8083      _Watchdog_Insert( &_Timer_Seconds_chain, &the_timer->Ticker );
    81       _Timer_Server_reset( TIMER_SERVER_RESET_SECONDS );
     84       _Timer_Server_reset_seconds_timer();
     85
    8286      _Thread_Enable_dispatch();
    8387      return RTEMS_SUCCESSFUL;
    8488  }
  • c/src/tests/sptests/sp31/sp31.scn

    RCS file: /usr1/CVS/rtems/c/src/tests/sptests/sp31/sp31.scn,v
    retrieving revision 1.1.2.1
    diff -u -r1.1.2.1 sp31.scn
     
    11*** TEST 31 ***
    22INIT - rtems_timer_create - creating timer 1
    33INIT - timer 1 has id (0x14010001)
     4INIT - rtems_timer_create - creating timer 2
     5INIT - timer 2 has id (0x14010002)
    46TA1 - rtems_timer_ident - identing timer 1
    57TA1 - timer 1 has id (0x14010001)
    6 TA1 - rtems_clock_get - 09:00:00   12/31/1988
     8TA1 - rtems_timer_ident - identing timer 2
     9TA1 - timer 2 has id (0x14010002)
     10TA1 - rtems_timer_server_fire_after - 1 second
     11TA1 - rtems_task_wake_after - 1/2 second
     12TA1 - rtems_timer_server_fire_after - timer 2 in 1/2 second
     13TA1 - rtems_timer_cancel - timer 1
     14TA1 - rtems_timer_cancel - timer 2
     15TA1 - rtems_timer_server_fire_after - timer 1 in 30 seconds
     16TA1 - rtems_timer_server_fire_after - timer 2 in 60 seconds
     17Timer 1 scheduled for 3050 ticks since boot
     18Timer Server scheduled for 3050 ticks since boot
     19TA1 - rtems_task_wake_after - 1 second
     20TA1 - rtems_timer_server_fire_after - timer 2 in 60 seconds
     21Timer 1 scheduled for 3050 ticks since boot
     22Timer Server scheduled for 3050 ticks since boot
     23TA1 - rtems_task_wake_after - 1 second
     24TA1 - rtems_timer_server_fire_after - timer 2 in 60 seconds
     25Timer 1 scheduled for 3050 ticks since boot
     26Timer Server scheduled for 3050 ticks since boot
     27TA1 - rtems_timer_cancel - timer 1
     28TA1 - rtems_timer_cancel - timer 2
     29TA1 - rtems_clock_get - 09:00:02   12/31/1988
    730TA1 - rtems_timer_server_fire_after - timer 1 in 3 seconds
    831TA1 - rtems_task_suspend( RTEMS_SELF )
    9 TA1 - rtems_clock_get - 09:00:03   12/31/1988
     32TA1 - rtems_clock_get - 09:00:05   12/31/1988
    1033TA1 - rtems_timer_server_fire_after - timer 1 in 3 seconds
    1134TA1 - rtems_task_wake_after - 1 second
    12 TA1 - rtems_clock_get - 09:00:04   12/31/1988
     35TA1 - rtems_clock_get - 09:00:06   12/31/1988
    1336TA1 - rtems_timer_reset - timer 1
    1437TA1 - rtems_task_suspend( RTEMS_SELF )
    15 TA1 - rtems_clock_get - 09:00:07   12/31/1988
     38TA1 - rtems_clock_get - 09:00:09   12/31/1988
    1639<pause>
    1740TA1 - rtems_timer_server_fire_after - timer 1 in 3 seconds
    1841TA1 - rtems_timer_cancel - timer 1
     
    2649TA1 - rtems_timer_cancel - timer 1
    2750TA1 - rtems_task_wake_after - YIELD (only task at priority)
    2851TA1 - timer_deleting - timer 1
    29 *** END OF TEST 31 ***
     52*** END OF TEST 31 *** 
  • c/src/tests/sptests/sp31/task1.c

    RCS file: /usr1/CVS/rtems/c/src/tests/sptests/sp31/task1.c,v
    retrieving revision 1.1.2.2
    diff -u -r1.1.2.2 task1.c
     
    1515 *  found in the file LICENSE in this distribution or at
    1616 *  http://www.OARcorp.com/rtems/license.html.
    1717 *
    18  *  $Id: task1.c,v 1.1.2.2 2002/01/29 18:20:46 joel Exp $
     18 *  $Id: task1.c,v 1.3 2002/01/29 18:20:59 joel Exp $
    1919 */
    2020
    2121#include "system.h"
    2222
     23volatile int TSR_fired;
     24
     25rtems_timer_service_routine Should_not_fire_TSR(
     26  rtems_id  ignored_id,
     27  void     *ignored_address
     28)
     29{
     30  TSR_fired = 1;
     31}
     32
    2333rtems_task Task_1(
    2434  rtems_task_argument argument
    2535)
     
    4252  directive_failed( status, "rtems_timer_ident" );
    4353  printf( "TA1 - timer 2 has id (0x%x)\n", tmid2 );
    4454
     55/* make sure insertion does not unintentionally fire a timer per PR147 */
     56
     57  TSR_fired = 0;
     58
     59  puts( "TA1 - rtems_timer_server_fire_after - 1 second" );
     60  status = rtems_timer_server_fire_after(
     61    tmid, TICKS_PER_SECOND, Should_not_fire_TSR, NULL );
     62  directive_failed( status, "rtems_timer_server_fire_after" );
     63
     64  puts( "TA1 - rtems_task_wake_after - 1/2 second" );
     65  status = rtems_task_wake_after( TICKS_PER_SECOND / 2 );
     66  directive_failed( status, "rtems_timer_server_fire_after" );
     67
     68  directive_failed( status, "rtems_timer_server_fire_after" );
     69  puts( "TA1 - rtems_timer_server_fire_after - timer 2 in 1/2 second" );
     70  status = rtems_timer_server_fire_after(
     71    tmid2, TICKS_PER_SECOND / 2, Should_not_fire_TSR, NULL );
     72  directive_failed( status, "rtems_timer_server_fire_after" );
     73
     74  if ( TSR_fired ) {
     75    puts( "TA1 - TSR fired and should not have!" );
     76    exit(1);
     77  }
     78
     79  puts( "TA1 - rtems_timer_cancel - timer 1" );
     80  status = rtems_timer_cancel( tmid );
     81  directive_failed( status, "rtems_timer_cancel" );
     82
     83  puts( "TA1 - rtems_timer_cancel - timer 2" );
     84  status = rtems_timer_cancel( tmid2 );
     85  directive_failed( status, "rtems_timer_cancel" );
     86
     87 
    4588/* now check that rescheduling an active timer works OK. */
    4689  puts( "TA1 - rtems_timer_server_fire_after - timer 1 in 30 seconds" );
    4790  status = rtems_timer_server_fire_after(