diff options
Diffstat (limited to 'cpukit/score/src/watchdoginsert.c')
-rw-r--r-- | cpukit/score/src/watchdoginsert.c | 121 |
1 files changed, 72 insertions, 49 deletions
diff --git a/cpukit/score/src/watchdoginsert.c b/cpukit/score/src/watchdoginsert.c index 272cac8db1..6b81c7b872 100644 --- a/cpukit/score/src/watchdoginsert.c +++ b/cpukit/score/src/watchdoginsert.c @@ -19,76 +19,99 @@ #endif #include <rtems/score/watchdogimpl.h> -#include <rtems/score/isrlevel.h> -#include <rtems/score/percpu.h> -void _Watchdog_Insert( - Watchdog_Header *header, - Watchdog_Control *the_watchdog +static void _Watchdog_Insert_fixup( + Watchdog_Header *header, + Watchdog_Control *next_watchdog, + Watchdog_Interval delta ) { - ISR_Level level; - Watchdog_Control *after; - uint32_t insert_isr_nest_level; - Watchdog_Interval delta_interval; + const Chain_Node *iterator_tail; + Chain_Node *iterator_node; + + next_watchdog->delta_interval -= delta; + iterator_node = _Chain_First( &header->Iterators ); + iterator_tail = _Chain_Immutable_tail( &header->Iterators ); - insert_isr_nest_level = _ISR_Nest_level; + while ( iterator_node != iterator_tail ) { + Watchdog_Iterator *iterator; - _ISR_Disable( level ); + iterator = (Watchdog_Iterator *) iterator_node; - /* - * Check to see if the watchdog has just been inserted by a - * higher priority interrupt. If so, abandon this insert. - */ + if ( iterator->current == &next_watchdog->Node ) { + iterator->delta_interval -= delta; + } - if ( the_watchdog->state != WATCHDOG_INACTIVE ) { - _ISR_Enable( level ); - return; + iterator_node = _Chain_Next( iterator_node ); } +} - the_watchdog->state = WATCHDOG_BEING_INSERTED; - _Watchdog_Sync_count++; +void _Watchdog_Insert_locked( + Watchdog_Header *header, + Watchdog_Control *the_watchdog, + ISR_lock_Context *lock_context +) +{ + if ( the_watchdog->state == WATCHDOG_INACTIVE ) { + Watchdog_Iterator iterator; + Chain_Node *current; + Chain_Node *next; + Watchdog_Interval delta; -restart: - delta_interval = the_watchdog->initial; + the_watchdog->state = WATCHDOG_BEING_INSERTED; - for ( after = _Watchdog_First( header ) ; - ; - after = _Watchdog_Next( after ) ) { + _Chain_Append_unprotected( &header->Iterators, &iterator.Node ); - if ( delta_interval == 0 || !_Watchdog_Next( after ) ) - break; + delta = the_watchdog->initial; + current = _Chain_Head( &header->Watchdogs ); - if ( delta_interval < after->delta_interval ) { - after->delta_interval -= delta_interval; - break; - } + while ( + ( next = _Chain_Next( current ) ) != _Chain_Tail( &header->Watchdogs ) + ) { + Watchdog_Control *next_watchdog; + Watchdog_Interval delta_next; - delta_interval -= after->delta_interval; + next_watchdog = (Watchdog_Control *) next; + delta_next = next_watchdog->delta_interval; - _ISR_Flash( level ); + if ( delta < delta_next ) { + _Watchdog_Insert_fixup( header, next_watchdog, delta ); + break; + } - if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) { - goto exit_insert; - } + iterator.delta_interval = delta - delta_next; + iterator.current = next; - if ( _Watchdog_Sync_level > insert_isr_nest_level ) { - _Watchdog_Sync_level = insert_isr_nest_level; - goto restart; - } - } + _Watchdog_Flash( header, lock_context ); + + if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) { + goto abort_insert; + } - _Watchdog_Activate( the_watchdog ); + delta = iterator.delta_interval; + current = iterator.current; + } - the_watchdog->delta_interval = delta_interval; + the_watchdog->delta_interval = delta; + the_watchdog->start_time = _Watchdog_Ticks_since_boot; + _Watchdog_Activate( the_watchdog ); + _Chain_Insert_unprotected( current, &the_watchdog->Node ); - _Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node ); +abort_insert: - the_watchdog->start_time = _Watchdog_Ticks_since_boot; + _Chain_Extract_unprotected( &iterator.Node ); + } +} + +void _Watchdog_Insert( + Watchdog_Header *header, + Watchdog_Control *the_watchdog +) +{ + ISR_lock_Context lock_context; -exit_insert: - _Watchdog_Sync_level = insert_isr_nest_level; - _Watchdog_Sync_count--; - _ISR_Enable( level ); + _Watchdog_Acquire( header, &lock_context ); + _Watchdog_Insert_locked( header, the_watchdog, &lock_context ); + _Watchdog_Release( header, &lock_context ); } |