Beispiel #1
0
static Thread_Control *_Scheduler_priority_SMP_Get_highest_ready(
  Scheduler_SMP_Control *self
)
{
  Thread_Control *highest_ready = NULL;

  if ( !_Priority_bit_map_Is_empty() ) {
    highest_ready = _Scheduler_priority_Ready_queue_first( &self->ready[ 0 ] );
  }

  return highest_ready;
}
/*
 * This method is invoked at the end of certain scheduling operations
 * to ensure that the highest priority ready thread cannot be scheduled
 * to execute. When we schedule with affinity, there is the possibility
 * that we need to migrate a thread to another core to ensure that the
 * highest priority ready threads are in fact scheduled.
 */
static void _Scheduler_priority_affinity_SMP_Check_for_migrations(
  Scheduler_Context *context
)
{
  Scheduler_priority_SMP_Context *self;
  Scheduler_Node                 *lowest_scheduled;
  Scheduler_Node                 *highest_ready;

  self = _Scheduler_priority_SMP_Get_self( context );

  while (1) {
    if ( _Priority_bit_map_Is_empty( &self->Bit_map ) ) {
      /* Nothing to do */
      break;
    }

    highest_ready =
      _Scheduler_priority_affinity_SMP_Get_highest_ready( context, NULL );

    lowest_scheduled =
      _Scheduler_priority_affinity_SMP_Get_lowest_scheduled(
        context,
        highest_ready,
        _Scheduler_SMP_Insert_priority_lifo_order
      );

    /*
     * If we can't find a thread to displace from the scheduled set,
     * then we have placed all the highest priority threads possible
     * in the scheduled set.
     *
     * We found the absolute highest priority thread without
     * considering affinity. But now we have to consider that thread's
     * affinity as we look to place it.
     */
    if ( lowest_scheduled == NULL )
      break;

    /*
     * FIXME: Do not consider threads using the scheduler helping protocol
     * since this could produce more than one thread in need for help in one
     * operation which is currently not possible.
     */
    if ( lowest_scheduled->help_state != SCHEDULER_HELP_YOURSELF )
      break;

    /*
     * But if we found a thread which is lower priority than one
     * in the ready set, then we need to swap them out.
     */

    _Scheduler_SMP_Node_change_state(
      _Scheduler_SMP_Node_downcast( lowest_scheduled ),
      SCHEDULER_SMP_NODE_READY
    );
    _Scheduler_Thread_change_state(
      _Scheduler_Node_get_user( lowest_scheduled ),
      THREAD_SCHEDULER_READY
    );

    _Scheduler_SMP_Allocate_processor(
      context,
      highest_ready,
      lowest_scheduled,
      _Scheduler_SMP_Allocate_processor_exact
    );

    _Scheduler_priority_SMP_Move_from_ready_to_scheduled(
      context,
      highest_ready
    );

    _Scheduler_priority_SMP_Move_from_scheduled_to_ready(
      context,
      lowest_scheduled
    );
  }
}