Подтвердить что ты не робот

Как предотвратить g++ от оптимизации цикла, управляемого переменной, которая может быть изменена IRQ?

Рассмотрим следующий фрагмент кода:

unsigned global;
while(global);

global изменяется в функции, вызываемой IRQ. Однако g++ удаляет тест "is-not-zero" и переводит цикл while в бесконечный цикл.

Отключение оптимизации компилятора решает проблему, но предлагает ли С++ для него конструкцию языка?

4b9b3361

Ответ 1

Объявите переменную как volatile:

volatile unsigned global;

Это ключевое слово, которое сообщает компилятору, что global может быть изменен в разных потоках, и все оптимизации должны быть отключены для него.

Ответ 2

Поскольку вы используете GCC, и вы говорите, что создание переменной volatile не работает, вы можете обмануть оптимизатора, считая, что цикл изменяет переменную, лежа в компиляторе:

while(global)
  asm volatile("" : "+g"(global));

Это инструкция встроенной сборки, в которой говорится, что она изменяет переменную (она передается в качестве операнда ввода-вывода). Но он пуст, поэтому, очевидно, он ничего не делает во время выполнения. Тем не менее, оптимизатор считает, что он изменяет переменную - программисты сказали так, а компилятор, запрещающий замену операнда (что означает просто замену одного текста другим), на самом деле не волнует тело встроенной сборки и не будет делать никаких забавные вещи к нему.

И поскольку тело пустое, а ограничение использует его наиболее общее, оно должно надежно работать на всех платформах, где GCC поддерживает встроенную сборку.

Ответ 3

Вы можете использовать атрибуты GCC в объявлении функции для отключения оптимизации на основе каждой функции:

void myfunc() __attribute__((optimize(0)));

Для получения дополнительной информации см. страницу GCC Function Attributes.