OSDev
http://osdev.su/

Включение мультизадачности в i386
http://osdev.su/viewtopic.php?f=6&t=124
Страница 1 из 2

Автор:  serg79 [ 19 сен 2007, 12:50 ]
Заголовок сообщения:  Включение мультизадачности в i386

Пытаюсь переключить i386 в мультизадачный режим, использую следующий алгоритм:
1 - подготавливаю дескриптор задачи TSS в GDT;
2 - загружаю селектор дескриптора задачи в TR ("ltr");
3 - сбрасываю флаг занятости "B" в дескрипторе текущей задаче;
4 - делаю дальний переход на текущую задачу.

Так вот, после пункта 4 процессор становиться. Кто знает, как грамотно запустить мультизадачность на i386 подскажите.

P.S. Если нужно больше информации, то спрашивайте.

Автор:  pushkoff [ 19 сен 2007, 14:49 ]
Заголовок сообщения:  Re: Включение мультизадачности в i386

многозадачность програмная или аппаратная? че-то непонял с первого взгляда...
При програмной прыжок вообще не надо делать, при аппаратной надо делать на другую задачу...

Автор:  serg79 [ 19 сен 2007, 15:23 ]
Заголовок сообщения:  Re: Включение мультизадачности в i386

Я для переключения процессора в мультизадачность использую следующий алгоритм:
Код:
; Main_TSS - это селектор некоторого определённого дескриптора TSS.
      mov     ax,Main_TSS
        ltr     ax      ;    Загружаем в регистр TR селектор
       ; дескриптора TSS задачи Main. Теперь текущая
      ; задача - это Main_TSS.

; Чистим Busy flag Main_TSS - он установился после загрузки селектора в TR
       mov     bx,offset GDT + Main_TSS
       and     byte ptr [ bx + 5 ],11111101b

; Переход на Main_TSS
       db      0eah; Этот код эквивалентен команде FAR JMP Main_TSS:00
        dw      00
 dw      Main_TSS

;    Вот здесь процессор сохранил контекст текущей задачи, т.е. заполнил
; поля TSS текущими значениями.
; Main_TSS:

;    А теперь процессор загрузил те же самые значения из TSS в регистры.
; Теперь процессор в режиме мультизадачности.

;    Установка Busy flag Main_TSS - она нужна, потому что был переход с
; Main_TSS на Main_TSS командой JMP - эта команда сбрасывает флаг занятости
; старой задачи, т.е. Main_TSS.
    mov     bx,offset GDT + Main_TSS
       or      byte ptr [ bx + 5 ],10b

Дело в том, что включение мультизадачного режима работы процессора не обязывает при этом иметь несколько задач и обязательно переключаться между ними, можно иметь одну задачу которая будет все время выполняться, но в тоже время это будет задачей т.к. будут задействованы регистр "TR" и использоваться структура "TSS". Так вот, я пытаюсь пока просто перенести текущий выполняемый контекст в задачу.

Если не сбрасывать флаг занятости задачи "B" в дескрипторе задачи, пере дальним переходом на нее "FAR JMP TSS:0" то у меня генерируется исключение общей защиты, т.к. на рабочую задачу переключаться нельзя (рекурсивный вызов задач запрещен).

И так я дохожу до пункта 4 ("FAR JMP TSS:0") и у меня все становиться. У меня такое ощущение, что я гдето просто чегото не доделываю.

Автор:  pushkoff [ 19 сен 2007, 18:43 ]
Заголовок сообщения:  Re: Включение мультизадачности в i386

Я когда парился с многозадачностью напаролся на те же грабли... роцессор запрещает переключаться на текущую ТСС даже если флаг Busy у неё сброшен... Таким способом я хотел снять ограничение на количество задач в системе и уменьшить размер ГДТ. Я вышел из положения использоав программную многозадачность, в ней используется только 1 ТСС, но переключение становится более длительным из-за необходимости каждый раз (верней только при смене процесса) копировать каталоги таблиц. Кстати, кто-нибудь думал над методами ускорения переключения процессов при программном переключении задач?

Автор:  serg79 [ 20 сен 2007, 09:14 ]
Заголовок сообщения:  Re: Включение мультизадачности в i386

Я так понимаю, что при переключении задачи процессор помимо флага занятости "busy" проверяет также сам селектор и если селектор тотже что и в регистре "TR" то он не разрешает переключиться на эту задачу.

Но тогда он должен сгенерировать исключение общей защиты, но этого не происходит. Я пробовал загружать в регистр "TR" селектор дескриптора кода и процессор отрабатывал как надо, генерировал исключение общей защиты. Пробовал вызывать "LJMP $D_TSS,$0" при установленном флаге "busy", исключение общей защиты также выкидывается. А при сброшенном флаге "busy" у меня при команде "LJMP $D_TSS,$0" вообще ничего не происходит, процессор просто встает (я так думаю). Почему не выкидывается какое либо исключение?

Хотя вы можете быть и правы. Дело в том, что я пробовал загружать регистр "TR" дескриптором задачи и не выполнять дальнего перехода, в этом случае все работает как надо: прерывания работают (таймер, клавиатура), исключения работают и основной код работает.

