OSDev

для всех
Текущее время: 13 дек 2018, 11:10

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




Начать новую тему Ответить на тему  [ Сообщений: 32 ]  На страницу 1, 2, 3, 4  След.
Автор Сообщение
 Заголовок сообщения: Измерение времени в ОС
СообщениеДобавлено: 10 сен 2013, 16:10 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
Решил вынести это отдельной темой, так как вопрос важный, среди прочего озадачился сейчас этим.
Для измерения временных промежутков, хотя бы даже для реализации имеющихся в популярных ОС вызовов sleep/usleep, использование IRQ0, IRQ8 не подходит в виду небольшого разрешения таймера и часов РВ. Поэтому решил сделать реализацию на основе инструкции RDTSC.

Собственно запрос числа тактов процессора с момента включения
Код:
/*-----------------------------------------------------------------------------
/       void get_cpu_ticks(u64int* ticks)
/----------------------------------------------------------------------------*/
.global     get_cpu_ticks

get_cpu_ticks:

        mov     4(%esp), %ebx
       
        rdtsc
       
        mov     %eax, (%ebx)
        mov     %edx, 4(%ebx)       
       
        ret

Для привязки к реальным временным единицам необходима тактовая частота CPU, которую я определяю в обработчике IRQ0, который выполняется с частотой BASE_FREQ = 1024 Гц
Код:
/*------------------------------------------------------------------------------
//   
//----------------------------------------------------------------------------*/
void timer_callback(registers_t regs)
{
   timer_tick++;

   if (tick_count == (BASE_FREQ >> 8 ))
   {
      tick_count = 0;

      get_cpu_ticks(&cpu_ticks1);
      dticks = (u32int) (cpu_ticks1 - cpu_ticks0);

      cpu_ticks0 = cpu_ticks1;

      cpu_freq = dticks << 8;
   }

   tick_count++;

   msg_reset();

   if (is_multitask())
   {
      task_switch();
   }
}

/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
u32int get_cpu_freq(void)
{
   return cpu_freq;
}


Сама реализация sleep(...)
Код:
/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
int   sleep_msec(u32int msec)
{
   u32int   ticks = 0;                  /* Time interval in CPU ticks */

   u64int   cpu_ticks0 = 0;               /* Initial CPU tick count */
   u64int   cpu_ticks1 = 0;               /* Actual CPU tick count */

   /* Get CPU ticks count */
   get_cpu_ticks(&cpu_ticks0);

   /* Calculate tick's count in 1 ms */
   u32int scaled_cpu_freq = get_cpu_freq()/MSEC;
   /* Tick's count in required time interval */
   u32int eq_ticks = msec*scaled_cpu_freq;

   do
   {
      /* Get CPU ticks count */
      get_cpu_ticks(&cpu_ticks1);
      /* Time interval in CPU ticks */
      ticks = (u32int) (cpu_ticks1 - cpu_ticks0);

   } while ( ticks <  eq_ticks);

   return 1;
}


На QEMU работает так
Изображение
Счетчик обновляется раз в секунду - sleep(1000). Тактовая частота моего хост-процессора 3400 МГц, вроде ок

Что интересно - Bochs показывает частоту 50 МГц, видимо такая частота эмулируется там программно, но счетчик обновляется раз в секунду, то есть и тут вроде всё ок
Изображение


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 10 сен 2013, 21:19 

Зарегистрирован: 19 май 2011, 14:54
Сообщения: 73
maisvendoo писал(а):
Для измерения временных промежутков, хотя бы даже для реализации имеющихся в популярных ОС вызовов sleep/usleep, использование IRQ0, IRQ8 не подходит в виду небольшого разрешения таймера и часов РВ. Поэтому решил сделать реализацию на основе инструкции RDTSC.

Сама реализация sleep(...)
Код:
/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
int   sleep_msec(u32int msec)
{
   u32int   ticks = 0;                  /* Time interval in CPU ticks */

   u64int   cpu_ticks0 = 0;               /* Initial CPU tick count */
   u64int   cpu_ticks1 = 0;               /* Actual CPU tick count */

   /* Get CPU ticks count */
   get_cpu_ticks(&cpu_ticks0);

   /* Calculate tick's count in 1 ms */
   u32int scaled_cpu_freq = get_cpu_freq()/MSEC;
   /* Tick's count in required time interval */
   u32int eq_ticks = msec*scaled_cpu_freq;

   do
   {
      /* Get CPU ticks count */
      get_cpu_ticks(&cpu_ticks1);
      /* Time interval in CPU ticks */
      ticks = (u32int) (cpu_ticks1 - cpu_ticks0);

   } while ( ticks <  eq_ticks);

   return 1;
}



