diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-02-18 08:36:26 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-03-04 13:36:10 +0100 |
commit | 03b900d3ed120ea919ea3eded7edbece3488cff3 (patch) | |
tree | 182781fc14fe15fd67caeb80e46f1c58495839c2 /cpukit/score/src | |
parent | score: Distribute clock tick to all online CPUs (diff) | |
download | rtems-03b900d3ed120ea919ea3eded7edbece3488cff3.tar.bz2 |
score: Replace watchdog handler implementation
Use a red-black tree instead of delta chains.
Close #2344.
Update #2554.
Update #2555.
Close #2606.
Diffstat (limited to 'cpukit/score/src')
-rw-r--r-- | cpukit/score/src/condition.c | 2 | ||||
-rw-r--r-- | cpukit/score/src/coretodset.c | 28 | ||||
-rw-r--r-- | cpukit/score/src/coretodtickle.c | 36 | ||||
-rw-r--r-- | cpukit/score/src/kern_tc.c | 3 | ||||
-rw-r--r-- | cpukit/score/src/smp.c | 1 | ||||
-rw-r--r-- | cpukit/score/src/threadinitialize.c | 4 | ||||
-rw-r--r-- | cpukit/score/src/threadqenqueue.c | 10 | ||||
-rw-r--r-- | cpukit/score/src/threadrestart.c | 12 | ||||
-rw-r--r-- | cpukit/score/src/threadtimeout.c | 4 | ||||
-rw-r--r-- | cpukit/score/src/watchdog.c | 36 | ||||
-rw-r--r-- | cpukit/score/src/watchdogadjust.c | 80 | ||||
-rw-r--r-- | cpukit/score/src/watchdoginsert.c | 132 | ||||
-rw-r--r-- | cpukit/score/src/watchdogremove.c | 172 | ||||
-rw-r--r-- | cpukit/score/src/watchdogtick.c | 78 |
14 files changed, 157 insertions, 441 deletions
diff --git a/cpukit/score/src/condition.c b/cpukit/score/src/condition.c index 22c2a9b97c..420681955a 100644 --- a/cpukit/score/src/condition.c +++ b/cpukit/score/src/condition.c @@ -282,7 +282,7 @@ static int _Condition_Wake( struct _Condition_Control *_condition, int count ) next = _Chain_Next( node ); thread = THREAD_CHAIN_NODE_TO_THREAD( node ); - _Watchdog_Remove_ticks( &thread->Timer ); + _Thread_Timer_remove( thread ); _Thread_Unblock( thread ); node = next; diff --git a/cpukit/score/src/coretodset.c b/cpukit/score/src/coretodset.c index 3230179414..b2efc07115 100644 --- a/cpukit/score/src/coretodset.c +++ b/cpukit/score/src/coretodset.c @@ -26,30 +26,26 @@ void _TOD_Set_with_timestamp( const Timestamp_Control *tod_as_timestamp ) { - struct timespec ts; - uint32_t nanoseconds; - Watchdog_Interval seconds_next; - Watchdog_Interval seconds_now; - Watchdog_Header *header; + struct timespec tod_as_timespec; + uint64_t tod_as_ticks; + uint32_t cpu_count; + uint32_t cpu_index; - _Timestamp_To_timespec( tod_as_timestamp, &ts ); - nanoseconds = ts.tv_nsec; - seconds_next = ts.tv_sec; + _Timestamp_To_timespec( tod_as_timestamp, &tod_as_timespec ); _Thread_Disable_dispatch(); - seconds_now = _TOD_Seconds_since_epoch(); + _Timecounter_Set_clock( &tod_as_timespec ); - _Timecounter_Set_clock( &ts ); + tod_as_ticks = _Watchdog_Ticks_from_timespec( &tod_as_timespec ); + cpu_count = _SMP_Get_processor_count(); - header = &_Watchdog_Seconds_header; + for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) { + Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); - if ( seconds_next < seconds_now ) - _Watchdog_Adjust_backward( header, seconds_now - seconds_next ); - else - _Watchdog_Adjust_forward( header, seconds_next - seconds_now ); + _Watchdog_Per_CPU_tickle_absolute( cpu, tod_as_ticks ); + } - _TOD.seconds_trigger = nanoseconds; _TOD.is_set = true; _Thread_Enable_dispatch(); diff --git a/cpukit/score/src/coretodtickle.c b/cpukit/score/src/coretodtickle.c deleted file mode 100644 index 3d7c71e1c1..0000000000 --- a/cpukit/score/src/coretodtickle.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file - * - * @brief Increments time of day at each clock tick - * - * @ingroup ScoreTOD - */ - -/* COPYRIGHT (c) 1989-2014. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include <rtems/score/todimpl.h> -#include <rtems/score/watchdogimpl.h> -#include <rtems/config.h> - -void _TOD_Tickle_ticks( void ) -{ - /* Update the counter of ticks since boot */ - _Watchdog_Ticks_since_boot += 1; - - _TOD.seconds_trigger += rtems_configuration_get_nanoseconds_per_tick(); - if ( _TOD.seconds_trigger >= 1000000000UL ) { - _TOD.seconds_trigger -= 1000000000UL; - _Watchdog_Tickle_seconds(); - } -} - diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c index e56c292ea3..316a16f05b 100644 --- a/cpukit/score/src/kern_tc.c +++ b/cpukit/score/src/kern_tc.c @@ -1971,6 +1971,7 @@ tc_ticktock(int cnt) return; count = 0; #else /* __rtems__ */ +#include <rtems/score/smp.h> void _Timecounter_Tick(void) { @@ -2021,7 +2022,7 @@ _Timecounter_Tick_simple(uint32_t delta, uint32_t offset, _Timecounter_Release(lock_context); - _Watchdog_Tick(_Per_CPU_Get()); + _Watchdog_Tick(_Per_CPU_Get_snapshot()); } #endif /* __rtems__ */ diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c index 9d9507d1b9..85256b044c 100644 --- a/cpukit/score/src/smp.c +++ b/cpukit/score/src/smp.c @@ -87,6 +87,7 @@ void _SMP_Handler_initialize( void ) for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) { Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); + _ISR_lock_Initialize( &cpu->Watchdog.Lock, "Watchdog" ); _SMP_ticket_lock_Initialize( &cpu->Lock ); _SMP_lock_Stats_initialize( &cpu->Lock_stats, "Per-CPU" ); } diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c index a49406f160..0b5fd3a125 100644 --- a/cpukit/score/src/threadinitialize.c +++ b/cpukit/score/src/threadinitialize.c @@ -160,6 +160,10 @@ bool _Thread_Initialize( the_thread->Start.budget_algorithm = budget_algorithm; the_thread->Start.budget_callout = budget_callout; + _ISR_lock_Initialize( &the_thread->Timer.Lock, "Thread Timer" ); + the_thread->Timer.header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ]; + _Watchdog_Preinitialize( &the_thread->Timer.Watchdog, cpu ); + switch ( budget_algorithm ) { case THREAD_CPU_BUDGET_ALGORITHM_NONE: case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE: diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c index 960783c74c..07618fc800 100644 --- a/cpukit/score/src/threadqenqueue.c +++ b/cpukit/score/src/threadqenqueue.c @@ -35,7 +35,7 @@ static void _Thread_queue_Unblock( Thread_Control *the_thread ) { - _Watchdog_Remove_ticks( &the_thread->Timer ); + _Thread_Timer_remove( the_thread ); _Thread_Unblock( the_thread ); #if defined(RTEMS_MULTIPROCESSING) @@ -84,8 +84,12 @@ void _Thread_queue_Enqueue_critical( */ if ( timeout != WATCHDOG_NO_TIMEOUT ) { _Thread_Wait_set_timeout_code( the_thread, timeout_code ); - _Watchdog_Initialize( &the_thread->Timer, _Thread_Timeout, 0, the_thread ); - _Watchdog_Insert_ticks( &the_thread->Timer, timeout ); + _Thread_Timer_insert_relative( + the_thread, + cpu_self, + _Thread_Timeout, + timeout + ); } success = _Thread_Wait_flags_try_change( diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c index 03b1fba8ff..d366f97a0f 100644 --- a/cpukit/score/src/threadrestart.c +++ b/cpukit/score/src/threadrestart.c @@ -84,7 +84,7 @@ static void _Thread_Make_zombie( Thread_Control *the_thread ) _Thread_Set_state( the_thread, STATES_ZOMBIE ); _Thread_queue_Extract_with_proxy( the_thread ); - _Watchdog_Remove_ticks( &the_thread->Timer ); + _Thread_Timer_remove( the_thread ); _ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context ); _Chain_Append_unprotected( &zombies->Chain, &the_thread->Object.Node ); @@ -191,7 +191,9 @@ static void _Thread_Start_life_change_for_executing( Thread_Control *executing ) { - _Assert( executing->Timer.state == WATCHDOG_INACTIVE ); + _Assert( + _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE + ); _Assert( executing->current_state == STATES_READY || executing->current_state == STATES_SUSPENDED @@ -246,7 +248,9 @@ void _Thread_Life_action_handler( /* Someone deleted us in the mean-time */ _Thread_Start_life_change_for_executing( executing ); } else { - _Assert( executing->Timer.state == WATCHDOG_INACTIVE ); + _Assert( + _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE + ); _Assert( executing->current_state == STATES_READY || executing->current_state == STATES_SUSPENDED @@ -274,7 +278,7 @@ static void _Thread_Start_life_change( _Thread_Set_state( the_thread, STATES_RESTARTING ); _Thread_queue_Extract_with_proxy( the_thread ); - _Watchdog_Remove_ticks( &the_thread->Timer ); + _Thread_Timer_remove( the_thread ); _Thread_Change_priority( the_thread, priority, diff --git a/cpukit/score/src/threadtimeout.c b/cpukit/score/src/threadtimeout.c index 8ecaebde06..59f6bd97f0 100644 --- a/cpukit/score/src/threadtimeout.c +++ b/cpukit/score/src/threadtimeout.c @@ -33,7 +33,7 @@ static void _Thread_Do_timeout( Thread_Control *the_thread ) _Thread_Lock_restore_default( the_thread ); } -void _Thread_Timeout( Objects_Id id, void *arg ) +void _Thread_Timeout( Watchdog_Control *watchdog ) { Thread_Control *the_thread; void *thread_lock; @@ -41,7 +41,7 @@ void _Thread_Timeout( Objects_Id id, void *arg ) Thread_Wait_flags wait_flags; bool unblock; - the_thread = arg; + the_thread = RTEMS_CONTAINER_OF( watchdog, Thread_Control, Timer.Watchdog ); thread_lock = _Thread_Lock_acquire( the_thread, &lock_context ); wait_flags = _Thread_Wait_flags_get( the_thread ); diff --git a/cpukit/score/src/watchdog.c b/cpukit/score/src/watchdog.c deleted file mode 100644 index 8d172fb8f9..0000000000 --- a/cpukit/score/src/watchdog.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file - * - * @brief Watchdog Handler Initialization - * @ingroup ScoreWatchdog - */ - -/* - * Watchdog Handler - * - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include <rtems/score/watchdogimpl.h> - -Watchdog_Header _Watchdog_Ticks_header; - -Watchdog_Header _Watchdog_Seconds_header; - -void _Watchdog_Handler_initialization( void ) -{ - _Watchdog_Ticks_since_boot = 0; - - _Watchdog_Header_initialize( &_Watchdog_Ticks_header ); - _Watchdog_Header_initialize( &_Watchdog_Seconds_header ); -} diff --git a/cpukit/score/src/watchdogadjust.c b/cpukit/score/src/watchdogadjust.c deleted file mode 100644 index 32b5f7990e..0000000000 --- a/cpukit/score/src/watchdogadjust.c +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file - * - * @brief Watchdog Adjust - * @ingroup ScoreWatchdog - */ - -/* - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include <rtems/score/watchdogimpl.h> - -void _Watchdog_Adjust_backward_locked( - Watchdog_Header *header, - Watchdog_Interval units -) -{ - if ( !_Watchdog_Is_empty( header ) ) { - _Watchdog_First( header )->delta_interval += units; - } -} - -void _Watchdog_Adjust_backward( - Watchdog_Header *header, - Watchdog_Interval units -) -{ - ISR_lock_Context lock_context; - - _Watchdog_Acquire( header, &lock_context ); - _Watchdog_Adjust_backward_locked( header, units ); - _Watchdog_Release( header, &lock_context ); -} - -void _Watchdog_Adjust_forward_locked( - Watchdog_Header *header, - Watchdog_Interval units, - ISR_lock_Context *lock_context -) -{ - while ( !_Watchdog_Is_empty( header ) && units > 0 ) { - Watchdog_Control *first = _Watchdog_First( header ); - - if ( units < first->delta_interval ) { - first->delta_interval -= units; - break; - } else { - units -= first->delta_interval; - first->delta_interval = 1; - - _Watchdog_Release( header, lock_context ); - - _Watchdog_Tickle( header ); - - _Watchdog_Acquire( header, lock_context ); - } - } -} - -void _Watchdog_Adjust_forward( - Watchdog_Header *header, - Watchdog_Interval units -) -{ - ISR_lock_Context lock_context; - - _Watchdog_Acquire( header, &lock_context ); - _Watchdog_Adjust_forward_locked( header, units, &lock_context ); - _Watchdog_Release( header, &lock_context ); -} diff --git a/cpukit/score/src/watchdoginsert.c b/cpukit/score/src/watchdoginsert.c index db15f55b0d..22fc7a5f76 100644 --- a/cpukit/score/src/watchdoginsert.c +++ b/cpukit/score/src/watchdoginsert.c @@ -1,17 +1,22 @@ /** - * @file + * @file * * @brief Watchdog Insert * @ingroup ScoreWatchdog */ - + /* - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. */ #if HAVE_CONFIG_H @@ -20,106 +25,41 @@ #include <rtems/score/watchdogimpl.h> -static void _Watchdog_Insert_fixup( - Watchdog_Header *header, - Watchdog_Control *the_watchdog, - Watchdog_Interval delta, - Watchdog_Control *next_watchdog, - Watchdog_Interval delta_next -) -{ - const Chain_Node *iterator_tail; - Chain_Node *iterator_node; - - next_watchdog->delta_interval = delta_next - delta; - - iterator_node = _Chain_First( &header->Iterators ); - iterator_tail = _Chain_Immutable_tail( &header->Iterators ); - - while ( iterator_node != iterator_tail ) { - Watchdog_Iterator *iterator; - - iterator = (Watchdog_Iterator *) iterator_node; - - if ( iterator->current == &next_watchdog->Node ) { - iterator->current = &the_watchdog->Node; - } - - iterator_node = _Chain_Next( iterator_node ); - } -} - -void _Watchdog_Insert_locked( +void _Watchdog_Insert( Watchdog_Header *header, Watchdog_Control *the_watchdog, - ISR_lock_Context *lock_context + uint64_t expire ) { - if ( the_watchdog->state == WATCHDOG_INACTIVE ) { - Watchdog_Iterator iterator; - Chain_Node *current; - Chain_Node *next; - Watchdog_Interval delta; - - the_watchdog->state = WATCHDOG_BEING_INSERTED; - - _Chain_Append_unprotected( &header->Iterators, &iterator.Node ); - - delta = the_watchdog->initial; - current = _Chain_Head( &header->Watchdogs ); + RBTree_Node **link; + RBTree_Node *parent; + RBTree_Node *old_first; + RBTree_Node *new_first; - while ( - ( next = _Chain_Next( current ) ) != _Chain_Tail( &header->Watchdogs ) - ) { - Watchdog_Control *next_watchdog; - Watchdog_Interval delta_next; + _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE ); - next_watchdog = (Watchdog_Control *) next; - delta_next = next_watchdog->delta_interval; + link = _RBTree_Root_reference( &header->Watchdogs ); + parent = NULL; + old_first = header->first; + new_first = &the_watchdog->Node.RBTree; - if ( delta < delta_next ) { - _Watchdog_Insert_fixup( - header, - the_watchdog, - delta, - next_watchdog, - delta_next - ); - break; - } + the_watchdog->expire = expire; - iterator.delta_interval = delta - delta_next; - iterator.current = next; + while ( *link != NULL ) { + Watchdog_Control *parent_watchdog; - _Watchdog_Flash( header, lock_context ); + parent = *link; + parent_watchdog = (Watchdog_Control *) parent; - if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) { - goto abort_insert; - } - - delta = iterator.delta_interval; - current = iterator.current; + if ( expire < parent_watchdog->expire ) { + link = _RBTree_Left_reference( parent ); + } else { + link = _RBTree_Right_reference( parent ); + new_first = old_first; } - - 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 ); } -} - -void _Watchdog_Insert( - Watchdog_Header *header, - Watchdog_Control *the_watchdog -) -{ - ISR_lock_Context lock_context; - _Watchdog_Acquire( header, &lock_context ); - _Watchdog_Insert_locked( header, the_watchdog, &lock_context ); - _Watchdog_Release( header, &lock_context ); + header->first = new_first; + _RBTree_Add_child( &the_watchdog->Node.RBTree, parent, link ); + _RBTree_Insert_color( &header->Watchdogs, &the_watchdog->Node.RBTree ); } diff --git a/cpukit/score/src/watchdogremove.c b/cpukit/score/src/watchdogremove.c index 2aa72a4e75..2605a67fa4 100644 --- a/cpukit/score/src/watchdogremove.c +++ b/cpukit/score/src/watchdogremove.c @@ -1,17 +1,22 @@ /** * @file * - * @brief Remove Watchdog from List + * @brief Remove Watchdog * @ingroup ScoreWatchdog */ /* - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. */ #if HAVE_CONFIG_H @@ -19,161 +24,18 @@ #endif #include <rtems/score/watchdogimpl.h> -#include <rtems/score/assert.h> - -static void _Watchdog_Remove_it( - Watchdog_Header *header, - Watchdog_Control *the_watchdog -) -{ - Chain_Node *next; - Watchdog_Interval delta; - const Chain_Node *iterator_tail; - Chain_Node *iterator_node; - - _Assert( the_watchdog->state == WATCHDOG_ACTIVE ); - - the_watchdog->state = WATCHDOG_INACTIVE; - the_watchdog->stop_time = _Watchdog_Ticks_since_boot; - - next = _Chain_Next( &the_watchdog->Node ); - delta = the_watchdog->delta_interval; - - if ( next != _Chain_Tail( &header->Watchdogs ) ) { - Watchdog_Control *next_watchdog; - - next_watchdog = (Watchdog_Control *) next; - next_watchdog->delta_interval += delta; - } - - _Chain_Extract_unprotected( &the_watchdog->Node ); - - iterator_node = _Chain_First( &header->Iterators ); - iterator_tail = _Chain_Immutable_tail( &header->Iterators ); - - while ( iterator_node != iterator_tail ) { - Watchdog_Iterator *iterator; - - iterator = (Watchdog_Iterator *) iterator_node; - - if ( iterator->current == next ) { - iterator->delta_interval += delta; - } - - if ( iterator->current == &the_watchdog->Node ) { - Chain_Node *previous = _Chain_Previous( &the_watchdog->Node ); - - iterator->current = previous; - - if ( previous != _Chain_Head( &header->Watchdogs ) ) { - Watchdog_Control *previous_watchdog; - - previous_watchdog = (Watchdog_Control *) previous; - iterator->delta_interval += previous_watchdog->delta_interval; - } - } - - iterator_node = _Chain_Next( iterator_node ); - } -} -Watchdog_States _Watchdog_Remove( +void _Watchdog_Remove( Watchdog_Header *header, Watchdog_Control *the_watchdog ) { - ISR_lock_Context lock_context; - Watchdog_States previous_state; - Watchdog_Interval now; - - _Watchdog_Acquire( header, &lock_context ); - previous_state = the_watchdog->state; - switch ( previous_state ) { - case WATCHDOG_INACTIVE: - break; - - case WATCHDOG_BEING_INSERTED: - - /* - * It is not actually on the chain so just change the state and - * the Insert operation we interrupted will be aborted. - */ - the_watchdog->state = WATCHDOG_INACTIVE; - now = _Watchdog_Ticks_since_boot; - the_watchdog->start_time = now; - the_watchdog->stop_time = now; - break; - - case WATCHDOG_ACTIVE: - _Watchdog_Remove_it( header, the_watchdog ); - break; - } - - _Watchdog_Release( header, &lock_context ); - return( previous_state ); -} - -void _Watchdog_Tickle( - Watchdog_Header *header -) -{ - ISR_lock_Context lock_context; - - _Watchdog_Acquire( header, &lock_context ); - - if ( !_Watchdog_Is_empty( header ) ) { - Watchdog_Control *first; - Watchdog_Interval delta; - - first = _Watchdog_First( header ); - delta = first->delta_interval; - - /* - * Although it is forbidden to insert watchdogs with a delta interval of - * zero it is possible to observe watchdogs with a delta interval of zero - * at this point. For example lets have a watchdog chain of one watchdog - * with a delta interval of one and insert a new one with an initial value - * of one. At the start of the insert procedure it will advance one step - * and reduce its delta interval by one yielding zero. Now a tick happens. - * This will remove the watchdog on the chain and update the insert - * iterator. Now the insert operation continues and will insert the new - * watchdog with a delta interval of zero. - */ - if ( delta > 0 ) { - --delta; - first->delta_interval = delta; + if ( _Watchdog_Is_scheduled( the_watchdog ) ) { + if ( header->first == &the_watchdog->Node.RBTree ) { + _Watchdog_Next_first( header, the_watchdog ); } - while ( delta == 0 ) { - bool run; - Watchdog_Service_routine_entry routine; - Objects_Id id; - void *user_data; - - run = ( first->state == WATCHDOG_ACTIVE ); - - _Watchdog_Remove_it( header, first ); - - routine = first->routine; - id = first->id; - user_data = first->user_data; - - _Watchdog_Release( header, &lock_context ); - - if ( run ) { - (*routine)( id, user_data ); - } - - _Watchdog_Acquire( header, &lock_context ); - - if ( _Watchdog_Is_empty( header ) ) { - break; - } - - first = _Watchdog_First( header ); - delta = first->delta_interval; - } + _RBTree_Extract( &header->Watchdogs, &the_watchdog->Node.RBTree ); + _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE ); } - - _Watchdog_Release( header, &lock_context ); } diff --git a/cpukit/score/src/watchdogtick.c b/cpukit/score/src/watchdogtick.c index e89c088350..ab7eadcf1d 100644 --- a/cpukit/score/src/watchdogtick.c +++ b/cpukit/score/src/watchdogtick.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 embedded brains GmbH. All rights reserved. + * Copyright (c) 2015, 2016 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -12,25 +12,81 @@ * http://www.rtems.org/license/LICENSE. */ -#include <rtems/score/assert.h> +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/score/watchdogimpl.h> #include <rtems/score/schedulerimpl.h> #include <rtems/score/threaddispatch.h> -#include <rtems/score/todimpl.h> -#include <rtems/score/watchdogimpl.h> +#include <rtems/score/timecounter.h> -#if HAVE_CONFIG_H -#include "config.h" +void _Watchdog_Do_tickle( + Watchdog_Header *header, + uint64_t now, +#ifdef RTEMS_SMP + ISR_lock_Control *lock, #endif + ISR_lock_Context *lock_context +) +{ + while ( true ) { + Watchdog_Control *the_watchdog; + + the_watchdog = (Watchdog_Control *) header->first; + + if ( the_watchdog == NULL ) { + break; + } + + if ( the_watchdog->expire <= now ) { + Watchdog_Service_routine_entry routine; + + _Watchdog_Next_first( header, the_watchdog ); + _RBTree_Extract( &header->Watchdogs, &the_watchdog->Node.RBTree ); + _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE ); + routine = the_watchdog->routine; + + _ISR_lock_Release_and_ISR_enable( lock, lock_context ); + ( *routine )( the_watchdog ); + _ISR_lock_ISR_disable_and_acquire( lock, lock_context ); + } else { + break; + } + } + + _ISR_lock_Release_and_ISR_enable( lock, lock_context ); +} void _Watchdog_Tick( Per_CPU_Control *cpu ) { - _Assert( !_Thread_Dispatch_is_enabled() ); + ISR_lock_Context lock_context; + uint64_t ticks; + struct timespec now; if ( _Per_CPU_Is_boot_processor( cpu ) ) { - _TOD_Tickle_ticks(); + ++_Watchdog_Ticks_since_boot; + } - _Watchdog_Tickle_ticks(); + _ISR_lock_ISR_disable_and_acquire( &cpu->Watchdog.Lock, &lock_context ); - _Scheduler_Tick(); - } + ticks = cpu->Watchdog.ticks; + _Assert( ticks < UINT64_MAX ); + ++ticks; + cpu->Watchdog.ticks = ticks; + + _Watchdog_Tickle( + &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ], + ticks, + &cpu->Watchdog.Lock, + &lock_context + ); + + _Timecounter_Getnanotime( &now ); + _Watchdog_Per_CPU_tickle_absolute( + cpu, + _Watchdog_Ticks_from_timespec( &now ) + ); + + _Scheduler_Tick( cpu ); } |