Результат реализации switch_to() на РРС не обязательно идентичен вызову х86; он берет указатели на current и next задачи и возвращает указатель на предыдущую выполнявшуюся задачу:
include/asm-ppc/system.h
38 extern struct task_struct * switch_to(struct task_struct *,
39 struct task_struct *);
90 #define switch_to(prev, next, last)
((last) = switch_to((prev), (next)))
91
92 struct thread_struct;
93 extern struct task_struct *_switch(struct thread_struct *prev,
94 struct thread_struct *next),-
В строке 88 switch_to () получает параметр типа task_struct и на строке 93
получает в качестве параметра thread_struct. Это необходимо для того, чтобы вхож-
дение в task_struct содержало архитектурно-зависимую информацию о регистрах
процессора, необходимую данному процессу. Теперь давайте рассмотрим реализацию
switch_to ().
/arch/ррс/kernel/process.с
200 struct task_struct * switch_to(struct task_struct
struct task_struct
'prev, "new)
) передается в set_ ентации РРС.
:t_context () через
I). Во время возвраще-ветствующей области
201 202 203 204 205
247 248 249 250 251 252
{
struct thread_struct *new_thread, *old_thread;
unsigned long s;
struct task_struct *last;
local_irq_save(s);
new_thread = &new->thread;
old_thread = ¤t->thread;
last = _switch(old_thread, new_thread),-
local_irq_restore(s);
return last;
}
Строка 205
Отключение прерываний перед переключением контекста.
Строки 247-248
Выполнение еще продолжается в контексте старого потока, а указатель на структуру потока передается в функцию _switch ().
Строка 249
Ассемблерная функция _switch() вызывается для выполнения работы по переключению двух структур потоков (см. следующий раздел).
Строка 250
Включение прерываний после переключения контекста.
Для лучшего понимания того, что нужно обменять в потоке РРС, нам нужно рассмотреть структуру thread_struct, передаваемую в строке 249.
Вы можете вспомнить из описания переключения контекста х86, что переключение официально не происходит до тех пор, пока мы не указываем на новый стек ядра. Это происходит в _switch ().
Отслеживание кода РРС для jrwitchO
По соглашению параметры С-функции РРС (слева направо) хранятся в гЗ, г4, г5,г12. При вхождении в switch () гЗ указывает на thread_struct для текущей задачи, а г4 указывает на thread_struct для новой задачи:
/arch/ppc/kernel/entry.S
437 _GLOBAL(_switch)
438 stwu rl,-INT_FRAME_SIZE(rl)
439 mflr rO
440 stw rO,INT_FRAME_SIZE+4(rl)
441 /* r3-rl2 сохраняются вызывающим -- Cort */
442 SAVE_NVGPRS(rl)
443 stw rO,_NIP(rl) /* возвращение в вызов переключателя */
444 mfmsr rll
458 1: stw rll,_MSR(rl)
459 mfcr rlO
460 stw rlO,_CCR(rl)
461 stw rl,KSP(r3) /* Установка старого указателя на стек */ 462
463 tophys(rO,r4)
464 CLR_TOP32(rO)
465 mtspr SPRG3,rO /* обновление физического адреса текущего THREAD */
466 lwz rl,KSP(r4) /* Загрузка нового указателя на стек */
467 /* сохранение старого текущего "последнего"
для возвращаемого значения */
468 mr r3,r2
Побайтовый механизм замены предыдущей thread_struct новой мы оставляем на ваше самостоятельное изучение. Это не сложно, а основы использования rl, г2, гЗ, SPRG3 и г4 вы можете увидеть в _switch ().
Строки 438-460
Окружение сохраняется в текущий стек с сохранением указателя на текущий стек в rl.
Строка 461
Далее окружение полностью сохраняется в текущую thread_struct, передающуюся через указатель в гЗ.
Строки 463—465
SPRG3 обновляется для указания на структуру потока для новой задачи. Строка 466
KSP - это отступ в структуре задачи (г4) в указателе на новый стек ядра задачи. Указатель на стек rl обновляется этим значением. (В этой точке выполняется переключение контекста РРС.)
представляет последнюю задачу.
Строка 469
Текущий указатель (г2) обновляется указателем на новую структуру задачи (г4). Строки 478-486
Восстановление оставшегося окружения из нового стека и возвращение в вызывающую функцию с предыдущей структурой задачи в гЗ.
На этом мы заканчиваем объяснение context_switch (). В этой точке процессор обменял два процесса: prev и next, вызванные context_switch в schedule ().
kernel/sched.с
1709 prev = context_switch(rq, prev, next);
Теперь prev указывает на процесс, который мы только что переключили, a next указывает на текущий процесс.
Теперь, когда мы обсудили планирование процессов в ядре Linux, мы можем разобраться в том, как планируются задачи, а именно, что вызывает schedule () и как процесс передает процессор другому процессу.