source: rtems/cpukit/score/src/watchdogtickle.c @ 54cf0e34

4.115
Last change on this file since 54cf0e34 was 54cf0e34, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 10, 2015 at 2:19:48 PM

score: Add Watchdog_Header

This type is intended to encapsulate all state to manage a watchdog
chain.

Update #2307.

  • Property mode set to 100644
File size: 3.3 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreWatchdog
5 * @brief Watchdog Tickle
6 */
7 
8/*
9 *  COPYRIGHT (c) 1989-1999.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/score/watchdogimpl.h>
22#include <rtems/score/isrlevel.h>
23
24void _Watchdog_Tickle(
25  Watchdog_Header *header
26)
27{
28  ISR_Level level;
29  Watchdog_Control *the_watchdog;
30  Watchdog_States  watchdog_state;
31
32  /*
33   * See the comment in watchdoginsert.c and watchdogadjust.c
34   * about why it's safe not to declare header a pointer to
35   * volatile data - till, 2003/7
36   */
37
38  _ISR_Disable( level );
39
40  if ( _Watchdog_Is_empty( header ) )
41    goto leave;
42
43  the_watchdog = _Watchdog_First( header );
44
45  /*
46   * For some reason, on rare occasions the_watchdog->delta_interval
47   * of the head of the watchdog chain is 0.  Before this test was
48   * added, on these occasions an event (which usually was supposed
49   * to have a timeout of 1 tick would have a delta_interval of 0, which
50   * would be decremented to 0xFFFFFFFF by the unprotected
51   * "the_watchdog->delta_interval--;" operation.
52   * This would mean the event would not timeout, and also the chain would
53   * be blocked, because a timeout with a very high number would be at the
54   * head, rather than at the end.
55   * The test "if (the_watchdog->delta_interval != 0)"
56   * here prevents this from occuring.
57   *
58   * We were not able to categorically identify the situation that causes
59   * this, but proved it to be true empirically.  So this check causes
60   * correct behaviour in this circumstance.
61   *
62   * The belief is that a race condition exists whereby an event at the head
63   * of the chain is removed (by a pending ISR or higher priority task)
64   * during the _ISR_Flash( level ); in _Watchdog_Insert, but the watchdog
65   * to be inserted has already had its delta_interval adjusted to 0, and
66   * so is added to the head of the chain with a delta_interval of 0.
67   *
68   * Steven Johnson - 12/2005 (gcc-3.2.3 -O3 on powerpc)
69   */
70  if (the_watchdog->delta_interval != 0) {
71    the_watchdog->delta_interval--;
72    if ( the_watchdog->delta_interval != 0 )
73      goto leave;
74  }
75
76  do {
77     watchdog_state = _Watchdog_Remove( the_watchdog );
78
79     _ISR_Enable( level );
80
81     switch( watchdog_state ) {
82       case WATCHDOG_ACTIVE:
83         (*the_watchdog->routine)(
84           the_watchdog->id,
85           the_watchdog->user_data
86         );
87         break;
88
89       case WATCHDOG_INACTIVE:
90         /*
91          *  This state indicates that the watchdog is not on any chain.
92          *  Thus, it is NOT on a chain being tickled.  This case should
93          *  never occur.
94          */
95         break;
96
97       case WATCHDOG_BEING_INSERTED:
98         /*
99          *  This state indicates that the watchdog is in the process of
100          *  BEING inserted on the chain.  Thus, it can NOT be on a chain
101          *  being tickled.  This case should never occur.
102          */
103         break;
104
105       case WATCHDOG_REMOVE_IT:
106         break;
107     }
108
109     _ISR_Disable( level );
110
111     the_watchdog = _Watchdog_First( header );
112   } while ( !_Watchdog_Is_empty( header ) &&
113             (the_watchdog->delta_interval == 0) );
114
115leave:
116   _ISR_Enable(level);
117}
Note: See TracBrowser for help on using the repository browser.