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

5
Last change on this file since 1d72f03 was 1d72f03, checked in by Sebastian Huber <sebastian.huber@…>, on 06/22/16 at 13:37:13

score: Silence integer conversion warnings

  • Property mode set to 100644
File size: 9.7 KB
RevLine 
[4b48ece0]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
[c499856]16 *  http://www.rtems.org/license/LICENSE.
[4b48ece0]17 */
18
19#ifndef _RTEMS_SCORE_WATCHDOGIMPL_H
20#define _RTEMS_SCORE_WATCHDOGIMPL_H
21
22#include <rtems/score/watchdog.h>
[80fca28]23#include <rtems/score/assert.h>
[6d253941]24#include <rtems/score/isrlock.h>
[90d8567]25#include <rtems/score/percpu.h>
[03b900d]26#include <rtems/score/rbtreeimpl.h>
27
28#include <sys/timespec.h>
[4b48ece0]29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34/**
35 *  @addtogroup ScoreWatchdog
36 *  @{
37 */
38
[0eae7ba9]39/**
[03b900d]40 * @brief Watchdog states.
[1ccbd052]41 */
[03b900d]42typedef enum {
[1ccbd052]43  /**
[03b900d]44   * @brief The watchdog is scheduled and a black node in the red-black tree.
[1ccbd052]45   */
[03b900d]46  WATCHDOG_SCHEDULED_BLACK,
[1ccbd052]47
48  /**
[03b900d]49   * @brief The watchdog is scheduled and a red node in the red-black tree.
[1ccbd052]50   */
[03b900d]51  WATCHDOG_SCHEDULED_RED,
[1ccbd052]52
53  /**
[03b900d]54   * @brief The watchdog is inactive.
[1ccbd052]55   */
[03b900d]56  WATCHDOG_INACTIVE,
[6d253941]57
[54cf0e34]58  /**
[03b900d]59   * @brief The watchdog is on a chain of pending watchdogs.
[1ccbd052]60   *
[03b900d]61   * This state is used by the timer server for example.
[1ccbd052]62   */
[03b900d]63  WATCHDOG_PENDING
64} Watchdog_State;
[4b48ece0]65
66/**
[03b900d]67 * @brief Watchdog initializer for static initialization.
[4b48ece0]68 *
[03b900d]69 * The processor of this watchdog is set to processor with index zero.
[4b48ece0]70 *
[03b900d]71 * @see _Watchdog_Preinitialize().
[4b48ece0]72 */
[03b900d]73#if defined(RTEMS_SMP)
74  #define WATCHDOG_INITIALIZER( routine ) \
75    { \
76      { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \
77      &_Per_CPU_Information[ 0 ].per_cpu, \
78      ( routine ), \
79      0 \
80    }
81#else
82  #define WATCHDOG_INITIALIZER( routine ) \
83    { \
84      { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \
85      ( routine ), \
86      0 \
87    }
88#endif
[6d253941]89
[03b900d]90RTEMS_INLINE_ROUTINE void _Watchdog_Header_initialize(
91  Watchdog_Header *header
[6d253941]92)
93{
[03b900d]94  _RBTree_Initialize_empty( &header->Watchdogs );
95  header->first = NULL;
[6d253941]96}
97
[03b900d]98RTEMS_INLINE_ROUTINE void _Watchdog_Header_destroy(
99  Watchdog_Header *header
[6d253941]100)
101{
[03b900d]102  /* Do nothing */
103  (void) header;
[6d253941]104}
105
[7cd2484]106/**
[90d8567]107 *  @brief Performs a watchdog tick.
[7cd2484]108 *
[90d8567]109 *  @param cpu The processor for this watchdog tick.
[7cd2484]110 */
[03b900d]111void _Watchdog_Tick( struct Per_CPU_Control *cpu );
[a382010c]112
[03b900d]113RTEMS_INLINE_ROUTINE Watchdog_State _Watchdog_Get_state(
114  const Watchdog_Control *the_watchdog
115)
116{
117  return RB_COLOR( &the_watchdog->Node.RBTree, Node );
118}
[4b48ece0]119
[03b900d]120RTEMS_INLINE_ROUTINE void _Watchdog_Set_state(
121  Watchdog_Control *the_watchdog,
122  Watchdog_State    state
123)
124{
125  RB_COLOR( &the_watchdog->Node.RBTree, Node ) = state;
126}
[4b48ece0]127
[03b900d]128RTEMS_INLINE_ROUTINE Per_CPU_Control *_Watchdog_Get_CPU(
129  const Watchdog_Control *the_watchdog
130)
131{
132#if defined(RTEMS_SMP)
133  return the_watchdog->cpu;
134#else
135  return _Per_CPU_Get_by_index( 0 );
136#endif
137}
[4b48ece0]138
[03b900d]139RTEMS_INLINE_ROUTINE void _Watchdog_Set_CPU(
[a382010c]140  Watchdog_Control *the_watchdog,
[03b900d]141  Per_CPU_Control  *cpu
142)
143{
144#if defined(RTEMS_SMP)
145  the_watchdog->cpu = cpu;
146#else
147  (void) cpu;
148#endif
149}
[4b48ece0]150
[80fca28]151/**
152 * @brief Pre-initializes a watchdog.
153 *
154 * This routine must be called before a watchdog is used in any way.  The
155 * exception are statically initialized watchdogs via WATCHDOG_INITIALIZER().
156 *
157 * @param[in] the_watchdog The uninitialized watchdog.
158 */
159RTEMS_INLINE_ROUTINE void _Watchdog_Preinitialize(
[03b900d]160  Watchdog_Control *the_watchdog,
161  Per_CPU_Control  *cpu
[80fca28]162)
163{
[03b900d]164  _Watchdog_Set_CPU( the_watchdog, cpu );
165  _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
166
[80fca28]167#if defined(RTEMS_DEBUG)
168  the_watchdog->routine = NULL;
[03b900d]169  the_watchdog->expire = 0;
[80fca28]170#endif
171}
172
[4b48ece0]173/**
[03b900d]174 * @brief Initializes a watchdog with a new service routine.
175 *
176 * The watchdog must be inactive.
[4b48ece0]177 */
178RTEMS_INLINE_ROUTINE void _Watchdog_Initialize(
179  Watchdog_Control               *the_watchdog,
[03b900d]180  Watchdog_Service_routine_entry  routine
[4b48ece0]181)
182{
[03b900d]183  _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE );
184  the_watchdog->routine = routine;
[4b48ece0]185}
186
[03b900d]187void _Watchdog_Do_tickle(
188  Watchdog_Header  *header,
189  uint64_t          now,
190#if defined(RTEMS_SMP)
191  ISR_lock_Control *lock,
192#endif
193  ISR_lock_Context *lock_context
194);
195
196#if defined(RTEMS_SMP)
197  #define _Watchdog_Tickle( header, now, lock, lock_context ) \
198    _Watchdog_Do_tickle( header, now, lock, lock_context )
199#else
200  #define _Watchdog_Tickle( header, now, lock, lock_context ) \
201    _Watchdog_Do_tickle( header, now, lock_context )
202#endif
203
[4b48ece0]204/**
[03b900d]205 * @brief Inserts a watchdog into the set of scheduled watchdogs according to
206 * the specified expiration time.
207 *
208 * The watchdog must be inactive.
[4b48ece0]209 */
[03b900d]210void _Watchdog_Insert(
211  Watchdog_Header  *header,
212  Watchdog_Control *the_watchdog,
213  uint64_t          expire
214);
[4b48ece0]215
[03b900d]216/**
217 * @brief In case the watchdog is scheduled, then it is removed from the set of
218 * scheduled watchdogs.
219 *
220 * The watchdog must be initialized before this call.
221 */
222void _Watchdog_Remove(
223  Watchdog_Header  *header,
[4b48ece0]224  Watchdog_Control *the_watchdog
[03b900d]225);
[4b48ece0]226
227/**
[03b900d]228 * @brief In case the watchdog is scheduled, then it is removed from the set of
229 * scheduled watchdogs.
230 *
231 * The watchdog must be initialized before this call.
232 *
233 * @retval 0 The now time is greater than or equal to the expiration time of
234 * the watchdog.
235 * @retval other The difference of the now and expiration time.
[4b48ece0]236 */
[03b900d]237RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Cancel(
238  Watchdog_Header  *header,
239  Watchdog_Control *the_watchdog,
240  uint64_t          now
[4b48ece0]241)
242{
[03b900d]243  uint64_t expire;
244  uint64_t remaining;
[4b48ece0]245
[03b900d]246  expire = the_watchdog->expire;
[4b48ece0]247
[03b900d]248  if ( now < expire ) {
249    remaining = expire - now;
250  } else {
251    remaining = 0;
252  }
[4b48ece0]253
[03b900d]254  _Watchdog_Remove( header, the_watchdog );
[4b48ece0]255
[03b900d]256  return remaining;
[4b48ece0]257}
258
[03b900d]259RTEMS_INLINE_ROUTINE bool _Watchdog_Is_scheduled(
260  const Watchdog_Control *the_watchdog
261)
[4b48ece0]262{
[03b900d]263  return _Watchdog_Get_state( the_watchdog ) < WATCHDOG_INACTIVE;
[4b48ece0]264}
265
[03b900d]266RTEMS_INLINE_ROUTINE void _Watchdog_Next_first(
267  Watchdog_Header  *header,
268  Watchdog_Control *the_watchdog
[4b48ece0]269)
270{
[03b900d]271  RBTree_Node *node = _RBTree_Right( &the_watchdog->Node.RBTree );
[4b48ece0]272
[03b900d]273  if ( node != NULL ) {
274    RBTree_Node *left;
[4b48ece0]275
[03b900d]276    while ( ( left = _RBTree_Left( node ) ) != NULL ) {
277      node = left;
278    }
[4b48ece0]279
[03b900d]280    header->first = node;
281  } else {
282    header->first = _RBTree_Parent( &the_watchdog->Node.RBTree );
283  }
[4b48ece0]284}
285
286/**
[03b900d]287 * @brief The bits necessary to store 1000000000 nanoseconds.
288 *
289 * The expiration time is an unsigned 64-bit integer.  To store absolute
290 * timeouts we use 30 bits (2**30 == 1073741824) for the nanoseconds and 34
291 * bits for the seconds since UNIX Epoch.  This leads to a year 2514 problem.
[4b48ece0]292 */
[03b900d]293#define WATCHDOG_BITS_FOR_1E9_NANOSECONDS 30
[4b48ece0]294
[03b900d]295RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_seconds(
296  uint32_t seconds
[4b48ece0]297)
298{
[03b900d]299  uint64_t ticks = seconds;
[4b48ece0]300
[03b900d]301  ticks <<= WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
[4b48ece0]302
[03b900d]303  return ticks;
[4b48ece0]304}
305
[03b900d]306RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_timespec(
307  const struct timespec *ts
[2903090]308)
309{
[03b900d]310  /*
311   * The seconds are in time_t which is a signed integer.  Thus this cast is
312   * subject to the year 2038 problem in case time_t is a 32-bit integer.
313   */
314  uint64_t ticks = (uint64_t) ts->tv_sec;
315
316  _Assert( ticks < 0x400000000 );
317  _Assert( ts->tv_nsec >= 0 );
318  _Assert( ts->tv_nsec < 1000000000 );
319
320  ticks <<= WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
[1d72f03]321  ticks |= (uint32_t) ts->tv_nsec;
[03b900d]322
323  return ticks;
[2903090]324}
325
[03b900d]326RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_acquire_critical(
327  Per_CPU_Control  *cpu,
328  ISR_lock_Context *lock_context
[2903090]329)
330{
[03b900d]331  _ISR_lock_Acquire( &cpu->Watchdog.Lock, lock_context );
[2903090]332}
333
[03b900d]334RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_release_critical(
335  Per_CPU_Control  *cpu,
336  ISR_lock_Context *lock_context
[4b48ece0]337)
338{
[03b900d]339  _ISR_lock_Release( &cpu->Watchdog.Lock, lock_context );
[4b48ece0]340}
341
[9a78f8a5]342RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Per_CPU_insert_relative(
[03b900d]343  Watchdog_Control *the_watchdog,
344  Per_CPU_Control  *cpu,
345  uint32_t          ticks
[4b48ece0]346)
347{
[03b900d]348  ISR_lock_Context lock_context;
[9a78f8a5]349  uint64_t expire;
[4b48ece0]350
[03b900d]351  _Watchdog_Set_CPU( the_watchdog, cpu );
[4b48ece0]352
[03b900d]353  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
[9a78f8a5]354  expire = cpu->Watchdog.ticks + ticks;
[03b900d]355  _Watchdog_Insert(
356    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
357    the_watchdog,
[9a78f8a5]358    expire
[03b900d]359  );
360  _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
[9a78f8a5]361
362  return expire;
[4b48ece0]363}
364
[03b900d]365RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_insert_absolute(
366  Watchdog_Control *the_watchdog,
367  Per_CPU_Control  *cpu,
368  uint64_t          expire
[4b48ece0]369)
370{
[03b900d]371  ISR_lock_Context lock_context;
[4b48ece0]372
[03b900d]373  _Watchdog_Set_CPU( the_watchdog, cpu );
[4b48ece0]374
[03b900d]375  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
376  _Watchdog_Insert(
377    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ],
378    the_watchdog,
379    expire
380  );
381  _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
[4b48ece0]382}
383
[03b900d]384RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove(
385  Watchdog_Control *the_watchdog,
386  Per_CPU_Control  *cpu,
387  Watchdog_Header  *header
[4b48ece0]388)
389{
[03b900d]390  ISR_lock_Context lock_context;
391
392  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
393  _Watchdog_Remove(
394    header,
395    the_watchdog
396  );
397  _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
[4b48ece0]398}
399
[03b900d]400RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove_relative(
401  Watchdog_Control *the_watchdog
[4b48ece0]402)
403{
[03b900d]404  Per_CPU_Control *cpu;
405
406  cpu = _Watchdog_Get_CPU( the_watchdog );
407  _Watchdog_Per_CPU_remove(
408    the_watchdog,
409    cpu,
410    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ]
411  );
[54cf0e34]412}
413
[03b900d]414RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove_absolute(
415  Watchdog_Control *the_watchdog
[54cf0e34]416)
417{
[03b900d]418  Per_CPU_Control *cpu;
419
420  cpu = _Watchdog_Get_CPU( the_watchdog );
421  _Watchdog_Per_CPU_remove(
422    the_watchdog,
423    cpu,
424    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ]
425  );
[54cf0e34]426}
[4b48ece0]427
[03b900d]428RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_tickle_absolute(
429  Per_CPU_Control *cpu,
430  uint64_t         now
[54cf0e34]431)
432{
[03b900d]433  ISR_lock_Context lock_context;
434
435  _ISR_lock_ISR_disable_and_acquire( &cpu->Watchdog.Lock, &lock_context );
436  _Watchdog_Tickle(
437    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ],
438    now,
439    &cpu->Watchdog.Lock,
440    &lock_context
441  );
[4b48ece0]442}
443
444/** @} */
445
446#ifdef __cplusplus
447}
448#endif
449
450#endif
451/* end of include file */
Note: See TracBrowser for help on using the repository browser.