From 1ccbd052910ed16131c74b0d5595c8a94066942d Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 15 Apr 2015 10:53:29 +0200 Subject: score: Add Watchdog_Iterator Rewrite the _Watchdog_Insert(), _Watchdog_Remove() and _Watchdog_Tickle() functions to use iterator items to synchronize concurrent operations. This makes it possible to get rid of the global variables _Watchdog_Sync_level and _Watchdog_Sync_count which are a blocking point for scalable SMP solutions. Update #2307. --- cpukit/score/src/watchdoginsert.c | 112 ++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 48 deletions(-) (limited to 'cpukit/score/src/watchdoginsert.c') diff --git a/cpukit/score/src/watchdoginsert.c b/cpukit/score/src/watchdoginsert.c index 0ad59ff61a..6d2df8222f 100644 --- a/cpukit/score/src/watchdoginsert.c +++ b/cpukit/score/src/watchdoginsert.c @@ -19,76 +19,92 @@ #endif #include -#include -#include -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_lock_Context lock_context; - 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; - insert_isr_nest_level = _ISR_Nest_level; + iterator_node = _Chain_First( &header->Iterators ); + iterator_tail = _Chain_Immutable_tail( &header->Iterators ); - _Watchdog_Acquire( header, &lock_context ); + while ( iterator_node != iterator_tail ) { + Watchdog_Iterator *iterator; - /* - * Check to see if the watchdog has just been inserted by a - * higher priority interrupt. If so, abandon this insert. - */ + iterator = (Watchdog_Iterator *) iterator_node; - if ( the_watchdog->state != WATCHDOG_INACTIVE ) { - _Watchdog_Release( header, &lock_context ); - return; + if ( iterator->current == &next_watchdog->Node ) { + iterator->delta_interval -= delta; + } + + iterator_node = _Chain_Next( iterator_node ); } +} - the_watchdog->state = WATCHDOG_BEING_INSERTED; - _Watchdog_Sync_count++; +void _Watchdog_Insert( + Watchdog_Header *header, + Watchdog_Control *the_watchdog +) +{ + ISR_lock_Context lock_context; -restart: - delta_interval = the_watchdog->initial; + _Watchdog_Acquire( header, &lock_context ); - for ( after = _Watchdog_First( header ) ; - ; - after = _Watchdog_Next( after ) ) { + if ( the_watchdog->state == WATCHDOG_INACTIVE ) { + Watchdog_Iterator iterator; + Chain_Node *current; + Chain_Node *next; + Watchdog_Interval delta; - if ( delta_interval == 0 || !_Watchdog_Next( after ) ) - break; + the_watchdog->state = WATCHDOG_BEING_INSERTED; - if ( delta_interval < after->delta_interval ) { - after->delta_interval -= delta_interval; - break; - } + _Chain_Append_unprotected( &header->Iterators, &iterator.Node ); - delta_interval -= after->delta_interval; + delta = the_watchdog->initial; + current = _Chain_Head( &header->Watchdogs ); - _Watchdog_Flash( header, &lock_context ); + while ( + ( next = _Chain_Next( current ) ) != _Chain_Tail( &header->Watchdogs ) + ) { + Watchdog_Control *next_watchdog; + Watchdog_Interval delta_next; - if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) { - goto exit_insert; - } + next_watchdog = (Watchdog_Control *) next; + delta_next = next_watchdog->delta_interval; - if ( _Watchdog_Sync_level > insert_isr_nest_level ) { - _Watchdog_Sync_level = insert_isr_nest_level; - goto restart; - } - } + if ( delta < delta_next ) { + _Watchdog_Insert_fixup( header, next_watchdog, delta ); + break; + } + + iterator.delta_interval = delta - delta_next; + iterator.current = next; - _Watchdog_Activate( the_watchdog ); + _Watchdog_Flash( header, &lock_context ); - the_watchdog->delta_interval = delta_interval; + if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) { + goto abort_insert; + } - _Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node ); + delta = iterator.delta_interval; + current = iterator.current; + } - the_watchdog->start_time = _Watchdog_Ticks_since_boot; + the_watchdog->delta_interval = delta; + the_watchdog->start_time = _Watchdog_Ticks_since_boot; + _Watchdog_Activate( the_watchdog ); + _Chain_Insert_unprotected( current, &the_watchdog->Node ); + +abort_insert: + + _Chain_Extract_unprotected( &iterator.Node ); + } -exit_insert: - _Watchdog_Sync_level = insert_isr_nest_level; - _Watchdog_Sync_count--; _Watchdog_Release( header, &lock_context ); } -- cgit v1.2.3