Exemplo n.º 1
0
void _RBTree_Initialize(
  RBTree_Control          *the_rbtree,
  RBTree_Compare_function  compare_function,
  void                    *starting_address,
  size_t                   number_nodes,
  size_t                   node_size,
  bool                     is_unique
)
{
  size_t      count;
  RBTree_Node *next;

  /* TODO: Error message? */
  if (!the_rbtree) return;

  /* could do sanity checks here */
  _RBTree_Initialize_empty(the_rbtree, compare_function, is_unique);

  count = number_nodes;
  next  = starting_address;
  while ( count-- ) {
    _RBTree_Insert(the_rbtree, next);
    next           = (RBTree_Node *)
                        _Addresses_Add_offset( (void *) next, node_size );
  }
}
Exemplo n.º 2
0
Scheduler_Void_or_thread _Scheduler_EDF_Yield(
  const Scheduler_Control *scheduler,
  Thread_Control          *the_thread
)
{
  Scheduler_EDF_Context *context =
    _Scheduler_EDF_Get_context( scheduler );
  Scheduler_EDF_Node    *node = _Scheduler_EDF_Thread_get_node( the_thread );

  /*
   * The RBTree has more than one node, enqueue behind the tasks
   * with the same priority in case there are such ones.
   */
  _RBTree_Extract( &context->Ready, &node->Node );
  _RBTree_Insert(
    &context->Ready,
    &node->Node,
    _Scheduler_EDF_Compare,
    false
  );

  _Scheduler_EDF_Schedule_body( scheduler, the_thread, false );

  SCHEDULER_RETURN_VOID_OR_NULL;
}
Exemplo n.º 3
0
void _Scheduler_EDF_Enqueue(
    Thread_Control    *the_thread
)
{
    Scheduler_EDF_Per_thread *sched_info =
        (Scheduler_EDF_Per_thread*) the_thread->scheduler_info;
    RBTree_Node *node = &(sched_info->Node);

    _RBTree_Insert( &_Scheduler_EDF_Ready_queue, node );
    sched_info->queue_state = SCHEDULER_EDF_QUEUE_STATE_YES;
}
Exemplo n.º 4
0
static void _Thread_queue_Priority_do_enqueue(
  Thread_queue_Heads *heads,
  Thread_Control     *the_thread
)
{
  _RBTree_Insert(
    &heads->Heads.Priority,
    &the_thread->Wait.Node.RBTree,
    _Thread_queue_Compare_priority,
    false
  );
}
Exemplo n.º 5
0
void _Scheduler_EDF_Change_priority(
  const Scheduler_Control *scheduler,
  Thread_Control          *the_thread,
  Priority_Control         new_priority,
  bool                     prepend_it
)
{
  Scheduler_EDF_Context *context =
    _Scheduler_EDF_Get_context( scheduler );
  Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread );

  _RBTree_Extract( &context->Ready, &node->Node );
  _RBTree_Insert( &context->Ready, &node->Node );
}
Exemplo n.º 6
0
static void _Thread_queue_Requeue_priority(
  Thread_Control   *the_thread,
  Priority_Control  new_priority,
  void             *context
)
{
  Thread_queue_Control *tq = context;

  _RBTree_Extract( &tq->Queues.Priority, &the_thread->RBNode );
  _RBTree_Insert(
    &tq->Queues.Priority,
    &the_thread->RBNode,
    _Thread_queue_Compare_priority,
    false
  );
}
Exemplo n.º 7
0
void _Thread_queue_Requeue(
  Thread_queue_Control *the_thread_queue,
  Thread_Control       *the_thread
)
{
  /*
   * Just in case the thread really wasn't blocked on a thread queue
   * when we get here.
   */
  if ( !the_thread_queue )
    return;

  /*
   * If queueing by FIFO, there is nothing to do. This only applies to
   * priority blocking discipline.
   */
  if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY ) {
    Thread_queue_Control *tq = the_thread_queue;
    ISR_Level             level;

    _ISR_Disable( level );
    if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
      _Thread_queue_Enter_critical_section( tq );

      /* extract the thread */
      _RBTree_Extract(
        &the_thread->Wait.queue->Queues.Priority,
        &the_thread->RBNode
      );

      /* enqueue the thread at the new priority */
      _RBTree_Insert(
        &the_thread_queue->Queues.Priority,
        &the_thread->RBNode,
        _Thread_queue_Compare_priority,
        false
      );
    }
    _ISR_Enable( level );
  }
}
Exemplo n.º 8
0
static void _Thread_queue_Priority_do_enqueue(
  Thread_queue_Heads *heads,
  Thread_Control     *the_thread
)
{
  Thread_queue_Priority_queue *priority_queue =
    _Thread_queue_Priority_queue( heads, the_thread );

#if defined(RTEMS_SMP)
  if ( _RBTree_Is_empty( &priority_queue->Queue ) ) {
    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
  }
#endif

  _RBTree_Insert(
    &priority_queue->Queue,
    &the_thread->Wait.Node.RBTree,
    _Thread_queue_Compare_priority,
    false
  );
}
Exemplo n.º 9
0
static void _Thread_queue_Priority_priority_change(
  Thread_Control     *the_thread,
  Priority_Control    new_priority,
  Thread_queue_Queue *queue
)
{
  Thread_queue_Heads *heads = queue->heads;

  _Assert( heads != NULL );

  _RBTree_Extract(
    &heads->Heads.Priority,
    &the_thread->Wait.Node.RBTree
  );
  _RBTree_Insert(
    &heads->Heads.Priority,
    &the_thread->Wait.Node.RBTree,
    _Thread_queue_Compare_priority,
    false
  );
}
Exemplo n.º 10
0
Scheduler_Void_or_thread _Scheduler_EDF_Change_priority(
    const Scheduler_Control *scheduler,
    Thread_Control          *the_thread,
    Priority_Control         new_priority,
    bool                     prepend_it
)
{
    Scheduler_EDF_Context *context =
        _Scheduler_EDF_Get_context( scheduler );
    Scheduler_EDF_Node *node = _Scheduler_EDF_Thread_get_node( the_thread );

    _RBTree_Extract( &context->Ready, &node->Node );
    _RBTree_Insert(
        &context->Ready,
        &node->Node,
        _Scheduler_EDF_Compare,
        false
    );

    SCHEDULER_RETURN_VOID_OR_NULL;
}
Exemplo n.º 11
0
void _RBTree_Initialize(
  RBTree_Control *the_rbtree,
  RBTree_Compare  compare,
  void           *starting_address,
  size_t          number_nodes,
  size_t          node_size,
  bool            is_unique
)
{
  size_t       count;
  RBTree_Node *next;

  /* could do sanity checks here */
  _RBTree_Initialize_empty( the_rbtree );

  count = number_nodes;
  next = starting_address;

  while ( count-- ) {
    _RBTree_Insert( the_rbtree, next, compare, is_unique );
    next = (RBTree_Node *) _Addresses_Add_offset( next, node_size );
  }
}
Exemplo n.º 12
0
void _Thread_queue_Enqueue(
  Thread_queue_Control *the_thread_queue,
  Thread_Control       *the_thread,
  States_Control        state,
  Watchdog_Interval     timeout
)
{
  ISR_lock_Context                 lock_context;
  Thread_blocking_operation_States sync_state;

#if defined(RTEMS_MULTIPROCESSING)
  if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet )
    the_thread = _Thread_MP_Allocate_proxy( state );
  else