Ладно суть такая, я хочу както удостовериться что режим мультизадачности работает, т.е. хочу посмотреть что поля структуры "TSS" заполняются при переключении задачи. Значит план у меня такой:
Код:
; Готовлю дескрипторы задач Main_TSS, Temp_TSS
; Загружаю "TR"
 movl $Main_TSS, %eax
       ltr %ax
; Все, мультизадачность запущена

; Переключаюсь на задачу Temp_TSS
    lcall $Temp_TSS,$0
; Вот сдесь процессор заполнит поля "TSS" задачи Main_TSS,
; сбрасывает флаг "B" в дескрипторе Main_TSS, потом
; считывает значения из "TSS" задачи Temp_TSS в регистры,
; устанавливает флаг "B" в дескрипторе Temp_TSS, в поле
; "link" структуры "TSS" задачи Temp_TSS записывается
; селектор дескриптора задачи Main_TSS, устанавливает
; флаг "NT" в "eflags" и передает управление коду задачи Temp_TSS

; Вот в этой части кода, уже будут заполнены структуры "TSS"
; как задачи Main_TSS так Temp_TSS и я их могу посматреть
1:    jmp 1b

; Задача Temp_TSS
.globl tmp_func
tmp_func:
        nop
        iret
; т.к. установлен флаг "NT" в регистре "eflags" то управление
; передается задаче чей селектор дескриптора храниться в поле
; "link" структуры "TSS" текущей выполняемой задачи.

Вот такие мысли. Как думайте, после того как задача Main_TSS встанет в бесконечном цикле "1: jmp 1b" структуры задач "TSS" будут заполнены?

И вообще правильно ли я понимаю суть вопроса и корректен ли данный алгоритм?

Автор:  serg79 [ 20 сен 2007, 11:03 ]
Заголовок сообщения:  Re: Включение мультизадачности в i386

Спасибо legos, сегодня вечером буду обратно пытаться все таки запустить задачи.

Автор:  pushkoff [ 20 сен 2007, 12:04 ]
Заголовок сообщения:  Re: Включение мультизадачности в i386

Цитата:
Pushkoff, я для упрощения кода, и увеличения кол-ва задач в системе использую только 2 дескриптора TSS в GDT -- каждый раз перед переключением прописываю в GDT ссылку на нужную структуру TSS.
Количество TSS - по одному на процесс. Вроде нормально получается, и код простой.
//legos

Я тоже об этом думал, но передумал... при твоей схеме каждому потоку надо дать участок памяти размером с ТСС + всякие дополнения, это при том что большая часть ТСС имеют одинаковые поля и большая часть контекста сохраниться в стеке. При програмном переключении весь контекст сохраняется в стеке а в описателе потока сохраняется только указатель на стек (при условии что стек ядра для всех потоков расположен в одном и том же месте) поэтому в целях экономии памяти я выбрал такой подход, но возникает проблема с временем переключения, ведь каждый раз нужно перезаписывать часть адреснго пространства (в моем случае 2 кб, но при смене процесса)... хотя при 36 разрядной адрессации нужно будет скопировать 32 байта.

Автор:  pushkoff [ 20 сен 2007, 13:11 ]
Заголовок сообщения:  Re: Включение мультизадачности в i386

legos, немогу с тобой не согласиться...
просто в моем случае экономия выходит довольно сильная... при 1024 потоках 4 мб у тебя против 256 кб у меня, при одинаковых размерах стека...
Надо сделать в вике статью об многозадачности типах и достоинствах...

Автор:  phantom-84 [ 20 сен 2007, 14:00 ]
Заголовок сообщения:  Re: Включение мультизадачности в i386

Цитата:
но переключение становится более длительным из-за необходимости каждый раз (верней только при смене процесса) копировать каталоги таблиц. Кстати, кто-нибудь думал над методами ускорения переключения процессов при программном переключении задач?
А зачем при переключении копировать каталоги таблиц? Записываешь в CR3 адрес каталога активируемого процесса и все. Каталоги таблиц для процессов (кроме idle-процессов, которые могут быть полность выгружены в своп) я храню в памяти постоянно. К тому же для готовых к выполнению процессов других нормальных вариантов просто нет.

Автор:  phantom-84 [ 20 сен 2007, 14:42 ]
Заголовок сообщения:  Re: Включение мультизадачности в i386

Цитата:
При програмном переключении весь контекст сохраняется в стеке а в описателе потока сохраняется только указатель на стек (при условии что стек ядра для всех потоков расположен в одном и том же месте) поэтому в целях экономии памяти я выбрал такой подход, но возникает проблема с временем переключения, ведь каждый раз нужно перезаписывать часть адреснго пространства (в моем случае 2 кб, но при смене процесса)...
Здесь все просто - нужно либо для каждого потока организовать свой стек ядра, либо сделать так, чтобы полноценно в режиме ядра мог выполняться только один поток процесса, а другие ожидали окончания его работы в режиме ядра - это можно сделать с помощью двухуровневого стека ядра - один уровень с фиксированной длиной и, возможно, местоположением для отработки входа любого потока процесса в режим ядра, а второй уровень для полноценной работы одного из потоков в режиме ядра.

Страница 1 из 2 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/