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

Last change on this file since 1d72f03 was 1d72f03, checked in by Sebastian Huber <sebastian.huber@…>, on Jun 22, 2016 at 1:37:13 PM

score: Silence integer conversion warnings

  • Property mode set to 100644
File size: 9.7 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/assert.h>
24#include <rtems/score/isrlock.h>
25#include <rtems/score/percpu.h>
26#include <rtems/score/rbtreeimpl.h>
27
28#include <sys/timespec.h>
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34/**
35 *  @addtogroup ScoreWatchdog
36 *  @{
37 */
38
39/**
40 * @brief Watchdog states.
41 */
42typedef enum {
43  /**
44   * @brief The watchdog is scheduled and a black node in the red-black tree.
45   */
46  WATCHDOG_SCHEDULED_BLACK,
47
48  /**
49   * @brief The watchdog is scheduled and a red node in the red-black tree.
50   */
51  WATCHDOG_SCHEDULED_RED,
52
53  /**
54   * @brief The watchdog is inactive.
55   */
56  WATCHDOG_INACTIVE,
57
58  /**
59   * @brief The watchdog is on a chain of pending watchdogs.
60   *
61   * This state is used by the timer server for example.
62   */
63  WATCHDOG_PENDING
64} Watchdog_State;
65
66/**
67 * @brief Watchdog initializer for static initialization.
68 *
69 * The processor of this watchdog is set to processor with index zero.
70 *
71 * @see _Watchdog_Preinitialize().
72 */
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
89
90RTEMS_INLINE_ROUTINE void _Watchdog_Header_initialize(
91  Watchdog_Header *header
92)
93{
94  _RBTree_Initialize_empty( &header->Watchdogs );
95  header->first = NULL;
96}
97
98RTEMS_INLINE_ROUTINE void _Watchdog_Header_destroy(
99  Watchdog_Header *header
100)
101{
102  /* Do nothing */
103  (void) header;
104}
105
106/**
107 *  @brief Performs a watchdog tick.
108 *
109 *  @param cpu The processor for this watchdog tick.
110 */
111void _Watchdog_Tick( struct Per_CPU_Control *cpu );
112
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}
119
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}
127
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}
138
139RTEMS_INLINE_ROUTINE void _Watchdog_Set_CPU(
140  Watchdog_Control *the_watchdog,
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}
150
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(
160  Watchdog_Control *the_watchdog,
161  Per_CPU_Control  *cpu
162)
163{
164  _Watchdog_Set_CPU( the_watchdog, cpu );
165  _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
166
167#if defined(RTEMS_DEBUG)
168  the_watchdog->routine = NULL;
169  the_watchdog->expire = 0;
170#endif
171}
172
173/**
174 * @brief Initializes a watchdog with a new service routine.
175 *
176 * The watchdog must be inactive.
177 */
178RTEMS_INLINE_ROUTINE void _Watchdog_Initialize(
179  Watchdog_Control               *the_watchdog,
180  Watchdog_Service_routine_entry  routine
181)
182{
183  _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE );
184  the_watchdog->routine = routine;
185}
186
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
204/**
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.
209 */
210void _Watchdog_Insert(
211  Watchdog_Header  *header,
212  Watchdog_Control *the_watchdog,
213  uint64_t          expire
214);
215
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,
224  Watchdog_Control *the_watchdog
225);
226
227/**
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.
236 */
237RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Cancel(
238  Watchdog_Header  *header,
239  Watchdog_Control *the_watchdog,
240  uint64_t          now
241)
242{
243  uint64_t expire;
244  uint64_t remaining;
245
246  expire = the_watchdog->expire;
247
248  if ( now < expire ) {
249    remaining = expire - now;
250  } else {
251    remaining = 0;
252  }
253
254  _Watchdog_Remove( header, the_watchdog );
255
256  return remaining;
257}
258
259RTEMS_INLINE_ROUTINE bool _Watchdog_Is_scheduled(
260  const Watchdog_Control *the_watchdog
261)
262{
263  return _Watchdog_Get_state( the_watchdog ) < WATCHDOG_INACTIVE;
264}
265
266RTEMS_INLINE_ROUTINE void _Watchdog_Next_first(
267  Watchdog_Header  *header,
268  Watchdog_Control *the_watchdog
269)
270{
271  RBTree_Node *node = _RBTree_Right( &the_watchdog->Node.RBTree );
272
273  if ( node != NULL ) {
274    RBTree_Node *left;
275
276    while ( ( left = _RBTree_Left( node ) ) != NULL ) {
277      node = left;
278    }
279
280    header->first = node;
281  } else {
282    header->first = _RBTree_Parent( &the_watchdog->Node.RBTree );
283  }
284}
285
286/**
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.
292 */
293#define WATCHDOG_BITS_FOR_1E9_NANOSECONDS 30
294
295RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_seconds(
296  uint32_t seconds
297)
298{
299  uint64_t ticks = seconds;
300
301  ticks <<= WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
302
303  return ticks;
304}
305
306RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_timespec(
307  const struct timespec *ts
308)
309{
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;
321  ticks |= (uint32_t) ts->tv_nsec;
322
323  return ticks;
324}
325
326RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_acquire_critical(
327  Per_CPU_Control  *cpu,
328  ISR_lock_Context *lock_context
329)
330{
331  _ISR_lock_Acquire( &cpu->Watchdog.Lock, lock_context );
332}
333
334RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_release_critical(
335  Per_CPU_Control  *cpu,
336  ISR_lock_Context *lock_context
337)
338{
339  _ISR_lock_Release( &cpu->Watchdog.Lock, lock_context );
340}
341
342RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Per_CPU_insert_relative(
343  Watchdog_Control *the_watchdog,
344  Per_CPU_Control  *cpu,
345  uint32_t          ticks
346)
347{
348  ISR_lock_Context lock_context;
349  uint64_t expire;
350
351  _Watchdog_Set_CPU( the_watchdog, cpu );
352
353  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
354  expire = cpu->Watchdog.ticks + ticks;
355  _Watchdog_Insert(
356    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
357    the_watchdog,
358    expire
359  );
360  _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
361
362  return expire;
363}
364
365RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_insert_absolute(
366  Watchdog_Control *the_watchdog,
367  Per_CPU_Control  *cpu,
368  uint64_t          expire
369)
370{
371  ISR_lock_Context lock_context;
372
373  _Watchdog_Set_CPU( the_watchdog, cpu );
374
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 );
382}
383
384RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove(
385  Watchdog_Control *the_watchdog,
386  Per_CPU_Control  *cpu,
387  Watchdog_Header  *header
388)
389{
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 );
398}
399
400RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove_relative(
401  Watchdog_Control *the_watchdog
402)
403{
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  );
412}
413
414RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove_absolute(
415  Watchdog_Control *the_watchdog
416)
417{
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  );
426}
427
428RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_tickle_absolute(
429  Per_CPU_Control *cpu,
430  uint64_t         now
431)
432{
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  );
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.