RTEMS 6.1-rc5
Loading...
Searching...
No Matches
watchdogimpl.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
12/*
13 * COPYRIGHT (c) 1989-2004.
14 * On-Line Applications Research Corporation (OAR).
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef _RTEMS_SCORE_WATCHDOGIMPL_H
39#define _RTEMS_SCORE_WATCHDOGIMPL_H
40
43#include <rtems/score/assert.h>
44#include <rtems/score/isrlock.h>
45#include <rtems/score/percpu.h>
47
48#include <sys/types.h>
49#include <sys/timespec.h>
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54
64typedef enum {
69
74
79
87
95#if defined(RTEMS_SMP)
96 #define WATCHDOG_INITIALIZER( routine ) \
97 { \
98 { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \
99 &_Per_CPU_Information[ 0 ].per_cpu, \
100 ( routine ), \
101 0 \
102 }
103#else
104 #define WATCHDOG_INITIALIZER( routine ) \
105 { \
106 { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \
107 ( routine ), \
108 0 \
109 }
110#endif
111
117static inline void _Watchdog_Header_initialize(
118 Watchdog_Header *header
119)
120{
121 _RBTree_Initialize_empty( &header->Watchdogs );
122 header->first = NULL;
123}
124
132static inline Watchdog_Control *_Watchdog_Header_first(
133 const Watchdog_Header *header
134)
135{
136 return (Watchdog_Control *) header->first;
137}
138
144static inline void _Watchdog_Header_destroy(
145 Watchdog_Header *header
146)
147{
148 /* Do nothing */
149 (void) header;
150}
151
157void _Watchdog_Tick( struct Per_CPU_Control *cpu );
158
166static inline Watchdog_State _Watchdog_Get_state(
167 const Watchdog_Control *the_watchdog
168)
169{
170 return (Watchdog_State) RTEMS_RB_COLOR( &the_watchdog->Node.RBTree, Node );
171}
172
179static inline void _Watchdog_Set_state(
180 Watchdog_Control *the_watchdog,
181 Watchdog_State state
182)
183{
184 RTEMS_RB_COLOR( &the_watchdog->Node.RBTree, Node ) = state;
185}
186
194static inline Per_CPU_Control *_Watchdog_Get_CPU(
195 const Watchdog_Control *the_watchdog
196)
197{
198#if defined(RTEMS_SMP)
199 return the_watchdog->cpu;
200#else
201 return _Per_CPU_Get_by_index( 0 );
202#endif
203}
204
211static inline void _Watchdog_Set_CPU(
212 Watchdog_Control *the_watchdog,
213 Per_CPU_Control *cpu
214)
215{
216#if defined(RTEMS_SMP)
217 the_watchdog->cpu = cpu;
218#else
219 (void) cpu;
220#endif
221}
222
231static inline void _Watchdog_Preinitialize(
232 Watchdog_Control *the_watchdog,
233 Per_CPU_Control *cpu
234)
235{
236 _Watchdog_Set_CPU( the_watchdog, cpu );
237 _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
238
239#if defined(RTEMS_DEBUG)
240 the_watchdog->routine = NULL;
241 the_watchdog->expire = 0;
242#endif
243}
244
253static inline void _Watchdog_Initialize(
254 Watchdog_Control *the_watchdog,
256)
257{
258 _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE );
259 the_watchdog->routine = routine;
260}
261
274 Watchdog_Header *header,
275 Watchdog_Control *first,
276 uint64_t now,
277#if defined(RTEMS_SMP)
278 ISR_lock_Control *lock,
279#endif
280 ISR_lock_Context *lock_context
281);
282
283#if defined(RTEMS_SMP)
284 #define _Watchdog_Tickle( header, first, now, lock, lock_context ) \
285 _Watchdog_Do_tickle( header, first, now, lock, lock_context )
286#else
287 #define _Watchdog_Tickle( header, first, now, lock, lock_context ) \
288 _Watchdog_Do_tickle( header, first, now, lock_context )
289#endif
290
302 Watchdog_Header *header,
303 Watchdog_Control *the_watchdog,
304 uint64_t expire
305);
306
317 Watchdog_Header *header,
318 Watchdog_Control *the_watchdog
319);
320
335static inline uint64_t _Watchdog_Cancel(
336 Watchdog_Header *header,
337 Watchdog_Control *the_watchdog,
338 uint64_t now
339)
340{
341 uint64_t expire;
342 uint64_t remaining;
343
344 expire = the_watchdog->expire;
345
346 if ( now < expire ) {
347 remaining = expire - now;
348 } else {
349 remaining = 0;
350 }
351
352 _Watchdog_Remove( header, the_watchdog );
353
354 return remaining;
355}
356
365static inline bool _Watchdog_Is_scheduled(
366 const Watchdog_Control *the_watchdog
367)
368{
369 return _Watchdog_Get_state( the_watchdog ) < WATCHDOG_INACTIVE;
370}
371
384static inline void _Watchdog_Next_first(
385 Watchdog_Header *header,
386 const Watchdog_Control *first
387)
388{
389 RBTree_Node *right;
390
391 /*
392 * This function uses the following properties of red-black trees:
393 *
394 * 1. Every leaf (NULL) is black.
395 *
396 * 2. If a node is red, then both its children are black.
397 *
398 * 3. Every simple path from a node to a descendant leaf contains the same
399 * number of black nodes.
400 *
401 * The first node has no left child. So every path from the first node has
402 * exactly one black node (including leafs). The first node cannot have a
403 * non-leaf black right child. It may have a red right child. In this case
404 * both children must be leafs.
405 */
406 _Assert( header->first == &first->Node.RBTree );
407 _Assert( _RBTree_Left( &first->Node.RBTree ) == NULL );
408 right = _RBTree_Right( &first->Node.RBTree );
409
410 if ( right != NULL ) {
411 _Assert( RTEMS_RB_COLOR( right, Node ) == RTEMS_RB_RED );
412 _Assert( _RBTree_Left( right ) == NULL );
413 _Assert( _RBTree_Right( right ) == NULL );
414 header->first = right;
415 } else {
416 header->first = _RBTree_Parent( &first->Node.RBTree );
417 }
418}
419
423#define WATCHDOG_MAXIMUM_TICKS UINT64_MAX
424
425#define WATCHDOG_NANOSECONDS_PER_SECOND 1000000000
426
435#define WATCHDOG_BITS_FOR_1E9_NANOSECONDS 30
436
443#define WATCHDOG_MAX_SECONDS 0x3ffffffff
444
453static inline bool _Watchdog_Is_valid_timespec(
454 const struct timespec *ts
455)
456{
457 return ts != NULL
458 && (unsigned long) ts->tv_nsec < WATCHDOG_NANOSECONDS_PER_SECOND;
459}
460
469static inline bool _Watchdog_Is_valid_interval_timespec(
470 const struct timespec *ts
471)
472{
473 return _Watchdog_Is_valid_timespec( ts ) && ts->tv_sec >= 0;
474}
475
486static inline const struct timespec * _Watchdog_Future_timespec(
487 struct timespec *now,
488 const struct timespec *delta
489)
490{
491 uint64_t sec;
492
493 if ( !_Watchdog_Is_valid_interval_timespec( delta ) ) {
494 return NULL;
495 }
496
497 sec = (uint64_t) now->tv_sec;
498 sec += (uint64_t) delta->tv_sec;
499 now->tv_nsec += delta->tv_nsec;
500
501 /* We have 2 * (2**63 - 1) + 1 == UINT64_MAX */
502 if ( now->tv_nsec >= WATCHDOG_NANOSECONDS_PER_SECOND ) {
503 now->tv_nsec -= WATCHDOG_NANOSECONDS_PER_SECOND;
504 ++sec;
505 }
506
507 if ( sec <= INT64_MAX ) {
508 now->tv_sec = sec;
509 } else {
510 now->tv_sec = INT64_MAX;
511 }
512
513 return now;
514}
515
524static inline bool _Watchdog_Is_far_future_timespec(
525 const struct timespec *ts
526)
527{
528 return ts->tv_sec > WATCHDOG_MAX_SECONDS;
529}
530
538static inline uint64_t _Watchdog_Ticks_from_seconds(
539 uint32_t seconds
540)
541{
542 uint64_t ticks = seconds;
543
545
546 return ticks;
547}
548
556static inline uint64_t _Watchdog_Ticks_from_timespec(
557 const struct timespec *ts
558)
559{
560 uint64_t ticks;
561
562 _Assert( _Watchdog_Is_valid_timespec( ts ) );
563 _Assert( ts->tv_sec >= 0 );
564 _Assert( !_Watchdog_Is_far_future_timespec( ts ) );
565
566 ticks = (uint64_t) ts->tv_sec;
568 ticks |= (uint32_t) ts->tv_nsec;
569
570 return ticks;
571}
572
580static inline void _Watchdog_Ticks_to_timespec(
581 uint64_t ticks,
582 struct timespec *ts
583)
584{
585 ts->tv_sec = ticks >> WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
586 ts->tv_nsec = ticks & ( ( 1U << WATCHDOG_BITS_FOR_1E9_NANOSECONDS ) - 1 );
587}
588
596static inline uint64_t _Watchdog_Ticks_from_sbintime( int64_t sbt )
597{
598 uint64_t ticks = ( sbt >> 32 ) << WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
599
600 ticks |= ( (uint64_t) 1000000000 * (uint32_t) sbt ) >> 32;
601
602 return ticks;
603}
604
611static inline void _Watchdog_Per_CPU_acquire_critical(
612 Per_CPU_Control *cpu,
613 ISR_lock_Context *lock_context
614)
615{
616 _ISR_lock_Acquire( &cpu->Watchdog.Lock, lock_context );
617}
618
625static inline void _Watchdog_Per_CPU_release_critical(
626 Per_CPU_Control *cpu,
627 ISR_lock_Context *lock_context
628)
629{
630 _ISR_lock_Release( &cpu->Watchdog.Lock, lock_context );
631}
632
643static inline uint64_t _Watchdog_Per_CPU_insert_ticks(
644 Watchdog_Control *the_watchdog,
645 Per_CPU_Control *cpu,
647)
648{
649 ISR_lock_Context lock_context;
650 Watchdog_Header *header;
651 uint64_t expire;
652
653 header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ];
654
655 _Watchdog_Set_CPU( the_watchdog, cpu );
656
657 _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
658 expire = ticks + cpu->Watchdog.ticks;
659 _Watchdog_Insert(header, the_watchdog, expire);
660 _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
661 return expire;
662}
663
675static inline uint64_t _Watchdog_Per_CPU_insert(
676 Watchdog_Control *the_watchdog,
677 Per_CPU_Control *cpu,
678 Watchdog_Header *header,
679 uint64_t expire
680)
681{
682 ISR_lock_Context lock_context;
683
684 _Watchdog_Set_CPU( the_watchdog, cpu );
685
686 _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
687 _Watchdog_Insert( header, the_watchdog, expire );
688 _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
689 return expire;
690}
691
699static inline void _Watchdog_Per_CPU_remove(
700 Watchdog_Control *the_watchdog,
701 Per_CPU_Control *cpu,
702 Watchdog_Header *header
703)
704{
705 ISR_lock_Context lock_context;
706
707 _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
709 header,
710 the_watchdog
711 );
712 _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
713}
714
720static inline void _Watchdog_Per_CPU_remove_ticks(
721 Watchdog_Control *the_watchdog
722)
723{
724 Per_CPU_Control *cpu;
725
726 cpu = _Watchdog_Get_CPU( the_watchdog );
727 _Watchdog_Per_CPU_remove(
728 the_watchdog,
729 cpu,
731 );
732}
733
736#ifdef __cplusplus
737}
738#endif
739
740#endif
741/* end of include file */
This header file provides the interfaces of the Assert Handler.
This header file provides interfaces of the Watchdog Handler which are used by the implementation and...
#define _Assert(_e)
Assertion similar to assert() controlled via RTEMS_DEBUG instead of NDEBUG and static analysis runs.
Definition: assert.h:96
#define _ISR_lock_Release(_lock, _context)
Releases an ISR lock inside an ISR disabled section.
Definition: isrlock.h:282
#define _ISR_lock_Acquire(_lock, _context)
Acquires an ISR lock inside an ISR disabled section.
Definition: isrlock.h:259
@ PER_CPU_WATCHDOG_TICKS
Index for tick clock per-CPU watchdog header.
Definition: percpu.h:353
Watchdog_State
Watchdog states.
Definition: watchdogimpl.h:64
#define WATCHDOG_BITS_FOR_1E9_NANOSECONDS
The bits necessary to store 1000000000 (= WATCHDOG_NANOSECONDS_PER_SECOND) nanoseconds.
Definition: watchdogimpl.h:435
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:43
void _Watchdog_Remove(Watchdog_Header *header, Watchdog_Control *the_watchdog)
In the case the watchdog is scheduled, then it is removed from the set of scheduled watchdogs.
Definition: watchdogremove.c:43
void _Watchdog_Tick(struct Per_CPU_Control *cpu)
Performs a watchdog tick.
Definition: watchdogtick.c:76
uint32_t Watchdog_Interval
Type is used to specify the length of intervals.
Definition: watchdogticks.h:59
#define WATCHDOG_MAX_SECONDS
The maximum number of seconds representable in the nanoseconds watchdog format.
Definition: watchdogimpl.h:443
void _Watchdog_Do_tickle(Watchdog_Header *header, Watchdog_Control *first, uint64_t now, ISR_lock_Context *lock_context)
Calls the routine of each not expired watchdog control node.
Definition: watchdogtick.c:46
Watchdog_Service_routine(* Watchdog_Service_routine_entry)(Watchdog_Control *)
Pointer to a watchdog service routine.
Definition: watchdog.h:85
@ WATCHDOG_SCHEDULED_BLACK
The watchdog is scheduled and a black node in the red-black tree.
Definition: watchdogimpl.h:68
@ WATCHDOG_INACTIVE
The watchdog is inactive.
Definition: watchdogimpl.h:78
@ WATCHDOG_PENDING
The watchdog is on a chain of pending watchdogs.
Definition: watchdogimpl.h:85
@ WATCHDOG_SCHEDULED_RED
The watchdog is scheduled and a red node in the red-black tree.
Definition: watchdogimpl.h:73
This header file provides the interfaces of the ISR Locks.
This header file provides interfaces of the Red-Black Tree Handler which are only used by the impleme...
This header file provides the interfaces of the Per-CPU Information.
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:94
Per CPU Core Structure.
Definition: percpu.h:384
Watchdog_Header Header[PER_CPU_WATCHDOG_COUNT]
Header for watchdogs.
Definition: percpu.h:513
uint64_t ticks
Watchdog ticks on this processor used for monotonic clock watchdogs.
Definition: percpu.h:506
struct Per_CPU_Control::@4403 Watchdog
Watchdog state for this processor.
Red-black tree node.
Definition: rbtree.h:73
The control block used to manage each watchdog timer.
Definition: watchdog.h:109
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:118
uint64_t expire
This field is the expiration time point.
Definition: watchdog.h:136
Watchdog_Service_routine_entry routine
This field is the function to invoke.
Definition: watchdog.h:133
union Watchdog_Control::@4413 Node
Nodes for the watchdog.
The watchdog header to manage scheduled watchdogs.
Definition: watchdog.h:90
RBTree_Node * first
The scheduled watchdog with the earliest expiration time or NULL in case no watchdog is scheduled.
Definition: watchdog.h:100
RBTree_Control Watchdogs
Red-black tree of scheduled watchdogs sorted by expiration time.
Definition: watchdog.h:94
This header file provides the interfaces of the Watchdog Handler related to watchdog ticks which are ...