[4b48ece0] | 1 | /** |
---|
| 2 | * @file |
---|
| 3 | * |
---|
[c53ec8c4] | 4 | * @ingroup RTEMSScoreWatchdog |
---|
| 5 | * |
---|
[4b48ece0] | 6 | * @brief Inlined Routines in the Watchdog Handler |
---|
| 7 | * |
---|
| 8 | * This file contains the static inline implementation of all inlined |
---|
| 9 | * routines in the Watchdog Handler. |
---|
| 10 | */ |
---|
| 11 | |
---|
| 12 | /* |
---|
| 13 | * COPYRIGHT (c) 1989-2004. |
---|
| 14 | * On-Line Applications Research Corporation (OAR). |
---|
| 15 | * |
---|
| 16 | * The license and distribution terms for this file may be |
---|
| 17 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 18 | * http://www.rtems.org/license/LICENSE. |
---|
[4b48ece0] | 19 | */ |
---|
| 20 | |
---|
| 21 | #ifndef _RTEMS_SCORE_WATCHDOGIMPL_H |
---|
| 22 | #define _RTEMS_SCORE_WATCHDOGIMPL_H |
---|
| 23 | |
---|
| 24 | #include <rtems/score/watchdog.h> |
---|
[ccc6695] | 25 | #include <rtems/score/watchdogticks.h> |
---|
[80fca28] | 26 | #include <rtems/score/assert.h> |
---|
[6d253941] | 27 | #include <rtems/score/isrlock.h> |
---|
[90d8567] | 28 | #include <rtems/score/percpu.h> |
---|
[03b900d] | 29 | #include <rtems/score/rbtreeimpl.h> |
---|
| 30 | |
---|
[afa92ab7] | 31 | #include <sys/types.h> |
---|
[03b900d] | 32 | #include <sys/timespec.h> |
---|
[4b48ece0] | 33 | |
---|
| 34 | #ifdef __cplusplus |
---|
| 35 | extern "C" { |
---|
| 36 | #endif |
---|
| 37 | |
---|
| 38 | /** |
---|
[c53ec8c4] | 39 | * @addtogroup RTEMSScoreWatchdog |
---|
| 40 | * |
---|
| 41 | * @{ |
---|
[4b48ece0] | 42 | */ |
---|
| 43 | |
---|
[0eae7ba9] | 44 | /** |
---|
[03b900d] | 45 | * @brief Watchdog states. |
---|
[1ccbd052] | 46 | */ |
---|
[03b900d] | 47 | typedef enum { |
---|
[1ccbd052] | 48 | /** |
---|
[03b900d] | 49 | * @brief The watchdog is scheduled and a black node in the red-black tree. |
---|
[1ccbd052] | 50 | */ |
---|
[03b900d] | 51 | WATCHDOG_SCHEDULED_BLACK, |
---|
[1ccbd052] | 52 | |
---|
| 53 | /** |
---|
[03b900d] | 54 | * @brief The watchdog is scheduled and a red node in the red-black tree. |
---|
[1ccbd052] | 55 | */ |
---|
[03b900d] | 56 | WATCHDOG_SCHEDULED_RED, |
---|
[1ccbd052] | 57 | |
---|
| 58 | /** |
---|
[03b900d] | 59 | * @brief The watchdog is inactive. |
---|
[1ccbd052] | 60 | */ |
---|
[03b900d] | 61 | WATCHDOG_INACTIVE, |
---|
[6d253941] | 62 | |
---|
[54cf0e34] | 63 | /** |
---|
[03b900d] | 64 | * @brief The watchdog is on a chain of pending watchdogs. |
---|
[1ccbd052] | 65 | * |
---|
[03b900d] | 66 | * This state is used by the timer server for example. |
---|
[1ccbd052] | 67 | */ |
---|
[03b900d] | 68 | WATCHDOG_PENDING |
---|
| 69 | } Watchdog_State; |
---|
[4b48ece0] | 70 | |
---|
| 71 | /** |
---|
[03b900d] | 72 | * @brief Watchdog initializer for static initialization. |
---|
[4b48ece0] | 73 | * |
---|
[03b900d] | 74 | * The processor of this watchdog is set to processor with index zero. |
---|
[4b48ece0] | 75 | * |
---|
[03b900d] | 76 | * @see _Watchdog_Preinitialize(). |
---|
[4b48ece0] | 77 | */ |
---|
[03b900d] | 78 | #if defined(RTEMS_SMP) |
---|
| 79 | #define WATCHDOG_INITIALIZER( routine ) \ |
---|
| 80 | { \ |
---|
| 81 | { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \ |
---|
| 82 | &_Per_CPU_Information[ 0 ].per_cpu, \ |
---|
| 83 | ( routine ), \ |
---|
| 84 | 0 \ |
---|
| 85 | } |
---|
| 86 | #else |
---|
| 87 | #define WATCHDOG_INITIALIZER( routine ) \ |
---|
| 88 | { \ |
---|
| 89 | { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \ |
---|
| 90 | ( routine ), \ |
---|
| 91 | 0 \ |
---|
| 92 | } |
---|
| 93 | #endif |
---|
[6d253941] | 94 | |
---|
[c53ec8c4] | 95 | /** |
---|
| 96 | * @brief Initializes the watchdog header. |
---|
| 97 | * |
---|
| 98 | * @param[out] header The header to initialize. |
---|
| 99 | */ |
---|
[03b900d] | 100 | RTEMS_INLINE_ROUTINE void _Watchdog_Header_initialize( |
---|
| 101 | Watchdog_Header *header |
---|
[6d253941] | 102 | ) |
---|
| 103 | { |
---|
[03b900d] | 104 | _RBTree_Initialize_empty( &header->Watchdogs ); |
---|
| 105 | header->first = NULL; |
---|
[6d253941] | 106 | } |
---|
| 107 | |
---|
[c53ec8c4] | 108 | /** |
---|
| 109 | * @brief Returns the first of the watchdog header. |
---|
| 110 | * |
---|
| 111 | * @param header The watchdog header to remove the first of. |
---|
| 112 | * |
---|
| 113 | * @return The first of @a header. |
---|
| 114 | */ |
---|
[89c0313] | 115 | RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Header_first( |
---|
| 116 | const Watchdog_Header *header |
---|
| 117 | ) |
---|
| 118 | { |
---|
| 119 | return (Watchdog_Control *) header->first; |
---|
| 120 | } |
---|
| 121 | |
---|
[c53ec8c4] | 122 | /** |
---|
| 123 | * @brief Destroys the watchdog header. |
---|
| 124 | * |
---|
| 125 | * @param header The watchdog header to destroy. |
---|
| 126 | */ |
---|
[03b900d] | 127 | RTEMS_INLINE_ROUTINE void _Watchdog_Header_destroy( |
---|
| 128 | Watchdog_Header *header |
---|
[6d253941] | 129 | ) |
---|
| 130 | { |
---|
[03b900d] | 131 | /* Do nothing */ |
---|
| 132 | (void) header; |
---|
[6d253941] | 133 | } |
---|
| 134 | |
---|
[7cd2484] | 135 | /** |
---|
[c53ec8c4] | 136 | * @brief Performs a watchdog tick. |
---|
[7cd2484] | 137 | * |
---|
[c53ec8c4] | 138 | * @param cpu The processor for this watchdog tick. |
---|
[7cd2484] | 139 | */ |
---|
[03b900d] | 140 | void _Watchdog_Tick( struct Per_CPU_Control *cpu ); |
---|
[a382010c] | 141 | |
---|
[c53ec8c4] | 142 | /** |
---|
| 143 | * @brief Gets the state of the watchdog. |
---|
| 144 | * |
---|
| 145 | * @param the_watchdog The watchdog to get the state of. |
---|
| 146 | * |
---|
| 147 | * @return The RB_COLOR of @a the_watchdog. |
---|
| 148 | */ |
---|
[03b900d] | 149 | RTEMS_INLINE_ROUTINE Watchdog_State _Watchdog_Get_state( |
---|
| 150 | const Watchdog_Control *the_watchdog |
---|
| 151 | ) |
---|
| 152 | { |
---|
[c5b7942] | 153 | return (Watchdog_State) RB_COLOR( &the_watchdog->Node.RBTree, Node ); |
---|
[03b900d] | 154 | } |
---|
[4b48ece0] | 155 | |
---|
[c53ec8c4] | 156 | /** |
---|
| 157 | * @brief Sets the state of the watchdog. |
---|
| 158 | * |
---|
| 159 | * @param[out] the_watchdog The watchdog to set the state of. |
---|
| 160 | * @param state The state to set the watchdog to. |
---|
| 161 | */ |
---|
[03b900d] | 162 | RTEMS_INLINE_ROUTINE void _Watchdog_Set_state( |
---|
| 163 | Watchdog_Control *the_watchdog, |
---|
| 164 | Watchdog_State state |
---|
| 165 | ) |
---|
| 166 | { |
---|
| 167 | RB_COLOR( &the_watchdog->Node.RBTree, Node ) = state; |
---|
| 168 | } |
---|
[4b48ece0] | 169 | |
---|
[c53ec8c4] | 170 | /** |
---|
| 171 | * @brief Gets the watchdog's cpu. |
---|
| 172 | * |
---|
| 173 | * @param the_watchdog The watchdog to get the cpu of. |
---|
| 174 | * |
---|
| 175 | * @return The cpu of the watchdog. |
---|
| 176 | */ |
---|
[03b900d] | 177 | RTEMS_INLINE_ROUTINE Per_CPU_Control *_Watchdog_Get_CPU( |
---|
| 178 | const Watchdog_Control *the_watchdog |
---|
| 179 | ) |
---|
| 180 | { |
---|
| 181 | #if defined(RTEMS_SMP) |
---|
| 182 | return the_watchdog->cpu; |
---|
| 183 | #else |
---|
| 184 | return _Per_CPU_Get_by_index( 0 ); |
---|
| 185 | #endif |
---|
| 186 | } |
---|
[4b48ece0] | 187 | |
---|
[c53ec8c4] | 188 | /** |
---|
| 189 | * @brief Sets the cpu for the watchdog. |
---|
| 190 | * |
---|
| 191 | * @param[out] the_watchdog The watchdog to set the cpu of. |
---|
| 192 | * @param cpu The cpu to be set as @a the_watchdog's cpu. |
---|
| 193 | */ |
---|
[03b900d] | 194 | RTEMS_INLINE_ROUTINE void _Watchdog_Set_CPU( |
---|
[a382010c] | 195 | Watchdog_Control *the_watchdog, |
---|
[03b900d] | 196 | Per_CPU_Control *cpu |
---|
| 197 | ) |
---|
| 198 | { |
---|
| 199 | #if defined(RTEMS_SMP) |
---|
| 200 | the_watchdog->cpu = cpu; |
---|
| 201 | #else |
---|
| 202 | (void) cpu; |
---|
| 203 | #endif |
---|
| 204 | } |
---|
[4b48ece0] | 205 | |
---|
[80fca28] | 206 | /** |
---|
| 207 | * @brief Pre-initializes a watchdog. |
---|
| 208 | * |
---|
| 209 | * This routine must be called before a watchdog is used in any way. The |
---|
| 210 | * exception are statically initialized watchdogs via WATCHDOG_INITIALIZER(). |
---|
| 211 | * |
---|
[c53ec8c4] | 212 | * @param[out] the_watchdog The uninitialized watchdog. |
---|
[80fca28] | 213 | */ |
---|
| 214 | RTEMS_INLINE_ROUTINE void _Watchdog_Preinitialize( |
---|
[03b900d] | 215 | Watchdog_Control *the_watchdog, |
---|
| 216 | Per_CPU_Control *cpu |
---|
[80fca28] | 217 | ) |
---|
| 218 | { |
---|
[03b900d] | 219 | _Watchdog_Set_CPU( the_watchdog, cpu ); |
---|
| 220 | _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE ); |
---|
| 221 | |
---|
[80fca28] | 222 | #if defined(RTEMS_DEBUG) |
---|
| 223 | the_watchdog->routine = NULL; |
---|
[03b900d] | 224 | the_watchdog->expire = 0; |
---|
[80fca28] | 225 | #endif |
---|
| 226 | } |
---|
| 227 | |
---|
[4b48ece0] | 228 | /** |
---|
[03b900d] | 229 | * @brief Initializes a watchdog with a new service routine. |
---|
| 230 | * |
---|
| 231 | * The watchdog must be inactive. |
---|
[c53ec8c4] | 232 | * |
---|
| 233 | * @param[out] the_watchdog The watchdog to initialize. |
---|
| 234 | * @param routing The service routine for @a the_watchdog. |
---|
[4b48ece0] | 235 | */ |
---|
| 236 | RTEMS_INLINE_ROUTINE void _Watchdog_Initialize( |
---|
| 237 | Watchdog_Control *the_watchdog, |
---|
[03b900d] | 238 | Watchdog_Service_routine_entry routine |
---|
[4b48ece0] | 239 | ) |
---|
| 240 | { |
---|
[03b900d] | 241 | _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE ); |
---|
| 242 | the_watchdog->routine = routine; |
---|
[4b48ece0] | 243 | } |
---|
| 244 | |
---|
[c53ec8c4] | 245 | /** |
---|
| 246 | * @brief Calls the routine of each not expired watchdog control node. |
---|
| 247 | * |
---|
| 248 | * @param header The watchdog header. |
---|
| 249 | * @param first The first watchdog control node. |
---|
| 250 | * @param now The current time to check the expiration time against. |
---|
| 251 | * @param lock The lock that is released before calling the routine and then |
---|
| 252 | * acquired after the call. |
---|
| 253 | * @param lock_context The lock context for the release before calling the |
---|
| 254 | * routine and for the acquire after. |
---|
| 255 | */ |
---|
[03b900d] | 256 | void _Watchdog_Do_tickle( |
---|
| 257 | Watchdog_Header *header, |
---|
[89c0313] | 258 | Watchdog_Control *first, |
---|
[03b900d] | 259 | uint64_t now, |
---|
| 260 | #if defined(RTEMS_SMP) |
---|
| 261 | ISR_lock_Control *lock, |
---|
| 262 | #endif |
---|
| 263 | ISR_lock_Context *lock_context |
---|
| 264 | ); |
---|
| 265 | |
---|
| 266 | #if defined(RTEMS_SMP) |
---|
[89c0313] | 267 | #define _Watchdog_Tickle( header, first, now, lock, lock_context ) \ |
---|
| 268 | _Watchdog_Do_tickle( header, first, now, lock, lock_context ) |
---|
[03b900d] | 269 | #else |
---|
[89c0313] | 270 | #define _Watchdog_Tickle( header, first, now, lock, lock_context ) \ |
---|
| 271 | _Watchdog_Do_tickle( header, first, now, lock_context ) |
---|
[03b900d] | 272 | #endif |
---|
| 273 | |
---|
[4b48ece0] | 274 | /** |
---|
[03b900d] | 275 | * @brief Inserts a watchdog into the set of scheduled watchdogs according to |
---|
| 276 | * the specified expiration time. |
---|
| 277 | * |
---|
| 278 | * The watchdog must be inactive. |
---|
[c53ec8c4] | 279 | * |
---|
| 280 | * @param[in, out] header The set of scheduler watchdogs to insert into. |
---|
| 281 | * @param[in, out] the_watchdog The watchdog to insert. |
---|
| 282 | * @param expire The expiration time for the watchdog. |
---|
[4b48ece0] | 283 | */ |
---|
[03b900d] | 284 | void _Watchdog_Insert( |
---|
| 285 | Watchdog_Header *header, |
---|
| 286 | Watchdog_Control *the_watchdog, |
---|
| 287 | uint64_t expire |
---|
| 288 | ); |
---|
[4b48ece0] | 289 | |
---|
[03b900d] | 290 | /** |
---|
[c53ec8c4] | 291 | * @brief In the case the watchdog is scheduled, then it is removed from the set of |
---|
[03b900d] | 292 | * scheduled watchdogs. |
---|
| 293 | * |
---|
| 294 | * The watchdog must be initialized before this call. |
---|
[c53ec8c4] | 295 | * |
---|
| 296 | * @param[in, out] header The scheduled watchdogs. |
---|
| 297 | * @param[in, out] the_watchdog The watchdog to remove. |
---|
[03b900d] | 298 | */ |
---|
| 299 | void _Watchdog_Remove( |
---|
| 300 | Watchdog_Header *header, |
---|
[4b48ece0] | 301 | Watchdog_Control *the_watchdog |
---|
[03b900d] | 302 | ); |
---|
[4b48ece0] | 303 | |
---|
| 304 | /** |
---|
[c53ec8c4] | 305 | * @brief In the case the watchdog is scheduled, then it is removed from the set of |
---|
[03b900d] | 306 | * scheduled watchdogs. |
---|
| 307 | * |
---|
| 308 | * The watchdog must be initialized before this call. |
---|
| 309 | * |
---|
[c53ec8c4] | 310 | * @param[in, out] header The scheduled watchdogs. |
---|
| 311 | * @param[in, out] the_watchdog The watchdog to remove. |
---|
| 312 | * @param now The current time. |
---|
| 313 | * |
---|
| 314 | * @retval other The difference of the now and expiration time. |
---|
[03b900d] | 315 | * @retval 0 The now time is greater than or equal to the expiration time of |
---|
| 316 | * the watchdog. |
---|
[4b48ece0] | 317 | */ |
---|
[03b900d] | 318 | RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Cancel( |
---|
| 319 | Watchdog_Header *header, |
---|
| 320 | Watchdog_Control *the_watchdog, |
---|
| 321 | uint64_t now |
---|
[4b48ece0] | 322 | ) |
---|
| 323 | { |
---|
[03b900d] | 324 | uint64_t expire; |
---|
| 325 | uint64_t remaining; |
---|
[4b48ece0] | 326 | |
---|
[03b900d] | 327 | expire = the_watchdog->expire; |
---|
[4b48ece0] | 328 | |
---|
[03b900d] | 329 | if ( now < expire ) { |
---|
| 330 | remaining = expire - now; |
---|
| 331 | } else { |
---|
| 332 | remaining = 0; |
---|
| 333 | } |
---|
[4b48ece0] | 334 | |
---|
[03b900d] | 335 | _Watchdog_Remove( header, the_watchdog ); |
---|
[4b48ece0] | 336 | |
---|
[03b900d] | 337 | return remaining; |
---|
[4b48ece0] | 338 | } |
---|
| 339 | |
---|
[c53ec8c4] | 340 | /** |
---|
| 341 | * @brief Checks if the watchdog is scheduled. |
---|
| 342 | * |
---|
| 343 | * @param the_watchdog The watchdog for the verification. |
---|
| 344 | * |
---|
| 345 | * @retval true The watchdog is scheduled. |
---|
| 346 | * @retval false The watchdog is inactive. |
---|
| 347 | */ |
---|
[03b900d] | 348 | RTEMS_INLINE_ROUTINE bool _Watchdog_Is_scheduled( |
---|
| 349 | const Watchdog_Control *the_watchdog |
---|
| 350 | ) |
---|
[4b48ece0] | 351 | { |
---|
[03b900d] | 352 | return _Watchdog_Get_state( the_watchdog ) < WATCHDOG_INACTIVE; |
---|
[4b48ece0] | 353 | } |
---|
| 354 | |
---|
[c53ec8c4] | 355 | /** |
---|
| 356 | * @brief Sets the first node of the header. |
---|
| 357 | * |
---|
| 358 | * Sets the first node of the header to either the leftmost child node of the |
---|
| 359 | * watchdog control node, or if not present sets it to the right child node of |
---|
| 360 | * the watchdog control node. if both are not present, the new first node is |
---|
| 361 | * the parent node of the current first node. |
---|
| 362 | * |
---|
| 363 | * @param[in, out] header The watchdog header. |
---|
| 364 | * @param the_watchdog The watchdog control node for the operation. |
---|
| 365 | */ |
---|
[03b900d] | 366 | RTEMS_INLINE_ROUTINE void _Watchdog_Next_first( |
---|
| 367 | Watchdog_Header *header, |
---|
| 368 | Watchdog_Control *the_watchdog |
---|
[4b48ece0] | 369 | ) |
---|
| 370 | { |
---|
[03b900d] | 371 | RBTree_Node *node = _RBTree_Right( &the_watchdog->Node.RBTree ); |
---|
[4b48ece0] | 372 | |
---|
[03b900d] | 373 | if ( node != NULL ) { |
---|
| 374 | RBTree_Node *left; |
---|
[4b48ece0] | 375 | |
---|
[03b900d] | 376 | while ( ( left = _RBTree_Left( node ) ) != NULL ) { |
---|
| 377 | node = left; |
---|
| 378 | } |
---|
[4b48ece0] | 379 | |
---|
[03b900d] | 380 | header->first = node; |
---|
| 381 | } else { |
---|
| 382 | header->first = _RBTree_Parent( &the_watchdog->Node.RBTree ); |
---|
| 383 | } |
---|
[4b48ece0] | 384 | } |
---|
| 385 | |
---|
[c3105894] | 386 | /** |
---|
| 387 | * @brief The maximum watchdog ticks value for the far future. |
---|
| 388 | */ |
---|
| 389 | #define WATCHDOG_MAXIMUM_TICKS UINT64_MAX |
---|
| 390 | |
---|
[adaf5c23] | 391 | #define WATCHDOG_NANOSECONDS_PER_SECOND 1000000000 |
---|
| 392 | |
---|
[4b48ece0] | 393 | /** |
---|
[adaf5c23] | 394 | * @brief The bits necessary to store 1000000000 |
---|
| 395 | * (= WATCHDOG_NANOSECONDS_PER_SECOND) nanoseconds. |
---|
[03b900d] | 396 | * |
---|
[9480815a] | 397 | * The expiration time is an unsigned 64-bit integer. To store nanoseconds |
---|
[03b900d] | 398 | * timeouts we use 30 bits (2**30 == 1073741824) for the nanoseconds and 34 |
---|
| 399 | * bits for the seconds since UNIX Epoch. This leads to a year 2514 problem. |
---|
[4b48ece0] | 400 | */ |
---|
[03b900d] | 401 | #define WATCHDOG_BITS_FOR_1E9_NANOSECONDS 30 |
---|
[4b48ece0] | 402 | |
---|
[adaf5c23] | 403 | /** |
---|
[9480815a] | 404 | * @brief The maximum number of seconds representable in the nanoseconds |
---|
| 405 | * watchdog format. |
---|
[adaf5c23] | 406 | * |
---|
| 407 | * We have 2**34 bits for the seconds part. |
---|
| 408 | */ |
---|
[9480815a] | 409 | #define WATCHDOG_MAX_SECONDS 0x3ffffffff |
---|
[adaf5c23] | 410 | |
---|
[c53ec8c4] | 411 | /** |
---|
| 412 | * @brief Checks if the timespec is a valid timespec for a watchdog. |
---|
| 413 | * |
---|
| 414 | * @param ts The timespec for the verification. |
---|
| 415 | * |
---|
| 416 | * @retval true The timespec is a valid timespec. |
---|
| 417 | * @retval false The timespec is invalid. |
---|
| 418 | */ |
---|
[adaf5c23] | 419 | RTEMS_INLINE_ROUTINE bool _Watchdog_Is_valid_timespec( |
---|
| 420 | const struct timespec *ts |
---|
| 421 | ) |
---|
| 422 | { |
---|
| 423 | return ts != NULL |
---|
| 424 | && (unsigned long) ts->tv_nsec < WATCHDOG_NANOSECONDS_PER_SECOND; |
---|
| 425 | } |
---|
| 426 | |
---|
[c53ec8c4] | 427 | /** |
---|
| 428 | * @brief Checks if the timespec is a valid interval timespec for a watchdog. |
---|
| 429 | * |
---|
| 430 | * @param ts The timespec for the verification. |
---|
| 431 | * |
---|
| 432 | * @retval true The timespec is a valid interval timespec. |
---|
| 433 | * @retval false The timespec is invalid. |
---|
| 434 | */ |
---|
[d16d07f] | 435 | RTEMS_INLINE_ROUTINE bool _Watchdog_Is_valid_interval_timespec( |
---|
| 436 | const struct timespec *ts |
---|
| 437 | ) |
---|
| 438 | { |
---|
| 439 | return _Watchdog_Is_valid_timespec( ts ) && ts->tv_sec >= 0; |
---|
| 440 | } |
---|
| 441 | |
---|
[c53ec8c4] | 442 | /** |
---|
| 443 | * @brief Adds the delta timespec to the current time if the delta is a valid |
---|
| 444 | * interval timespec. |
---|
| 445 | * |
---|
| 446 | * @param[in, out] now The current time. |
---|
| 447 | * @param delta The delta timespec for the addition. |
---|
| 448 | * |
---|
| 449 | * @retval pointer Pointer to the now timespec. |
---|
| 450 | * @retval NULL @a delta is not a valid interval timespec. |
---|
| 451 | */ |
---|
[3e81d52] | 452 | RTEMS_INLINE_ROUTINE const struct timespec * _Watchdog_Future_timespec( |
---|
| 453 | struct timespec *now, |
---|
| 454 | const struct timespec *delta |
---|
| 455 | ) |
---|
| 456 | { |
---|
| 457 | uint64_t sec; |
---|
| 458 | |
---|
| 459 | if ( !_Watchdog_Is_valid_interval_timespec( delta ) ) { |
---|
| 460 | return NULL; |
---|
| 461 | } |
---|
| 462 | |
---|
| 463 | sec = (uint64_t) now->tv_sec; |
---|
| 464 | sec += (uint64_t) delta->tv_sec; |
---|
| 465 | now->tv_nsec += delta->tv_nsec; |
---|
| 466 | |
---|
| 467 | /* We have 2 * (2**63 - 1) + 1 == UINT64_MAX */ |
---|
| 468 | if ( now->tv_nsec >= WATCHDOG_NANOSECONDS_PER_SECOND ) { |
---|
| 469 | now->tv_nsec -= WATCHDOG_NANOSECONDS_PER_SECOND; |
---|
| 470 | ++sec; |
---|
| 471 | } |
---|
| 472 | |
---|
| 473 | if ( sec <= INT64_MAX ) { |
---|
| 474 | now->tv_sec = sec; |
---|
| 475 | } else { |
---|
| 476 | now->tv_sec = INT64_MAX; |
---|
| 477 | } |
---|
| 478 | |
---|
| 479 | return now; |
---|
| 480 | } |
---|
| 481 | |
---|
[c53ec8c4] | 482 | /** |
---|
| 483 | * @brief Checks if the timespec is too far in the future. |
---|
| 484 | * |
---|
| 485 | * @param ts The timespec for the verification. |
---|
| 486 | * |
---|
| 487 | * @retval true @a ts is too far in the future. |
---|
| 488 | * @retval false @a ts is not too far in the future. |
---|
| 489 | */ |
---|
[9480815a] | 490 | RTEMS_INLINE_ROUTINE bool _Watchdog_Is_far_future_timespec( |
---|
[7ed377b] | 491 | const struct timespec *ts |
---|
| 492 | ) |
---|
| 493 | { |
---|
[9480815a] | 494 | return ts->tv_sec > WATCHDOG_MAX_SECONDS; |
---|
[adaf5c23] | 495 | } |
---|
| 496 | |
---|
[c53ec8c4] | 497 | /** |
---|
| 498 | * @brief Converts the seconds to ticks. |
---|
| 499 | * |
---|
| 500 | * @param seconds The seconds to convert to ticks. |
---|
| 501 | * |
---|
| 502 | * @return @a seconds converted to ticks. |
---|
| 503 | */ |
---|
[3a4e044] | 504 | RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_seconds( |
---|
[03b900d] | 505 | uint32_t seconds |
---|
[4b48ece0] | 506 | ) |
---|
| 507 | { |
---|
[03b900d] | 508 | uint64_t ticks = seconds; |
---|
[4b48ece0] | 509 | |
---|
[03b900d] | 510 | ticks <<= WATCHDOG_BITS_FOR_1E9_NANOSECONDS; |
---|
[4b48ece0] | 511 | |
---|
[03b900d] | 512 | return ticks; |
---|
[4b48ece0] | 513 | } |
---|
| 514 | |
---|
[c53ec8c4] | 515 | /** |
---|
| 516 | * @brief Converts the timespec in ticks. |
---|
| 517 | * |
---|
| 518 | * @param ts The timespec to convert to ticks. |
---|
| 519 | * |
---|
| 520 | * @return @a ts converted to ticks. |
---|
| 521 | */ |
---|
[3a4e044] | 522 | RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_timespec( |
---|
[03b900d] | 523 | const struct timespec *ts |
---|
[2903090] | 524 | ) |
---|
| 525 | { |
---|
[adaf5c23] | 526 | uint64_t ticks; |
---|
[03b900d] | 527 | |
---|
[adaf5c23] | 528 | _Assert( _Watchdog_Is_valid_timespec( ts ) ); |
---|
| 529 | _Assert( ts->tv_sec >= 0 ); |
---|
[9480815a] | 530 | _Assert( !_Watchdog_Is_far_future_timespec( ts ) ); |
---|
[03b900d] | 531 | |
---|
[adaf5c23] | 532 | ticks = (uint64_t) ts->tv_sec; |
---|
[03b900d] | 533 | ticks <<= WATCHDOG_BITS_FOR_1E9_NANOSECONDS; |
---|
[1d72f03] | 534 | ticks |= (uint32_t) ts->tv_nsec; |
---|
[03b900d] | 535 | |
---|
| 536 | return ticks; |
---|
[2903090] | 537 | } |
---|
| 538 | |
---|
[c53ec8c4] | 539 | /** |
---|
| 540 | * @brief Converts the sbintime in ticks. |
---|
| 541 | * |
---|
| 542 | * @param sbt The sbintime to convert to ticks. |
---|
| 543 | * |
---|
| 544 | * @return @a sbt converted to ticks. |
---|
| 545 | */ |
---|
[ef23838] | 546 | RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_sbintime( int64_t sbt ) |
---|
[afa92ab7] | 547 | { |
---|
| 548 | uint64_t ticks = ( sbt >> 32 ) << WATCHDOG_BITS_FOR_1E9_NANOSECONDS; |
---|
| 549 | |
---|
| 550 | ticks |= ( (uint64_t) 1000000000 * (uint32_t) sbt ) >> 32; |
---|
| 551 | |
---|
| 552 | return ticks; |
---|
| 553 | } |
---|
| 554 | |
---|
[c53ec8c4] | 555 | /** |
---|
| 556 | * @brief Acquires the per cpu watchdog lock in a critical section. |
---|
| 557 | * |
---|
| 558 | * @param cpu The cpu to acquire the watchdog lock of. |
---|
| 559 | * @param lock_context The lock context. |
---|
| 560 | */ |
---|
[03b900d] | 561 | RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_acquire_critical( |
---|
| 562 | Per_CPU_Control *cpu, |
---|
| 563 | ISR_lock_Context *lock_context |
---|
[2903090] | 564 | ) |
---|
| 565 | { |
---|
[03b900d] | 566 | _ISR_lock_Acquire( &cpu->Watchdog.Lock, lock_context ); |
---|
[2903090] | 567 | } |
---|
| 568 | |
---|
[c53ec8c4] | 569 | /** |
---|
| 570 | * @brief Releases the per cpu watchdog lock in a critical section. |
---|
| 571 | * |
---|
| 572 | * @param cpu The cpu to release the watchdog lock of. |
---|
| 573 | * @param lock_context The lock context. |
---|
| 574 | */ |
---|
[03b900d] | 575 | RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_release_critical( |
---|
| 576 | Per_CPU_Control *cpu, |
---|
| 577 | ISR_lock_Context *lock_context |
---|
[4b48ece0] | 578 | ) |
---|
| 579 | { |
---|
[03b900d] | 580 | _ISR_lock_Release( &cpu->Watchdog.Lock, lock_context ); |
---|
[4b48ece0] | 581 | } |
---|
| 582 | |
---|
[c53ec8c4] | 583 | /** |
---|
| 584 | * @brief Sets the watchdog's cpu to the given instance and sets its expiration |
---|
| 585 | * time to the watchdog expiration time of the cpu plus the ticks. |
---|
| 586 | * |
---|
| 587 | * @param[in, out] the_watchdog The watchdog to set the cpu and expiration time of. |
---|
| 588 | * @param cpu The cpu for the watchdog. |
---|
| 589 | * @param ticks The ticks to add to the expiration time. |
---|
| 590 | * |
---|
| 591 | * @return The new expiration time of the watchdog. |
---|
| 592 | */ |
---|
[91ce012c] | 593 | RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Per_CPU_insert_ticks( |
---|
[00c620c] | 594 | Watchdog_Control *the_watchdog, |
---|
| 595 | Per_CPU_Control *cpu, |
---|
| 596 | Watchdog_Interval ticks |
---|
[4b48ece0] | 597 | ) |
---|
| 598 | { |
---|
[00c620c] | 599 | ISR_lock_Context lock_context; |
---|
| 600 | Watchdog_Header *header; |
---|
| 601 | uint64_t expire; |
---|
| 602 | |
---|
[9480815a] | 603 | header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ]; |
---|
[4b48ece0] | 604 | |
---|
[03b900d] | 605 | _Watchdog_Set_CPU( the_watchdog, cpu ); |
---|
[4b48ece0] | 606 | |
---|
[03b900d] | 607 | _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context ); |
---|
[f23d470] | 608 | expire = ticks + cpu->Watchdog.ticks; |
---|
| 609 | _Watchdog_Insert(header, the_watchdog, expire); |
---|
| 610 | _Watchdog_Per_CPU_release_critical( cpu, &lock_context ); |
---|
[9a78f8a5] | 611 | return expire; |
---|
[4b48ece0] | 612 | } |
---|
| 613 | |
---|
[c53ec8c4] | 614 | /** |
---|
| 615 | * @brief Sets the watchdog's cpu and inserts it with the given expiration time |
---|
| 616 | * in the scheduled watchdogs. |
---|
| 617 | * |
---|
| 618 | * @param[in, out] the_watchdog The watchdog to set cpu and expiration time of. |
---|
| 619 | * @param cpu The cpu for the operation. |
---|
| 620 | * @param[in, out] header The scheduled watchdogs. |
---|
| 621 | * @param expire The expiration time for the watchdog. |
---|
| 622 | * |
---|
| 623 | * @return The expiration time of the watchdog. |
---|
| 624 | */ |
---|
[9480815a] | 625 | RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Per_CPU_insert( |
---|
[00c620c] | 626 | Watchdog_Control *the_watchdog, |
---|
| 627 | Per_CPU_Control *cpu, |
---|
[9480815a] | 628 | Watchdog_Header *header, |
---|
[00c620c] | 629 | uint64_t expire |
---|
[4b48ece0] | 630 | ) |
---|
| 631 | { |
---|
[9480815a] | 632 | ISR_lock_Context lock_context; |
---|
[4b48ece0] | 633 | |
---|
[03b900d] | 634 | _Watchdog_Set_CPU( the_watchdog, cpu ); |
---|
[4b48ece0] | 635 | |
---|
[03b900d] | 636 | _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context ); |
---|
[9480815a] | 637 | _Watchdog_Insert( header, the_watchdog, expire ); |
---|
[03b900d] | 638 | _Watchdog_Per_CPU_release_critical( cpu, &lock_context ); |
---|
[f23d470] | 639 | return expire; |
---|
[4b48ece0] | 640 | } |
---|
| 641 | |
---|
[c53ec8c4] | 642 | /** |
---|
| 643 | * @brief Removes the watchdog from the cpu and the scheduled watchdogs. |
---|
| 644 | * |
---|
| 645 | * @param[in, out] the_watchdog The watchdog to remove. |
---|
| 646 | * @param cpu The cpu to remove the watchdog from. |
---|
| 647 | * @param[in, out] The scheduled watchdogs. |
---|
| 648 | */ |
---|
[03b900d] | 649 | RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove( |
---|
| 650 | Watchdog_Control *the_watchdog, |
---|
| 651 | Per_CPU_Control *cpu, |
---|
| 652 | Watchdog_Header *header |
---|
[4b48ece0] | 653 | ) |
---|
| 654 | { |
---|
[03b900d] | 655 | ISR_lock_Context lock_context; |
---|
| 656 | |
---|
| 657 | _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context ); |
---|
| 658 | _Watchdog_Remove( |
---|
| 659 | header, |
---|
| 660 | the_watchdog |
---|
| 661 | ); |
---|
| 662 | _Watchdog_Per_CPU_release_critical( cpu, &lock_context ); |
---|
[4b48ece0] | 663 | } |
---|
| 664 | |
---|
[c53ec8c4] | 665 | /** |
---|
| 666 | * @brief Removes the watchdog from the cpu and the scheduled watchdogs. |
---|
| 667 | * |
---|
| 668 | * @param[in, out] the_watchdog The watchdog to remove. |
---|
| 669 | */ |
---|
[9480815a] | 670 | RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove_ticks( |
---|
[03b900d] | 671 | Watchdog_Control *the_watchdog |
---|
[54cf0e34] | 672 | ) |
---|
| 673 | { |
---|
[03b900d] | 674 | Per_CPU_Control *cpu; |
---|
| 675 | |
---|
| 676 | cpu = _Watchdog_Get_CPU( the_watchdog ); |
---|
| 677 | _Watchdog_Per_CPU_remove( |
---|
| 678 | the_watchdog, |
---|
| 679 | cpu, |
---|
[9480815a] | 680 | &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ] |
---|
[03b900d] | 681 | ); |
---|
[54cf0e34] | 682 | } |
---|
[4b48ece0] | 683 | |
---|
| 684 | /** @} */ |
---|
| 685 | |
---|
| 686 | #ifdef __cplusplus |
---|
| 687 | } |
---|
| 688 | #endif |
---|
| 689 | |
---|
| 690 | #endif |
---|
| 691 | /* end of include file */ |
---|