Возобновление управляющего тракта ядра
Ассемблерный код с меткой resume kernei выполняется, если возобновляемая программа работает в режиме ядра:
resume_kernel:cli ; эти три инструкции
cmpl $0, 0x14(ebp) ; отсутствуют, если вытеснение в ядре j z need_resched ; не поддерживается
restore_all: popl ebx popl ecx popl edx popl esi popl edi popl ebp popl eax popl ds popl es addl $4, esp iret
Если поле preempt count дескриптора thread info равно нулю (вытеснение в ядре включено), ядро переходит ПО метке need_resched. В противном случае необходимо возобновить выполнение прерванной программы. Функция загружает в регистры значения, сохраненные, когда возникло прерывание или исключение, и получает управление, выполнив инструкцию iret.
Проверка вытеснения в ядре
Когда выполняется этот код, ни один из незавершенных управляющих трактов ядра не является обработчиком исключения. В противном случае поле preempt count было бы больше нуля. Однако, как было сказано в разд. "Вложенное выполнение обработчиков исключений и прерываний" ранее в этой главе, возможно наличие до двух управляющих трактов ядра, ассоциированных с исключениями (помимо того, который завершается).
need_resched:
movl 0x8(ebp), есх
testb $ (1«TIF_NEED_RESCHED) , cl
jz restore_all
testl $0x00000200,0x30(esp)
jz restore_all
call preempt_schedule_irq
jmp need_resched
Если флаг ТIF_NEЕD_RESСНЕD В ПОЛе flags Дескриптора current->thread_info равен нулю, переключение процессов не требуется, и совершается переход на метку restore aii. Переход на ту же метку совершается, если возобновляемый управляющий тракт ядра работал при отключенных локальных прерываниях. В этом случае переключение процессов могло бы повредить структуры данных ядра
Если требуется переключение процесса, вызывается функция preempt_ schedule_irq . Она устанавливает флаг PREEMPT_ACTIVE В поле preempt_count, временно записывает-1 в счетчик глобальных блокировок ядра, включает локальные прерывания и вызывает функцию schedule о, чтобы выбрать другой процесс. Когда возобновится выполнение первого процесса, функция preempt_schedule_irq восстанавливает предыдущее значение счетчика глобальных блокировок, сбрасывает флаг preempt active и отключает локальные прерывания. Функция schedule о будет многократно вызвана, пока флаг tif need resched текущего процесса остается установленным.
Возобновление программы режима пользователя
Если программа, выполнение которой должно быть возобновлено, работает в режиме пользователя, совершается переход на метку resume userspace:
resume_userspace: cli
movl 0x8(ebp), ecx andl $0x0000ff6e, ecx je restore_all jmp work_pending
После отключения локальных прерываний производится проверка значения поля flags дескриптора current->thread_info. Если никакой флаг, кроме tif_syscall_trace, tif_syscall_audit и tif_singlestep, не установлен, значит, больше ничего предпринимать не нужно. Совершается переход на метку restore aii, что приводит к возобновлению работы программы пользовательского режима.
Предыдущая страница | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | Следующая страница