Ejemplo n.º 1
0
static rtems_task Init(rtems_task_argument ignored)
{
    Freechain_Control fc;
    test_node *node;

    TEST_BEGIN();

    _Freechain_Initialize(&fc, NULL, 0, sizeof(test_node));
    rtems_test_assert(_Chain_Is_empty(&fc.Free));

    _Freechain_Initialize(&fc, malloc, 1, SIZE_MAX);
    rtems_test_assert(_Chain_Is_empty(&fc.Free));

    rtems_test_assert(_Freechain_Get(&fc, NULL, 0, sizeof(test_node)) == NULL);

    rtems_test_assert(_Freechain_Get(&fc, malloc, 1, SIZE_MAX) == NULL);

    /* check whether freechain put and get works correctly*/

    _Freechain_Put(&fc, NULL);

    puts( "INIT - Get node from freechain - OK" );
    node = _Freechain_Get(&fc, malloc, 1, sizeof(test_node));
    node->x = 1;

    puts( "INIT - Put node back to freechain - OK" );
    _Freechain_Put(&fc, node);

    puts( "INIT - Verify freechain node put and get - OK" );
    node = _Freechain_Get(&fc, NULL, 0, sizeof(test_node));
    rtems_test_assert(node->x == 1);

    TEST_END();
    rtems_test_exit(0);
}
Ejemplo n.º 2
0
void _Watchdog_Adjust(
  Chain_Control               *header,
  Watchdog_Adjust_directions   direction,
  Watchdog_Interval            units
)
{
  ISR_Level level;

  _ISR_Disable( level );

  /*
   * NOTE: It is safe NOT to make 'header' a pointer
   *       to volatile data (contrast this with watchdoginsert.c)
   *       because we call _Watchdog_Tickle() below and
   *       hence the compiler must not assume *header to remain
   *       unmodified across that call.
   *
   *       Till Straumann, 7/2003
   */
  if ( !_Chain_Is_empty( header ) ) {
    switch ( direction ) {
      case WATCHDOG_BACKWARD:
        _Watchdog_First( header )->delta_interval += units;
        break;
      case WATCHDOG_FORWARD:
        while ( units ) {
          if ( units < _Watchdog_First( header )->delta_interval ) {
            _Watchdog_First( header )->delta_interval -= units;
            break;
          } else {
            units -= _Watchdog_First( header )->delta_interval;
            _Watchdog_First( header )->delta_interval = 1;

            _ISR_Enable( level );

            _Watchdog_Tickle( header );

            _ISR_Disable( level );

            if ( _Chain_Is_empty( header ) )
              break;
          }
        }
        break;
    }
  }

  _ISR_Enable( level );

}
Thread_Control *_Thread_queue_Dequeue_fifo(
  Thread_queue_Control *the_thread_queue
)
{
  ISR_Level              level;
  Thread_Control *the_thread;

  _ISR_Disable( level );
  if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) {

    the_thread = (Thread_Control *)
       _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );

    the_thread->Wait.queue = NULL;
    if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
      _ISR_Enable( level );
      _Thread_Unblock( the_thread );
    } else {
      _Watchdog_Deactivate( &the_thread->Timer );
      _ISR_Enable( level );
      (void) _Watchdog_Remove( &the_thread->Timer );
      _Thread_Unblock( the_thread );
    }

#if defined(RTEMS_MULTIPROCESSING)
    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
      _Thread_MP_Free_proxy( the_thread );
