summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-02-18 08:36:26 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-03-04 13:36:10 +0100
commit03b900d3ed120ea919ea3eded7edbece3488cff3 (patch)
tree182781fc14fe15fd67caeb80e46f1c58495839c2 /cpukit/score/src
parentscore: Distribute clock tick to all online CPUs (diff)
downloadrtems-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.c2
-rw-r--r--cpukit/score/src/coretodset.c28
-rw-r--r--cpukit/score/src/coretodtickle.c36
-rw-r--r--cpukit/score/src/kern_tc.c3
-rw-r--r--cpukit/score/src/smp.c1
-rw-r--r--cpukit/score/src/threadinitialize.c4
-rw-r--r--cpukit/score/src/threadqenqueue.c10
-rw-r--r--cpukit/score/src/threadrestart.c12
-rw-r--r--cpukit/score/src/threadtimeout.c4
-rw-r--r--cpukit/score/src/watchdog.c36
-rw-r--r--cpukit/score/src/watchdogadjust.c80
-rw-r--r--cpukit/score/src/watchdoginsert.c132
-rw-r--r--cpukit/score/src/watchdogremove.c172
-rw-r--r--cpukit/score/src/watchdogtick.c78
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 );
}