void _Chain_Initialize(
  Chain_Control *the_chain,
  void           *starting_address,
  size_t         number_nodes,
  size_t         node_size
)
{
  size_t      count;
  Chain_Node *current;
  Chain_Node *next;

  count                     = number_nodes;
  current                   = _Chain_Head( the_chain );
  the_chain->permanent_null = NULL;
  next                      = starting_address;
  while ( count-- ) {
    current->next  = next;
    next->previous = current;
    current        = next;
    next           = (Chain_Node *)
                        _Addresses_Add_offset( (void *) next, node_size );
  }
  current->next    = _Chain_Tail( the_chain );
  the_chain->last  = current;
}
Beispiel #2
0
void _Chain_Initialize(
  Chain_Control *the_chain,
  void           *starting_address,
  size_t         number_nodes,
  size_t         node_size
)
{
  size_t count = number_nodes;
  Chain_Node *head = _Chain_Head( the_chain );
  Chain_Node *tail = _Chain_Tail( the_chain );
  Chain_Node *current = head;
  Chain_Node *next = starting_address;

  head->previous = NULL;

  while ( count-- ) {
    current->next  = next;
    next->previous = current;
    current        = next;
    next           = (Chain_Node *)
                        _Addresses_Add_offset( (void *) next, node_size );
  }

  current->next = tail;
  tail->previous = current;
}
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 );
  }
}
Beispiel #4
0
static void test_chain_control_layout(void)
{
  Chain_Control chain;

  puts( "INIT - Verify rtems_chain_control layout" );

  rtems_test_assert(
    sizeof(Chain_Control)
      == sizeof(Chain_Node) + sizeof(Chain_Node *)
  );
  rtems_test_assert(
    sizeof(Chain_Control)
      == 3 * sizeof(Chain_Node *)
  );
  rtems_test_assert(
    _Chain_Previous( _Chain_Head( &chain ) )
      == _Chain_Next( _Chain_Tail( &chain ) )
  );

#if !defined( RTEMS_SMP )
  rtems_test_assert(
    sizeof(Chain_Control)
      == sizeof(rtems_chain_control)
  );
#endif
}
Beispiel #5
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 );
}
Beispiel #6
0
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 );
  }
}
Beispiel #7
0
static void _Watchdog_Remove_it(
  Watchdog_Header   *header,
  Watchdog_Control  *the_watchdog
)
{
  Chain_Node        *next;
  Watchdog_Interval  delta;
  const Chain_Node  *iterator_tail;
  Chain_Node        *iterator_node;

  _Assert( the_watchdog->state == WATCHDOG_ACTIVE );

  the_watchdog->state = WATCHDOG_INACTIVE;
  the_watchdog->stop_time = _Watchdog_Ticks_since_boot;

  next = _Chain_Next( &the_watchdog->Node );
  delta = the_watchdog->delta_interval;

  if ( next != _Chain_Tail( &header->Watchdogs ) ) {
    Watchdog_Control *next_watchdog;

    next_watchdog = (Watchdog_Control *) next;
    next_watchdog->delta_interval += delta;
  }

  _Chain_Extract_unprotected( &the_watchdog->Node );

  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 ) {
      iterator->delta_interval += delta;
    }

    if ( iterator->current == &the_watchdog->Node ) {
      Chain_Node *previous = _Chain_Previous( &the_watchdog->Node );

      iterator->current = previous;

      if ( previous != _Chain_Head( &header->Watchdogs ) ) {
        Watchdog_Control *previous_watchdog;

        previous_watchdog = (Watchdog_Control *) previous;
        iterator->delta_interval += previous_watchdog->delta_interval;
      }
    }

    iterator_node = _Chain_Next( iterator_node );
  }
}
Beispiel #8
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 );
}
Beispiel #9
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 );
}
Beispiel #10
0
Thread_blocking_operation_States _Thread_queue_Enqueue_priority (
    Thread_queue_Control *the_thread_queue,
    Thread_Control       *the_thread,
    ISR_Level            *level_p
)
{
    Priority_Control     search_priority;
    Thread_Control      *search_thread;
    ISR_Level            level;
    Chain_Control       *header;
    uint32_t             header_index;
    Chain_Node          *the_node;
    Chain_Node          *next_node;
    Chain_Node          *previous_node;
    Chain_Node          *search_node;
    Priority_Control     priority;
    States_Control       block_state;

    _Chain_Initialize_empty( &the_thread->Wait.Block2n );

    priority     = the_thread->current_priority;
    header_index = _Thread_queue_Header_number( priority );
    header       = &the_thread_queue->Queues.Priority[ header_index ];
    block_state  = the_thread_queue->state;

    if ( _Thread_queue_Is_reverse_search( priority ) )
        goto restart_reverse_search;

restart_forward_search:
    search_priority = PRIORITY_MINIMUM - 1;
    _ISR_Disable( level );
    search_thread = (Thread_Control *) header->first;
    while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
        search_priority = search_thread->current_priority;
        if ( priority <= search_priority )
            break;

#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
        search_thread = (Thread_Control *) search_thread->Object.Node.next;
        if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
            break;
        search_priority = search_thread->current_priority;
        if ( priority <= search_priority )
            break;
#endif
        _ISR_Flash( level );
        if ( !_States_Are_set( search_thread->current_state, block_state) ) {
            _ISR_Enable( level );
            goto restart_forward_search;
        }
        search_thread =
            (Thread_Control *)search_thread->Object.Node.next;
    }

    if ( the_thread_queue->sync_state !=
            THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
        goto synchronize;

    the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;

    if ( priority == search_priority )
        goto equal_priority;

    search_node   = (Chain_Node *) search_thread;
    previous_node = search_node->previous;
    the_node      = (Chain_Node *) the_thread;

    the_node->next         = search_node;
    the_node->previous     = previous_node;
    previous_node->next    = the_node;
    search_node->previous  = the_node;
    the_thread->Wait.queue = the_thread_queue;
    _ISR_Enable( level );
    return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;

restart_reverse_search:
    search_priority     = PRIORITY_MAXIMUM + 1;

    _ISR_Disable( level );
    search_thread = (Thread_Control *) header->last;
    while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
        search_priority = search_thread->current_priority;
        if ( priority >= search_priority )
            break;
#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
        search_thread = (Thread_Control *) search_thread->Object.Node.previous;
        if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
            break;
        search_priority = search_thread->current_priority;
        if ( priority >= search_priority )
            break;
#endif
        _ISR_Flash( level );
        if ( !_States_Are_set( search_thread->current_state, block_state) ) {
            _ISR_Enable( level );
            goto restart_reverse_search;
        }
        search_thread = (Thread_Control *)
                        search_thread->Object.Node.previous;
    }

    if ( the_thread_queue->sync_state !=
            THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
        goto synchronize;

    the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;

    if ( priority == search_priority )
        goto equal_priority;

    search_node = (Chain_Node *) search_thread;
    next_node   = search_node->next;
    the_node    = (Chain_Node *) the_thread;

    the_node->next          = next_node;
    the_node->previous      = search_node;
    search_node->next       = the_node;
    next_node->previous    = the_node;
    the_thread->Wait.queue = the_thread_queue;
    _ISR_Enable( level );
    return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;

equal_priority:               /* add at end of priority group */
    search_node   = _Chain_Tail( &search_thread->Wait.Block2n );
    previous_node = search_node->previous;
    the_node      = (Chain_Node *) the_thread;

    the_node->next         = search_node;
    the_node->previous     = previous_node;
    previous_node->next    = the_node;
    search_node->previous  = the_node;
    the_thread->Wait.queue = the_thread_queue;
    _ISR_Enable( level );
    return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;

synchronize:
    /*
     *  An interrupt completed the thread's blocking request.
     *  For example, the blocking thread could have been given
     *  the mutex by an ISR or timed out.
     *
     *  WARNING! Returning with interrupts disabled!
     */
    *level_p = level;
    return the_thread_queue->sync_state;
}
Beispiel #11
0
static int _Condition_Wake( struct _Condition_Control *_condition, int count )
{
  Condition_Control  *condition;
  ISR_lock_Context    lock_context;
  Thread_queue_Heads *heads;
  Chain_Control       unblock;
  Chain_Node         *node;
  Chain_Node         *tail;
  int                 woken;

  condition = _Condition_Get( _condition );
  _ISR_lock_ISR_disable( &lock_context );
  _Condition_Queue_acquire_critical( condition, &lock_context );

  /*
   * In common uses cases of condition variables there are normally no threads
   * on the queue, so check this condition early.
   */
  heads = condition->Queue.Queue.heads;
  if ( __predict_true( heads == NULL ) ) {
    _Condition_Queue_release( condition, &lock_context );

    return 0;
  }

  woken = 0;
  _Chain_Initialize_empty( &unblock );
  while ( count > 0 && heads != NULL ) {
    const Thread_queue_Operations *operations;
    Thread_Control                *first;
    bool                           do_unblock;

    operations = CONDITION_TQ_OPERATIONS;
    first = ( *operations->first )( heads );

    do_unblock = _Thread_queue_Extract_locked(
      &condition->Queue.Queue,
      operations,
      first
    );
    if (do_unblock) {
      _Chain_Append_unprotected( &unblock, &first->Wait.Node.Chain );
    }

    ++woken;
    --count;
    heads = condition->Queue.Queue.heads;
  }

  node = _Chain_First( &unblock );
  tail = _Chain_Tail( &unblock );
  if ( node != tail ) {
    Per_CPU_Control *cpu_self;

    cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
    _Condition_Queue_release( condition, &lock_context );

    do {
      Thread_Control *thread;
      Chain_Node     *next;

      next = _Chain_Next( node );
      thread = THREAD_CHAIN_NODE_TO_THREAD( node );
      _Watchdog_Remove_ticks( &thread->Timer );
      _Thread_Unblock( thread );

      node = next;
    } while ( node != tail );

    _Thread_Dispatch_enable( cpu_self );
  } else {
    _Condition_Queue_release( condition, &lock_context );
  }

  return woken;
}
Beispiel #12
0
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 ));
}