OSDev

для всех
Текущее время: 28 апр 2024, 00:45

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




Начать новую тему Ответить на тему  [ Сообщений: 160 ]  На страницу Пред.  1 ... 12, 13, 14, 15, 16
Автор Сообщение
СообщениеДобавлено: 03 сен 2013, 21:07 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
maisvendoo писал(а):
Кстати - офигенная идея запуска процесса в его же контексте. Ни прерывания выключать не надо, ни планировщик останавливать. Задача запускает сама себя
В никсах изначально присутствовала эта фишка, причем использовалась явно. Но форк на меня нагонял большую тоску. Поэтому я сделал гибридный вариант, которым весьма доволен. Я дошел до этого сам, хотя конечно это весьма распространенное решение.


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

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

В общем, на приведенном скриншоте - весь ассортимент: процесс hello запущенный из процесса ядра, дочерний процесс, запущенный из этого процесса, потоки запущенные процессом ядра, и поток запущенный процессом hello.
Создание стека потока, запускаемого из процесса выполняется в куче, расположенной в ВАП процесса-родителя. Причем каталог переключается планировщиком, нигде нет принудительных переключений :). Кучи всех процессов имеют одинаковые виртуальные адреса, но физически лежат в разных местах, как и положено

Ещё раз убедился в прогрессивности предложенной схема запуска - если правильно работает планировщик, не надо задумываться в каком контексте у тебя происходят действия

Add: Сегодня попробовал написать на асме хелловорд для своей системы. Исходник ничем не отличается от аналогичного для, скажем, Linux (разве что в линукс int 80h а не int 50h)
Код:
/*-----------------------------------------------------------------------------
/
/       Test GNU assembler program for PhantomEx
/       (c) maisvendoo, 04.09.2013
/
/----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
 *      Constants
 *---------------------------------------------------------------------------*/
.set    cur_x,          0
.set    cur_y,          15
.set    VIDEO_MEMORY,   0x15000000

.set    SYS_EXIT,        0
.set    SYS_VPRINT,      0x0D     
/*-----------------------------------------------------------------------------
 *      Data section
 *---------------------------------------------------------------------------*/
.data
   
msg:
        .ascii  "I'm test GNU assembler program!!!\n"
/*-----------------------------------------------------------------------------
 *      Code section
 *---------------------------------------------------------------------------*/
.text
        .comm   vs,4,1
       
        .global _start
       
_start:
        /* Fill vs structure */
        mov $vs, %edx               /* &vs --> EDX */
        mov $cur_x, %ebx            /* vs.cur_x init */
        mov %ebx, (%edx)
        mov $cur_y, %ebx            /* vs.cur_y init */
        mov %ebx, 1(%edx)
        mov $VIDEO_MEMORY, %ebx     /* vs.vmemory init */
        mov %ebx, 2(%edx)
        /* Call system function SYS_VPRINT */
        mov $SYS_VPRINT, %eax
        mov $vs, %ebx
        mov $msg, %ecx
        int $0x50
        /* Call system function SYS_EXIT */
        mov $SYS_EXIT, %eax
        int $0x50
       
        ret

Кроме того исправил критическую ошибку в менеджере кучи ядра, всплывшую после того, как я приступил к аккуратному удалению "мусора" после загрузки/завершения процессов/потоков, так как в тестовом варианте всё работало без удаления динамики. Теперь куча вроде освобождается нормально, не генерируя после этого #PF (там было наложение блоков памяти при выделении с выравниванием по 4К)


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

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
Решил перенести это обсуждение сюда - сабж непосредственно связан с темой ветки
phantom-84 писал(а):
В классическом мьютексе используется ожидание при доступе к занятому объекту/структуре. Не хотите использовать ожидание, попробуйте хотя бы вместо простого зацикливания дополнительно делать SwitchToNext

Вот попробовал принудительно переключаться
Код:
/*-----------------------------------------------------------------------------
/
/       Critical section lock
/       (c) maisvendoo, 05.09.2013
/
/----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
/       bool mutex_lock(mutex_t* mutex, bool wait)
/----------------------------------------------------------------------------*/
.global     mutex_lock
.extern     task_switch
.extern     sync_msg

