RTEMS 7.0-rc1
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 (void) the_watchdog;
202 return _Per_CPU_Get_by_index( 0 );
203#endif
204}
205
212static inline void _Watchdog_Set_CPU(
213 Watchdog_Control *the_watchdog,
214 Per_CPU_Control *cpu
215)
216{
217#if defined(RTEMS_SMP)
218 the_watchdog->cpu = cpu;
219#else
220 (void) the_watchdog;
221 (void) cpu;
222#endif
223}
224
233static inline void _Watchdog_Preinitialize(
234 Watchdog_Control *the_watchdog,
235 Per_CPU_Control *cpu
236)
237{
238 _Watchdog_Set_CPU( the_watchdog, cpu );
239 _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
240
241#if defined(RTEMS_DEBUG)
242 the_watchdog->routine = NULL;
243 the_watchdog->expire = 0;
244#endif
245}
246
255static inline void _Watchdog_Initialize(
256 Watchdog_Control *the_watchdog,
258)
259{
260 _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE );
261 the_watchdog->routine = routine;
262}
263
276 Watchdog_Header *header,
277 Watchdog_Control *first,
278 uint64_t now,
279#if defined(RTEMS_SMP)
280 ISR_lock_Control *lock,
281#endif
282 ISR_lock_Context *lock_context
283);
284
285#if defined(RTEMS_SMP)
286 #define _Watchdog_Tickle( header, first, now, lock, lock_context ) \
287 _Watchdog_Do_tickle( header, first, now, lock, lock_context )
288#else
289 #define _Watchdog_Tickle( header, first, now, lock, lock_context ) \
290 _Watchdog_Do_tickle( header, first, now, lock_context )
291#endif
292
304 Watchdog_Header *header,
305 Watchdog_Control *the_watchdog,
306 uint64_t expire
307);
308
319 Watchdog_Header *header,
320 Watchdog_Control *the_watchdog
321);
322
337static inline uint64_t _Watchdog_Cancel(
338 Watchdog_Header *header,
339 Watchdog_Control *the_watchdog,
340 uint64_t now
341)
342{
343 uint64_t expire;
344 uint64_t remaining;
345
346 expire = the_watchdog->expire;
347
348 if ( now < expire ) {
349 remaining = expire - now;
350 } else {
351 remaining = 0;
352 }
353
354 _Watchdog_Remove( header, the_watchdog );
355
356 return remaining;
357}
358
367static inline bool _Watchdog_Is_scheduled(
368 const Watchdog_Control *the_watchdog
369)
370{
371 return _Watchdog_Get_state( the_watchdog ) < WATCHDOG_INACTIVE;
372}
373
386static inline void _Watchdog_Next_first(
387 Watchdog_Header *header,
388 const Watchdog_Control *first
389)
390{
391 RBTree_Node *right;
392
393 /*
394 * This function uses the following properties of red-black trees:
395 *
396 * 1. Every leaf (NULL) is black.
397 *
398 * 2. If a node is red, then both its children are black.
399 *
400 * 3. Every simple path from a node to a descendant leaf contains the same
401 * number of black nodes.
402 *
403 * The first node has no left child. So every path from the first node has
404 * exactly one black node (including leafs). The first node cannot have a
405 * non-leaf black right child. It may have a red right child. In this case
406 * both children must be leafs.
407 */
408 _Assert( header->first == &first->Node.RBTree );
409 _Assert( _RBTree_Left( &first->Node.RBTree ) == NULL );
410 right = _RBTree_Right( &first->Node.RBTree );
411
412 if ( right != NULL ) {
413 _Assert( RTEMS_RB_COLOR( right, Node ) == RTEMS_RB_RED );
414 _Assert( _RBTree_Left( right ) == NULL );
415 _Assert( _RBTree_Right( right ) == NULL );
416 header->first = right;
417 } else {
418 header->first = _RBTree_Parent( &first->Node.RBTree );
419 }
420}
421
425#define WATCHDOG_MAXIMUM_TICKS UINT64_MAX
426
427#define WATCHDOG_NANOSECONDS_PER_SECOND 1000000000
428
437#define WATCHDOG_BITS_FOR_1E9_NANOSECONDS 30
438
445#define WATCHDOG_MAX_SECONDS 0x3ffffffff
446
455static inline bool _Watchdog_Is_valid_timespec(
456 const struct timespec *ts
457)
458{
459 return ts != NULL
460 && (unsigned long) ts->tv_nsec < WATCHDOG_NANOSECONDS_PER_SECOND;
461}
462
471static inline bool _Watchdog_Is_valid_interval_timespec(
472 const struct timespec *ts
473)
474{
475 return _Watchdog_Is_valid_timespec( ts ) && ts->tv_sec >= 0;
476}
477
488static inline const struct timespec * _Watchdog_Future_timespec(
489 struct timespec *now,
490 const struct timespec *delta
491)
492{
493 uint64_t sec;
494
495 if ( !_Watchdog_Is_valid_interval_timespec( delta ) ) {
496 return NULL;
497 }
498
499 sec = (uint64_t) now->tv_sec;
500 sec += (uint64_t) delta->tv_sec;
501 now->tv_nsec += delta->tv_nsec;
502
503 /* We have 2 * (2**63 - 1) + 1 == UINT64_MAX */
504 if ( now->tv_nsec >= WATCHDOG_NANOSECONDS_PER_SECOND ) {
505 now->tv_nsec -= WATCHDOG_NANOSECONDS_PER_SECOND;
506 ++sec;
507 }
508
509 if ( sec <= INT64_MAX ) {
510 now->tv_sec = sec;
511 } else {
512 now->tv_sec = INT64_MAX;
513 }
514
515 return now;
516}
517
526static inline bool _Watchdog_Is_far_future_timespec(
527 const struct timespec *ts
528)
529{
530 return ts->tv_sec > WATCHDOG_MAX_SECONDS;
531}
532
540static inline uint64_t _Watchdog_Ticks_from_seconds(
541 uint32_t seconds
542)
543{
544 uint64_t ticks = seconds;
545
547
548 return ticks;
549}
550
558static inline uint64_t _Watchdog_Ticks_from_timespec(
559 const struct timespec *ts
560)
561{
562 uint64_t ticks;
563
564 _Assert( _Watchdog_Is_valid_timespec( ts ) );
565 _Assert( ts->tv_sec >= 0 );
566 _Assert( !_Watchdog_Is_far_future_timespec( ts ) );
567
568 ticks = (uint64_t) ts->tv_sec;
570 ticks |= (uint32_t) ts->tv_nsec;
571
572 return ticks;
573}
574
582static inline void _Watchdog_Ticks_to_timespec(
583 uint64_t ticks,
584 struct timespec *ts
585)
586{
587 ts->tv_sec = ticks >> WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
588 ts->tv_nsec = ticks & ( ( 1U << WATCHDOG_BITS_FOR_1E9_NANOSECONDS ) - 1 );
589}
590
598static inline uint64_t _Watchdog_Ticks_from_sbintime( int64_t sbt )
599{
600 uint64_t ticks = ( sbt >> 32 ) << WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
601
602 ticks |= ( (uint64_t) 1000000000 * (uint32_t) sbt ) >> 32;
603
604 return ticks;
605}
606
613static inline void _Watchdog_Per_CPU_acquire_critical(
614 Per_CPU_Control *cpu,
615 ISR_lock_Context *lock_context
616)
617{
618 _ISR_lock_Acquire( &cpu->Watchdog.Lock, lock_context );
619#ifndef RTEMS_SMP
620 (void) cpu;
621#endif
622}
623
630static inline void _Watchdog_Per_CPU_release_critical(
631 Per_CPU_Control *cpu,
632 ISR_lock_Context *lock_context
633)
634{
635 _ISR_lock_Release( &cpu->Watchdog.Lock, lock_context );
636#ifndef RTEMS_SMP
637 (void) cpu;
638#endif
639}
640
651static inline uint64_t _Watchdog_Per_CPU_insert_ticks(
652 Watchdog_Control *the_watchdog,
653 Per_CPU_Control *cpu,
655)
656{
657 ISR_lock_Context lock_context;
658 Watchdog_Header *header;
659 uint64_t expire;
660
661 header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ];
662
663 _Watchdog_Set_CPU( the_watchdog, cpu );
664
665 _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
666 expire = ticks + cpu->Watchdog.ticks;
667 _Watchdog_Insert(header, the_watchdog, expire);
668 _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
669 return expire;
670}
671
683static inline uint64_t _Watchdog_Per_CPU_insert(
684 Watchdog_Control *the_watchdog,
685 Per_CPU_Control *cpu,
686 Watchdog_Header *header,
687 uint64_t expire
688)
689{
690 ISR_lock_Context lock_context;
691
692 _Watchdog_Set_CPU( the_watchdog, cpu );
693
694 _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
695 _Watchdog_Insert( header, the_watchdog, expire );
696 _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
697 return expire;
698}
699
707static inline void _Watchdog_Per_CPU_remove(
708 Watchdog_Control *the_watchdog,
709 Per_CPU_Control *cpu,
710 Watchdog_Header *header
711)
712{
713 ISR_lock_Context lock_context;
714
715 _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
717 header,
718 the_watchdog
719 );
720 _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
721}
722
728static inline void _Watchdog_Per_CPU_remove_ticks(
729 Watchdog_Control *the_watchdog
730)
731{
732 Per_CPU_Control *cpu;
733
734 cpu = _Watchdog_Get_CPU( the_watchdog );
735 _Watchdog_Per_CPU_remove(
736 the_watchdog,
737 cpu,
739 );
740}
741
744#ifdef __cplusplus
745}
746#endif
747
748#endif
749/* 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:437
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:445
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
struct Per_CPU_Control::@4363 Watchdog
Watchdog state for this processor.
uint64_t ticks
Watchdog ticks on this processor used for monotonic clock watchdogs.
Definition: percpu.h:506
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
union Watchdog_Control::@4373 Node
Nodes for the watchdog.
Watchdog_Service_routine_entry routine
This field is the function to invoke.
Definition: watchdog.h:133
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 ...