#endif

    return the_thread;
  }

  _ISR_Enable( level );
  return NULL;
}
Ejemplo n.º 4
0
static Thread_queue_Heads *_Thread_queue_Queue_enqueue(
  Thread_queue_Queue *queue,
  Thread_Control     *the_thread,
  void             ( *initialize )( Thread_queue_Heads *, Thread_Control * ),
  void             ( *enqueue )( Thread_queue_Heads *, Thread_Control * )
)
{
  Thread_queue_Heads *heads;
  Thread_queue_Heads *spare_heads;

  heads = queue->heads;
  spare_heads = the_thread->Wait.spare_heads;
  the_thread->Wait.spare_heads = NULL;

  if ( heads == NULL ) {
    _Assert( spare_heads != NULL );
    _Assert( _Chain_Is_empty( &spare_heads->Free_chain ) );

    heads = spare_heads;
    queue->heads = heads;
    _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
    ( *initialize )( heads, the_thread );
  } else {
    _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
    ( *enqueue )( heads, the_thread );
  }

  return heads;
}
void _POSIX_Threads_cancel_run(
  Thread_Control *the_thread
)
{
  POSIX_Cancel_Handler_control      *handler;
  Chain_Control                     *handler_stack;
  POSIX_API_Control                 *thread_support;
  ISR_Level                          level;

  thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ];

  handler_stack = &thread_support->Cancellation_Handlers;

  thread_support->cancelability_state = PTHREAD_CANCEL_DISABLE;

  while ( !_Chain_Is_empty( handler_stack ) ) {
    _ISR_Disable( level );
      handler = (POSIX_Cancel_Handler_control *)
           _Chain_Tail( handler_stack )->previous;
      _Chain_Extract_unprotected( &handler->Node );
    _ISR_Enable( level );

    (*handler->routine)( handler->arg );

    _Workspace_Free( handler );
  }
}
Ejemplo n.º 6
0
void _Watchdog_Report_chain(
  const char        *name,
  Chain_Control     *header
)
{
  ISR_Level          level;
  Chain_Node        *node;

  _ISR_Disable( level );
    printk( "Watchdog Chain: %s %p\n", name, header );
    if ( !_Chain_Is_empty( header ) ) {
      for ( node = _Chain_First( header ) ;
            node != _Chain_Tail(header) ;
            node = node->next )
      {
        Watchdog_Control *watch = (Watchdog_Control *) node;

        _Watchdog_Report( NULL, watch );
      }
      printk( "== end of %s \n", name );
    } else {
      printk( "Chain is empty\n" );
    }
  _ISR_Enable( level );
}
Ejemplo n.º 7
0
static void _Timer_server_Reset_tod_system_watchdog(
  Timer_server_Control *ts
)
{
  ISR_Level level;

  _Timer_server_Stop_tod_system_watchdog( ts );

  _ISR_Disable( level );
  if ( !_Chain_Is_empty( &ts->TOD_watchdogs.Chain ) ) {
    Watchdog_Interval delta_interval =
      _Watchdog_First( &ts->TOD_watchdogs.Chain )->delta_interval;
    _ISR_Enable( level );

    /*
     *  The unit is SECONDS here.
     */
    _Watchdog_Insert_seconds(
      &ts->TOD_watchdogs.System_watchdog,
      delta_interval
    );
  } else {
    _ISR_Enable( level );
  }
}
Ejemplo n.º 8
0
void *_Freechain_Get(
  Freechain_Control   *freechain,
  Freechain_Allocator  allocator,
  size_t               number_nodes_to_extend,
  size_t               node_size
)
{
  _Assert( node_size >= sizeof( Chain_Node ) );

  if ( _Chain_Is_empty( &freechain->Free ) && number_nodes_to_extend > 0 ) {
    void *starting_address;

    starting_address = ( *allocator )( number_nodes_to_extend * node_size );
    number_nodes_to_extend *= ( starting_address != NULL );

    _Chain_Initialize(
      &freechain->Free,
      starting_address,
      number_nodes_to_extend,
      node_size
    );
  }

  return _Chain_Get_unprotected( &freechain->Free );
}
boolean _POSIX_signals_Clear_signals(
  POSIX_API_Control  *api,
  int                 signo,
  siginfo_t          *info,
  boolean             is_global,
  boolean             check_blocked
)
{
  sigset_t                    mask;
  sigset_t                    signals_blocked;
  ISR_Level                   level;
  boolean                     do_callout;
  POSIX_signals_Siginfo_node *psiginfo;

  mask = signo_to_mask( signo );

  do_callout = FALSE;

  /* set blocked signals based on if checking for them, SIGNAL_ALL_MASK
   * insures that no signals are blocked and all are checked.
   */

  if ( check_blocked )
    signals_blocked = ~api->signals_blocked;
  else
    signals_blocked = SIGNAL_ALL_MASK;

  /* XXX this is not right for siginfo type signals yet */
  /* XXX since they can't be cleared the same way */

  _ISR_Disable( level );
    if ( is_global ) {
       if ( mask & (_POSIX_signals_Pending & signals_blocked) ) {
         if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) {
           psiginfo = (POSIX_signals_Siginfo_node *)
             _Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] );
           if ( _Chain_Is_empty( &_POSIX_signals_Siginfo[ signo ] ) )
             _POSIX_signals_Clear_process_signals( mask );
           if ( psiginfo ) {
             *info = psiginfo->Info;
             _Chain_Append_unprotected(
               &_POSIX_signals_Inactive_siginfo,
               &psiginfo->Node
             );
           } else
             do_callout = FALSE;
         } else
           _POSIX_signals_Clear_process_signals( mask );
         do_callout = TRUE;
       }
    } else {
      if ( mask & (api->signals_pending & signals_blocked) ) {
        api->signals_pending &= ~mask;
        do_callout = TRUE;
      }
    }
  _ISR_Enable( level );
  return do_callout;
}
Ejemplo n.º 10
0
static Thread_Control *_Thread_queue_FIFO_first(
  Thread_queue_Heads *heads
)
{
  Chain_Control *fifo = &heads->Heads.Fifo;

  return _Chain_Is_empty( fifo ) ?
    NULL : THREAD_CHAIN_NODE_TO_THREAD( _Chain_First( fifo ) );
}
Ejemplo n.º 11
0
Thread_Control *_Thread_queue_First_fifo(
  Thread_queue_Control *the_thread_queue
)
{
  if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) )
    return (Thread_Control *) _Chain_First( &the_thread_queue->Queues.Fifo );

  return NULL;
}
Ejemplo n.º 12
0
Thread_Control *_Thread_queue_Dequeue(
  Thread_queue_Control *the_thread_queue
)
{
  Thread_Control                   *the_thread;
  ISR_lock_Context                  lock_context;
  Thread_blocking_operation_States  sync_state;

  the_thread = NULL;
  _Thread_queue_Acquire( &lock_context );

  /*
   * Invoke the discipline specific dequeue method.
   */
  if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_FIFO ) {
    if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) {
      the_thread = (Thread_Control *)
       _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );
    }
  } else { /* must be THREAD_QUEUE_DISCIPLINE_PRIORITY */
    RBTree_Node    *first;

    first = _RBTree_Get( &the_thread_queue->Queues.Priority, RBT_LEFT );
    if ( first ) {
      the_thread = THREAD_RBTREE_NODE_TO_THREAD( first );
      _Thread_Priority_restore_default_change_handler( the_thread );
      _Thread_Lock_restore_default( the_thread );
    }
  }

  if ( the_thread == NULL ) {
    /*
     * We did not find a thread to unblock in the queue.  Maybe the executing
     * thread is about to block on this thread queue.
     */
    sync_state = the_thread_queue->sync_state;
    if ( (sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT) ||
         (sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED) ) {
      the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SATISFIED;
      the_thread = _Thread_Executing;
    } else {
      _Thread_queue_Release( &lock_context );
      return NULL;
    }
  }

  /*
   * We found a thread to unblock.
   *
   * NOTE: This is invoked with interrupts still disabled.
   */
  _Thread_blocking_operation_Finalize( the_thread, &lock_context );

  return the_thread;
}
Ejemplo n.º 13
0
Chain_Node *_Chain_Get(
  Chain_Control *the_chain
)
{
  Chain_Node *return_node;

  return_node = NULL;
    if ( !_Chain_Is_empty( the_chain ) )
      return_node = _Chain_Get_first_unprotected( the_chain );
  return return_node;
}
Ejemplo n.º 14
0
static Thread_Control *_Thread_queue_FIFO_first(
  Thread_queue_Heads *heads
)
{
  Chain_Control *fifo = &heads->Heads.Fifo;
  Chain_Node    *first;

  _Assert( !_Chain_Is_empty( fifo ) );
  first = _Chain_First( fifo );

  return THREAD_CHAIN_NODE_TO_THREAD( first );
}
Ejemplo n.º 15
0
Thread_Control *_Thread_queue_Dequeue(
  Thread_queue_Control *the_thread_queue
)
{
  Thread_Control *the_thread;
  ISR_Level       level;
  Thread_blocking_operation_States  sync_state;

  the_thread = NULL;
  _ISR_Disable( level );

  /*
   * Invoke the discipline specific dequeue method.
   */
  if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_FIFO ) {
    if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) {
      the_thread = (Thread_Control *)
       _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );
    }
  } else { /* must be THREAD_QUEUE_DISCIPLINE_PRIORITY */
    RBTree_Node    *first;

    first = _RBTree_Get( &the_thread_queue->Queues.Priority, RBT_LEFT );
    if ( first ) {
      the_thread = THREAD_RBTREE_NODE_TO_THREAD( first );
    }
  }

  /*
   * We did not find a thread to unblock.
   */
  if ( !the_thread ) {
    sync_state = the_thread_queue->sync_state;
    if ( (sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT) ||
         (sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED) ) {
      the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SATISFIED;
      the_thread = _Thread_Executing;
    }
    _ISR_Enable( level );
    return NULL;
  }

  /*
   * We found a thread to unblock.
   *
   * NOTE: This is invoked with interrupts still disabled.
   */
  _Thread_blocking_operation_Finalize( the_thread, level );

  return the_thread;
}
Ejemplo n.º 16
0
Chain_Node *_Chain_Get(
  Chain_Control *the_chain
)
{
  ISR_Level          level;
  Chain_Node *return_node;

  return_node = NULL;
  _ISR_Disable( level );
    if ( !_Chain_Is_empty( the_chain ) )
      return_node = _Chain_Get_first_unprotected( the_chain );
  _ISR_Enable( level );
  return return_node;
}
Ejemplo n.º 17
0
static Thread_Control *_Thread_queue_FIFO_first(
  Thread_queue_Heads *heads
)
{
  Chain_Control  *fifo;
  Chain_Node     *first;
  Scheduler_Node *scheduler_node;

  fifo = &heads->Heads.Fifo;
  _Assert( !_Chain_Is_empty( fifo ) );
  first = _Chain_First( fifo );
  scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( first );

  return _Scheduler_Node_get_owner( scheduler_node );
}
Thread_Control *_Thread_queue_First_priority (
  Thread_queue_Control *the_thread_queue
)
{
  uint32_t   index;

  for( index=0 ;
       index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
       index++ ) {
    if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) )
      return (Thread_Control *)
        the_thread_queue->Queues.Priority[ index ].first;
  }
  return NULL;
}
Ejemplo n.º 19
0
void pthread_cleanup_pop(
    int    execute
)
{
    POSIX_Cancel_Handler_control      *handler;
    POSIX_Cancel_Handler_control      tmp_handler;
    Chain_Control                     *handler_stack;
    POSIX_API_Control                 *thread_support;
    ISR_Level                          level;

    thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];

    handler_stack = &thread_support->Cancellation_Handlers;

    /*
     * We need interrupts disabled to safely check the chain and pull
     * the last element off.  But we also need dispatching disabled to
     * ensure that we do not get prempted and deleted while we are holding
     * memory that needs to be freed.
     */

    _Thread_Disable_dispatch();
    _ISR_Disable( level );

    if ( _Chain_Is_empty( handler_stack ) ) {
        _Thread_Enable_dispatch();
        _ISR_Enable( level );
        return;
    }

    handler = (POSIX_Cancel_Handler_control *)
              _Chain_Tail( handler_stack )->previous;
    _Chain_Extract_unprotected( &handler->Node );

    _ISR_Enable( level );

    tmp_handler = *handler;

    _Workspace_Free( handler );

    _Thread_Enable_dispatch();

    if ( execute )
        (*tmp_handler.routine)( tmp_handler.arg );
}
Ejemplo n.º 20
0
static void _Timer_server_Get_watchdogs_that_fire_now(
  Timer_server_Control *ts,
  Chain_Control *insert_chain,
  Chain_Control *fire_chain
)
{
  /*
   *  Afterwards all timer inserts are directed to this chain and the interval
   *  and TOD chains will be no more modified by other parties.
   */
  ts->insert_chain = insert_chain;

  while ( true ) {
    ISR_Level level;

    /*
     *  Remove all the watchdogs that need to fire so we can invoke them.
     */
    _Timer_server_Process_interval_watchdogs(
      &ts->Interval_watchdogs,
      fire_chain
    );
    _Timer_server_Process_tod_watchdogs( &ts->TOD_watchdogs, fire_chain );

    /*
     *  The insertions have to take place here, because they reference the
     *  current time.  The previous process methods take a snapshot of the
     *  current time.  In case someone inserts a watchdog with an initial value
     *  of zero it will be processed in the next iteration of the timer server
     *  body loop.
     */
    _Timer_server_Process_insertions( ts );

    _ISR_Disable( level );
    if ( _Chain_Is_empty( insert_chain ) ) {
      ts->insert_chain = NULL;
      _ISR_Enable( level );

      break;
    } else {
      _ISR_Enable( level );
    }
  }
}
Ejemplo n.º 21
0
static Thread_Control *_Thread_queue_Priority_first(
  Thread_queue_Heads *heads
)
{
  Thread_queue_Priority_queue *priority_queue;
  RBTree_Node                 *first;

#if defined(RTEMS_SMP)
  _Assert( !_Chain_Is_empty( &heads->Heads.Fifo ) );
  priority_queue = (Thread_queue_Priority_queue *)
    _Chain_First( &heads->Heads.Fifo );
#else
  priority_queue = &heads->Heads.Priority;
#endif

  _Assert( !_RBTree_Is_empty( &priority_queue->Queue ) );
  first = _RBTree_Minimum( &priority_queue->Queue );

  return THREAD_RBTREE_NODE_TO_THREAD( first );
}
Ejemplo n.º 22
0
ER ref_mbx(
  T_RMBX *pk_rmbx,
  ID      mbxid
)
{
  register ITRON_Mailbox_Control *the_mailbox;
  Objects_Locations               location;
  Chain_Control                  *pending;

  if ( !pk_rmbx )
    return E_PAR;

  the_mailbox = _ITRON_Mailbox_Get( mbxid, &location );
  switch ( location ) {
#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:
#endif
    case OBJECTS_ERROR:
      return _ITRON_Mailbox_Clarify_get_id_error( mbxid );

    case OBJECTS_LOCAL:

      pending = &the_mailbox->message_queue.Pending_messages;
      if ( _Chain_Is_empty( pending ) )
        pk_rmbx->pk_msg = NULL;
      else
        pk_rmbx->pk_msg = (T_MSG *) pending->first;

      /*
       *  Fill in whether or not there is a waiting task
       */

      if ( !_Thread_queue_First( &the_mailbox->message_queue.Wait_queue ) )
        pk_rmbx->wtsk = FALSE;
      else
        pk_rmbx->wtsk = TRUE;

      break;
  }
  _ITRON_return_errorno( E_OK );
}
Ejemplo n.º 23
0
static void _Thread_queue_Queue_extract(
  Thread_queue_Queue *queue,
  Thread_queue_Heads *heads,
  Thread_Control     *the_thread,
  void             ( *extract )( Thread_queue_Heads *, Thread_Control * )
)
{
  _Assert( heads != NULL );

  the_thread->Wait.spare_heads = RTEMS_CONTAINER_OF(
    _Chain_Get_first_unprotected( &heads->Free_chain ),
    Thread_queue_Heads,
    Free_node
  );

  if ( _Chain_Is_empty( &heads->Free_chain ) ) {
    queue->heads = NULL;
  }

  ( *extract )( heads, the_thread );
}
Ejemplo n.º 24
0
void _POSIX_signals_Clear_process_signals(
  int signo
)
{
  sigset_t   mask;
  bool       clear_signal;

  clear_signal = true;
  mask         = signo_to_mask( signo );

  ISR_Level  level;

  _ISR_Disable( level );
    if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) {
      if ( !_Chain_Is_empty( &_POSIX_signals_Siginfo[ signo ] ) )
       clear_signal = false;
    }
    if ( clear_signal ) {
      _POSIX_signals_Pending &= ~mask;
    }
  _ISR_Enable( level );
}
Ejemplo n.º 25
0
static Thread_Control *_Thread_queue_Priority_first(
  Thread_queue_Heads *heads
)
{
  Thread_queue_Priority_queue *priority_queue;
  RBTree_Node                 *first;
  Scheduler_Node              *scheduler_node;

#if defined(RTEMS_SMP)
  _Assert( !_Chain_Is_empty( &heads->Heads.Fifo ) );
  priority_queue = (Thread_queue_Priority_queue *)
    _Chain_First( &heads->Heads.Fifo );
#else
  priority_queue = &heads->Heads.Priority;
#endif

  _Assert( !_RBTree_Is_empty( &priority_queue->Queue ) );
  first = _RBTree_Minimum( &priority_queue->Queue );
  scheduler_node = SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( first );

  return _Scheduler_Node_get_owner( scheduler_node );
}
Ejemplo n.º 26
0
Archivo: init.c Proyecto: Dipupo/rtems
static void test_chain_iterator( void )
{
  Chain_Control chain;
  Chain_Iterator_registry reg;
  Chain_Iterator fit;
  Chain_Iterator bit;
  Chain_Node a;
  Chain_Node b;
  Chain_Node c;

  puts( "INIT - Verify Chain_Iterator" );

  rtems_test_assert( _Chain_Is_empty( &static_reg.Iterators ));

  _Chain_Initialize_empty( &chain );
  _Chain_Iterator_registry_initialize( &reg );
  _Chain_Iterator_initialize( &chain, &reg, &fit, CHAIN_ITERATOR_FORWARD );
  _Chain_Iterator_initialize( &chain, &reg, &bit, CHAIN_ITERATOR_BACKWARD );

  rtems_test_assert( _Chain_Iterator_next( &fit ) == _Chain_Tail( &chain ));
  rtems_test_assert( _Chain_Iterator_next( &bit ) == _Chain_Head( &chain ));

  _Chain_Iterator_set_position( &fit, _Chain_Head( &chain ) );
  _Chain_Iterator_set_position( &bit, _Chain_Tail( &chain ) );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == _Chain_Tail( &chain ));
  rtems_test_assert( _Chain_Iterator_next( &bit ) == _Chain_Head( &chain ));

  _Chain_Append_unprotected( &chain, &a );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &a );

  _Chain_Append_unprotected( &chain, &b );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &b );

  _Chain_Append_unprotected( &chain, &c );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &c );

  update_registry_and_extract( &reg, &b );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &c );

  _Chain_Insert_unprotected( &a, &b );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &c );

  update_registry_and_extract( &reg, &c );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &b );

  _Chain_Append_unprotected( &chain, &c );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &c );

  update_registry_and_extract( &reg, &a );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &b );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &c );

  _Chain_Prepend_unprotected( &chain, &a );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &c );

  update_registry_and_extract( &reg, &a );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &b );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &c );

  update_registry_and_extract( &reg, &b );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &c );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &c );

  update_registry_and_extract( &reg, &c );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == _Chain_Tail( &chain ));
  rtems_test_assert( _Chain_Iterator_next( &bit ) == _Chain_Head( &chain ));

  _Chain_Append_unprotected( &chain, &a );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &a );

  _Chain_Append_unprotected( &chain, &b );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &b );

  _Chain_Append_unprotected( &chain, &c );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &c );

  update_registry_and_extract( &reg, &c );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &b );

  update_registry_and_extract( &reg, &b );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == &a );
  rtems_test_assert( _Chain_Iterator_next( &bit ) == &a );

  update_registry_and_extract( &reg, &a );
  rtems_test_assert( _Chain_Iterator_next( &fit ) == _Chain_Tail( &chain ));
  rtems_test_assert( _Chain_Iterator_next( &bit ) == _Chain_Head( &chain ));

  rtems_test_assert( !_Chain_Is_empty( &reg.Iterators ));
  _Chain_Iterator_destroy( &fit );
  rtems_test_assert( !_Chain_Is_empty( &reg.Iterators ));
  _Chain_Iterator_destroy( &bit );
  rtems_test_assert( _Chain_Is_empty( &reg.Iterators ));
}
Ejemplo n.º 27
0
static void _Timer_server_Insert_timer_and_make_snapshot(
  Timer_server_Control *ts,
  Timer_Control *timer
)
{
  Watchdog_Control *first_watchdog;
  Watchdog_Interval delta_interval;
  Watchdog_Interval last_snapshot;
  Watchdog_Interval snapshot;
  Watchdog_Interval delta;
  ISR_Level level;

  /*
   *  We have to update the time snapshots here, because otherwise we may have
   *  problems with the integer range of the delta values.  The time delta DT
   *  from the last snapshot to now may be arbitrarily long.  The last snapshot
   *  is the reference point for the delta chain.  Thus if we do not update the
   *  reference point we have to add DT to the initial delta of the watchdog
   *  being inserted.  This could result in an integer overflow.
   */

  _Thread_Disable_dispatch();

  if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) {
    /*
     *  We have to advance the last known ticks value of the server and update
     *  the watchdog chain accordingly.
     */
    _ISR_Disable( level );
    snapshot = _Watchdog_Ticks_since_boot;
    last_snapshot = ts->Interval_watchdogs.last_snapshot;
    if ( !_Chain_Is_empty( &ts->Interval_watchdogs.Chain ) ) {
      first_watchdog = _Watchdog_First( &ts->Interval_watchdogs.Chain );

      /*
       *  We assume adequate unsigned arithmetic here.
       */
      delta = snapshot - last_snapshot;

      delta_interval = first_watchdog->delta_interval;
      if (delta_interval > delta) {
        delta_interval -= delta;
      } else {
        delta_interval = 0;
      }
      first_watchdog->delta_interval = delta_interval;
    }
    ts->Interval_watchdogs.last_snapshot = snapshot;
    _ISR_Enable( level );

    _Watchdog_Insert( &ts->Interval_watchdogs.Chain, &timer->Ticker );

    if ( !ts->active ) {
      _Timer_server_Reset_interval_system_watchdog( ts );
    }
  } else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
    /*
     *  We have to advance the last known seconds value of the server and update
     *  the watchdog chain accordingly.
     */
    _ISR_Disable( level );
    snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch();
    last_snapshot = ts->TOD_watchdogs.last_snapshot;
    if ( !_Chain_Is_empty( &ts->TOD_watchdogs.Chain ) ) {
      first_watchdog = _Watchdog_First( &ts->TOD_watchdogs.Chain );
      delta_interval = first_watchdog->delta_interval;
      if ( snapshot > last_snapshot ) {
        /*
         *  We advanced in time.
         */
        delta = snapshot - last_snapshot;
        if (delta_interval > delta) {
          delta_interval -= delta;
        } else {
          delta_interval = 0;
        }
      } else {
        /*
         *  Someone put us in the past.
         */
        delta = last_snapshot - snapshot;
        delta_interval += delta;
      }
      first_watchdog->delta_interval = delta_interval;
    }
    ts->TOD_watchdogs.last_snapshot = snapshot;
    _ISR_Enable( level );

    _Watchdog_Insert( &ts->TOD_watchdogs.Chain, &timer->Ticker );

    if ( !ts->active ) {
      _Timer_server_Reset_tod_system_watchdog( ts );
    }
  }

  _Thread_Enable_dispatch();
}
Ejemplo n.º 28
0
/**
 *  @brief Timer server body.
 *
 *  This is the server for task based timers.  This task executes whenever a
 *  task-based timer should fire.  It services both "after" and "when" timers.
 *  It is not created automatically but must be created explicitly by the
 *  application before task-based timers may be initiated.  The parameter
 *  @a arg points to the corresponding timer server control block.
 */
