Перейти к содержанию
    

Здравствуйте.

В очередной раз начитался про volatile + чудные компиляторы и насмотревшись "глупых" примеров родился вопрос: стоит ли указывать переменные и/или кольцевые буферы, используемые в прерывании, как volatile, если ни одна из переменных при объявлении не принимает значение, все необходимые начальные значения прописываются в отдельной функции (все изменения таких переменных в любом случае делаются атомарно, с запретом прерываний)?

Т.е. компилятор при работе с такими переменными (например, байтом флагов) в принципе не располагает информацией о их значениях, чтобы как-то вырезать условия с их проверкой, как изображается в примерах с неиспользованием volatile.

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чтения этих переменных делается напрямую или тоже через интерфейсные функции? Если напрямую, то volitalie нужен. Если нет - то еще не факт, что он не нужен :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поэтому, если сперва читаем, а уже выходя из функции пишем, то по идее volatile не нужен.

 

Кстати, обращение к переменным volatile компилятор может произвольно перемещать относительно переменных не-volatile и, я думаю, в определенных ситуациях на этом можно словить не мало приколов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В очередной раз начитался про volatile + чудные компиляторы и насмотревшись "глупых" примеров родился вопрос: стоит ли указывать переменные и/или кольцевые буферы, используемые в прерывании, как volatile, если ни одна из переменных при объявлении не принимает значение, все необходимые начальные значения прописываются в отдельной функции (все изменения таких переменных в любом случае делаются атомарно, с запретом прерываний)?

Атомарность тут не при чём.

Компилятор может например перенести значение переменной в регистр. И будете Вы в неё писать хоть атомарно, хоть нет, обработчик прерывания этого не знает когда захочет её прочитать из памяти где осталось старое значение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тогда и я своё видение изложу

 

В документацию не лазил пишу на память могу где-то в чем-то ошибиться.

 

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

 

PS а компилятор про ваш код знает всё, если эта переменная пишется/читается в прерывании то именно она будет использована хоть с указанием ключевого слова volatile хоть без него и не важно где она расположена в памяти или регистре, ведь код обработки прерывания также компилируется линкуется в единое целое.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

PS а компилятор про ваш код знает всё, если эта переменная пишется/читается в прерывании то именно она будет использована хоть с указанием ключевого слова volatile хоть без него и не важно где она расположена в памяти или регистре, ведь код обработки прерывания также компилируется линкуется в единое целое.

Как "именно она будет использована" в ISR если она находится в регистре???

Компилятор о коде не может "знать всё" хотя бы потому, что код вообще может не проходить через компилятор, а быть получен из объектников/библиотек.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Переменная не "путешествует" во время выполнения из памяти в регистр или обратно, если компилятор определил ей место в памяти или в регистре то она там и будет, но если ей определенно место в регистре то компилятор код добавит при входе в ISR "push" при выходе "pop" и то при условии если этот регистр используется во время обработки прерывания.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Переменная не "путешествует" во время выполнения из памяти в регистр или обратно, если компилятор определил ей место в памяти или в регистре то она там и будет, но если ей определенно место в регистре то компилятор код добавит при входе в ISR "push" при выходе "pop" и то при условии если этот регистр используется во время обработки прерывания.

 

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

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

Переменная именно что "путешествует". Она может находиться в памяти, а через такт - уже в регистре, а потом опять в памяти. Это и есть работа оптимизатора.

Пример:

int x;

void f()

{

x += N1; //1

...

x += N2; //2

...

x += N3; //3

}

В точке 1 компилятор может загрузить x в какой-либо регистр и все обращения внутри f() к этой переменной выполнять с этим с регистром, и выгрузить её в ОЗУ только перед выходом из функции.

Или не перед выходом, а на любом участке выполнения, где сочтёт это оптимальным.

Это вполне допустимое поведение.

А теперь представьте что будет, если где-то во время выполнения f() вызвался ISR, который обратился к переменной x.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

int x;

void f()

{

x += N1; //1

...

x += N2; //2

...

x += N3; //3

}

 

