Watchdog_States _Watchdog_Remove( Watchdog_Control *the_watchdog ) { ISR_Level level; Watchdog_States previous_state; Watchdog_Control *next_watchdog; _ISR_Disable( level ); 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; break; case WATCHDOG_ACTIVE: case WATCHDOG_REMOVE_IT: the_watchdog->state = WATCHDOG_INACTIVE; next_watchdog = _Watchdog_Next( the_watchdog ); if ( _Watchdog_Next(next_watchdog) ) next_watchdog->delta_interval += the_watchdog->delta_interval; if ( _Watchdog_Sync_count ) _Watchdog_Sync_level = _ISR_Nest_level; _Chain_Extract_unprotected( &the_watchdog->Node ); break; } the_watchdog->stop_time = _Watchdog_Ticks_since_boot; _ISR_Enable( level ); return( previous_state ); }
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 ); }