static rtems_task _Timer_server_Body(
  rtems_task_argument arg
)
{
  Timer_server_Control *ts = (Timer_server_Control *) arg;
  Chain_Control insert_chain;
  Chain_Control fire_chain;

  _Chain_Initialize_empty( &insert_chain );
  _Chain_Initialize_empty( &fire_chain );

  while ( true ) {
    _Timer_server_Get_watchdogs_that_fire_now( ts, &insert_chain, &fire_chain );

    if ( !_Chain_Is_empty( &fire_chain ) ) {
      /*
       *  Fire the watchdogs.
       */
      while ( true ) {
        Watchdog_Control *watchdog;
        ISR_Level level;

        /*
         *  It is essential that interrupts are disable here since an interrupt
         *  service routine may remove a watchdog from the chain.
         */
        _ISR_Disable( level );
        watchdog = (Watchdog_Control *) _Chain_Get_unprotected( &fire_chain );
        if ( watchdog != NULL ) {
          watchdog->state = WATCHDOG_INACTIVE;
          _ISR_Enable( level );
        } else {
          _ISR_Enable( level );

          break;
        }

        /*
         *  The timer server may block here and wait for resources or time.
         *  The system watchdogs are inactive and will remain inactive since
         *  the active flag of the timer server is true.
         */
        (*watchdog->routine)( watchdog->id, watchdog->user_data );
      }
    } else {
      ts->active = false;

      /*
       *  Block until there is something to do.
       */
      _Thread_Disable_dispatch();
        _Thread_Set_state( ts->thread, STATES_DELAYING );
        _Timer_server_Reset_interval_system_watchdog( ts );
        _Timer_server_Reset_tod_system_watchdog( ts );
      _Thread_Enable_dispatch();

      ts->active = true;

      /*
       *  Maybe an interrupt did reset the system timers, so we have to stop
       *  them here.  Since we are active now, there will be no more resets
       *  until we are inactive again.
       */
      _Timer_server_Stop_interval_system_watchdog( ts );
      _Timer_server_Stop_tod_system_watchdog( ts );
    }
  }
}
Ejemplo n.º 29
0
Thread_Control *_Thread_queue_Dequeue_priority(
    Thread_queue_Control *the_thread_queue
)
{
    uint32_t        index;
    ISR_Level       level;
    Thread_Control *the_thread = NULL;  /* just to remove warnings */
    Thread_Control *new_first_thread;
    Chain_Node     *head;
    Chain_Node     *tail;
    Chain_Node     *new_first_node;
    Chain_Node     *new_second_node;
    Chain_Node     *last_node;
    Chain_Node     *next_node;
    Chain_Node     *previous_node;

    _ISR_Disable( level );
    for( index=0 ;
            index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
            index++ ) {
        if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) {
            the_thread = (Thread_Control *) _Chain_First(
                             &the_thread_queue->Queues.Priority[ index ]
                         );
            goto dequeue;
        }
    }

    /*
     * We did not find a thread to unblock.
     */
    _ISR_Enable( level );
    return NULL;

