реклама на сайте
подробности

 
 
5 страниц V  < 1 2 3 4 5 >  
Reply to this topicStart new topic
> Вопрос по volatile
Baser
сообщение Jan 18 2017, 14:06
Сообщение #31


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(Alt.F4 @ Jan 18 2017, 14:33) *
Ну как бы изменения делаем атомарно, это уже обсудили.

Ну как бы вам уже несколько человек на пальцах объяснили, что атомарность тут не причем sm.gif
Попробую еще раз:
Если глобальная переменная не объявлена volatile, то ваша функция из главного цикла, работая с этой переменной,
имеет право (но не обязана) поместить её копию в регистр или в стек.
И внутри функции работать с этой копией (атомарно или как хочет) согласно вашей программы.
И только при выходе из функции записать эту копию в основное глобальное место.
Т.е. во время работы функции могут быть две копии (и различные!).

Прерывания этого не знают и работают с переменной из глобальной памяти.
И функция при выходе результат работы прерывания затирает.

А если объявить эту глобальную переменную volatile, то компилятору будет запрещено делать копии и работать с ними.
Все изменения этой переменной будут происходить только по основному месту хранения.
Go to the top of the page
 
+Quote Post
DASM
сообщение Jan 18 2017, 14:32
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



Господа никогда не понимал таких споров. Процесс важен или результат? Сюрпризы возможны, не проще ли дать volatile и забыть?
Go to the top of the page
 
+Quote Post
RobFPGA
сообщение Jan 18 2017, 15:08
Сообщение #33


Профессионал
*****

Группа: Свой
Сообщений: 1 214
Регистрация: 23-12-04
Пользователь №: 1 643



Приветствую!
Цитата(Baser @ Jan 18 2017, 17:06) *
Ну как бы вам уже несколько человек на пальцах объяснили, что атомарность тут не причем sm.gif
...
Если глобальная переменная не объявлена volatile, то ваша функция из главного цикла, работая с этой переменной,
имеет право (но не обязана) поместить её копию в регистр или в стек.
И внутри функции работать с этой копией (атомарно или как хочет) согласно вашей программы.
И только при выходе из функции записать эту копию в основное глобальное место.
Т.е. во время работы функции могут быть две копии (и различные!).

Прерывания этого не знают и работают с переменной из глобальной памяти.
И функция при выходе результат работы прерывания затирает.

А если объявить эту глобальную переменную volatile, то компилятору будет запрещено делать копии и работать с ними.
Все изменения этой переменной будут происходить только по основному месту хранения.

Простите но это фигня "... а не заливная рыба ..." wacko.gif Вы тоже путаете атомарность и Volatile.
Глобальная переменная может быт считана в регистр для работы с ней, но копироваться при этом в стек она не будет.

Еще раз "Volatile указывает компилятору что значение переменной может изменится ВНЕ текущего контекста зоны видимости переменной"
Другими словами - меняет правило расчета "срока жизни" переменной в текущем контексте кода.
Это значит что если в текущем контексте функции/таска/isr требуется несколько чтений из переменной то ВСЕ они БУДУТ РЕАЛЬНО выполнены из актуального местоположения переменной. И не важно - будет ли изменятся или нет переменная этом контексте.
Например если var не volatile и Вы хотите:
Код
   sum += var;
  sum += var;

компилятор может сделать одно чтение var затем умножение на 2 и сложение с sum так как срок жизни переменной не заканчивается
если будет volatile - то ВСЕГДА будет 2 чтения из памяти.

Вот еще пример - иногда требуется только сам факт чтения/записи переменной (без реальных значений) для выполнения какого либо действия в периферии. Без volatile такое "бессмысленное расточительство" режется на корню "слишком умным" компилятором.

Удачи! Rob.


Go to the top of the page
 
+Quote Post
Укушенный воблой
сообщение Jan 18 2017, 16:14
Сообщение #34


Частый гость
**

