source: rtems/cpukit/score/src/watchdog.c @ 5e9b32b

4.104.114.84.95
Last change on this file since 5e9b32b was 5e9b32b, checked in by Joel Sherrill <joel.sherrill@…>, on 09/26/95 at 19:27:15

posix support initially added

  • Property mode set to 100644
File size: 6.3 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_REINSERT: 
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  Watchdog_Insert_modes  insert_mode
145)
146{
147  ISR_Level          level;
148  Watchdog_Control  *after;
149  unsigned32         insert_isr_nest_level;
150  Watchdog_Interval  delta_interval;
151 
152
153  insert_isr_nest_level   = _ISR_Nest_level;
154  the_watchdog->state = WATCHDOG_REINSERT;
155
156  _Watchdog_Sync_count++;
157restart:
158  delta_interval = the_watchdog->initial;
159
160  _ISR_Disable( level );
161
162  for ( after = _Watchdog_First( header ) ;
163        ;
164        after = _Watchdog_Next( after ) ) {
165
166     if ( delta_interval == 0 || !_Watchdog_Next( after ) )
167       break;
168
169     if ( delta_interval < after->delta_interval ) {
170       after->delta_interval -= delta_interval;
171       break;
172     }
173
174     delta_interval -= after->delta_interval;
175
176     /*
177      *  If you experience problems comment out the _ISR_Flash line.  This
178      *  (3.2.0) is the first release with this critical section redesigned.
179      *  Under certain circumstances, the PREVIOUS critical section algorithm
180      *  used around this flash point allows interrupts to execute
181      *  which violated the design assumptions.  The critical section
182      *  mechanism used here WAS redesigned to address this.
183      */
184
185     _ISR_Flash( level );
186
187     if ( the_watchdog->state != WATCHDOG_REINSERT ) {
188       goto exit_insert;
189     }
190
191     if ( _Watchdog_Sync_level > insert_isr_nest_level ) {
192       _Watchdog_Sync_level = insert_isr_nest_level;
193       _ISR_Enable( level );
194       goto restart;
195     }
196  }
197
198  if ( insert_mode == WATCHDOG_ACTIVATE_NOW )
199    _Watchdog_Activate( the_watchdog );
200
201  the_watchdog->delta_interval = delta_interval;
202
203  _Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node );
204
205exit_insert:
206  _Watchdog_Sync_level = insert_isr_nest_level;
207  _Watchdog_Sync_count--;
208  _ISR_Enable( level );
209}
210
211/*PAGE
212 *
213 *  _Watchdog_Tickle
214 *
215 *  This routine decrements the delta counter in response to a tick.  The
216 *  delta chain is updated accordingly.
217 *
218 *  Input parameters:
219 *    header - pointer to the delta chain to be tickled
220 *
221 *  Output parameters: NONE
222 */
223
224void _Watchdog_Tickle(
225  Chain_Control *header
226)
227{
228  Watchdog_Control *the_watchdog;
229
230  if ( _Chain_Is_empty( header ) )
231    return;
232
233  the_watchdog = _Watchdog_First( header );
234  the_watchdog->delta_interval--;
235  if ( the_watchdog->delta_interval != 0 )
236    return;
237
238  do {
239     switch( _Watchdog_Remove( the_watchdog ) ) {
240       case WATCHDOG_ACTIVE:
241         (*the_watchdog->routine)(
242           the_watchdog->id,
243           the_watchdog->user_data
244         );
245         break;
246       case WATCHDOG_REINSERT:
247         _Watchdog_Insert( header, the_watchdog, WATCHDOG_ACTIVATE_NOW );
248         break;
249       case WATCHDOG_INACTIVE:
250       case WATCHDOG_REMOVE_IT:
251         break;
252     }
253     the_watchdog = _Watchdog_First( header );
254   } while ( !_Chain_Is_empty( header ) &&
255             (the_watchdog->delta_interval == 0) );
256}
Note: See TracBrowser for help on using the repository browser.