summaryrefslogblamecommitdiffstats
path: root/cpukit/score/src/watchdoginsert.c
blob: 6d2df8222f4df531fca9d02be199af1707b54db0 (plain) (tree)
1
2
3
4
5
6
7
8
9

         
  




                         
                            
                                                    


                                                           
                                         

   



                   
                                     
 



                                   

 

                                  
 
                                         
 

                                                              
 

                                            
 
                                                   
 




                                                      
   
 
 





                                
 
                                             
 




                                                   
 
                                                  
 
                                                                    
 

                                                
 




                                                                            
 

                                                 
 






                                                               
 
                                               
 


                                                             
 


                                      
 








                                                              
 
                                             
 
/**
 * @file 
 *
 * @brief Watchdog Insert
 * @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>

static void _Watchdog_Insert_fixup(
  Watchdog_Header   *header,
  Watchdog_Control  *next_watchdog,
  Watchdog_Interval  delta
)
{
  const Chain_Node *iterator_tail;
  Chain_Node       *iterator_node;

  next_watchdog->delta_interval -= 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->delta_interval -= delta;
    }

    iterator_node = _Chain_Next( iterator_node );
  }
}

void _Watchdog_Insert(
  Watchdog_Header  *header,
  Watchdog_Control *the_watchdog
)
{
  ISR_lock_Context lock_context;

  _Watchdog_Acquire( header, &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 );
  }

  _Watchdog_Release( header, &lock_context );
}