Группа: Участник
Сообщений: 197
Регистрация: 8-07-16
Пользователь №: 92 484



Цитата(jcxz @ Jan 16 2017, 14:19) *
Атомарность тут не при чём.
Компилятор может например перенести значение переменной в регистр. И будете Вы в неё писать хоть атомарно, хоть нет, обработчик прерывания этого не знает когда захочет её прочитать из памяти где осталось старое значение.

Если переменная не объявлена как регистЕр, то никуда компилятор её не перенесёт. Не вводите людей в заблуждение.

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

Цитата(gerber @ Jan 16 2017, 17:55) *
Компилятор (и примкнувший к нему линкер) вообще ничего не знают про прерывания. Есть только функции, расположенные по определенным адресам. А то, что эти функции могут обрабатывать прерывания, и прерывать другие функции в любом месте, знает только разработчик на основе архитектуры контроллера, под который он пишет программу.
А в вашем примере и volatile не спасет, так как суммирование x и чисел N1,N2,N3 неатомарно.

Есть такая штука, называется "сохранение контекста прерванной задачи".
Хотя конечно есть двухбайтовые команды работы напрямую с РВВ, обращение к которым должно происходить в соседних тактах процессора.
Тогда ой. Нужно запрещать прерывания перед такой критической последовательностью команд.
Иначе вообше может произойти катастрофа если прерывание разорвет двухбайтовую последовательность команд

Цитата(Alt.F4 @ Jan 17 2017, 22:45) *
jcxz, вот именное такие: "например можете в цикле ждать когда установится некий флажок" (цитирую Вас же).

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

Проблема: компилятор оптимизируя вырезает кусок кода считая его лишним.
На основании чего он это делает? Он знает, что некая переменная имеет в текущий момент определенное состояние.
Значит, если на входе функции мы не присваиваем ей какое либо значение и затем не проверяем эту переменную на другие значения (что для компилятора кажется безумным и он это режет), то и volatile не нужен.

Именно так. Именно для этого введен волатйл. Чтобы запретить компилятору "оптимизировать" (чаще всего просто удалять) куски кода, которые содержат якобы не изменяемые и не используемые переменные
Go to the top of the page
 
+Quote Post
Baser
сообщение Jan 18 2017, 16:38
Сообщение #35


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(RobFPGA @ Jan 18 2017, 17:08) *
Простите но это фигня "... а не заливная рыба ..." wacko.gif Вы тоже путаете атомарность и Volatile.

Ничего не имею против ваших разъяснений работы volatile, но доводов того, что "моя заливная рыба" это фигня, я у вас не нашел. laughing.gif

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

Цитата
Глобальная переменная может быт считана в регистр для работы с ней, но копироваться при этом в стек она не будет.

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

Цитата(DASM @ Jan 18 2017, 16:32) *
Господа никогда не понимал таких споров. Процесс важен или результат?

Для достижения желаемого результата неплохо бы разбираться в особенностях процесса rolleyes.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 18 2017, 17:06
Сообщение #36


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Укушенный воблой @ Jan 18 2017, 18:14) *
Если переменная не объявлена как регистЕр, то никуда компилятор её не перенесёт.

Вы, как обычно, совершенно ничего не смыслите в том, о чем пытаетесь писать. Разумеется компилятор может и делает это. Да и квалификатор register уже давно у большинства компиляторов просто игнорируется.
Цитата
Не вводите людей в заблуждение.

Это по Вас.
Цитата
Именно для этого введен волатйл. Чтобы запретить компилятору "оптимизировать" (чаще всего просто удалять) куски кода, которые содержат якобы не изменяемые и не используемые переменные

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


Цитата(Baser @ Jan 18 2017, 18:38) *
Атомарность это запрещение различных прерываний, исключений, переключения задач и т.д. на каком-то участке кода.

Никак нет. То, что описали, это критическая секция, точнее один из вариантов ее реализации.
Соответственно и все, что дальше написали это не о чем sad.gif