dequeue:
    the_thread->Wait.queue = NULL;
    new_first_node   = _Chain_First( &the_thread->Wait.Block2n );
    new_first_thread = (Thread_Control *) new_first_node;
    next_node        = the_thread->Object.Node.next;
    previous_node    = the_thread->Object.Node.previous;

    if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
        last_node       = _Chain_Last( &the_thread->Wait.Block2n );
        new_second_node = new_first_node->next;

        previous_node->next      = new_first_node;
        next_node->previous      = new_first_node;
        new_first_node->next     = next_node;
        new_first_node->previous = previous_node;

        if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
            /* > two threads on 2-n */
            head = _Chain_Head( &new_first_thread->Wait.Block2n );
            tail = _Chain_Tail( &new_first_thread->Wait.Block2n );

            new_second_node->previous = head;
            head->next = new_second_node;
            tail->previous = last_node;
            last_node->next = tail;
        }
    } else {
        previous_node->next = next_node;
        next_node->previous = previous_node;
    }

    if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
        _ISR_Enable( level );
        _Thread_Unblock( the_thread );
    } else {
        _Watchdog_Deactivate( &the_thread->Timer );
        _ISR_Enable( level );
        (void) _Watchdog_Remove( &the_thread->Timer );
        _Thread_Unblock( the_thread );
    }

