Тонкости использования модификатора volatile

Ваш код работает, пока Вы не включили оптимизацию? Ваш код работает только когда отключены прерывания? Ваш драйвер работает как психованный? Задачи работают в изоляции, но не работают в одновременно? Возможно, при оптимизации компилятор посчитал необходимым изменить фрагмент кода основываясь на том, что не нашел кода, который изменят определенный объект. Примером такой ситуации может служить работа с регистрами устройства отображенными в память, работа с общими объектами в много-потоковых программах.

Приведу пример. Нажатие кнопки устанавливает единицу в восьмом бите регистра REG1. Этот регистр отображен в память по адресу 0×02140040. Допустим, что для упрощения работы вы решили использовать макрос, который указывает на эту область памяти:

[cc lang="c" tab_size="2" lines="40"]
#define REG1(*( int32_t *) 0×02140040)
[/cc]

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

[cc lang="c" tab_size="2" lines="40"]
while ((REG1 & 0х100) == 0);
[/cc]

При оптимизации компилятор может предположить, что в теле цикла значение REG1 не меняется и, следовательно, незачем постоянно проверять условие. Вот что из этого может получиться:

[cc lang="c" tab_size="2" lines="40"]
while ((REG1 & 0х100) == 0) for (;;);
[/cc]

Об этой и других проблемах, которые могут возникнуть читайте в статье Dan Saks Use volatile judiciously. В ней описаны возможные ошибки при включенной оптимизации и методы их решения.

До появления модификатора volatile программистам приходилось помещать код драйвера в отдельный файл, компилировать его без оптимизации и потом компилировать все остальные файлы с включенной оптимизацией. Некоторые компиляторы имели возможность использования pragma, что позволяло отключить оптимизацию для части кода. С появлением модификатора volatile, появилась возможность отключать оптимизацию только для необходимых объектов.

Если вам интересно, тогда прочитайте статью Nigel Jones Introduction to the Volatile Keyword.  Там простыми словами описан синтаксис и случаи применения модификатора volatile, с примерами ошибок при работе с регистрами периферийных устройств, обработчиками прерываний и много-потоковыми программами.

Интересная заметка Ian Lance Taylor об использовании модификатора volatile в языке програмирования С. Правда в ней опускается метод использования volatile для много-потоковых программ, поэтому в догонку статья Andrei Alexandrescu - volatile – Multithreaded Programmer’s Best Friend.

Разобравшись с использованием volatile ознакомьтесь со статьей Dan Saks Place volatile accurately, где описана проблема с которой вы можете столкнуться используя указатели на регистры отображенные в память.


Leave a Reply

You must be logged in to post a comment.

blog comments powered by Disqus