Цитата(Baser @ Jan 18 2017, 16:06) *
А если объявить эту глобальную переменную volatile, то компилятору будет запрещено делать копии и работать с ними.
Все изменения этой переменной будут происходить только по основному месту хранения.

Расскажите это создателям ARM ядра и множества других с Load-Store sm.gif. Они просто не умеют, так, как Вы представляете.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Baser
сообщение Jan 18 2017, 18:09
Сообщение #37


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(zltigo @ Jan 18 2017, 19:06) *
Никак нет. То, что описали, это критическая секция, точнее один из вариантов ее реализации.
Соответственно и все, что дальше написали это не о чем sad.gif

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

Цитата(zltigo @ Jan 18 2017, 19:06) *
Расскажите это создателям ARM ядра и множества других с Load-Store sm.gif. Они просто не умеют, так, как Вы представляете.

Наверно, здесь был не точен. Конечно, volatile не создаст атомарный доступ к переменной, но хотя бы предотвратит создание компилятором её "долгоживущих" копий.
Go to the top of the page
 
+Quote Post
Укушенный воблой
сообщение Jan 18 2017, 18:31
Сообщение #38


Частый гость
**

Группа: Участник
Сообщений: 197
Регистрация: 8-07-16
Пользователь №: 92 484



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

Ведь компилятор не может проследить все случаи где я получаю доступ к переменной через указатель на неё
Go to the top of the page
 
+Quote Post
aiwa
сообщение Jan 18 2017, 22:36
Сообщение #39


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Цитата(Укушенный воблой @ Jan 18 2017, 20:31) *
А если я работаю с переменной через указатель на неё, то что?
Я должен такую переменную объявлять как волатайл?

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


Цитата(DASM @ Jan 18 2017, 16:32) *
Господа никогда не понимал таких споров. Процесс важен или результат? Сюрпризы возможны, не проще ли дать volatile и забыть?

"Споры" нужны для того, чтобы понять при каких ситуациях "сюрпризы возможны".
Go to the top of the page
 
+Quote Post
Укушенный воблой
сообщение Jan 19 2017, 04:18
Сообщение #40


Частый гость
**

Группа: Участник
Сообщений: 197
Регистрация: 8-07-16
Пользователь №: 92 484



Цитата(aiwa @ Jan 18 2017, 22:36) *
Правила те же: указатель должен быть объявлен как указатель на volatile-переменную.

А сама переменная?
Сама переменная должна объявляться как волатАЙл если её используют через указатель?
Что-то то я не видел в реальном коде разных разработчиков этого

Причем используют неявно. Без использования операции "взятие адреса" (амперсанд)
Go to the top of the page
 
+Quote Post
XVR
сообщение Jan 19 2017, 06:34
Сообщение #41


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(Укушенный воблой @ Jan 19 2017, 07:18) *
А сама переменная?
Сама переменная должна объявляться как волатАЙл если её используют через указатель?
Нет. Компилятор вещь достаточно умная - он понимает что такое указатель и к чему может привести взятие адреса переменной (для этой переменной)
Он даже понимает кое что в том, куда этот указатель может указывать - см ключевое слово restrict и опцию ansi alias ( http://www.atmos.washington.edu/~ovens/ifo...nsi_alias_f.htm )

Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Jan 19 2017, 06:54
Сообщение #42


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



jcxz, а мне Ваши примеры напоминают троллинг, повторение описанного ранее.
Я не вижу причин для сбоя в Вашем коде. В описанной ситуации функция не увидит возведение флажка, при втором входе в функцию все будет Ок. Повторюсь: где проблема?
Да и пример я бы назвал "странным" (читай так делать нельзя), т.к. оба прерывания используют один и тот же байт-флаг и если они сработают друг за другом, то Вы не будете знать, что сработало первое.

Цитата
Если записи нет, а есть только чтения, то компилятор заменит все чтения этой переменной загрузкой константы в регистр.
А потом компоновщик увидит, что к этой переменной нет ни одного обращения и удалит её за ненадобностью.
Какой еще константы, если она переменная? Как это нет обращения, Вы же ее читаете.

Цитата
И функция при выходе результат работы прерывания затирает.
Если переменная изменяется в функции, то это делать надо атомарно, и тогда не будет описанной Вами проблемы. Если что, то volatile не спасет от написанного Вами.

Цитата
Вот еще пример - иногда требуется только сам факт чтения/записи переменной (без реальных значений) для выполнения какого либо действия в периферии. Без volatile такое "бессмысленное расточительство" режется на корню "слишком умным" компилятором.
Хороший пример, добавляем в копилку. Хотя можно объявить переменную глобально или extern, тоже будет работать.

Цитата
"Споры" нужны для того, чтобы понять при каких ситуациях "сюрпризы возможны".

Пока имеем следующие ситуации требущие объявления volatile:
1) Переменные в блокирующих операций (ожидание определенного значения в цикле)
2) Все системные регистры, в том числе ввода/вывода (хотя они де-факто volatile)
3) Переменные в которые "просто читаем" из какого-либо регистра (как вариант, используем глобальную или extern переменную)


