OSDev

для всех
Текущее время: 10 май 2024, 01:36

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 160 ]  На страницу Пред.  1, 2, 3, 4, 5, 6, 7, 8 ... 16  След.
Автор Сообщение
СообщениеДобавлено: 14 авг 2013, 21:37 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
maisvendoo писал(а):
Хм, действительно можно даже не делать call switch_task, а просто поместить в стек точку входа в функцию потока.
Точку входа нужно поместить в стек в любом случае.

Код:
/* Идем по кольцевой очереди в поисках активного потока */
В очереди можно держать только активные потоки. Пассивные - в других очередях.

Смены current в switch_task вообще не увидел.

Код:
   /* Заполняем стек потока */
   u32int eflags;

   asm volatile ("pushf; pop %0":"=r"(eflags));
Т.к. ты это делаешь с запрещенными прерываниями, у тебя и новая задача будет запускаться с запрещенными прерываниями. Хотя в действительности этого не происходит, т.к. в конце переключалки ты не восстанавливаешь сохраненные флаги, а разрешаешь прерывания явно.

Код:
   esp[0] = eflags;
   esp[-1] = 0x1;
   esp[-2] = 0x2;
   esp[-3] = (u32int) entry_point;
Очень интересно. eflags сохраняется за пределами стека. Что такое esp[-1] и esp[-2] и для чего они нужны, для меня вообще большая загадка. А esp[-4] видимо эмитирует работу пролога сишной функции.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 14 авг 2013, 22:57 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
phantom-84 писал(а):
Смены current в switch_task вообще не увидел

Так вот же
Код:
current_thread = (thread_t*) current_thread->list_item.next;

поле next - указатель на структуру следующего потока

phantom-84 писал(а):
а разрешаешь прерывания явно

Н-да, в пользовательском режиме такое не пройдет.

Что касается этого
Код:
esp[-1] = 0x1;
esp[-2] = 0x2;

то честно говоря заполнил стек наперед заданными числами, и в отладчике смотрел какую позицию процессор получает как адрес возврата. Я понимаю что это чит, ну надо было как-то запустить, теперь ковыряюсь с разбором, пока не разберусь дальше не пойду.

P.S.: наверное вот так будет лучше ;)
Код:
void switch_task(void)
{
   if (multi_task)
   {
      
      asm volatile ("cli");

      
      asm volatile ("mov %%esp, %0":"=a"(current_thread->state.esp));
      
      do
      {
         current_thread = (thread_t*) current_thread->list_item.next;
         current_proc = (process_t*) current_proc->list_item.next;

      }   while ( (current_thread->suspend) || (current_proc->suspend) );
      
      asm volatile ("mov %0, %%cr3"::"a"(current_proc->page_dir));

      asm volatile ("mov %0, %%esp"::"a"(current_thread->state.esp));

      /* Восстанавливаем регистр флагов из стека, неявно разрешая прерывания */
      asm volatile ("popf");
   }
}

вместе с вот этим
Код:
esp[-1] = eflags;
esp[-3] = (u32int) entry_point;


Последний раз редактировалось maisvendoo 14 авг 2013, 23:28, всего редактировалось 4 раз(а).

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 14 авг 2013, 23:18 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
maisvendoo писал(а):
Так вот же
Да, не увидел. Для меня использование цикла выглядит как-то непривычно.

Цитата:
наверное вот так будет лучше
Да, только перед cli сделай pushf. Поменяй местами значения esp[-1] и esp[-3]. Размер кадра уменьши до 12 байт.


Последний раз редактировалось phantom-84 14 авг 2013, 23:32, всего редактировалось 2 раз(а).

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 14 авг 2013, 23:21 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
phantom-84 писал(а):
Для меня использование цикла выглядит как-то непривычно.

если не держать замороженные потоки в очереди с активными тогда без цикла, сначала так и было, пока не стал использовать suspend


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 14 авг 2013, 23:47 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
Я подредактировал пред. пост. Имеется в виду такой стековый кадр:

esp[-1]: стартовый адрес;
esp[-2]: имитирует действия пролога (видимо, содержит значение EBP - можно использовать для задания начального значения EBP);
esp[-3]: EFLAGS.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 авг 2013, 00:47 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
phantom-84 писал(а):
esp[-2]: имитирует действия пролога (видимо, содержит значение EBP - можно использовать для задания начального значения EBP);

Да, ebp, ибо при вызове сишной функции уже в её теле происходит
Код:
push ebp
mov ebp, esp
.
.
.
тут что-то делаем
.
.
.
pop ebp
ret

То есть в моем случае имеем дизассемблированный хвост переключалки
Код:
.
.
.
popf       ;Выталкиваю флаги из стека нового потока
pop ebp
ret

Все значения корректны у меня, адрес возврата и флаги, но падает из-за #PF...

P.S.:
phantom-84 писал(а):
Да, только перед cli сделай pushf

Сначала не понял зачем, потом въехал - для следующих переключений. Добавил, заработало с popf :)

Со структурой стекового кадра задачи разобрался вроде, ещё раз спасибо :)

Добавил две функции - приостановка потока и корректный выход из него
Код:
/*-----------------------------------------------------------------------------
 *      Suspend thread
 *---------------------------------------------------------------------------*/
void thread_suspend(thread_t* thread, bool suspend)
{
   thread->suspend = suspend;
}

/*-----------------------------------------------------------------------------
 *      Correct exit from thread
 *---------------------------------------------------------------------------*/
