Как сделать задержку на время, меньшее чем тик системного таймера,
т.к. известно, что частота таймера много меньше чем частота процессора.
Устроит направление на любой ресурс, или пример реализации на любом известном вам языке программирования.
Как сделать задержку на время, меньшее чем тик системного таймера,
т.к. известно, что частота таймера много меньше чем частота процессора.
Устроит направление на любой ресурс, или пример реализации на любом известном вам языке программирования.
Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.
22 марта 2009 в 11:05
> Задержка получается в среднем на 60% (подозрительно много!)
> дольше чем задается.
В полне нормальная ситуация… Ради эксперимента можешь извратиться и попробовать следующее: отключитьDMA для сидюка, перегрузиться, запустить копирование чего-то большого с диска и повторить эксперимент с задержкой. Результаты должны еще больще расплыться во времени, ибо сидюк в режиме прерываний будет съедать очень много процессорного времени на высоких уровнях IRQL.
> Ну мне нечего собственно излагать. Просто для самообразования.
Ну тогда почитай слудующее:
David A. Solomon and Mark E. Russinovich – Inside Windows 2000
Walter Oney – Microsoft Windows Driver Model
а вот Jf. Richter лучше не читать – введет в заблуждение относительно зедержек и процесорного времени. Это чисто под винду.. но принципы одни и теже…
22 марта 2009 в 1:05
> Интересно знать, получилась ли действительно задержка?
Ну если можно так сказать. Задержка получается в среднем на 60% (подозрительно много!) дольше чем задается, я ее просто корректирую – и получаю нужное значение.
> И вообще если бы изложил все подробности задачи – можно было бы что то советовать.
Ну мне нечего собственно излагать. Просто для самообразования.
21 марта 2009 в 22:05
Вообще если это нужно для синхронизации с утсройством.. то про user-mode вообще нужно забыть… ибо приемлимая работа с устройством может быть выполнена только из драйвера в kernel-mode в ISR процедуре (хотя функционал системных функций будет минимальным потому как высокий IRQL). И вообще если бы изложил все подробности задачи – можно было бы что то советовать…
21 марта 2009 в 22:04
#17 прав. Интересно знать, получилась ли действительно задержка? Подтвердил ли длительность задержки осциллограф? И зачем вообще это было нужно, если не для какого-нибудь устройства.
for(volatile int i=0;i<1000000;i++); не будет съеден оптимизацией.
21 марта 2009 в 18:03
В user-mode крайне сложно получить заданную задержку.. все ожидаемые функции нужно трактовать не ОЖИДАТЬ ДО, а ПРОБУДИТЬСЯ ПОСЛЕ…. и это ПОСЛЕ может наступить за долго указаного интервала времени. Тоже относиться к Kernel-mode, с той разницей что в Kernel mode можно ухитриться всетаки получить приемлимую задержку. Все потоки пользовательского режима, не важно какого приоритета выполняются на так называемом IRQL = PASSIVE_LEVEL, и с успехом ПРЕРЫВАЮТСЯ любыми потоками IRQL которых выше. И ваш поток пробудиться ПОСЛЕ, ПОСЛЕ, ПОСЛЕ…
21 марта 2009 в 1:05
CloseHandle, я понял, я тормознул
второй вариант мне не нужен, задержка единоразовая
еще раз спасибо )
21 марта 2009 в 0:04
Крайне глупое решение.
У Вас будет происходить утечка дескрипторов
Нужно делать так
[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]
20 марта 2009 в 22:05
Всем большое спасибо за помощь!
Антон Щиров, вам особенно!
Конечное решение:
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;
}
20 марта 2009 в 22:03
Period – да. А dueTime – нет.
Указывайте Period = 0 и после каждого срабатывания заново вызывайте SetWaitableTimer()
20 марта 2009 в 22:02
Антон Щиров,
увы, один из параметров SetWaitableTimer есть"…The period of the timer, in milliseconds…"
миллисекунды, это даже не микросекунды, так что..
20 марта 2009 в 22:00
Тимур Магомедов,
спасибо, попытаюсь разобраться
Александр Васюченко,
кроме всего прочего, такой цикл будет беспощадно "съеден" оптимизацией, а без оптимизации в real-time задержке резона нет.
20 марта 2009 в 22:00
Cyber Max,
не могли бы вы объяснить почему в user-mode это невозможно?
Дело в том, что то решение, которое я видел было именно под user-mode.
20 марта 2009 в 22:00
CreateWaitableTimer() разрешение до 100 наносекунд
20 марта 2009 в 21:04
цикл процессор грузит, а задержка этого делать не должна
20 марта 2009 в 20:03
А если цикл использовать? Вот вам и задержка на несколько тактов процессора:
for(int i=0;i<1000000;i++);
20 марта 2009 в 19:03
А зачем это надо?О_о
20 марта 2009 в 14:03
На платформе Windows в kernel-mode можно попробовать использовать функции:
VOID
KeStallExecutionProcessor(
IN ULONGMicroSeconds
);
и
NTSTATUS
KeDelayExecutionThread(
IN KPROCESSOR_MODEWaitMode,
IN BOOLEANAlertable,
IN PLARGE_INTEGERInterval
);
В User-mode не реально вообще добиться столь минимальных задержек.
А вообще что Windows что Linux ОС – не realtime… вдрядли получиться получить приемлимую задержку.
20 марта 2009 в 4:04
//lwn.net/images/pdf/LDD3/ch07.pdf
Отличная реализация на C в ядре линукс
//lxr.linux.no/linux+v2.6.28.8/+search
20 марта 2009 в 2:00
в том то и дело, что частоту по идее как-то можно сменить..
это я и пытаюсь узнать
20 марта 2009 в 1:05
а сменить саму частоту таймера никак?… или ты хочешь сделать задержку меньше, чем в 1 мс?