source: rtems/cpukit/score/include/rtems/score/watchdogimpl.h @ 1ccbd052

4.115
Last change on this file since 1ccbd052 was 1ccbd052, checked in by Sebastian Huber <sebastian.huber@…>, on 04/15/15 at 08:53:29

score: Add Watchdog_Iterator

Rewrite the _Watchdog_Insert(), _Watchdog_Remove() and
_Watchdog_Tickle() functions to use iterator items to synchronize
concurrent operations. This makes it possible to get rid of the global
variables _Watchdog_Sync_level and _Watchdog_Sync_count which are a
blocking point for scalable SMP solutions.

Update #2307.

  • Property mode set to 100644
File size: 10.5 KB
Line 
1/**
2 * @file
3 *
4 * @brief Inlined Routines in the Watchdog Handler
5 *
6 * This file contains the static inline implementation of all inlined
7 * routines in the Watchdog Handler.
8 */
9
10/*
11 *  COPYRIGHT (c) 1989-2004.
12 *  On-Line Applications Research Corporation (OAR).
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#ifndef _RTEMS_SCORE_WATCHDOGIMPL_H
20#define _RTEMS_SCORE_WATCHDOGIMPL_H
21
22#include <rtems/score/watchdog.h>
23#include <rtems/score/chainimpl.h>
24#include <rtems/score/isrlock.h>
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
30/**
31 *  @addtogroup ScoreWatchdog
32 *  @{
33 */
34
35/**
36 * @brief Watchdog initializer for static initialization.
37 *
38 * @see _Watchdog_Initialize().
39 */
40#define WATCHDOG_INITIALIZER( routine, id, user_data ) \
41  { \
42    { NULL, NULL }, \
43    WATCHDOG_INACTIVE, \
44    0, 0, 0, 0, \
45    ( routine ), ( id ), ( user_data ) \
46  }
47
48/**
49 * @brief Iterator item to synchronize concurrent insert, remove and tickle
50 * operations.
51 */
52typedef struct {
53  /**
54   * @brief A node for a Watchdog_Header::Iterators chain.
55   */
56  Chain_Node Node;
57
58  /**
59   * @brief The current delta interval of the new watchdog to insert.
60   */
61  Watchdog_Interval delta_interval;
62
63  /**
64   * @brief The current watchdog of the chain on the way to insert the new
65   * watchdog.
66   */
67  Chain_Node *current;
68} Watchdog_Iterator;
69
70/**
71 * @brief Watchdog header.
72 */
73typedef struct {
74  /**
75   * @brief ISR lock to protect this watchdog chain.
76   */
77  ISR_LOCK_MEMBER( Lock )
78
79  /**
80   * @brief The chain of active or transient watchdogs.
81   */
82  Chain_Control Watchdogs;
83
84  /**
85   * @brief Currently active iterators.
86   *
87   * The iterators are registered in _Watchdog_Insert() and updated in case the
88   * watchdog chain changes.
89   */
90  Chain_Control Iterators;
91} Watchdog_Header;
92
93/**
94 *  @brief Watchdog chain which is managed at ticks.
95 *
96 *  This is the watchdog chain which is managed at ticks.
97 */
98SCORE_EXTERN Watchdog_Header _Watchdog_Ticks_header;
99
100/**
101 *  @brief Watchdog chain which is managed at second boundaries.
102 *
103 *  This is the watchdog chain which is managed at second boundaries.
104 */
105SCORE_EXTERN Watchdog_Header _Watchdog_Seconds_header;
106
107RTEMS_INLINE_ROUTINE void _Watchdog_Acquire(
108  Watchdog_Header  *header,
109  ISR_lock_Context *lock_context
110)
111{
112  _ISR_lock_ISR_disable_and_acquire( &header->Lock, lock_context );
113}
114
115RTEMS_INLINE_ROUTINE void _Watchdog_Release(
116  Watchdog_Header  *header,
117  ISR_lock_Context *lock_context
118)
119{
120  _ISR_lock_Release_and_ISR_enable( &header->Lock, lock_context );
121}
122
123RTEMS_INLINE_ROUTINE void _Watchdog_Flash(
124  Watchdog_Header  *header,
125  ISR_lock_Context *lock_context
126)
127{
128  _ISR_lock_Flash( &header->Lock, lock_context );
129}
130
131/**
132 *  @brief Initialize the watchdog handler.
133 *
134 *  This routine initializes the watchdog handler.  The watchdog
135 *  synchronization flag is initialized and the watchdog chains are
136 *  initialized and emptied.
137 */
138void _Watchdog_Handler_initialization( void );
139
140/**
141 *  @brief Removes @a the_watchdog from the watchdog chain.
142 *
143 *  This routine removes @a the_watchdog from the watchdog chain on which
144 *  it resides and returns the state @a the_watchdog timer was in.
145 *
146 *  @param[in] header The watchdog chain.
147 *  @param[in] the_watchdog will be removed
148 *  @retval the state in which @a the_watchdog was in when removed
149 */
150Watchdog_States _Watchdog_Remove (
151  Watchdog_Header  *header,
152  Watchdog_Control *the_watchdog
153);
154
155/**
156 * @brief Actually removes an WATCHDOG_ACTIVE or WATCHDOG_REMOVE_IT watchdog.
157 *
158 * @see _Watchdog_Remove() and _Watchdog_Tickle().
159 */
160void _Watchdog_Remove_it(
161  Watchdog_Header  *header,
162  Watchdog_Control *the_watchdog
163);
164
165/**
166 *  @brief Adjusts the header watchdog chain in the backward direction for
167 *  units ticks.
168 *
169 *  @param[in] header The watchdog chain.
170 *  @param[in] units The units of ticks to adjust.
171 */
172void _Watchdog_Adjust_backward(
173  Watchdog_Header   *header,
174  Watchdog_Interval  units
175);
176
177/**
178 *  @brief Adjusts the header watchdog chain in the forward direction for units
179 *  ticks.
180 *
181 *  This may lead to several _Watchdog_Tickle() invocations.
182 *
183 *  @param[in] header The watchdog chain.
184 *  @param[in] units The units of ticks to adjust.
185 */
186void _Watchdog_Adjust_forward(
187  Watchdog_Header   *header,
188  Watchdog_Interval  units
189);
190
191/**
192 *  @brief Adjusts the @a header watchdog chain in the forward
193 *  @a direction for @a units_arg ticks.
194 *
195 *  This routine adjusts the @a header watchdog chain in the forward
196 *  @a direction for @a units_arg ticks.
197 *
198 *  @param[in] header is the watchdog chain to adjust
199 *  @param[in] units_arg is the number of units to adjust @a header
200 *  @param[in] to_fire is a pointer to an initialized Chain_Control to which
201 *             all watchdog instances that are to be fired will be placed.
202 *
203 *  @note This always adjusts forward.
204 */
205void _Watchdog_Adjust_to_chain(
206  Watchdog_Header   *header,
207  Watchdog_Interval  units_arg,
208  Chain_Control     *to_fire
209
210);
211
212/**
213 *  @brief Inserts @a the_watchdog into the @a header watchdog chain
214 *  for a time of @a units.
215 *
216 *  This routine inserts @a the_watchdog into the @a header watchdog chain
217 *  for a time of @a units.
218 *  Update the delta interval counters.
219 *
220 *  @param[in] header is @a the_watchdog list to insert @a the_watchdog on
221 *  @param[in] the_watchdog is the watchdog to insert
222 */
223void _Watchdog_Insert (
224  Watchdog_Header  *header,
225  Watchdog_Control *the_watchdog
226);
227
228/**
229 *  @brief This routine is invoked at appropriate intervals to update
230 *  the @a header watchdog chain.
231 *
232 *  This routine is invoked at appropriate intervals to update
233 *  the @a header watchdog chain.
234 *  This routine decrements the delta counter in response to a tick.
235 *
236 *  @param[in] header is the watchdog chain to tickle
237 */
238void _Watchdog_Tickle (
239  Watchdog_Header *header
240);
241
242/**
243 * This routine initializes the specified watchdog.  The watchdog is
244 * made inactive, the watchdog id and handler routine are set to the
245 * specified values.
246 */
247
248RTEMS_INLINE_ROUTINE void _Watchdog_Initialize(
249  Watchdog_Control               *the_watchdog,
250  Watchdog_Service_routine_entry  routine,
251  Objects_Id                      id,
252  void                           *user_data
253)
254{
255  the_watchdog->state     = WATCHDOG_INACTIVE;
256  the_watchdog->routine   = routine;
257  the_watchdog->id        = id;
258  the_watchdog->user_data = user_data;
259}
260
261/**
262 * This routine returns true if the watchdog timer is in the ACTIVE
263 * state, and false otherwise.
264 */
265
266RTEMS_INLINE_ROUTINE bool _Watchdog_Is_active(
267  Watchdog_Control *the_watchdog
268)
269{
270
271  return ( the_watchdog->state == WATCHDOG_ACTIVE );
272
273}
274
275/**
276 * This routine activates THE_WATCHDOG timer which is already
277 * on a watchdog chain.
278 */
279
280RTEMS_INLINE_ROUTINE void _Watchdog_Activate(
281  Watchdog_Control *the_watchdog
282)
283{
284
285  the_watchdog->state = WATCHDOG_ACTIVE;
286
287}
288
289/**
290 * This routine deactivates THE_WATCHDOG timer which will remain
291 * on a watchdog chain.
292 */
293
294RTEMS_INLINE_ROUTINE void _Watchdog_Deactivate(
295  Watchdog_Control *the_watchdog
296)
297{
298
299  the_watchdog->state = WATCHDOG_REMOVE_IT;
300
301}
302
303/**
304 * This routine is invoked at each clock tick to update the ticks
305 * watchdog chain.
306 */
307
308RTEMS_INLINE_ROUTINE void _Watchdog_Tickle_ticks( void )
309{
310
311  _Watchdog_Tickle( &_Watchdog_Ticks_header );
312
313}
314
315/**
316 * This routine is invoked at each clock tick to update the seconds
317 * watchdog chain.
318 */
319
320RTEMS_INLINE_ROUTINE void _Watchdog_Tickle_seconds( void )
321{
322
323  _Watchdog_Tickle( &_Watchdog_Seconds_header );
324
325}
326
327/**
328 * This routine inserts THE_WATCHDOG into the ticks watchdog chain
329 * for a time of UNITS ticks.  The INSERT_MODE indicates whether
330 * THE_WATCHDOG is to be activated automatically or later, explicitly
331 * by the caller.
332 */
333
334RTEMS_INLINE_ROUTINE void _Watchdog_Insert_ticks(
335  Watchdog_Control      *the_watchdog,
336  Watchdog_Interval      units
337)
338{
339
340  the_watchdog->initial = units;
341
342  _Watchdog_Insert( &_Watchdog_Ticks_header, the_watchdog );
343
344}
345
346/**
347 * This routine inserts THE_WATCHDOG into the seconds watchdog chain
348 * for a time of UNITS seconds.  The INSERT_MODE indicates whether
349 * THE_WATCHDOG is to be activated automatically or later, explicitly
350 * by the caller.
351 */
352
353RTEMS_INLINE_ROUTINE void _Watchdog_Insert_seconds(
354  Watchdog_Control      *the_watchdog,
355  Watchdog_Interval      units
356)
357{
358
359  the_watchdog->initial = units;
360
361  _Watchdog_Insert( &_Watchdog_Seconds_header, the_watchdog );
362
363}
364
365RTEMS_INLINE_ROUTINE Watchdog_States _Watchdog_Remove_ticks(
366  Watchdog_Control *the_watchdog
367)
368{
369  return _Watchdog_Remove( &_Watchdog_Ticks_header, the_watchdog );
370}
371
372RTEMS_INLINE_ROUTINE Watchdog_States _Watchdog_Remove_seconds(
373  Watchdog_Control *the_watchdog
374)
375{
376  return _Watchdog_Remove( &_Watchdog_Seconds_header, the_watchdog );
377}
378
379/**
380 * This routine resets THE_WATCHDOG timer to its state at INSERT
381 * time.  This routine is valid only on interval watchdog timers
382 * and is used to make an interval watchdog timer fire "every" so
383 * many ticks.
384 */
385
386RTEMS_INLINE_ROUTINE void _Watchdog_Reset_ticks(
387  Watchdog_Control *the_watchdog
388)
389{
390
391  _Watchdog_Remove_ticks( the_watchdog );
392
393  _Watchdog_Insert( &_Watchdog_Ticks_header, the_watchdog );
394
395}
396
397/**
398 * This routine returns a pointer to the watchdog timer following
399 * THE_WATCHDOG on the watchdog chain.
400 */
401
402RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Next(
403  Watchdog_Control *the_watchdog
404)
405{
406
407  return ( (Watchdog_Control *) the_watchdog->Node.next );
408
409}
410
411/**
412 * This routine returns a pointer to the watchdog timer preceding
413 * THE_WATCHDOG on the watchdog chain.
414 */
415
416RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Previous(
417  Watchdog_Control *the_watchdog
418)
419{
420
421  return ( (Watchdog_Control *) the_watchdog->Node.previous );
422
423}
424
425/**
426 * This routine returns a pointer to the first watchdog timer
427 * on the watchdog chain HEADER.
428 */
429
430RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_First(
431  Watchdog_Header *header
432)
433{
434
435  return ( (Watchdog_Control *) _Chain_First( &header->Watchdogs ) );
436
437}
438
439/**
440 * This routine returns a pointer to the last watchdog timer
441 * on the watchdog chain HEADER.
442 */
443
444RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Last(
445  Watchdog_Header *header
446)
447{
448
449  return ( (Watchdog_Control *) _Chain_Last( &header->Watchdogs ) );
450
451}
452
453RTEMS_INLINE_ROUTINE bool _Watchdog_Is_empty(
454  const Watchdog_Header *header
455)
456{
457  return _Chain_Is_empty( &header->Watchdogs );
458}
459
460RTEMS_INLINE_ROUTINE void _Watchdog_Header_initialize(
461  Watchdog_Header *header
462)
463{
464  _ISR_lock_Initialize( &header->Lock, "Watchdog" );
465  _Chain_Initialize_empty( &header->Watchdogs );
466  _Chain_Initialize_empty( &header->Iterators );
467}
468
469/** @} */
470
471#ifdef __cplusplus
472}
473#endif
474
475#endif
476/* end of include file */
Note: See TracBrowser for help on using the repository browser.