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; the_watchdog->state = WATCHDOG_BEING_INSERTED; _Chain_Append_unprotected( &header->Iterators, &iterator.Node ); delta = the_watchdog->initial; current = _Chain_Head( &header->Watchdogs ); while ( ( next = _Chain_Next( current ) ) != _Chain_Tail( &header->Watchdogs ) ) { Watchdog_Control *next_watchdog; Watchdog_Interval delta_next; next_watchdog = (Watchdog_Control *) next; delta_next = next_watchdog->delta_interval; if ( delta < delta_next ) { _Watchdog_Insert_fixup( header, next_watchdog, delta ); break; } iterator.delta_interval = delta - delta_next; iterator.current = next; _Watchdog_Flash( header, lock_context ); if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) { goto abort_insert; } delta = iterator.delta_interval; current = iterator.current; } 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( Chain_Control *header, Watchdog_Control *the_watchdog ) { ISR_Level level; Watchdog_Control *after; uint32_t insert_isr_nest_level; Watchdog_Interval delta_interval; insert_isr_nest_level = _ISR_Nest_level; _ISR_Disable( level ); /* * Check to see if the watchdog has just been inserted by a * higher priority interrupt. If so, abandon this insert. */ if ( the_watchdog->state != WATCHDOG_INACTIVE ) { _ISR_Enable( level ); return; } the_watchdog->state = WATCHDOG_BEING_INSERTED; _Watchdog_Sync_count++; restart: delta_interval = the_watchdog->initial; /* * We CANT use _Watchdog_First() here, because a TICK interrupt * could modify the chain during the _ISR_Flash() below. Hence, * the header is pointing to volatile data. The _Watchdog_First() * INLINE routine (but not the macro - note the subtle difference) * casts away the 'volatile'... * * Also, this is only necessary because we call no other routine * from this piece of code, hence the compiler thinks it's safe to * cache *header!! * * Till Straumann, 7/2003 (gcc-3.2.2 -O4 on powerpc) * */ for ( after = (Watchdog_Control *) ((volatile Chain_Control *)header)->first ; ; after = _Watchdog_Next( after ) ) { if ( delta_interval == 0 || !_Watchdog_Next( after ) ) break; if ( delta_interval < after->delta_interval ) { after->delta_interval -= delta_interval; break; } delta_interval -= after->delta_interval; /* * If you experience problems comment out the _ISR_Flash line. * 3.2.0 was the first release with this critical section redesigned. * Under certain circumstances, the PREVIOUS critical section algorithm * used around this flash point allowed interrupts to execute * which violated the design assumptions. The critical section * mechanism used here WAS redesigned to address this. */ _ISR_Flash( level ); if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) { goto exit_insert; } if ( _Watchdog_Sync_level > insert_isr_nest_level ) { _Watchdog_Sync_level = insert_isr_nest_level; goto restart; } } _Watchdog_Activate( the_watchdog ); the_watchdog->delta_interval = delta_interval; _Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node ); the_watchdog->start_time = _Watchdog_Ticks_since_boot; exit_insert: _Watchdog_Sync_level = insert_isr_nest_level; _Watchdog_Sync_count--; _ISR_Enable( level ); }
void _Watchdog_Insert( Watchdog_Header *header, Watchdog_Control *the_watchdog ) { ISR_Level level; Watchdog_Control *after; uint32_t insert_isr_nest_level; Watchdog_Interval delta_interval; insert_isr_nest_level = _ISR_Nest_level; _ISR_Disable( level ); /* * Check to see if the watchdog has just been inserted by a * higher priority interrupt. If so, abandon this insert. */ if ( the_watchdog->state != WATCHDOG_INACTIVE ) { _ISR_Enable( level ); return; } the_watchdog->state = WATCHDOG_BEING_INSERTED; _Watchdog_Sync_count++; restart: delta_interval = the_watchdog->initial; for ( after = _Watchdog_First( header ) ; ; after = _Watchdog_Next( after ) ) { if ( delta_interval == 0 || !_Watchdog_Next( after ) ) break; if ( delta_interval < after->delta_interval ) { after->delta_interval -= delta_interval; break; } delta_interval -= after->delta_interval; _ISR_Flash( level ); if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) { goto exit_insert; } if ( _Watchdog_Sync_level > insert_isr_nest_level ) { _Watchdog_Sync_level = insert_isr_nest_level; goto restart; } } _Watchdog_Activate( the_watchdog ); the_watchdog->delta_interval = delta_interval; _Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node ); the_watchdog->start_time = _Watchdog_Ticks_since_boot; exit_insert: _Watchdog_Sync_level = insert_isr_nest_level; _Watchdog_Sync_count--; _ISR_Enable( level ); }