source: rtems/cpukit/score/src/watchdoginsert.c @ 9c615b7

4.11
Last change on this file since 9c615b7 was 9c615b7, checked in by Sebastian Huber <sebastian.huber@…>, on 01/04/16 at 08:55:59

score: Fix watchdog insert

Under certain conditions a new watchdog was inserted with a wrong
and very large delta interval due to a wrong iterator update.

Bug was introduced by 1ccbd052910ed16131c74b0d5595c8a94066942d.

Close #2507.

  • Property mode set to 100644
File size: 2.9 KB
Line 
1/**
2 * @file
3 *
4 * @brief Watchdog Insert
5 * @ingroup ScoreWatchdog
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
23static void _Watchdog_Insert_fixup(
24  Watchdog_Header   *header,
25  Watchdog_Control  *the_watchdog,
26  Watchdog_Interval  delta,
27  Watchdog_Control  *next_watchdog,
28  Watchdog_Interval  delta_next
29)
30{
31  const Chain_Node *iterator_tail;
32  Chain_Node       *iterator_node;
33
34  next_watchdog->delta_interval = delta_next - delta;
35
36  iterator_node = _Chain_First( &header->Iterators );
37  iterator_tail = _Chain_Immutable_tail( &header->Iterators );
38
39  while ( iterator_node != iterator_tail ) {
40    Watchdog_Iterator *iterator;
41
42    iterator = (Watchdog_Iterator *) iterator_node;
43
44    if ( iterator->current == &next_watchdog->Node ) {
45      iterator->current = &the_watchdog->Node;
46    }
47
48    iterator_node = _Chain_Next( iterator_node );
49  }
50}
51
52void _Watchdog_Insert_locked(
53  Watchdog_Header  *header,
54  Watchdog_Control *the_watchdog,
55  ISR_lock_Context *lock_context
56)
57{
58  if ( the_watchdog->state == WATCHDOG_INACTIVE ) {
59    Watchdog_Iterator  iterator;
60    Chain_Node        *current;
61    Chain_Node        *next;
62    Watchdog_Interval  delta;
63
64    the_watchdog->state = WATCHDOG_BEING_INSERTED;
65
66    _Chain_Append_unprotected( &header->Iterators, &iterator.Node );
67
68    delta = the_watchdog->initial;
69    current = _Chain_Head( &header->Watchdogs );
70
71    while (
72      ( next = _Chain_Next( current ) ) != _Chain_Tail( &header->Watchdogs )
73    ) {
74      Watchdog_Control  *next_watchdog;
75      Watchdog_Interval  delta_next;
76
77      next_watchdog = (Watchdog_Control *) next;
78      delta_next = next_watchdog->delta_interval;
79
80      if ( delta < delta_next ) {
81        _Watchdog_Insert_fixup(
82          header,
83          the_watchdog,
84          delta,
85          next_watchdog,
86          delta_next
87        );
88        break;
89      }
90
91      iterator.delta_interval = delta - delta_next;
92      iterator.current = next;
93
94      _Watchdog_Flash( header, lock_context );
95
96      if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
97        goto abort_insert;
98      }
99
100      delta = iterator.delta_interval;
101      current = iterator.current;
102    }
103
104    the_watchdog->delta_interval = delta;
105    the_watchdog->start_time = _Watchdog_Ticks_since_boot;
106    _Watchdog_Activate( the_watchdog );
107    _Chain_Insert_unprotected( current, &the_watchdog->Node );
108
109abort_insert:
110
111    _Chain_Extract_unprotected( &iterator.Node );
112  }
113}
114
115void _Watchdog_Insert(
116  Watchdog_Header  *header,
117  Watchdog_Control *the_watchdog
118)
119{
120  ISR_lock_Context lock_context;
121
122  _Watchdog_Acquire( header, &lock_context );
123  _Watchdog_Insert_locked( header, the_watchdog, &lock_context );
124  _Watchdog_Release( header, &lock_context );
125}
Note: See TracBrowser for help on using the repository browser.