source: rtems/c/src/exec/score/src/watchdog.c @ 11ab74e

4.104.114.84.95
Last change on this file since 11ab74e 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
Line 
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>
17#include <rtems/score/isr.h>
18#include <rtems/score/watchdog.h>
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{
33  _Watchdog_Sync_count = 0;
34  _Watchdog_Sync_level = 0;
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;
60
61    case WATCHDOG_BEING_INSERTED: 
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
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
79      if ( _Watchdog_Sync_count )
80        _Watchdog_Sync_level = _ISR_Nest_level;
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,
107  Watchdog_Interval            units
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,
143  Watchdog_Control      *the_watchdog
144)
145{
146  ISR_Level          level;
147  Watchdog_Control  *after;
148  unsigned32         insert_isr_nest_level;
149  Watchdog_Interval  delta_interval;
150 
151
152  insert_isr_nest_level   = _ISR_Nest_level;
153  the_watchdog->state = WATCHDOG_BEING_INSERTED;
154
155  _Watchdog_Sync_count++;
156restart:
157  delta_interval = the_watchdog->initial;
158
159  _ISR_Disable( level );
160
161  for ( after = _Watchdog_First( header ) ;
162        ;
163        after = _Watchdog_Next( after ) ) {
164
165     if ( delta_interval == 0 || !_Watchdog_Next( after ) )
166       break;
167
168     if ( delta_interval < after->delta_interval ) {
169       after->delta_interval -= delta_interval;
170       break;
171     }
172
173     delta_interval -= after->delta_interval;
174
175     /*
176      *  If you experience problems comment out the _ISR_Flash line. 
177      *  3.2.0 was the first release with this critical section redesigned.
178      *  Under certain circumstances, the PREVIOUS critical section algorithm
179      *  used around this flash point allowed interrupts to execute
180      *  which violated the design assumptions.  The critical section
181      *  mechanism used here WAS redesigned to address this.
182      */
183
184     _ISR_Flash( level );
185
186     if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
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     }
195  }
196
197  _Watchdog_Activate( the_watchdog );
198
199  the_watchdog->delta_interval = delta_interval;
200
201  _Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node );
202
203exit_insert:
204  _Watchdog_Sync_level = insert_isr_nest_level;
205  _Watchdog_Sync_count--;
206  _ISR_Enable( level );
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;
244
245       case WATCHDOG_INACTIVE:
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
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.