Еще пару примеров и можно делать мини-FAQ по теме вопроса sm.gif
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 19 2017, 07:09
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Alt.F4 @ Jan 19 2017, 09:54) *
jcxz, а мне Ваши примеры напоминают троллинг, повторение описанного ранее.
Я не вижу причин для сбоя в Вашем коде. В описанной ситуации функция не увидит возведение флажка, при втором входе в функцию все будет Ок. Повторюсь: где проблема?

Очевидно что Вы и читать исходники не умеете. Посмотрите ещё раз на тот код. Вы ничего не поняли.
Я там вроде всё предельно разжевал, дальше некуда.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 19 2017, 07:11
Сообщение #44


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Alt.F4 @ Jan 19 2017, 08:54) *
Пока имеем следующие ситуации требущие объявления volatile:
Не надо изобретать велосипед. Есть два критения:
1) если переменная используется в двух потоках (читай - в основном цикле и прерывании). Компилятор обязан при каждом обращении на чтение вычитывать ее из ОЗУ и при каждом обращении на запись класть обратно.
2) если важен порядок доступа к этой переменной (читай - регистры периферии). Компилятор обязан делать то же самое, что и п.1, кроме этого не имеет права менять местами обращения к этой переменной относительно обращений к другим volatile.

QUOTE (Укушенный воблой @ Jan 19 2017, 06:18) *
Сама переменная должна объявляться как волатАЙл если её используют через указатель?
Какая разница, как к ней обращаются? Если она попадает под указзанные выше два критерия - должна быть volatile. Все. И указатель должен иметь тип "указатель на volatile". Зачем так сделано - подумайте самостоятельно.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 19 2017, 07:18
Сообщение #45


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Alt.F4 @ Jan 19 2017, 09:54) *
Да и пример я бы назвал "странным" (читай так делать нельзя), т.к. оба прерывания используют один и тот же байт-флаг и если они сработают друг за другом, то Вы не будете знать, что сработало первое.

Специально для Вас разжёвываю: функционал isr1 и isr2 взаимосвязан - если произошло одно, то выставление второго не нужно и даже запрещено (нужно знать какое было первое). И процедура сервиса, будучи запущенной, проверит и обслужит события.
Если совсем уже до детского уровня разжевать, например: это прерывания от двух счётчиков, запущенных от одного события, считающих с разной частотой, кто досчитает первым - тот и должен послать Int. Процедуре сервиса важно знать кто был первый, но обработка - общая.
Go to the top of the page
 
+Quote Post

5 страниц V  < 1 2 3 4 5 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 02:54
Рейтинг@Mail.ru


Страница сгенерированна за 0.01513 секунд с 7
ELECTRONIX ©2004-2016