#endif
  /*
   *  Set the blocking state for this thread queue in the thread.
   */
  _Thread_Set_state( the_thread, state );

  /*
   *  If the thread wants to timeout, then schedule its timer.
   */
  if ( timeout ) {
    _Watchdog_Initialize(
       &the_thread->Timer,
       _Thread_queue_Timeout,
       the_thread->Object.id,
       NULL
    );

    _Watchdog_Insert_ticks( &the_thread->Timer, timeout );
  }

  /*
   * Now initiate the enqueuing and checking if the blocking operation
   * should be completed or the thread has had its blocking condition
   * satisfied before we got here.
   */
  _Thread_queue_Acquire( &lock_context );

  sync_state = the_thread_queue->sync_state;
  the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;

  if ( sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
    /*
     * Invoke the discipline specific enqueue method.
     */
    if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_FIFO ) {
      _Chain_Append_unprotected(
        &the_thread_queue->Queues.Fifo,
        &the_thread->Object.Node
      );
    } else { /* must be THREAD_QUEUE_DISCIPLINE_PRIORITY */
      _Thread_Lock_set( the_thread, &_Thread_queue_Lock );
      _Thread_Priority_set_change_handler(
        the_thread,
        _Thread_queue_Requeue_priority,
        the_thread_queue
      );
      _RBTree_Insert(
        &the_thread_queue->Queues.Priority,
        &the_thread->RBNode,
        _Thread_queue_Compare_priority,
        false
      );
    }

    the_thread->Wait.queue = the_thread_queue;
    the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
    _Thread_queue_Release( &lock_context );
  } else {
    /* Cancel a blocking operation due to ISR */

    _Assert(
      sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT ||
        sync_state == THREAD_BLOCKING_OPERATION_SATISFIED
    );

    _Thread_blocking_operation_Finalize( the_thread, &lock_context );
  }
}
Exemplo n.º 13
0
int pthread_setspecific(
  pthread_key_t  key,
  const void    *value
)
{
  POSIX_Keys_Control          *the_key;
  Objects_Locations            location;
  POSIX_Keys_Key_value_pair   *value_pair_ptr;
  RBTree_Node                 *p;
  POSIX_Keys_Key_value_pair    search_node;
  Thread_Control              *executing;

  the_key = _POSIX_Keys_Get( key, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      executing = _Thread_Executing;
      p = _POSIX_Keys_Find( key, executing, &search_node );
      if ( p != NULL ) {
        value_pair_ptr = POSIX_KEYS_RBTREE_NODE_TO_KEY_VALUE_PAIR( p );
        value_pair_ptr->value = value;
      } else {
        value_pair_ptr = _POSIX_Keys_Key_value_pair_allocate();

        if ( !value_pair_ptr ) {
          _Objects_Put( &the_key->Object );

          return ENOMEM;
        }

        value_pair_ptr->key = key;
        value_pair_ptr->thread = executing;
        value_pair_ptr->value = value;
        /* The insert can only go wrong if the same node is already in a unique
         * tree. This has been already checked with the _RBTree_Find() */
        _RBTree_Insert(
          &_POSIX_Keys_Key_value_lookup_tree,
          &value_pair_ptr->Key_value_lookup_node,
          _POSIX_Keys_Key_value_compare,
          true
        );

        /** append rb_node to the thread API extension's chain */
        _Chain_Append_unprotected(
          &_Thread_Executing->Key_Chain,
          &value_pair_ptr->Key_values_per_thread_node
        );
      }

      _Objects_Put( &the_key->Object );

      return 0;

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:   /* should never happen */
#endif
    case OBJECTS_ERROR:
      break;
  }

  return EINVAL;
}