source: rtems/cpukit/score/src/watchdog.c @ 60b791ad

4.104.114.84.95
Last change on this file since 60b791ad was 60b791ad, checked in by Joel Sherrill <joel.sherrill@…>, on 02/17/98 at 23:46:28

updated copyright to 1998

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