source: rtems/cpukit/score/src/watchdog.c @ 8bdcfc4

4.104.114.84.95
Last change on this file since 8bdcfc4 was 8d0b7d96, checked in by Joel Sherrill <joel.sherrill@…>, on 12/01/95 at 22:03:55

Insert mode argument to _Watchdog_Insert removed. Now are watchdog timers
are automatically activated upon insertion.

  • Property mode set to 100644
File size: 6.6 KB
RevLine 
[ac7d5ef0]1/*
2 *  Watchdog Handler
3 *
4 *
5 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
6 *  On-Line Applications Research Corporation (OAR).
7 *  All rights assigned to U.S. Government, 1994.
8 *
9 *  This material may be reproduced by or for the U.S. Government pursuant
10 *  to the copyright license under the clause at DFARS 252.227-7013.  This
11 *  notice must appear in all copies of this file and its derivatives.
12 *
13 *  $Id$
14 */
15
16#include <rtems/system.h>
[5e9b32b]17#include <rtems/score/isr.h>
18#include <rtems/score/watchdog.h>
[ac7d5ef0]19
20/*PAGE
21 *
22 *  _Watchdog_Handler_initialization
23 *
24 *  This routine initializes the watchdog handler.
25 *
26 *  Input parameters:  NONE
27 *
28 *  Output parameters: NONE
29 */
30
31void _Watchdog_Handler_initialization( void )
32{
[88d594a]33  _Watchdog_Sync_count = 0;
34  _Watchdog_Sync_level = 0;
[ac7d5ef0]35  _Chain_Initialize_empty( &_Watchdog_Ticks_chain );
36  _Chain_Initialize_empty( &_Watchdog_Seconds_chain );
37}
38
39/*PAGE
40 *
41 *  _Watchdog_Remove
42 *
43 *  The routine removes a watchdog from a delta chain and updates
44 *  the delta counters of the remaining watchdogs.
45 */
46
47Watchdog_States _Watchdog_Remove(
48  Watchdog_Control *the_watchdog
49)
50{
51  ISR_Level                level;
52  Watchdog_States          previous_state;
53  Watchdog_Control *next_watchdog;
54
55  _ISR_Disable( level );
56  previous_state = the_watchdog->state;
57  switch ( previous_state ) {
58    case WATCHDOG_INACTIVE:
59      break;
[88d594a]60
[eedbfd9]61    case WATCHDOG_BEING_INSERTED: 
[88d594a]62   
63      /*
64       *  It is not actually on the chain so just change the state and
65       *  the Insert operation we interrupted will be aborted.
66       */
67      the_watchdog->state = WATCHDOG_INACTIVE;
68      break;
69
[ac7d5ef0]70    case WATCHDOG_ACTIVE:
71    case WATCHDOG_REMOVE_IT:
72
73      the_watchdog->state = WATCHDOG_INACTIVE;
74      next_watchdog = _Watchdog_Next( the_watchdog );
75
76      if ( _Watchdog_Next(next_watchdog) )
77        next_watchdog->delta_interval += the_watchdog->delta_interval;
78
[88d594a]79      if ( _Watchdog_Sync_count )
80        _Watchdog_Sync_level = _ISR_Nest_level;
[ac7d5ef0]81
82      _Chain_Extract_unprotected( &the_watchdog->Node );
83      break;
84  }
85  _ISR_Enable( level );
86  return( previous_state );
87}
88
89/*PAGE
90 *
91 *  _Watchdog_Adjust
92 *
93 *  This routine adjusts the delta chain backward or forward in response
94 *  to a time change.
95 *
96 *  Input parameters:
97 *    header    - pointer to the delta chain to be adjusted
98 *    direction - forward or backward adjustment to delta chain
99 *    units     - units to adjust
100 *
101 *  Output parameters:
102 */
103
104void _Watchdog_Adjust(
105  Chain_Control               *header,
106  Watchdog_Adjust_directions   direction,
[3a4ae6c]107  Watchdog_Interval            units
[ac7d5ef0]108)
109{
110  if ( !_Chain_Is_empty( header ) ) {
111    switch ( direction ) {
112      case WATCHDOG_BACKWARD:
113        _Watchdog_First( header )->delta_interval += units;
114        break;
115      case WATCHDOG_FORWARD:
116        while ( units ) {
117          if ( units < _Watchdog_First( header )->delta_interval ) {
118            _Watchdog_First( header )->delta_interval -= units;
119            break;
120          } else {
121            units -= _Watchdog_First( header )->delta_interval;
122            _Watchdog_First( header )->delta_interval = 1;
123            _Watchdog_Tickle( header );
124            if ( _Chain_Is_empty( header ) )
125              break;
126          }
127        }
128        break;
129    }
130  }
131}
132
133/*PAGE
134 *
135 *  _Watchdog_Insert
136 *
137 *  This routine inserts a watchdog timer on to the appropriate delta
138 *  chain while updating the delta interval counters.
139 */
140
141void _Watchdog_Insert(
142  Chain_Control         *header,
[8d0b7d96]143  Watchdog_Control      *the_watchdog
[ac7d5ef0]144)
145{
[3a4ae6c]146  ISR_Level          level;
147  Watchdog_Control  *after;
148  unsigned32         insert_isr_nest_level;
149  Watchdog_Interval  delta_interval;
[88d594a]150 
151
152  insert_isr_nest_level   = _ISR_Nest_level;
[eedbfd9]153  the_watchdog->state = WATCHDOG_BEING_INSERTED;
[ac7d5ef0]154
[88d594a]155  _Watchdog_Sync_count++;
156restart:
157  delta_interval = the_watchdog->initial;
[ac7d5ef0]158
159  _ISR_Disable( level );
160
161  for ( after = _Watchdog_First( header ) ;
162        ;
[88d594a]163        after = _Watchdog_Next( after ) ) {
[ac7d5ef0]164
[88d594a]165     if ( delta_interval == 0 || !_Watchdog_Next( after ) )
[ac7d5ef0]166       break;
167
[88d594a]168     if ( delta_interval < after->delta_interval ) {
169       after->delta_interval -= delta_interval;
[ac7d5ef0]170       break;
171     }
172
[88d594a]173     delta_interval -= after->delta_interval;
[ac7d5ef0]174
175     /*
[8d0b7d96]176      *  If you experience problems comment out the _ISR_Flash line. 
177      *  3.2.0 was the first release with this critical section redesigned.
[88d594a]178      *  Under certain circumstances, the PREVIOUS critical section algorithm
[8d0b7d96]179      *  used around this flash point allowed interrupts to execute
[88d594a]180      *  which violated the design assumptions.  The critical section
181      *  mechanism used here WAS redesigned to address this.
[ac7d5ef0]182      */
183
184     _ISR_Flash( level );
[88d594a]185
[eedbfd9]186     if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
[88d594a]187       goto exit_insert;
188     }
189
190     if ( _Watchdog_Sync_level > insert_isr_nest_level ) {
191       _Watchdog_Sync_level = insert_isr_nest_level;
192       _ISR_Enable( level );
193       goto restart;
194     }
[ac7d5ef0]195  }
196
[8d0b7d96]197  _Watchdog_Activate( the_watchdog );
[ac7d5ef0]198
[88d594a]199  the_watchdog->delta_interval = delta_interval;
[ac7d5ef0]200
[88d594a]201  _Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node );
[ac7d5ef0]202
[88d594a]203exit_insert:
204  _Watchdog_Sync_level = insert_isr_nest_level;
205  _Watchdog_Sync_count--;
206  _ISR_Enable( level );
[ac7d5ef0]207}
208
209/*PAGE
210 *
211 *  _Watchdog_Tickle
212 *
213 *  This routine decrements the delta counter in response to a tick.  The
214 *  delta chain is updated accordingly.
215 *
216 *  Input parameters:
217 *    header - pointer to the delta chain to be tickled
218 *
219 *  Output parameters: NONE
220 */
221
222void _Watchdog_Tickle(
223  Chain_Control *header
224)
225{
226  Watchdog_Control *the_watchdog;
227
228  if ( _Chain_Is_empty( header ) )
229    return;
230
231  the_watchdog = _Watchdog_First( header );
232  the_watchdog->delta_interval--;
233  if ( the_watchdog->delta_interval != 0 )
234    return;
235
236  do {
237     switch( _Watchdog_Remove( the_watchdog ) ) {
238       case WATCHDOG_ACTIVE:
239         (*the_watchdog->routine)(
240           the_watchdog->id,
241           the_watchdog->user_data
242         );
243         break;
[eedbfd9]244
[ac7d5ef0]245       case WATCHDOG_INACTIVE:
[eedbfd9]246         /*
247          *  This state indicates that the watchdog is not on any chain.
248          *  Thus, it is NOT on a chain being tickled.  This case should
249          *  never occur.
250          */
251         break;
252
253       case WATCHDOG_BEING_INSERTED:
254         /*
255          *  This state indicates that the watchdog is in the process of
256          *  BEING inserted on the chain.  Thus, it can NOT be on a chain
257          *  being tickled.  This case should never occur.
258          */
259         break;
260
[ac7d5ef0]261       case WATCHDOG_REMOVE_IT:
262         break;
263     }
264     the_watchdog = _Watchdog_First( header );
265   } while ( !_Chain_Is_empty( header ) &&
266             (the_watchdog->delta_interval == 0) );
267}
Note: See TracBrowser for help on using the repository browser.