source: rtems/cpukit/include/rtems/score/watchdogimpl.h @ ccc6695

5
Last change on this file since ccc6695 was ccc6695, checked in by Sebastian Huber <sebastian.huber@…>, on 11/08/18 at 10:50:24

score: Introduce <rtems/score/watchdogticks.h>

Separate the definitions related to watchdog ticks from the watchdog
structures.

Update #3598.

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