|
|
|
Вопрос по volatile |
|
|
|
Jan 16 2017, 15:41
|
Гуру
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713
|
Цитата(SlavaV @ Jan 16 2017, 18:14) Переменная не "путешествует" во время выполнения из памяти в регистр или обратно, если компилятор определил ей место в памяти или в регистре то она там и будет, но если ей определенно место в регистре то компилятор код добавит при входе в ISR "push" при выходе "pop" и то при условии если этот регистр используется во время обработки прерывания.
PS может я чего не знаю, но почему в процедуре обработки прерывания нельзя обращаться к переменным расположенным в регистре? Каким образом обращаться-то??? К переменной, расположенной в регистре в фоновой задаче и выгруженной куда-то в стек при активации прерывания. Переменная именно что "путешествует". Она может находиться в памяти, а через такт - уже в регистре, а потом опять в памяти. Это и есть работа оптимизатора. Пример: int x; void f() { x += N1; //1 ... x += N2; //2 ... x += N3; //3 } В точке 1 компилятор может загрузить x в какой-либо регистр и все обращения внутри f() к этой переменной выполнять с этим с регистром, и выгрузить её в ОЗУ только перед выходом из функции. Или не перед выходом, а на любом участке выполнения, где сочтёт это оптимальным. Это вполне допустимое поведение. А теперь представьте что будет, если где-то во время выполнения f() вызвался ISR, который обратился к переменной x.
|
|
|
|
|
Jan 16 2017, 16:44
|
Гуру
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095
|
QUOTE (SlavaV @ Jan 16 2017, 17:55) вы считаете разработчиков компилятора недалёкими людьми которые не предполагают, что прерывание может возникнуть в любой момент времени? Нет - мы знаем, что они умные люди и понимают, что программист хочен получить малнькую и быструю программу, а не большую и медленную. Также они понимают, что только программист знает, что должна делать его программа. Поэтому они придумали volatile. QUOTE (SlavaV @ Jan 16 2017, 17:55) PS описанное вами поведение переменной ни на практике ни в теории я не видел ни разу. Или вы мало видели, или никогда не включали оптимизацию.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 16 2017, 16:55
|
Знающий
Группа: Участник
Сообщений: 750
Регистрация: 1-11-11
Пользователь №: 68 088
|
Цитата(SlavaV @ Jan 16 2017, 18:55) вы считаете разработчиков компилятора недалёкими людьми которые не предполагают, что прерывание может возникнуть в любой момент времени? Компилятор (и примкнувший к нему линкер) вообще ничего не знают про прерывания. Есть только функции, расположенные по определенным адресам. А то, что эти функции могут обрабатывать прерывания, и прерывать другие функции в любом месте, знает только разработчик на основе архитектуры контроллера, под который он пишет программу. А в вашем примере и volatile не спасет, так как суммирование x и чисел N1,N2,N3 неатомарно.
Сообщение отредактировал gerber - Jan 16 2017, 17:04
--------------------
"... часами я мог наблюдать, как люди работают." (М. Горький)
|
|
|
|
|
Jan 16 2017, 17:40
|
Гуру
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713
|
Цитата(gerber @ Jan 16 2017, 19:55) А в вашем примере и volatile не спасет, так как суммирование x и чисел N1,N2,N3 неатомарно. Атомарность - это совсем другой вопрос. Я же ничего не писал про тип доступа из ISR. ISR может просто доступ на чтение сделать, чему неатомарность никак не помешает. Цитата(Alt.F4 @ Jan 16 2017, 20:10) Снова приведен пример, как и во всех статьях. В реальности такую ситуации с тупым инкрементом или другой подобной логикой не встретить, имхо. Думается мне, что проблема высосана из пальца и требует ну совсем исключительных условий для объявления volatile. "Тупой инкремент" там для примера. На его месте могут быть любые другие операции модификации x. Перемежающиеся другими операциями если Вы не поняли. Если Вы не встречали такую ситуацию в реале, то смею предположить, что вообще не занимаетесь программированием. Например: элементарный буфер данных, в который фоновая программа пишет данные, передвигая после каждой записи указатель позиции, а ISR, читает эту позицию и на основании её значения - данные из буфера. Вот записали Вы данные, передвинули позицию, дальше например можете в цикле ждать когда установится некий флажок (устанавливаемый в ISR и прописанный отдельно, с volatile), а ISR смотрит - позиция-то не изменилась, значит данных нет. А в это время новая позиция просто в регистре лежит. Так и будет фоновый процесс бесконечно ждать.
|
|
|
|
|
Jan 16 2017, 19:03
|
Гуру
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847
|
Пример (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: Бесконечный цикл исчез
|
|
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|