добавим к вашему коду:

 

ISR fff()

{

x++;

}

вы считаете разработчиков компилятора недалёкими людьми которые не предполагают, что прерывание может возникнуть в любой момент времени?

 

PS описанное вами поведение переменной ни на практике ни в теории я не видел ни разу.

На этом я удаляюсь из обсуждения

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вы считаете разработчиков компилятора недалёкими людьми которые не предполагают, что прерывание может возникнуть в любой момент времени?
Нет - мы знаем, что они умные люди и понимают, что программист хочен получить малнькую и быструю программу, а не большую и медленную. Также они понимают, что только программист знает, что должна делать его программа. Поэтому они придумали volatile.

PS описанное вами поведение переменной ни на практике ни в теории я не видел ни разу.
Или вы мало видели, или никогда не включали оптимизацию.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вы считаете разработчиков компилятора недалёкими людьми которые не предполагают, что прерывание может возникнуть в любой момент времени?

Компилятор (и примкнувший к нему линкер) вообще ничего не знают про прерывания. Есть только функции, расположенные по определенным адресам. А то, что эти функции могут обрабатывать прерывания, и прерывать другие функции в любом месте, знает только разработчик на основе архитектуры контроллера, под который он пишет программу.

А в вашем примере и volatile не спасет, так как суммирование x и чисел N1,N2,N3 неатомарно.

Изменено пользователем gerber

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Снова приведен пример, как и во всех статьях. В реальности такую ситуации с тупым инкрементом или другой подобной логикой не встретить, имхо.

Думается мне, что проблема высосана из пальца и требует ну совсем исключительных условий для объявления volatile.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А в вашем примере и volatile не спасет, так как суммирование x и чисел N1,N2,N3 неатомарно.

Атомарность - это совсем другой вопрос. Я же ничего не писал про тип доступа из ISR. ISR может просто доступ на чтение сделать, чему неатомарность никак не помешает.

 

Снова приведен пример, как и во всех статьях. В реальности такую ситуации с тупым инкрементом или другой подобной логикой не встретить, имхо.

Думается мне, что проблема высосана из пальца и требует ну совсем исключительных условий для объявления volatile.

"Тупой инкремент" там для примера. На его месте могут быть любые другие операции модификации x. Перемежающиеся другими операциями если Вы не поняли.

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

Например: элементарный буфер данных, в который фоновая программа пишет данные, передвигая после каждой записи указатель позиции, а ISR, читает эту позицию и на основании её значения - данные из буфера.

Вот записали Вы данные, передвинули позицию, дальше например можете в цикле ждать когда установится некий флажок (устанавливаемый в ISR и прописанный отдельно, с volatile),

а ISR смотрит - позиция-то не изменилась, значит данных нет. А в это время новая позиция просто в регистре лежит. Так и будет фоновый процесс бесконечно ждать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пример (https://gcc.godbolt.org/)

Код (компилятор ARM gcc 5.4.1, опции -O3)

int flag;

void isr() {flag=1;}

void wait()
{
  flag = 0;
  while(!flag);
}

Предположим, что процедура isr вызывется из приерывания (по таймеру)

Результат:

isr():
        mov     r2, #1
        ldr     r3, .L2
        str     r2, [r3]
        bx      lr
.L2:
        .word   .LANCHOR0
wait():
        mov     r2, #0
        ldr     r3, .L7
        str     r2, [r3]
.L5:
        b       .L5
.L7:
        .word   .LANCHOR0
flag:

Как видим wait заканчивается бесконечным циклом.

 

Добавим volatile

 

isr():
        mov     r2, #1
        ldr     r3, .L2
        str     r2, [r3]
        bx      lr
.L2:
        .word   .LANCHOR0
wait():
        mov     r3, #0
        ldr     r2, .L9
        str     r3, [r2]
.L5:
        ldr     r3, [r2]
        cmp     r3, #0
        beq     .L5
        bx      lr
.L9:
        .word   .LANCHOR0
flag:

 

Бесконечный цикл исчез

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...