RTEMS  5.0.0
watchdogimpl.h
Go to the documentation of this file.
1 
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>
24 #include <rtems/score/assert.h>
25 #include <rtems/score/isrlock.h>
26 #include <rtems/score/percpu.h>
27 #include <rtems/score/rbtreeimpl.h>
28 
29 #include <sys/types.h>
30 #include <sys/timespec.h>
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
44 typedef enum {
49 
54 
59 
67 
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
91 
92 RTEMS_INLINE_ROUTINE void _Watchdog_Header_initialize(
93  Watchdog_Header *header
94 )
95 {
97  header->first = NULL;
98 }
99 
100 RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Header_first(
101  const Watchdog_Header *header
102 )
103 {
104  return (Watchdog_Control *) header->first;
105 }
106 
107 RTEMS_INLINE_ROUTINE void _Watchdog_Header_destroy(
108  Watchdog_Header *header
109 )
110 {
111  /* Do nothing */
112  (void) header;
113 }
114 
120 void _Watchdog_Tick( struct Per_CPU_Control *cpu );
121 
122 RTEMS_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 }
128 
129 RTEMS_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 }
136 
137 RTEMS_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 }
147 
148 RTEMS_INLINE_ROUTINE void _Watchdog_Set_CPU(
149  Watchdog_Control *the_watchdog,
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 }
159 
169  Watchdog_Control *the_watchdog,
170  Per_CPU_Control *cpu
171 )
172 {
173  _Watchdog_Set_CPU( the_watchdog, cpu );
174  _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
175 
176 #if defined(RTEMS_DEBUG)
177  the_watchdog->routine = NULL;
178  the_watchdog->expire = 0;
179 #endif
180 }
181 
188  Watchdog_Control *the_watchdog,
190 )
191 {
192  _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE );
193  the_watchdog->routine = routine;
194 }
195 
196 void _Watchdog_Do_tickle(
197  Watchdog_Header *header,
198  Watchdog_Control *first,
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)
207  #define _Watchdog_Tickle( header, first, now, lock, lock_context ) \
208  _Watchdog_Do_tickle( header, first, now, lock, lock_context )
209 #else
210  #define _Watchdog_Tickle( header, first, now, lock, lock_context ) \
211  _Watchdog_Do_tickle( header, first, now, lock_context )
212 #endif
213 
220 void _Watchdog_Insert(
221  Watchdog_Header *header,
222  Watchdog_Control *the_watchdog,
223  uint64_t expire
224 );
225 
232 void _Watchdog_Remove(
233  Watchdog_Header *header,
234  Watchdog_Control *the_watchdog
235 );
236 
248  Watchdog_Header *header,
249  Watchdog_Control *the_watchdog,
250  uint64_t now
251 )
252 {
253  uint64_t expire;
254  uint64_t remaining;
255 
256  expire = the_watchdog->expire;
257 
258  if ( now < expire ) {
259  remaining = expire - now;
260  } else {
261  remaining = 0;
262  }
263 
264  _Watchdog_Remove( header, the_watchdog );
265 
266  return remaining;
267 }
268 
269 RTEMS_INLINE_ROUTINE bool _Watchdog_Is_scheduled(
270  const Watchdog_Control *the_watchdog
271 )
272 {
273  return _Watchdog_Get_state( the_watchdog ) < WATCHDOG_INACTIVE;
274 }
275 
276 RTEMS_INLINE_ROUTINE void _Watchdog_Next_first(
277  Watchdog_Header *header,
278  Watchdog_Control *the_watchdog
279 )
280 {
281  RBTree_Node *node = _RBTree_Right( &the_watchdog->Node.RBTree );
282 
283  if ( node != NULL ) {
284  RBTree_Node *left;
285 
286  while ( ( left = _RBTree_Left( node ) ) != NULL ) {
287  node = left;
288  }
289 
290  header->first = node;
291  } else {
292  header->first = _RBTree_Parent( &the_watchdog->Node.RBTree );
293  }
294 }
295 
299 #define WATCHDOG_MAXIMUM_TICKS UINT64_MAX
300 
301 #define WATCHDOG_NANOSECONDS_PER_SECOND 1000000000
302 
311 #define WATCHDOG_BITS_FOR_1E9_NANOSECONDS 30
312 
319 #define WATCHDOG_MAX_SECONDS 0x3ffffffff
320 
321 RTEMS_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 
329 RTEMS_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 
336 RTEMS_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 
366 RTEMS_INLINE_ROUTINE bool _Watchdog_Is_far_future_timespec(
367  const struct timespec *ts
368 )
369 {
370  return ts->tv_sec > WATCHDOG_MAX_SECONDS;
371 }
372 
373 RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_seconds(
374  uint32_t seconds
375 )
376 {
377  uint64_t ticks = seconds;
378 
380 
381  return ticks;
382 }
383 
384 RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_timespec(
385  const struct timespec *ts
386 )
387 {
388  uint64_t ticks;
389 
390  _Assert( _Watchdog_Is_valid_timespec( ts ) );
391  _Assert( ts->tv_sec >= 0 );
392  _Assert( !_Watchdog_Is_far_future_timespec( ts ) );
393 
394  ticks = (uint64_t) ts->tv_sec;
396  ticks |= (uint32_t) ts->tv_nsec;
397 
398  return ticks;
399 }
400 
401 RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_sbintime( int64_t sbt )
402 {
403  uint64_t ticks = ( sbt >> 32 ) << WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
404 
405  ticks |= ( (uint64_t) 1000000000 * (uint32_t) sbt ) >> 32;
406 
407  return ticks;
408 }
409 
410 RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_acquire_critical(
411  Per_CPU_Control *cpu,
412  ISR_lock_Context *lock_context
413 )
414 {
415  _ISR_lock_Acquire( &cpu->Watchdog.Lock, lock_context );
416 }
417 
418 RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_release_critical(
419  Per_CPU_Control *cpu,
420  ISR_lock_Context *lock_context
421 )
422 {
423  _ISR_lock_Release( &cpu->Watchdog.Lock, lock_context );
424 }
425 
426 RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Per_CPU_insert_ticks(
427  Watchdog_Control *the_watchdog,
428  Per_CPU_Control *cpu,
429  Watchdog_Interval ticks
430 )
431 {
432  ISR_lock_Context lock_context;
433  Watchdog_Header *header;
434  uint64_t expire;
435 
436  header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ];
437 
438  _Watchdog_Set_CPU( the_watchdog, cpu );
439 
440  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
441  expire = ticks + cpu->Watchdog.ticks;
442  _Watchdog_Insert(header, the_watchdog, expire);
443  _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
444  return expire;
445 }
446 
447 RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Per_CPU_insert(
448  Watchdog_Control *the_watchdog,
449  Per_CPU_Control *cpu,
450  Watchdog_Header *header,
451  uint64_t expire
452 )
453 {
454  ISR_lock_Context lock_context;
455 
456  _Watchdog_Set_CPU( the_watchdog, cpu );
457 
458  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
459  _Watchdog_Insert( header, the_watchdog, expire );
460  _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
461  return expire;
462 }
463 
464 RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove(
465  Watchdog_Control *the_watchdog,
466  Per_CPU_Control *cpu,
467  Watchdog_Header *header
468 )
469 {
470  ISR_lock_Context lock_context;
471 
472  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
474  header,
475  the_watchdog
476  );
477  _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
478 }
479 
480 RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove_ticks(
481  Watchdog_Control *the_watchdog
482 )
483 {
484  Per_CPU_Control *cpu;
485 
486  cpu = _Watchdog_Get_CPU( the_watchdog );
487  _Watchdog_Per_CPU_remove(
488  the_watchdog,
489  cpu,
491  );
492 }
493 
496 #ifdef __cplusplus
497 }
498 #endif
499 
500 #endif
501 /* end of include file */
void _Watchdog_Insert(Watchdog_Header *header, Watchdog_Control *the_watchdog, uint64_t expire)
Inserts a watchdog into the set of scheduled watchdogs according to the specified expiration time...
Definition: watchdoginsert.c:28
RBTree_Node * first
The scheduled watchdog with the earliest expiration time or NULL in case no watchdog is scheduled...
Definition: watchdog.h:78
void _Watchdog_Tick(struct Per_CPU_Control *cpu)
Performs a watchdog tick.
Definition: watchdogtick.c:54
Watchdog_Header Header[PER_CPU_WATCHDOG_COUNT]
Header for watchdogs.
Definition: percpu.h:416
The watchdog is scheduled and a black node in the red-black tree.
Definition: watchdogimpl.h:48
#define _ISR_lock_Acquire(_lock, _context)
Acquires an ISR lock inside an ISR disabled section.
Definition: isrlock.h:278
#define RTEMS_INLINE_ROUTINE
Definition: basedefs.h:65
The watchdog is on a chain of pending watchdogs.
Definition: watchdogimpl.h:65
uint64_t expire
This field is the expiration time point.
Definition: watchdog.h:114
uint64_t ticks
Protects all watchdog operations on this processor.
Definition: percpu.h:409
RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Cancel(Watchdog_Header *header, Watchdog_Control *the_watchdog, uint64_t now)
In case the watchdog is scheduled, then it is removed from the set of scheduled watchdogs.
Definition: watchdogimpl.h:247
The control block used to manage each watchdog timer.
Definition: watchdog.h:87
Red-black tree node.
Definition: rbtree.h:50
ISR lock control.
Definition: isrlock.h:56
Watchdog_Service_routine_entry routine
This field is the function to invoke.
Definition: watchdog.h:111
RBTree_Control Watchdogs
Red-black tree of scheduled watchdogs sorted by expiration time.
Definition: watchdog.h:72
RTEMS_INLINE_ROUTINE void _Watchdog_Initialize(Watchdog_Control *the_watchdog, Watchdog_Service_routine_entry routine)
Initializes a watchdog with a new service routine.
Definition: watchdogimpl.h:187
RBTree_Node RBTree
this field is a red-black tree node structure and allows this to be placed on a red-black tree used t...
Definition: watchdog.h:96
void _Watchdog_Remove(Watchdog_Header *header, Watchdog_Control *the_watchdog)
In case the watchdog is scheduled, then it is removed from the set of scheduled watchdogs.
Definition: watchdogremove.c:28
Per CPU Core Structure.
Definition: percpu.h:290
RTEMS_INLINE_ROUTINE RBTree_Node * _RBTree_Right(const RBTree_Node *the_node)
Return pointer to the right of this node.
Definition: rbtree.h:324
#define _ISR_lock_Release(_lock, _context)
Releases an ISR lock inside an ISR disabled section.
Definition: isrlock.h:301
RTEMS_INLINE_ROUTINE RBTree_Node * _RBTree_Parent(const RBTree_Node *the_node)
Returns a pointer to the parent of this node.
Definition: rbtree.h:281
Watchdog_State
Watchdog states.
Definition: watchdogimpl.h:44
RTEMS_INLINE_ROUTINE void _Watchdog_Preinitialize(Watchdog_Control *the_watchdog, Per_CPU_Control *cpu)
Pre-initializes a watchdog.
Definition: watchdogimpl.h:168
The watchdog is inactive.
Definition: watchdogimpl.h:58
Constants and Structures Associated with Watchdog Timers.
The watchdog is scheduled and a red node in the red-black tree.
Definition: watchdogimpl.h:53
Inlined Routines Associated with Red-Black Trees.
#define WATCHDOG_BITS_FOR_1E9_NANOSECONDS
The bits necessary to store 1000000000 (= WATCHDOG_NANOSECONDS_PER_SECOND) nanoseconds.
Definition: watchdogimpl.h:311
#define WATCHDOG_MAX_SECONDS
The maximum number of seconds representable in the nanoseconds watchdog format.
Definition: watchdogimpl.h:319
uint32_t Watchdog_Interval
Type is used to specify the length of intervals.
Definition: watchdogticks.h:36
The watchdog header to manage scheduled watchdogs.
Definition: watchdog.h:68
RTEMS_INLINE_ROUTINE RBTree_Node * _RBTree_Left(const RBTree_Node *the_node)
Return pointer to the left of this node.
Definition: rbtree.h:297
struct Per_CPU_Control::@3973 Watchdog
Watchdog state for this processor.
union Watchdog_Control::@3983 Node
Nodes for the watchdog.
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:65
Index for tick clock per-CPU watchdog header.
Definition: percpu.h:259
ISR Locks.
RTEMS_INLINE_ROUTINE void _RBTree_Initialize_empty(RBTree_Control *the_rbtree)
Initialize this RBTree as empty.
Definition: rbtree.h:387
Watchdog_Service_routine(* Watchdog_Service_routine_entry)(Watchdog_Control *)
Pointer to a watchdog service routine.
Definition: watchdog.h:63
#define NULL
Requests a GPIO pin group configuration.
Definition: bestcomm_api.h:77