void thread_exit(thread_t* thread)
{
   /* Disable all interrupts */
   asm volatile ("cli");

   /* Remove thread from queue */
   list_remove(&thread->list_item);

   /* Free thread's memory (handler and stack) */
   free(thread->stack);
   free(thread);

   /* Load to ECX switch function address */
   asm volatile ("mov %0, %%ecx"::"a"(&switch_task));

   /* Enable all interrupts */
   asm volatile ("sti");

   /* Jump to switch_task() */
   asm volatile ("call *%ecx");
}


В том же линуксе, если поток не зациклен while (1) без pthread_exit(...) наблюдается вывал программы. Тут же столкнулся с тем что такой вот поток
Код:
void task01(void)
{
   print_text_XY(0, 10, "I'm task #1");
   print_dec_XY(13, 10, count01);
   count01++;   
}

при выходе закономерно плюет управление в никуда. А вот так
Код:
void task01(void)
{
   print_text_XY(0, 10, "I'm task #1");
   print_dec_XY(13, 10, count01);
   count01++;
   thread_exit(thread01);
}

всё норм

P.P.S.: Запилил виртуальные экраны для каждого потока. Теперь всё ровненько без принудительной синхронизации
Изображение
функция потока стала такого вида
Код:
/*------------------------------------------------------------------------------
//      Thread #1
//----------------------------------------------------------------------------*/
void task01(void)
{
   char tmp_str[256];

   vs01 = (vscreen_t*) get_vscreen();

   while (1)
   {
      vs01->cur_x = 0;
      vs01->cur_y = 11;

      dec2dec_str(count01, tmp_str);

      vprint_text(vs01, "I'm thread #1: ");

      vs01->cur_x = 16;

      vprint_text(vs01, tmp_str);

      count01++;
   }

   destroy_vscreen(vs01);
   thread_exit(thread01);
}

Но скажем при обращении к "куче" всё равно потребна синхронизация, в каждом потоке выполняется маллок при старте


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 авг 2013, 20:00 

Зарегистрирован: 10 апр 2012, 23:19
Сообщения: 277
maisvendoo писал(а):
scuter писал(а):
а дайте пожалюйста образ мем детекторы

Алгоритм определения объема доступной памяти что-ли?

нет мне образ дискеты нужен, (которых просто показывает память),

я собрал образ детектора из исходников от сюда http://dev64.wordpress.com/osdev/
только вот он использует 64-битный код, ну там всякие RAX RCX RBX, то есть 64-х битные регистры.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 авг 2013, 20:39 
Аватара пользователя

Зарегистрирован: 16 май 2007, 23:46
Сообщения: 1126
[offtop]
ИХМО рано вам ещё ОСдеом заниматься.
Память определяется в реальном 16 битном режиме при помощи int 15h
Большинство не занимается разработкой загрузчика, а использую уже готовый загрузчик с поддержкой Multi Boot Specification, согласно которой эти данные просто передаются как параметры.
Работы на 30 минут. Из них 15 на гугл и чтения документации.
[/offtop]


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 авг 2013, 20:44 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
maisvendoo писал(а):
Сначала не понял зачем, потом въехал - для следующих переключений. Добавил, заработало с popf :)
Да, этот метод хорош еще и тем, что по виду переключалка - это обычная подпрограмма - на каждый push (sub esp) должен быть свой pop (add esp).

Цитата:
Добавил две функции - приостановка потока
При такой реализации поток не сможет сразу приостановить сам себя.

Цитата:
и корректный выход из него
Лучше чтобы завершающие действия по уничтожению выполнял другой поток. Иначе в определенный момент получится так, что выполняется формально несуществующий поток.

Еще я заметил, что в некоторых функциях ты надолго запрещаешь прерывания - это не есть хорошо.

Цитата:
В том же линуксе, если поток не зациклен while (1) без pthread_exit(...) наблюдается вывал программы. Тут же столкнулся с тем что такой вот поток [...] при выходе закономерно плюет управление в никуда. А вот так [...] всё норм
Можно в стеке потока оставлять адрес функции завершения. Хотя я думаю, что это лишнее.

Цитата:
P.P.S.: Запилил виртуальные экраны для каждого потока. Теперь всё ровненько без принудительной синхронизации [...] Но скажем при обращении к "куче" всё равно потребна синхронизация, в каждом потоке выполняется маллок при старте
Естественно, такие "виртуальные экраны" - это временное решение. Можно было сделать и синхронный вывод (с прокруткой экрана или без), но в этот нет особого смысла, лучше тогда сразу сделать функцию синхронной печати строк. Что касается системных функций и их синхронной работы, то это вообще отдельная история. Если кратко, то можно сделать функции повторно входимыми и нет. У меня и системный сервис, и внутренние функции ядра являются повторно входимыми. Нет повторной входимости только для функций вирт. устройств (для облегчения разработки драйверов устройств) - ядро само синхронизирует доступ к таким функциям, а также отвергает их циклические вызовы.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 авг 2013, 22:30 

Зарегистрирован: 10 апр 2012, 23:19
Сообщения: 277
pavia писал(а):
ИХМО рано вам ещё ОСдеом заниматься.
Память определяется в реальном 16 битном режиме при помощи int 15h
Большинство не занимается разработкой загрузчика, а использую уже готовый загрузчик с поддержкой Multi Boot Specification, согласно которой эти данные просто передаются как параметры.
Работы на 30 минут. Из них 15 на гугл и чтения документации.

кароче у вас зимой снега не допросишся.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 160 ]  На страницу Пред.  1, 2, 3, 4, 5, 6, 7, 8 ... 16  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB