аналог Sleep в ядре
От: dorador Россия  
Дата: 01.02.12 12:35
Оценка:
Пытаюсь организовать тайм-аут на нулевом кольце. Я пробовал использовать следующие варианты:

void Sleep(ULONG time_out)
{
    PKTIMER pTimer = (PKTIMER)ExAllocatePool(NonPagedPool, sizeof(KTIMER));
    KeInitializeTimer(pTimer);
    LARGE_INTEGER itvtime;
    itvtime.QuadPart = -((LONGLONG)time_out) * 10000;
    KeSetTimer(pTimer, itvtime, NULL);
    KeWaitForSingleObject(pTimer, Executive, KernelMode, FALSE, NULL);
    KeCancelTimer(pTimer);
    ExFreePool(pTimer);
}

это вариант с интервальным таймером, вроде всё совершенно понятно, всё должно работать

void Sleep(ULONG time_out)
{
    LARGE_INTEGER due_time;
    due_time.QuadPart = -((LONGLONG) time_out) * 10000;
    NTSTATUS status = KeDelayExecutionThread(KernelMode, FALSE, &due_time);
}

здесь тоже вроде всё ясно

void Sleep(ULONG time_out)
{
    LARGE_INTEGER Frequency;
    LARGE_INTEGER zero_time = KeQueryPerformanceCounter(&Frequency);
    ULONG wait_time;
    do {
        LARGE_INTEGER cur_time = KeQueryPerformanceCounter(NULL);
        wait_time = ULONG((cur_time.QuadPart - zero_time.QuadPart) * 1000000 / Frequency.QuadPart);
    } while(wait_time < time_out);
}

где-то прочитал что этот вариант не рекомендуется
так вот, у меня правильно работает только последний вариант
я проверяю так:
    LARGE_INTEGER start_ticks;
    LARGE_INTEGER stop_ticks;
    ULONG inc_ticks = KeQueryTimeIncrement();
    KeQueryTickCount(&start_ticks);
    for(long i = 0; i < 1000; i++)
    {
        Sleep(1000);
    }
    KeQueryTickCount(&stop_ticks);
    ULONG mstime = ((stop_ticks.QuadPart - start_ticks.QuadPart) * inc_ticks) / 10000;

то есть я должен получать 1000 мсек паузы
Адекватную цифру (примерно или ровно 1000) я получаю только при использовании KeQueryPerformanceCounter
а при использовании первых двух способов я получаю или например 1953 или например 15689, какая конкретная цифра, это зависит от компьютера
то же самое контролирую на 3-м кольце:
    LARGE_INTEGER Frequency, StartPerformCount, StopPerformCount;
    int bHighRes = QueryPerformanceFrequency (&Frequency);
    QueryPerformanceCounter (&StartPerformCount);
        // здесь вызов DeviceIoControl который выполняет вышеуказанный Sleep цикл
    QueryPerformanceCounter (&StopPerformCount);
    double msTime = (double)(StopPerformCount.QuadPart - StartPerformCount.QuadPart) / (double)Frequency.QuadPart * 1.E3;

ну и ручные часы и устный счет секунд ( ) говорит о том, что первые два способа выполняются дольше, чем должны бы.
Скажите плиз где я неправ или у вас такая же фигня?
заранее всем спасибо
Re: аналог Sleep в ядре
От: Аноним  
Дата: 01.02.12 12:52
Оценка:
D>ну и ручные часы и устный счет секунд ( ) говорит о том, что первые два способа выполняются дольше, чем должны бы.
D>Скажите плиз где я неправ или у вас такая же фигня?
D>заранее всем спасибо

Это фигня называется квант процессорного времени. Любая функция, выполняющая ожидание, отдает квант от вызвавшего потока другому. Соответственно, ваш поток, даже если его просили спать 500мкс, проспит до окончания отданного кванта ( а то и дольше если будут более приоритетные задачи ) когда случится перепланировка. Единственный вариант проснутся раньше — это досрочная перепланировка. Она может случиться например после окончания высокприоритетной операции ввода/вывода.

Бороться с этим грозным явлением можно только укорачивая квант. Он должен не превосходить точность, с которой вы собираетсь отмерять интервалы.
Re[2]: аналог Sleep в ядре
От: dorador Россия  
Дата: 02.02.12 12:57
Оценка:
Здравствуйте, Аноним, Вы писали:

D>>ну и ручные часы и устный счет секунд ( ) говорит о том, что первые два способа выполняются дольше, чем должны бы.

D>>Скажите плиз где я неправ или у вас такая же фигня?
D>>заранее всем спасибо

А>Это фигня называется квант процессорного времени. Любая функция, выполняющая ожидание, отдает квант от вызвавшего потока другому. Соответственно, ваш поток, даже если его просили спать 500мкс, проспит до окончания отданного кванта ( а то и дольше если будут более приоритетные задачи ) когда случится перепланировка. Единственный вариант проснутся раньше — это досрочная перепланировка. Она может случиться например после окончания высокприоритетной операции ввода/вывода.


А>Бороться с этим грозным явлением можно только укорачивая квант. Он должен не превосходить точность, с которой вы собираетсь отмерять интервалы.


Спасибо! Поразмышлял и поэкспериментировал, в том числе над самой функцией Sleep(). Получилось, что адекватное время выдерживается слипом тогда, когда он близок к какой-то величине, наверное к этому кванту, который как я понимаю обычно составляет 10-20 или больше миллисекунд.
У меня получилось, что Sleep() на 3-м кольце ведёт себя точно так же, как интервальный таймер и KeDelayExecutionThread на нулевом кольце. И меньше чем на 10 или больше миллисекунд (на разных компах по-разному) засыпать нет смысла.
Если выводы неправильны, поправьте, плиз.
Re[3]: аналог Sleep в ядре
От: Аноним  
Дата: 02.02.12 13:04
Оценка:
D>Спасибо! Поразмышлял и поэкспериментировал, в том числе над самой функцией Sleep(). Получилось, что адекватное время выдерживается слипом тогда, когда он близок к какой-то величине, наверное к этому кванту, который как я понимаю обычно составляет 10-20 или больше миллисекунд.
D>У меня получилось, что Sleep() на 3-м кольце ведёт себя точно так же, как интервальный таймер и KeDelayExecutionThread на нулевом кольце. И меньше чем на 10 или больше миллисекунд (на разных компах по-разному) засыпать нет смысла.
D>Если выводы неправильны, поправьте, плиз.

В общем да. Остается добавить, что квант можно уменьшить, в том числе и из юзер мода. Многие проги уменьшают его до 1ms и даже меньше.
Re[4]: аналог Sleep в ядре
От: S_snowfall  
Дата: 02.02.12 12:34
Оценка:
Здравствуйте, Аноним, Вы писали:


D>>Спасибо! Поразмышлял и поэкспериментировал, в том числе над самой функцией Sleep(). Получилось, что адекватное время выдерживается слипом тогда, когда он близок к какой-то величине, наверное к этому кванту, который как я понимаю обычно составляет 10-20 или больше миллисекунд.

D>>У меня получилось, что Sleep() на 3-м кольце ведёт себя точно так же, как интервальный таймер и KeDelayExecutionThread на нулевом кольце. И меньше чем на 10 или больше миллисекунд (на разных компах по-разному) засыпать нет смысла.
D>>Если выводы неправильны, поправьте, плиз.

А>В общем да. Остается добавить, что квант можно уменьшить, в том числе и из юзер мода. Многие проги уменьшают его до 1ms и даже меньше.


Это распространенное, но все же заблуждение. Изменение частоты системного таймера практически не оказывает влияния на длительность кванта. Почему — описано например вот здесь: http://www.rsdn.ru/forum/winapi/4159851.1.aspx
Автор: Mr. None
Дата: 16.02.11
Re: аналог Sleep в ядре
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 03.02.12 09:44
Оценка: +1
Здравствуйте, dorador, Вы писали:

D>
D>{
D>    PKTIMER pTimer = (PKTIMER)ExAllocatePool(...);
...
D>    ExFreePool(pTimer);
D>}
D>


По теме, собственно, Вам ответили, а у меня другой вопрос — такое нынче считается хорошим стилем программирования? В смысле — динамическое выделение малого количества памяти, используемой локально в блоке.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: аналог Sleep в ядре
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 03.02.12 09:44
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Многие проги уменьшают его до 1ms и даже меньше.


Чтоб меньше — нужно HAL переделывать. Стандартный даст минимум 976 мкс.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: аналог Sleep в ядре
От: dorador Россия  
Дата: 08.02.12 09:24
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, dorador, Вы писали:


D>>
D>>{
D>>    PKTIMER pTimer = (PKTIMER)ExAllocatePool(...);
ЕМ>...
D>>    ExFreePool(pTimer);
D>>}
D>>


ЕМ>По теме, собственно, Вам ответили, а у меня другой вопрос — такое нынче считается хорошим стилем программирования? В смысле — динамическое выделение малого количества памяти, используемой локально в блоке.


Эта память должна быть в device extension или в nonpaged pool. Как должен был поступить стильный программер?
Re[5]: аналог Sleep в ядре
От: dorador Россия  
Дата: 08.02.12 09:28
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, <Аноним>, Вы писали:


А>>Многие проги уменьшают его до 1ms и даже меньше.


ЕМ>Чтоб меньше — нужно HAL переделывать. Стандартный даст минимум 976 мкс.


Так можно выдерживать паузу гарантированно (ну хотя бы примерно) в 1 мсек?
Re[3]: аналог Sleep в ядре
От: x64 Россия  
Дата: 08.02.12 11:58
Оценка: 2 (1)
D>Как должен был поступить стильный программер?

Разместить объект на стеке.
По поводу выгрузки стека здесь:

Stack swapping never occurs for wait states that are initiated by kernel-mode components, regardless of whether stack swapping is enabled.

Re[4]: аналог Sleep в ядре
От: dorador Россия  
Дата: 08.02.12 14:29
Оценка:
Здравствуйте, x64, Вы писали:

D>>Как должен был поступить стильный программер?


x64>Разместить объект на стеке.

x64>По поводу выгрузки стека здесь:

x64>

x64>Stack swapping never occurs for wait states that are initiated by kernel-mode components, regardless of whether stack swapping is enabled.


стек в режиме ядра можно считать nonpaged?
не знал, спасибо
зы: хотя по-другому было бы не логично
Re[5]: аналог Sleep в ядре
От: x64 Россия  
Дата: 08.02.12 14:46
Оценка:
D>стек в режиме ядра можно считать nonpaged?

Нет, стек в режиме ядра paged, если явно не указано иное, но на время ядерного ожидания (т.е. параметр WaitMode = KernelMode) стек становится non-paged.
Re[6]: аналог Sleep в ядре
От: algosan  
Дата: 08.02.12 21:27
Оценка:
Здравствуйте, x64, Вы писали:

D>>стек в режиме ядра можно считать nonpaged?


x64>Нет, стек в режиме ядра paged, если явно не указано иное, но на время ядерного ожидания (т.е. параметр WaitMode = KernelMode) стек становится non-paged.


Все неверно. Стек потока в ядре невыгружаемый, за исключением момента, когда поток висит в ожидании, к примеру KeWaitForSingleObject с аргументом UserMode, в этом случае системный поток KeSwapProcessOrStack по прошествии некоторого времени превратит странички стека из невыгружаемых в выгружаемые.
Re[7]: аналог Sleep в ядре
От: x64 Россия  
Дата: 08.02.12 22:52
Оценка:
A>Стек потока в ядре невыгружаемый...

Да-да, сорри, ошибся немного. Мысль-то донести хотел, что на время ядерного ожидания ядро гарантирует, что стек выгружен не будет.
Re[6]: аналог Sleep в ядре
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 09.02.12 15:10
Оценка:
Здравствуйте, dorador, Вы писали:

D>Так можно выдерживать паузу гарантированно (ну хотя бы примерно) в 1 мсек?


Нет, конечно. Никаких гарантий реалтайма в винде нет. Если заряжать таймер на 1 мс, то просто большинство интервалов будет отмерено достаточно точно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: аналог Sleep в ядре
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 09.02.12 15:10
Оценка:
Здравствуйте, dorador, Вы писали:

D>Эта память должна быть в device extension или в nonpaged pool.


А в device extension какая-то особенная память?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: аналог Sleep в ядре
От: dorador Россия  
Дата: 10.02.12 19:12
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, dorador, Вы писали:


D>>Эта память должна быть в device extension или в nonpaged pool.


ЕМ>А в device extension какая-то особенная память?


да, device extension размещается в nonpaged pool , но я просто цитировал описание KeInitializeTimer

Storage for a timer object must be resident: in the device extension of a driver-created device object, in the controller extension of a driver-created controller object, or in nonpaged pool allocated by the caller.

 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.