Чем же такая реализация решает проблемы неточности IRQ0, IRQ8? Такая реализация sleep_msec на 100% загружает одно из ядер процессора на время своего выполнения, что не приемлемо для нормальной работы. Может, я конечно, что-то недопонял в коде.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 10 сен 2013, 21:49 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
По идее в качестве "эталона" времени здесь используется продолжительность такта процессора, то намного меньше самого малого периода срабатывания IRQ0. Виндозный QueryPerformanceCounter() тоже построен на использовании RDTSC.
achesnokov писал(а):
Такая реализация sleep_msec на 100% загружает одно из ядер процессора на время своего выполнения

Кроме как зациклить выполнение потока на время задержки пока ничего не придумал


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 10 сен 2013, 22:11 

Зарегистрирован: 19 май 2011, 14:54
Сообщения: 73
maisvendoo писал(а):
По идее в качестве "эталона" времени здесь используется продолжительность такта процессора, то намного меньше самого малого периода срабатывания IRQ0. Виндозный QueryPerformanceCounter() тоже построен на использовании RDTSC.
achesnokov писал(а):
Такая реализация sleep_msec на 100% загружает одно из ядер процессора на время своего выполнения

Кроме как зациклить выполнение потока на время задержки пока ничего не придумал


QueryPerformanceCounter() по названию своему определяет и назначение свое - измерение "времени" выполнения фрагмента кода.

Правильная реализация sleep/sleep_msec должна приводить к приостановке текущего треда (и если это необходимо к переключению процессов). Будиться тред должен по прерыванию. Никто ничего лучше не придумал. Если не хватает точности, просто увеличивается частота прерывания IRQ0. Тред точно разбудить нельзя. +- 1 срабатывание IRQ0 - предельная точность.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 10 сен 2013, 22:17 
Аватара пользователя

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 10 сен 2013, 22:20 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1070
Откуда: Балаково
Непонятно, как sleep() применяется для измерения временных промежутков.


Последний раз редактировалось Himik 10 сен 2013, 22:28, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 10 сен 2013, 22:27 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
sleep - здесь, пример на котором проверял корректность работы. Главное тут пока get_cpu_ticks() и get_cpu_freq(). Последняя пытается учитывать что частота меняется - в консоль она выдает именно текущую частоту, которая пересчитывается раз в 1/256 секунды
achesnokov писал(а):
на 100% загружает одно из ядер процессора

М-да, а однопроцессорный/одноядерный повесит вообще. Ну этот код не претендует на академичность, это первая проба в этом направлении


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 10 сен 2013, 23:01 
Аватара пользователя

Зарегистрирован: 16 май 2007, 23:46
Сообщения: 1092
По поводу замера скорости процессора.

Цитата:
sleep - здесь, пример на котором проверял корректность работы. Главное тут пока get_cpu_ticks() и get_cpu_freq(). Последняя пытается учитывать что частота меняется - в консоль она выдает именно текущую частоту, которая пересчитывается раз в 1/256 секунды

Реализация бредовая, TSC имеет фиксированную частоту и именно её вы меряете. Исключение PentiumM в котором она плавала.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 10 сен 2013, 23:35 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
pavia писал(а):
Реализация бредовая

Понял уже


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 10 сен 2013, 23:41 

Зарегистрирован: 26 мар 2012, 17:32
Сообщения: 208
Только ли Pentium M? По-моему, на многих ~старых процессорах TSC совпадала с частотой процессора, так что весьма так имела право меняться (особенно при использовании функций энергопотребления).

2 ТС: откуда такое увлечение асмом там где можно обойтись без него, да ещё и в вырвиглазном синтаксисе? Есть же inline asm (правда, тут тоже может понадобиться AT&T, но писанины хотя бы меньше), есть intrinsic'и.
На тему Bochs - он же симулятор, у него такты честные и весьма детерминированные. Максимум что получалось выжать (на 3ГГц core i3) не начиная замедляться - около 300M, и то в особо удачных моментах, так-то до сих пор 50M - довольно оптимальное значение, ну может 100.
На тему sleep и прочего - тут нужны довольно интересные структуры данных чтобы была очередь (с возможностью быстро добавлять элементы в нужное место, т.е., например, ещё дерево к ней) кого и когда пробуждать, а так же какое-то общесистемное время, которое монотонно и может корректироваться по разным источникам времени. TSC весьма удобен, конечно, но в многопроцессорных системах с ним проблема + не везде его частота стабильна.
В общем, например, для переключения задач и тому подобного очень удобен local APIC timer.


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

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


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

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


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

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