#if defined(RTEMS_MULTIPROCESSING)
    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
        _Thread_MP_Free_proxy( the_thread );
#endif
    return( the_thread );
}
void _Watchdog_Tickle(
  Chain_Control *header
)
{
  ISR_Level level;
  Watchdog_Control *the_watchdog;
  Watchdog_States  watchdog_state;

  /*
   * See the comment in watchdoginsert.c and watchdogadjust.c
   * about why it's safe not to declare header a pointer to
   * volatile data - till, 2003/7
   */

  _ISR_Disable( level );

  if ( _Chain_Is_empty( header ) )
    goto leave;

  the_watchdog = _Watchdog_First( header );
  
  /*
   * For some reason, on rare occasions the_watchdog->delta_interval
   * of the head of the watchdog chain is 0.  Before this test was
   * added, on these occasions an event (which usually was supposed
   * to have a timeout of 1 tick would have a delta_interval of 0, which
   * would be decremented to 0xFFFFFFFF by the unprotected 
   * "the_watchdog->delta_interval--;" operation.
   * This would mean the event would not timeout, and also the chain would
   * be blocked, because a timeout with a very high number would be at the
   * head, rather than at the end.
   * The test "if (the_watchdog->delta_interval != 0)"
   * here prevents this from occuring. 
   * 
   * We were not able to categorically identify the situation that causes 
   * this, but proved it to be true empirically.  So this check causes 
   * correct behaviour in this circumstance.
   * 
   * The belief is that a race condition exists whereby an event at the head
   * of the chain is removed (by a pending ISR or higher priority task)
   * during the _ISR_Flash( level ); in _Watchdog_Insert, but the watchdog 
   * to be inserted has already had its delta_interval adjusted to 0, and 
   * so is added to the head of the chain with a delta_interval of 0.  
   * 
   * Steven Johnson - 12/2005 (gcc-3.2.3 -O3 on powerpc)
   */
  if (the_watchdog->delta_interval != 0) {
    the_watchdog->delta_interval--;
    if ( the_watchdog->delta_interval != 0 )
      goto leave;
  }      

  do {
     watchdog_state = _Watchdog_Remove( the_watchdog );

     _ISR_Enable( level );

     switch( watchdog_state ) {
       case WATCHDOG_ACTIVE:
         (*the_watchdog->routine)(
           the_watchdog->id,
           the_watchdog->user_data
         );
         break;

       case WATCHDOG_INACTIVE:
         /*
          *  This state indicates that the watchdog is not on any chain.
          *  Thus, it is NOT on a chain being tickled.  This case should
          *  never occur.
          */
         break;

       case WATCHDOG_BEING_INSERTED:
         /*
          *  This state indicates that the watchdog is in the process of
          *  BEING inserted on the chain.  Thus, it can NOT be on a chain
          *  being tickled.  This case should never occur.
          */
         break;

       case WATCHDOG_REMOVE_IT:
         break;
     }

	 _ISR_Disable( level );

     the_watchdog = _Watchdog_First( header );
   } while ( !_Chain_Is_empty( header ) &&
             (the_watchdog->delta_interval == 0) );

leave:
   _ISR_Enable(level);
}