summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src/watchdoginsert.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-04-15 10:53:29 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-05-19 12:00:43 +0200
commit1ccbd052910ed16131c74b0d5595c8a94066942d (patch)
treea0c675b888d112efe455165bde2d9f0803392d3f /cpukit/score/src/watchdoginsert.c
parentscore: Add _Watchdog_Acquire|Release|Flash() (diff)
downloadrtems-1ccbd052910ed16131c74b0d5595c8a94066942d.tar.bz2
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.
Diffstat (limited to 'cpukit/score/src/watchdoginsert.c')
-rw-r--r--cpukit/score/src/watchdoginsert.c112
1 files changed, 64 insertions, 48 deletions
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 <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_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 );
}