File indexing completed on 2025-05-11 08:24:13
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
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
0057
0058
0059
0060
0061
0062
0063
0064 typedef enum {
0065
0066
0067
0068 WATCHDOG_SCHEDULED_BLACK,
0069
0070
0071
0072
0073 WATCHDOG_SCHEDULED_RED,
0074
0075
0076
0077
0078 WATCHDOG_INACTIVE,
0079
0080
0081
0082
0083
0084
0085 WATCHDOG_PENDING
0086 } Watchdog_State;
0087
0088
0089
0090
0091
0092
0093
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
0114
0115
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
0127
0128
0129
0130
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
0141
0142
0143
0144 static inline void _Watchdog_Header_destroy(
0145 Watchdog_Header *header
0146 )
0147 {
0148
0149 (void) header;
0150 }
0151
0152
0153
0154
0155
0156
0157 void _Watchdog_Tick( struct Per_CPU_Control *cpu );
0158
0159
0160
0161
0162
0163
0164
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
0175
0176
0177
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
0189
0190
0191
0192
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
0207
0208
0209
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
0225
0226
0227
0228
0229
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
0247
0248
0249
0250
0251
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
0264
0265
0266
0267
0268
0269
0270
0271
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
0293
0294
0295
0296
0297
0298
0299
0300
0301 void _Watchdog_Insert(
0302 Watchdog_Header *header,
0303 Watchdog_Control *the_watchdog,
0304 uint64_t expire
0305 );
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316 void _Watchdog_Remove(
0317 Watchdog_Header *header,
0318 Watchdog_Control *the_watchdog
0319 );
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
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
0359
0360
0361
0362
0363
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
0374
0375
0376
0377
0378
0379
0380
0381
0382
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
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
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
0422
0423 #define WATCHDOG_MAXIMUM_TICKS UINT64_MAX
0424
0425 #define WATCHDOG_NANOSECONDS_PER_SECOND 1000000000
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435 #define WATCHDOG_BITS_FOR_1E9_NANOSECONDS 30
0436
0437
0438
0439
0440
0441
0442
0443 #define WATCHDOG_MAX_SECONDS 0x3ffffffff
0444
0445
0446
0447
0448
0449
0450
0451
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
0463
0464
0465
0466
0467
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
0478
0479
0480
0481
0482
0483
0484
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
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
0518
0519
0520
0521
0522
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
0533
0534
0535
0536
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
0551
0552
0553
0554
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
0575
0576
0577
0578
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
0591
0592
0593
0594
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
0607
0608
0609
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
0621
0622
0623
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
0635
0636
0637
0638
0639
0640
0641
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
0666
0667
0668
0669
0670
0671
0672
0673
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
0694
0695
0696
0697
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
0717
0718
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