singlepost

Как сделать задержку? << На главную или назад  

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

20 ответов в теме “Как сделать задержку?”

  1. 20
    Cyber Max ответил:

    > Задержка получается в среднем на 60% (подозрительно много!)
    > дольше чем задается.

    В полне нормальная ситуация… Ради эксперимента можешь извратиться и попробовать следующее: отключитьDMA для сидюка, перегрузиться, запустить копирование чего-то большого с диска и повторить эксперимент с задержкой. Результаты должны еще больще расплыться во времени, ибо сидюк в режиме прерываний будет съедать очень много процессорного времени на высоких уровнях IRQL.

    > Ну мне нечего собственно излагать. Просто для самообразования.
    Ну тогда почитай слудующее:
    David A. Solomon and Mark E. Russinovich – Inside Windows 2000
    Walter Oney – Microsoft Windows Driver Model
    а вот Jf. Richter лучше не читать – введет в заблуждение относительно зедержек и процесорного времени. Это чисто под винду.. но принципы одни и теже…

  2. 19
    Андрей Горбоконь ответил:

    > Интересно знать, получилась ли действительно задержка?
    Ну если можно так сказать. Задержка получается в среднем на 60% (подозрительно много!) дольше чем задается, я ее просто корректирую – и получаю нужное значение.

    > И вообще если бы изложил все подробности задачи – можно было бы что то советовать.

    Ну мне нечего собственно излагать. Просто для самообразования.

  3. 18
    Cyber Max ответил:

    Вообще если это нужно для синхронизации с утсройством.. то про user-mode вообще нужно забыть… ибо приемлимая работа с устройством может быть выполнена только из драйвера в kernel-mode в ISR процедуре (хотя функционал системных функций будет минимальным потому как высокий IRQL). И вообще если бы изложил все подробности задачи – можно было бы что то советовать…

  4. 17
    Тимур Магомедов ответил:

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

    for(volatile int i=0;i<1000000;i++); не будет съеден оптимизацией.

  5. 16
    Cyber Max ответил:

    В user-mode крайне сложно получить заданную задержку.. все ожидаемые функции нужно трактовать не ОЖИДАТЬ ДО, а ПРОБУДИТЬСЯ ПОСЛЕ…. и это ПОСЛЕ может наступить за долго указаного интервала времени. Тоже относиться к Kernel-mode, с той разницей что в Kernel mode можно ухитриться всетаки получить приемлимую задержку. Все потоки пользовательского режима, не важно какого приоритета выполняются на так называемом IRQL = PASSIVE_LEVEL, и с успехом ПРЕРЫВАЮТСЯ любыми потоками IRQL которых выше. И ваш поток пробудиться ПОСЛЕ, ПОСЛЕ, ПОСЛЕ…

  6. 15
    Андрей Горбоконь ответил:

    CloseHandle, я понял, я тормознул :)
    второй вариант мне не нужен, задержка единоразовая
    еще раз спасибо )

  7. 14
    Антон Щиров ответил:

    Крайне глупое решение.

    У Вас будет происходить утечка дескрипторов

    Нужно делать так
    [src]
    int Delay(__int64 delay)
    {
    HANDLE hTimer = NULL;
    LARGE_INTEGER liDueTime;
    liDueTime.QuadPart = -delay;
    hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
    SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0);
    WaitForSingleObject(hTimer, INFINITE);
    ==>CloseHandle(hTimer);
    return 0;
    }
    [/src]
    А еще лучше так
    [src]int Delay(HANDLE hTimer, __int64 delay)
    {
    LARGE_INTEGER liDueTime;
    liDueTime.QuadPart = -delay;
    SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0);
    WaitForSingleObject(hTimer, INFINITE);
    return 0;
    }
    ……………..
    HANDLEhTimer = CreateWaitableTimer(NULL, TRUE, NULL);
    Delay(hTimer, 100);
    Delay(hTimer, 100);
    Delay(hTimer, 100);
    CloseHandle(hTimer)
    [/src]

  8. 13
    Андрей Горбоконь ответил:

    Всем большое спасибо за помощь!
    Антон Щиров, вам особенно! :)

    Конечное решение:

    int Delay(__int64 delay)
    {
    HANDLE hTimer = NULL;
    LARGE_INTEGER liDueTime;
    liDueTime.QuadPart = -delay;
    hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
    SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0);
    WaitForSingleObject(hTimer, INFINITE);
    return 0;
    }

  9. 12
    Антон Щиров ответил:

    Period – да. А dueTime – нет.

    Указывайте Period = 0 и после каждого срабатывания заново вызывайте SetWaitableTimer()

  10. 11
    Андрей Горбоконь ответил:

    Антон Щиров,
    увы, один из параметров SetWaitableTimer есть"…The period of the timer, in milliseconds…" :(
    миллисекунды, это даже не микросекунды, так что..

  11. 10
    Андрей Горбоконь ответил:

    Тимур Магомедов,
    спасибо, попытаюсь разобраться

    Александр Васюченко,
    кроме всего прочего, такой цикл будет беспощадно "съеден" оптимизацией, а без оптимизации в real-time задержке резона нет.

  12. 9
    Андрей Горбоконь ответил:

    Cyber Max,
    не могли бы вы объяснить почему в user-mode это невозможно?
    Дело в том, что то решение, которое я видел было именно под user-mode.

  13. 8
    Антон Щиров ответил:

    CreateWaitableTimer() разрешение до 100 наносекунд

  14. 7
    Мишка Епихин ответил:

    цикл процессор грузит, а задержка этого делать не должна

  15. 6
    Александр Васюченко ответил:

    А если цикл использовать? Вот вам и задержка на несколько тактов процессора:

    for(int i=0;i<1000000;i++);

  16. 5
    Мишка Епихин ответил:

    А зачем это надо?О_о

  17. 4
    Cyber Max ответил:

    На платформе Windows в kernel-mode можно попробовать использовать функции:

    VOID
    KeStallExecutionProcessor(
    IN ULONGMicroSeconds
    );

    и

    NTSTATUS
    KeDelayExecutionThread(
    IN KPROCESSOR_MODEWaitMode,
    IN BOOLEANAlertable,
    IN PLARGE_INTEGERInterval
    );

    В User-mode не реально вообще добиться столь минимальных задержек.

    А вообще что Windows что Linux ОС – не realtime… вдрядли получиться получить приемлимую задержку.

  18. 3
    Тимур Магомедов ответил:

    //lwn.net/images/pdf/LDD3/ch07.pdf
    Отличная реализация на C в ядре линукс
    //lxr.linux.no/linux+v2.6.28.8/+search

  19. 2
    Андрей Горбоконь ответил:

    в том то и дело, что частоту по идее как-то можно сменить..
    это я и пытаюсь узнать

  20. 1
    Андрей Щипцов ответил:

    а сменить саму частоту таймера никак?… или ты хочешь сделать задержку меньше, чем в 1 мс?

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.