Разработка ядра Linux | страница 67
• Функция >load_balance()
находит непустой список заданий, соответствующий самому высокому приоритету (с самым маленьким номером), так как важно более равномерно распределять задания с высоким приоритетом, чем с низким.
• Каждое задание с данным приоритетом анализируется для определения задания, которое не выполняется, не запрещено для миграции из-за процессорной привязки и не активно в кэше. Если найдена задача, которая удовлетворяет этому критерию, то вызывается функция >pull_task()
для проталкивания этой задачи из наиболее загруженной очереди в данную очередь.
• Пока очереди выполнения остаются разбалансированными, предыдущие два шага повторяются и необходимое количество заданий проталкивается из самой загруженной очереди выполнения в данную очередь выполнения. В конце концов, когда дисбаланс устранен, очередь выполнения разблокируется и происходит возврат из функции >load_balance()
.
Далее показана функция >load_balance()
, немного упрощенная, но содержащая все важные детали.
>static int load_balance(int this_cpu, runqueue_t *this_rq,
> struct sched_domain *sd, enum idle_type idle) {
> struct sched_group *group;
> runqueue_t *busiest;
> unsigned long imbalance;
> int nr_moved;
> spin_lock(&this_rq->lock);
> group = find_busiest_group(sd, this_cpu, &imbalance, idle);
> if (!group)
> goto out_balanced;
> busiest = find_busiest_queue(group);
> if (!busiest)
> goto out_balanced;
> nr_moved = 0;
> if (busiest->nr_running > 1) {
> double_lock_balance(this_rq, busiest);
> nr_moved = move_tasks(this_rq, this_cpu, busiest,
> imbalance, sd, idle);
> spin_unlock(&busiest->lock);
> }
> spin_unlock(&this_rq->lock);
> if (!nr_moved) {
> sd->nr_balance_failed++;
> if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) {
> int wake = 0;
> spin_lock(&busiest->lock);
> if (!busiest->active_balance) {
> busiest->active_balance = 1;
> busiest->push_cpu = this_cpu;
> wake = 1;
> }
> spin_unlock(&busiest->lock);
> if (wake)
> wake_up_process(busiest->migration_thread);
> sd->nr_balance_failed = sd->cache_nice_tries;
> }
> } else
> sd->nr_balance_failed = 0;
> sd->balance_interval = sd->min_interval;
> return nr_moved;
>out_balanced:
> spin_unlock(&this_rq->lock);
> if (sd->balance_interval < sd->max_interval)
> sd->balance_interval *= 2;
> return 0;
>}
Вытеснение и переключение контекста
Переключение контекста — это переключение от одной, готовой к выполнению задачи к другой. Это переключение производится с помощью функции >context_switch()