Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:13

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreWatchdog
0007  *
0008  * @brief This header file provides interfaces of the
0009  *   @ref RTEMSScoreWatchdog which are only used by the implementation.
0010  */
0011 
0012 /*
0013  *  COPYRIGHT (c) 1989-2004.
0014  *  On-Line Applications Research Corporation (OAR).
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifndef _RTEMS_SCORE_WATCHDOGIMPL_H
0039 #define _RTEMS_SCORE_WATCHDOGIMPL_H
0040 
0041 #include <rtems/score/watchdog.h>
0042 #include <rtems/score/watchdogticks.h>
0043 #include <rtems/score/assert.h>
0044 #include <rtems/score/isrlock.h>
0045 #include <rtems/score/percpu.h>
0046 #include <rtems/score/rbtreeimpl.h>
0047 
0048 #include <sys/types.h>
0049 #include <sys/timespec.h>
0050 
0051 #ifdef __cplusplus
0052 extern "C" {
0053 #endif
0054 
0055 /**
0056  * @addtogroup RTEMSScoreWatchdog
0057  *
0058  * @{
0059  */
0060 
0061 /**
0062  * @brief Watchdog states.
0063  */
0064 typedef enum {
0065   /**
0066    * @brief The watchdog is scheduled and a black node in the red-black tree.
0067    */
0068   WATCHDOG_SCHEDULED_BLACK,
0069 
0070   /**
0071    * @brief The watchdog is scheduled and a red node in the red-black tree.
0072    */
0073   WATCHDOG_SCHEDULED_RED,
0074 
0075   /**
0076    * @brief The watchdog is inactive.
0077    */
0078   WATCHDOG_INACTIVE,
0079 
0080   /**
0081    * @brief The watchdog is on a chain of pending watchdogs.
0082    *
0083    * This state is used by the timer server for example.
0084    */
0085   WATCHDOG_PENDING
0086 } Watchdog_State;
0087 
0088 /**
0089  * @brief Watchdog initializer for static initialization.
0090  *
0091  * The processor of this watchdog is set to processor with index zero.
0092  *
0093  * @see _Watchdog_Preinitialize().
0094  */
0095 #if defined(RTEMS_SMP)
0096   #define WATCHDOG_INITIALIZER( routine ) \
0097     { \
0098       { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \
0099       &_Per_CPU_Information[ 0 ].per_cpu, \
0100       ( routine ), \
0101       0 \
0102     }
0103 #else
0104   #define WATCHDOG_INITIALIZER( routine ) \
0105     { \
0106       { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \
0107       ( routine ), \
0108       0 \
0109     }
0110 #endif
0111 
0112 /**
0113  * @brief Initializes the watchdog header.
0114  *
0115  * @param[out] header The header to initialize.
0116  */
0117 static inline void _Watchdog_Header_initialize(
0118   Watchdog_Header *header
0119 )
0120 {
0121   _RBTree_Initialize_empty( &header->Watchdogs );
0122   header->first = NULL;
0123 }
0124 
0125 /**
0126  * @brief Returns the first of the watchdog header.
0127  *
0128  * @param header The watchdog header to remove the first of.
0129  *
0130  * @return The first of @a header.
0131  */
0132 static inline Watchdog_Control *_Watchdog_Header_first(
0133   const Watchdog_Header *header
0134 )
0135 {
0136   return (Watchdog_Control *) header->first;
0137 }
0138 
0139 /**
0140  * @brief Destroys the watchdog header.
0141  *
0142  * @param header The watchdog header to destroy.
0143  */
0144 static inline void _Watchdog_Header_destroy(
0145   Watchdog_Header *header
0146 )
0147 {
0148   /* Do nothing */
0149   (void) header;
0150 }
0151 
0152 /**
0153  * @brief Performs a watchdog tick.
0154  *
0155  * @param cpu The processor for this watchdog tick.
0156  */
0157 void _Watchdog_Tick( struct Per_CPU_Control *cpu );
0158 
0159 /**
0160  * @brief Gets the state of the watchdog.
0161  *
0162  * @param the_watchdog The watchdog to get the state of.
0163  *
0164  * @return The RTEMS_RB_COLOR of @a the_watchdog.
0165  */
0166 static inline Watchdog_State _Watchdog_Get_state(
0167   const Watchdog_Control *the_watchdog
0168 )
0169 {
0170   return (Watchdog_State) RTEMS_RB_COLOR( &the_watchdog->Node.RBTree, Node );
0171 }
0172 
0173 /**
0174  * @brief Sets the state of the watchdog.
0175  *
0176  * @param[out] the_watchdog The watchdog to set the state of.
0177  * @param state The state to set the watchdog to.
0178  */
0179 static inline void _Watchdog_Set_state(
0180   Watchdog_Control *the_watchdog,
0181   Watchdog_State    state
0182 )
0183 {
0184   RTEMS_RB_COLOR( &the_watchdog->Node.RBTree, Node ) = state;
0185 }
0186 
0187 /**
0188  * @brief Gets the watchdog's cpu.
0189  *
0190  * @param the_watchdog The watchdog to get the cpu of.
0191  *
0192  * @return The cpu of the watchdog.
0193  */
0194 static inline Per_CPU_Control *_Watchdog_Get_CPU(
0195   const Watchdog_Control *the_watchdog
0196 )
0197 {
0198 #if defined(RTEMS_SMP)
0199   return the_watchdog->cpu;
0200 #else
0201   return _Per_CPU_Get_by_index( 0 );
0202 #endif
0203 }
0204 
0205 /**
0206  * @brief Sets the cpu for the watchdog.
0207  *
0208  * @param[out] the_watchdog The watchdog to set the cpu of.
0209  * @param cpu The cpu to be set as @a the_watchdog's cpu.
0210  */
0211 static inline void _Watchdog_Set_CPU(
0212   Watchdog_Control *the_watchdog,
0213   Per_CPU_Control  *cpu
0214 )
0215 {
0216 #if defined(RTEMS_SMP)
0217   the_watchdog->cpu = cpu;
0218 #else
0219   (void) cpu;
0220 #endif
0221 }
0222 
0223 /**
0224  * @brief Pre-initializes a watchdog.
0225  *
0226  * This routine must be called before a watchdog is used in any way.  The
0227  * exception are statically initialized watchdogs via WATCHDOG_INITIALIZER().
0228  *
0229  * @param[out] the_watchdog The uninitialized watchdog.
0230  */
0231 static inline void _Watchdog_Preinitialize(
0232   Watchdog_Control *the_watchdog,
0233   Per_CPU_Control  *cpu
0234 )
0235 {
0236   _Watchdog_Set_CPU( the_watchdog, cpu );
0237   _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
0238 
0239 #if defined(RTEMS_DEBUG)
0240   the_watchdog->routine = NULL;
0241   the_watchdog->expire = 0;
0242 #endif
0243 }
0244 
0245 /**
0246  * @brief Initializes a watchdog with a new service routine.
0247  *
0248  * The watchdog must be inactive.
0249  *
0250  * @param[out] the_watchdog The watchdog to initialize.
0251  * @param routing The service routine for @a the_watchdog.
0252  */
0253 static inline void _Watchdog_Initialize(
0254   Watchdog_Control               *the_watchdog,
0255   Watchdog_Service_routine_entry  routine
0256 )
0257 {
0258   _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE );
0259   the_watchdog->routine = routine;
0260 }
0261 
0262 /**
0263  * @brief Calls the routine of each not expired watchdog control node.
0264  *
0265  * @param header The watchdog header.
0266  * @param first The first watchdog control node.
0267  * @param now The current time to check the expiration time against.
0268  * @param lock The lock that is released before calling the routine and then
0269  *      acquired after the call.
0270  * @param lock_context The lock context for the release before calling the
0271  *      routine and for the acquire after.
0272  */
0273 void _Watchdog_Do_tickle(
0274   Watchdog_Header  *header,
0275   Watchdog_Control *first,
0276   uint64_t          now,
0277 #if defined(RTEMS_SMP)
0278   ISR_lock_Control *lock,
0279 #endif
0280   ISR_lock_Context *lock_context
0281 );
0282 
0283 #if defined(RTEMS_SMP)
0284   #define _Watchdog_Tickle( header, first, now, lock, lock_context ) \
0285     _Watchdog_Do_tickle( header, first, now, lock, lock_context )
0286 #else
0287   #define _Watchdog_Tickle( header, first, now, lock, lock_context ) \
0288     _Watchdog_Do_tickle( header, first, now, lock_context )
0289 #endif
0290 
0291 /**
0292  * @brief Inserts a watchdog into the set of scheduled watchdogs according to
0293  * the specified expiration time.
0294  *
0295  * The watchdog must be inactive.
0296  *
0297  * @param[in, out] header The set of scheduler watchdogs to insert into.
0298  * @param[in, out] the_watchdog The watchdog to insert.
0299  * @param expire The expiration time for the watchdog.
0300  */
0301 void _Watchdog_Insert(
0302   Watchdog_Header  *header,
0303   Watchdog_Control *the_watchdog,
0304   uint64_t          expire
0305 );
0306 
0307 /**
0308  * @brief In the case the watchdog is scheduled, then it is removed from the set of
0309  * scheduled watchdogs.
0310  *
0311  * The watchdog must be initialized before this call.
0312  *
0313  * @param[in, out] header The scheduled watchdogs.
0314  * @param[in, out] the_watchdog The watchdog to remove.
0315  */
0316 void _Watchdog_Remove(
0317   Watchdog_Header  *header,
0318   Watchdog_Control *the_watchdog
0319 );
0320 
0321 /**
0322  * @brief In the case the watchdog is scheduled, then it is removed from the set of
0323  * scheduled watchdogs.
0324  *
0325  * The watchdog must be initialized before this call.
0326  *
0327  * @param[in, out] header The scheduled watchdogs.
0328  * @param[in, out] the_watchdog The watchdog to remove.
0329  * @param now The current time.
0330  *
0331  * @retval other The difference of the now and expiration time.
0332  * @retval 0 The now time is greater than or equal to the expiration time of
0333  * the watchdog.
0334  */
0335 static inline uint64_t _Watchdog_Cancel(
0336   Watchdog_Header  *header,
0337   Watchdog_Control *the_watchdog,
0338   uint64_t          now
0339 )
0340 {
0341   uint64_t expire;
0342   uint64_t remaining;
0343 
0344   expire = the_watchdog->expire;
0345 
0346   if ( now < expire ) {
0347     remaining = expire - now;
0348   } else {
0349     remaining = 0;
0350   }
0351 
0352   _Watchdog_Remove( header, the_watchdog );
0353 
0354   return remaining;
0355 }
0356 
0357 /**
0358  * @brief Checks if the watchdog is scheduled.
0359  *
0360  * @param the_watchdog The watchdog for the verification.
0361  *
0362  * @retval true The watchdog is scheduled.
0363  * @retval false The watchdog is inactive.
0364  */
0365 static inline bool _Watchdog_Is_scheduled(
0366   const Watchdog_Control *the_watchdog
0367 )
0368 {
0369   return _Watchdog_Get_state( the_watchdog ) < WATCHDOG_INACTIVE;
0370 }
0371 
0372 /**
0373  * @brief Sets the first watchdog of the watchdog collection to the next
0374  * watchdog of the current first watchdog.
0375  *
0376  * This function may be used during watchdog removals, see _Watchdog_Remove()
0377  * and _Watchdog_Tickle().
0378  *
0379  * @param[in, out] header is the watchdog collection header.
0380  *
0381  * @param first is the current first watchdog which should be removed
0382  *   afterwards.
0383  */
0384 static inline void _Watchdog_Next_first(
0385   Watchdog_Header        *header,
0386   const Watchdog_Control *first
0387 )
0388 {
0389   RBTree_Node *right;
0390 
0391   /*
0392    * This function uses the following properties of red-black trees:
0393    *
0394    * 1. Every leaf (NULL) is black.
0395    *
0396    * 2. If a node is red, then both its children are black.
0397    *
0398    * 3. Every simple path from a node to a descendant leaf contains the same
0399    *    number of black nodes.
0400    *
0401    * The first node has no left child.  So every path from the first node has
0402    * exactly one black node (including leafs).  The first node cannot have a
0403    * non-leaf black right child.  It may have a red right child.  In this case
0404    * both children must be leafs.
0405    */
0406   _Assert( header->first == &first->Node.RBTree );
0407   _Assert( _RBTree_Left( &first->Node.RBTree ) == NULL );
0408   right = _RBTree_Right( &first->Node.RBTree );
0409 
0410   if ( right != NULL ) {
0411     _Assert( RTEMS_RB_COLOR( right, Node ) == RTEMS_RB_RED );
0412     _Assert( _RBTree_Left( right ) == NULL );
0413     _Assert( _RBTree_Right( right ) == NULL );
0414     header->first = right;
0415   } else {
0416     header->first = _RBTree_Parent( &first->Node.RBTree );
0417   }
0418 }
0419 
0420 /**
0421  * @brief The maximum watchdog ticks value for the far future.
0422  */
0423 #define WATCHDOG_MAXIMUM_TICKS UINT64_MAX
0424 
0425 #define WATCHDOG_NANOSECONDS_PER_SECOND 1000000000
0426 
0427 /**
0428  * @brief The bits necessary to store 1000000000
0429  * (= WATCHDOG_NANOSECONDS_PER_SECOND) nanoseconds.
0430  *
0431  * The expiration time is an unsigned 64-bit integer.  To store nanoseconds
0432  * timeouts we use 30 bits (2**30 == 1073741824) for the nanoseconds and 34
0433  * bits for the seconds since UNIX Epoch.  This leads to a year 2514 problem.
0434  */
0435 #define WATCHDOG_BITS_FOR_1E9_NANOSECONDS 30
0436 
0437 /**
0438  * @brief The maximum number of seconds representable in the nanoseconds
0439  * watchdog format.
0440  *
0441  * We have 2**34 bits for the seconds part.
0442  */
0443 #define WATCHDOG_MAX_SECONDS 0x3ffffffff
0444 
0445 /**
0446  * @brief Checks if the timespec is a valid timespec for a watchdog.
0447  *
0448  * @param ts The timespec for the verification.
0449  *
0450  * @retval true The timespec is a valid timespec.
0451  * @retval false The timespec is invalid.
0452  */
0453 static inline bool _Watchdog_Is_valid_timespec(
0454   const struct timespec *ts
0455 )
0456 {
0457   return ts != NULL
0458     && (unsigned long) ts->tv_nsec < WATCHDOG_NANOSECONDS_PER_SECOND;
0459 }
0460 
0461 /**
0462  * @brief Checks if the timespec is a valid interval timespec for a watchdog.
0463  *
0464  * @param ts The timespec for the verification.
0465  *
0466  * @retval true The timespec is a valid interval timespec.
0467  * @retval false The timespec is invalid.
0468  */
0469 static inline bool _Watchdog_Is_valid_interval_timespec(
0470   const struct timespec *ts
0471 )
0472 {
0473   return _Watchdog_Is_valid_timespec( ts ) && ts->tv_sec >= 0;
0474 }
0475 
0476 /**
0477  * @brief Adds the delta timespec to the current time if the delta is a valid
0478  * interval timespec.
0479  *
0480  * @param[in, out] now The current time.
0481  * @param delta The delta timespec for the addition.
0482  *
0483  * @retval pointer Pointer to the now timespec.
0484  * @retval NULL @a delta is not a valid interval timespec.
0485  */
0486 static inline const struct timespec * _Watchdog_Future_timespec(
0487   struct timespec       *now,
0488   const struct timespec *delta
0489 )
0490 {
0491   uint64_t sec;
0492 
0493   if ( !_Watchdog_Is_valid_interval_timespec( delta ) ) {
0494     return NULL;
0495   }
0496 
0497   sec = (uint64_t) now->tv_sec;
0498   sec += (uint64_t) delta->tv_sec;
0499   now->tv_nsec += delta->tv_nsec;
0500 
0501   /* We have 2 * (2**63 - 1) + 1 == UINT64_MAX */
0502   if ( now->tv_nsec >= WATCHDOG_NANOSECONDS_PER_SECOND ) {
0503     now->tv_nsec -= WATCHDOG_NANOSECONDS_PER_SECOND;
0504     ++sec;
0505   }
0506 
0507   if ( sec <= INT64_MAX ) {
0508     now->tv_sec = sec;
0509   } else {
0510     now->tv_sec = INT64_MAX;
0511   }
0512 
0513   return now;
0514 }
0515 
0516 /**
0517  * @brief Checks if the timespec is too far in the future.
0518  *
0519  * @param ts The timespec for the verification.
0520  *
0521  * @retval true @a ts is too far in the future.
0522  * @retval false @a ts is not too far in the future.
0523  */
0524 static inline bool _Watchdog_Is_far_future_timespec(
0525   const struct timespec *ts
0526 )
0527 {
0528   return ts->tv_sec > WATCHDOG_MAX_SECONDS;
0529 }
0530 
0531 /**
0532  * @brief Converts the seconds to ticks.
0533  *
0534  * @param seconds The seconds to convert to ticks.
0535  *
0536  * @return @a seconds converted to ticks.
0537  */
0538 static inline uint64_t _Watchdog_Ticks_from_seconds(
0539   uint32_t seconds
0540 )
0541 {
0542   uint64_t ticks = seconds;
0543 
0544   ticks <<= WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
0545 
0546   return ticks;
0547 }
0548 
0549 /**
0550  * @brief Converts the timespec in ticks.
0551  *
0552  * @param ts The timespec to convert to ticks.
0553  *
0554  * @return @a ts converted to ticks.
0555  */
0556 static inline uint64_t _Watchdog_Ticks_from_timespec(
0557   const struct timespec *ts
0558 )
0559 {
0560   uint64_t ticks;
0561 
0562   _Assert( _Watchdog_Is_valid_timespec( ts ) );
0563   _Assert( ts->tv_sec >= 0 );
0564   _Assert( !_Watchdog_Is_far_future_timespec( ts ) );
0565 
0566   ticks = (uint64_t) ts->tv_sec;
0567   ticks <<= WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
0568   ticks |= (uint32_t) ts->tv_nsec;
0569 
0570   return ticks;
0571 }
0572 
0573 /**
0574  * @brief Converts the ticks to timespec.
0575  *
0576  * @param ticks are the ticks to convert.
0577  *
0578  * @param[out] ts is the timespec to return the converted ticks.
0579  */
0580 static inline void _Watchdog_Ticks_to_timespec(
0581   uint64_t         ticks,
0582   struct timespec *ts
0583 )
0584 {
0585   ts->tv_sec = ticks >> WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
0586   ts->tv_nsec = ticks & ( ( 1U << WATCHDOG_BITS_FOR_1E9_NANOSECONDS ) - 1 );
0587 }
0588 
0589 /**
0590  * @brief Converts the sbintime in ticks.
0591  *
0592  * @param sbt The sbintime to convert to ticks.
0593  *
0594  * @return @a sbt converted to ticks.
0595  */
0596 static inline uint64_t _Watchdog_Ticks_from_sbintime( int64_t sbt )
0597 {
0598   uint64_t ticks = ( sbt >> 32 ) << WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
0599 
0600   ticks |= ( (uint64_t) 1000000000 * (uint32_t) sbt ) >> 32;
0601 
0602   return ticks;
0603 }
0604 
0605 /**
0606  * @brief Acquires the per cpu watchdog lock in a critical section.
0607  *
0608  * @param cpu The cpu to acquire the watchdog lock of.
0609  * @param lock_context The lock context.
0610  */
0611 static inline void _Watchdog_Per_CPU_acquire_critical(
0612   Per_CPU_Control  *cpu,
0613   ISR_lock_Context *lock_context
0614 )
0615 {
0616   _ISR_lock_Acquire( &cpu->Watchdog.Lock, lock_context );
0617 }
0618 
0619 /**
0620  * @brief Releases the per cpu watchdog lock in a critical section.
0621  *
0622  * @param cpu The cpu to release the watchdog lock of.
0623  * @param lock_context The lock context.
0624  */
0625 static inline void _Watchdog_Per_CPU_release_critical(
0626   Per_CPU_Control  *cpu,
0627   ISR_lock_Context *lock_context
0628 )
0629 {
0630   _ISR_lock_Release( &cpu->Watchdog.Lock, lock_context );
0631 }
0632 
0633 /**
0634  * @brief Sets the watchdog's cpu to the given instance and sets its expiration
0635  *      time to the watchdog expiration time of the cpu plus the ticks.
0636  *
0637  * @param[in, out] the_watchdog The watchdog to set the cpu and expiration time of.
0638  * @param cpu The cpu for the watchdog.
0639  * @param ticks The ticks to add to the expiration time.
0640  *
0641  * @return The new expiration time of the watchdog.
0642  */
0643 static inline uint64_t _Watchdog_Per_CPU_insert_ticks(
0644   Watchdog_Control  *the_watchdog,
0645   Per_CPU_Control   *cpu,
0646   Watchdog_Interval  ticks
0647 )
0648 {
0649   ISR_lock_Context  lock_context;
0650   Watchdog_Header  *header;
0651   uint64_t          expire;
0652 
0653   header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ];
0654 
0655   _Watchdog_Set_CPU( the_watchdog, cpu );
0656 
0657   _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
0658   expire = ticks + cpu->Watchdog.ticks;
0659   _Watchdog_Insert(header, the_watchdog, expire);
0660   _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
0661   return expire;
0662 }
0663 
0664 /**
0665  * @brief Sets the watchdog's cpu and inserts it with the given expiration time
0666  *      in the scheduled watchdogs.
0667  *
0668  * @param[in, out] the_watchdog The watchdog to set cpu and expiration time of.
0669  * @param cpu The cpu for the operation.
0670  * @param[in, out] header The scheduled watchdogs.
0671  * @param expire The expiration time for the watchdog.
0672  *
0673  * @return The expiration time of the watchdog.
0674  */
0675 static inline uint64_t _Watchdog_Per_CPU_insert(
0676   Watchdog_Control *the_watchdog,
0677   Per_CPU_Control  *cpu,
0678   Watchdog_Header  *header,
0679   uint64_t          expire
0680 )
0681 {
0682   ISR_lock_Context lock_context;
0683 
0684   _Watchdog_Set_CPU( the_watchdog, cpu );
0685 
0686   _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
0687   _Watchdog_Insert( header, the_watchdog, expire );
0688   _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
0689   return expire;
0690 }
0691 
0692 /**
0693  * @brief Removes the watchdog from the cpu and the scheduled watchdogs.
0694  *
0695  * @param[in, out] the_watchdog The watchdog to remove.
0696  * @param cpu The cpu to remove the watchdog from.
0697  * @param[in, out] The scheduled watchdogs.
0698  */
0699 static inline void _Watchdog_Per_CPU_remove(
0700   Watchdog_Control *the_watchdog,
0701   Per_CPU_Control  *cpu,
0702   Watchdog_Header  *header
0703 )
0704 {
0705   ISR_lock_Context lock_context;
0706 
0707   _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
0708   _Watchdog_Remove(
0709     header,
0710     the_watchdog
0711   );
0712   _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
0713 }
0714 
0715 /**
0716  * @brief Removes the watchdog from the cpu and the scheduled watchdogs.
0717  *
0718  * @param[in, out] the_watchdog The watchdog to remove.
0719  */
0720 static inline void _Watchdog_Per_CPU_remove_ticks(
0721   Watchdog_Control *the_watchdog
0722 )
0723 {
0724   Per_CPU_Control *cpu;
0725 
0726   cpu = _Watchdog_Get_CPU( the_watchdog );
0727   _Watchdog_Per_CPU_remove(
0728     the_watchdog,
0729     cpu,
0730     &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ]
0731   );
0732 }
0733 
0734 /** @} */
0735 
0736 #ifdef __cplusplus
0737 }
0738 #endif
0739 
0740 #endif
0741 /* end of include file */