mutex_lock:

        mov     $1, %eax        /* old_value */
       
        mov     4(%esp), %ebx   /* mutex* */
        mov     8(%esp), %edx   /* wait */
       

        xchg    %eax, (%ebx)
       
        and     %edx, %eax
        test    %eax, %eax
        jnz     sync_msg
        /*jnz   task_switch */
       
        not     %eax

        ret

Вместе с переключением, для теста, выполняется выдача в консоль сообщения, что бы знать, что произошло переключение при наскоке на захваченный мьютекс. Это пока что сработало лишь однажды, при тестировании ассемблерной версии memcpy
Изображение
Синхронизируется тут выделение памяти в куче ядра. Думаю потестить ещё более жестоко, с последующим выводом данных о занятых блоках памяти в куче.
Кроме того, сделал на основе атомарной операции остановку/запуск планировщика
Код:
/*-----------------------------------------------------------------------------
/       Start scheduler
/----------------------------------------------------------------------------*/
.global     start

start:
           
            mov     $1, %eax
            xchg    %eax, multi_task   
           
            ret

/*-----------------------------------------------------------------------------
/       Stop scheduler
/----------------------------------------------------------------------------*/
.global     stop

stop:
           
            xor     %eax, %eax
            xchg    %eax, multi_task   
           
            ret

Эти функции вызываются у меня теперь везде, где я использовал cli/sti, да собственно запрет прерываний я делал с целью остановить переключение задач - действительно это ужасно: если стоит планировщик, всё связанное с прерываниями не обязательно должно выключатся.

Пока видна разница только в результате компиляции - реализация на C выполняется так
Изображение

P.S.: В ядре всё больше и больше ассемблерного кода... Планирую перевести на него все операции с массивами памяти и строками - библиотеки stdlib и string. Речь о переносимости пока что не идет.


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

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
maisvendoo писал(а):
Решил перенести это обсуждение сюда - сабж непосредственно связан с темой ветки
phantom-84 писал(а):
В классическом мьютексе используется ожидание при доступе к занятому объекту/структуре. Не хотите использовать ожидание, попробуйте хотя бы вместо простого зацикливания дополнительно делать SwitchToNext

Вот попробовал принудительно переключаться...
Я имел в виду что-то типа этого:
Код:
@@:
  mov eax,1
  xchg eax,[ebx]
  and eax,eax
  jz @f
  call SwitchToNext
  jmp @b
@@:
Т.е. цикл нужно оставить, т.к. блокировка может сохраняться (или даже завершаться и выполняться повторно) во время полного обхода очереди выполнения. Мы лишь избавляемся от зацикливания, на котором время тратится впустую.

Код:
        and     %edx, %eax
        test    %eax, %eax
        jnz     sync_msg
Здесь test - лишняя инструкция.

Цитата:
Кроме того, сделал на основе атомарной операции остановку/запуск планировщика...
Не увидел существенных отличий от того, что было.


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

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

Сделал так
Код:
/*-----------------------------------------------------------------------------
/       bool mutex_lock(mutex_t* mutex, bool lock)
/----------------------------------------------------------------------------*/
.global     mutex_lock
.extern     task_switch
.extern     sync_msg

mutex_lock:

        mov     $1, %eax        /* old_value */
       
        mov     4(%esp), %ebx   /* mutex* */
        mov     8(%esp), %edx   /* wait */       

        xchg    %eax, (%ebx)
       
        and     %edx, %eax
        jz      return
        /*call    sync_msg*/
        call    task_switch
        jmp     mutex_lock
       
return:     
        not     %eax

        ret

тоже работает. Вроде даже без глюков.

Урааа!!! Во что хотел написать - передал первое сообщение из ядра в приложение
Изображение
Таким же способом можно и из приложения в приложение посылать, причем приложения не видят очередь напрямую, а складывают принятые/передаваемые данные в своем ВАП


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

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
Написал драйвер клавиатуры уровня ring 3
Код:
/*-----------------------------------------------------------------------------
 *
 *       Keyboard driver for PhantomEx
 *       (c) maisvendoo, 08.09.2013
 *
 *-----------------------------------------------------------------------------*/
#include   "kbdrv.h"

/*-----------------------------------------------------------------------------
 *      Entry point function
 *---------------------------------------------------------------------------*/
