Поклонники языка С могут поинтересоваться, какие есть гарантии, что указанные циклы будут действительно выполняться? Обычно компилятор С может выполнить чтение указанной переменной всего один раз. В обычной ситуации нет никакой гарантии, что переменная jiffies
будет считываться на каждой итерации цикла. Нам же необходимо, чтобы значение переменной jiffies
считывалось на каждой итерации цикла, так как это значение увеличивается в другом месте, а именно в прерывании таймера. Именно поэтому данная переменная определена в файле
с атрибутом volatile
. Ключевое слово volatile
указывает компилятору, что эту переменную необходимо считывать из того места, где она хранится в оперативной памяти, и никогда не использовать копию, хранящуюся в регистре процессора. Это гарантирует, что указанный цикл выполнится, как и ожидается.
Короткие задержки
Иногда коду ядра (и снопа обычно драйверам) необходимы задержки на очень короткие интервалы времени (короче, чем период системного таймера), причем интервал должен отслеживаться с достаточно высокой точностью. Это часто необходимо для синхронизации с аппаратным обеспечением, для которого описано некоторое минимальное время выполнения действий, и которое часто бывает меньше одной миллисекунды. В случае таких малых значений времени невозможно использовать задержки на основании переменной jiffies
, как показано в предыдущем примере. При частоте системного таймера, равной 100 Гц, значение периода системного таймера достаточно большое — 10 миллисекунд! Даже при частоте системного таймера 1000 Гц, период системного таймера равен одной миллисекунде. Ясно, что необходимо другое решение, которое обеспечивает более короткие и точные задержки.
Ядро предоставляет две функции для обеспечения микросекундных и миллисекундных задержек, которые определены в файле
и не используют переменную jiffies
.
void udelay(unsigned long usecs);
void mdelay(unsigned long msecs);
Первая функция позволяет задержать выполнение на указанное количество
udelay(150); /* задержка на 150 μs */
Функция udelay()
выполнена на основе цикла, для которого известно, сколько итераций необходимо выполнить за указанный период времени. Функция mdelay()
выполнена на основе функции udelay()
. Так как в ядре известно, сколько циклов процессор может выполнить в одну секунду (смотрите ниже замечание по поводу характеристики BogoMlPS), функция udelay()
просто масштабирует это значение для того, чтобы скорректировать количество итераций цикла для получения указанной задержки.