Многозадачность
Я пока дошел только до одного способа реализовать многозадачность:
Прерывание от таймера делаю задачей.
При генерации этого прерывания происходит переключение на задачу-обработчик прерывания таймера.
Суть обработчика пока проста: берем очередной селектор TSS из очереди и делаем JMP на него. Затем (то есть после очередного срабатывания таймера) стираем бит занятости последней выполненой задачи.
На время всех операций в обработчике запрещаю прерывания, чтобы не допустить его рекурсивного вызова (разрешаю перед JMP'ом на очередную задачу и запрещаю сразу после него). В очереди всегда присутствует задача с пустым бесконечным циклом.
Какие принципиальные минусы у такой организации? (И каковы альтернативы?)
Требуется критика или просто мнение.
Какие принципиальные минусы у такой организации? (И каковы альтернативы?)
Защещенный режим процессора.
Защещенный режим процессора.
Не очень понял...
Другой вариант:
Прерывание от таймера делаю просто прерыванием (interrupt с автоматическим запрещением IQR), тогда рекурсивный вызов обработчика уже не приведет к вызову задачи из самой себя.
Между двумя процессами происходит только одно переключение контекста задачи, а не два.
Я так подозреваю, что вызов прерывания (сохранение в стеке адреса возврата и флагов) занимает меньше времени, чем вызов задачи. Так или нет? Хотя, там ведь тоже надо регистры сохранять...
В первом приближении что-то такое:
irq0_timer proc
push Все_что_надо
mov al,20h
out 20h,al ;сигнал контроллеру прерываний
mov ax,селектор_сегмента_в_котором_очередь_задач
mov ds,ax
lab3:
mov di,ds:[0] ;берем смещение селектора текущей задачи в очереди (хранится как первое слово в сегменте, а за ним уже сами селекторы задач)
add di,2 ;следующая
cmp di,510
jc lab1
mov di,2 ;если очередь закончилась, то с начала
lab1:
mov ds:[0],di ;сохраняем новое смещение
mov bx,[di] ;берем селектор из очереди
str ax
cmp ax,bx ;сравниваем с селектором прерваной задачи
jz lab2 ;если та же самая задача, то возврат без переключения контекста
cmp bx,0 ;если в очереди 0000, значит свободное место (пропускаем и ищем следующую)
jz lab3
sub di,2 ;указывает на адрес для JMP'а (смещение и селектор, причем смещение - младшее слово, оно нам не интересно)
db 0ffh ;jmp absolute [di]
db 02dh
lab2:
pop Все_что_надо
db 66h
iret ;возврат к выполнению прерваной задачи
irq0_timer endp
Еще вопрос: как часто надо переключать задачи в ОС с принудительным вытеснением?
И я так и не разобрался - сколько же тактов занимает переключение контекста задачи (сама аппаратная смена контекста, скажем, по команде JMP selector_TSS:XXXX)?