int main(void)
{
   msg_t   msg;   /* Driver message structure */

   while (1)
   {
      /* Read scan code from keyboard buffer */
      u8int keyb = key_scan();

      /* Key nonzero */
      if (keyb)
      {
         /* Fill message structure */
         msg.id = MSG_KEYBOARD;   /* Keyboard driver's message ID */
         msg.dest_pid = 1;      /* Here will in focus application ID!!! */
         msg.data_size = 1;      /* Data size - one byte */
         msg.buff[0] = keyb;      /* Data buffer */

         /* Send message */
         msg_send(&msg);
      }
   }

   return 0;
}

Для обеспечения его работы есть низкоуровневая обвязка в виде обработчика IRQ1, читающего порты и формирующего буфер нажатых клавиш
Код:
/*-----------------------------------------------------------------------------
 *
 *---------------------------------------------------------------------------*/
void keyb_handler(registers_t regs)
{
   u8int   scan_code = 0;
   u8int   status = 0;
   u8int   ctrl = 0;

   /* Read keyboard state */
   status = inb(KBD_STATE_REG);

   /* Reading buffer is full? */
   if (status & KBD_IS_READDATA)
   {

      /* Fill keyboard ring buffer */
      if (kb_tail >= KEY_BUFFER_SIZE)
      {
         kb_tail = 0;
      }

      kb_tail++;

      key_buff[kb_tail - 1] = inb(KBD_DATA_PORT);

      /* Set and reset bit 7 by keyboard control register */
      ctrl = inb(KBD_CTRL_REG);
      ctrl |= 0x80;
      outb(KBD_CTRL_REG, ctrl);
      ctrl &= 0x7F;
      outb(KBD_CTRL_REG, ctrl);
   }
}

Драйвер читает содержимое буфера клавиатуры системным вызовом key_scan() и посылает находящемуся в фокусе ввода приложению сообщение с этим скан-кодом - системный вызов msg_send(...).

В приложении организован прием сообщений в цикле с последующей обработкой
Код:
while (1)
   {
        dec2dec_str(*count, tmp);

         s8int noerr = msg_recv(&msg); /* Прием - выборка сообщения из очереди */

         if (noerr && (msg.id == 0x01) ) /* Проверка факта приема и типа сообщения */
         {
            /* Если сообщение от драйвера клавиатуры - выводим на экран скан-код */
                        strcpy(tmp, "Key 0x");
            byte2hex_str(msg.buff[0], tmp2);
            strcat(tmp, tmp2);

            vs.cur_x = strlen(msg0) + 1;
            vs.cur_y = 22;

            vprint(&vs, tmp);
         }

         (*count)++;
   }

Работает всё вроде без сбоев
Изображение


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

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

Код:
      /* Fill keyboard ring buffer */
      if (kb_tail >= KEY_BUFFER_SIZE)
      {
         kb_tail = 0;
      }

      kb_tail++;
Если использовать размер очереди, кратный степени двойки, то можно "сворачивать" буфер AND'ом. Я использую это в том числе и для событийной очереди.

Не увидел обработки переполнения буфера.

Код:
      /* Set and reset bit 7 by keyboard control register */
      ctrl = inb(KBD_CTRL_REG);
      ctrl |= 0x80;
      outb(KBD_CTRL_REG, ctrl);
      ctrl &= 0x7F;
      outb(KBD_CTRL_REG, ctrl);
Не понял, что это.

Цитата:
Драйвер читает содержимое буфера клавиатуры системным вызовом key_scan() и посылает находящемуся в фокусе ввода приложению сообщение с этим скан-кодом - системный вызов msg_send(...).
Нужно выполнять трансляцию сканкода непосредственно в первичном обработчике или отправлять вместе с ним состояние "сдвиговых" клавиш и индикаторов. Я использую смешанный подход: сканкод транслирую в уникальный виртуальный код клавиши (в виртуальный код могут складываться несколько сканкодов, т.е. для префиксов используется предбуфер), вместе с которым отправляю shift-статус и led-статус для дальнейшей "высокоуровневой" трансляции.


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

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

Гхм, у Зубкова прочитал что
Цитата:
обработчик аппаратного прерывания клавиатуры должен установить бит 7 порта 61h, а затем вернуть его в исходное состояние

Собственно и проделал это


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

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
Это древность. Нынче к клаве относятся только 60h и 64h.


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

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

То-то я думаю почему установленный бит при считывании пропадает :lol:. Книжка 2004 года издания, и это третье издание, стереотипное


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 160 ]  На страницу Пред.  1 ... 12, 13, 14, 15, 16

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


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

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


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

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