|
Переполнен стек |
|
|
|
Oct 8 2011, 23:18
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Сергей Борщ @ Oct 8 2011, 11:59)  Я, напротив, на 100% уверен, что компилятор может сделать иначе и с оптимизацией у него все в порядке. Если тело этих read_... ему доступно и оно не имеет побочных эффектов - то имеет полное право. Значит фтопку такой компилятор. Побочный эффект - прерывания будут запрещены дольше чем требуется либо не тогда когда нужно! Volatile инструкция как раз и указывает компилятору на то, что изменение порядка следования действий влечет к непредсказуемому результату. Допустим компилятор видит, что расчет переменной "a" состоит из расчета переменной "b" плюс какие-то длительные дополнительные действия. Пусть эффективность функции "foo" будет выше если вначале расчитать значение переменной "b", а затем значение переменной "a". Но увеличив эффективность функции можно убить эффективность/функциональность всей системы, если поменяется порядок следования volatile инструкции. (я не зря в примере нарисовал всего три действия, перестановка расчета любой из переменных - выглядит как перестановка запрета прерываний)! Если вдруг заметите, что gcc при каких-то опциях оптимизации меняет порядок следования volatile инструкции, - стоит репортить баг и пусть фиксят компилятор. И нам дайте знать в какой версии такое имеет место быть, чтобы ее не пользовать! ) Цитата(Сергей Борщ @ Oct 8 2011, 11:59)  Боюсь, с учетом сказанного выше, на данный момент не существует способа объяснить компилятору допустимость этого. Очень жаль, что они тогда оптимизируют в gcc непонятно. burst инструкция (STRM) при работе с DDR/SDRAM будет до 8 крат быстрее в сравнении с одиночными STR.
|
|
|
|
|
Oct 10 2011, 07:13
|

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

|
QUOTE (defunct @ Oct 9 2011, 02:18)  Если вдруг заметите, что gcc при каких-то опциях оптимизации меняет порядок следования volatile инструкции, - стоит репортить баг и пусть фиксят компилятор. volatile как раз говорит о побочном эффекте. Я же написал - если содержимое этих функций не имеет побочных эффектов. И если в этих функциях нет volatile и нет вызова внешних функций - компилятор имеет право. А volatile вы сами рекомендуете в них убрать.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 10 2011, 21:39
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Сергей Борщ @ Oct 10 2011, 10:13)  volatile как раз говорит о побочном эффекте. Я же написал - если содержимое этих функций не имеет побочных эффектов. И если в этих функциях нет volatile и нет вызова внешних функций - компилятор имеет право. А volatile вы сами рекомендуете в них убрать. Так-с Расставим точки над i. Вот ваша цитата: Цитата Кстати, и буфер тоже должен быть volatile. В противном случае компилятор имеет полное право перенести запись в буфер после изменения Head и разрешения прерывания. Я утверждаю - не должен он быть volatile, и рекомендую буфер и его элементы НЕ обьявлять как volatile. Пусть компилятор оптимизирует запись и обращения к буферу. Потому что разрешение прерывания - есть volatile инструкция, и компилятор ни при каких условиях (если в нем нет багов) не имеет права изменять ее порядок появления в коде. Он не может перенести запись после разрешения прерываний как вы говорите, т.к. поменяется порядок volatile инструкции "sei". Кстати команда "RETI" в GCC также объявлена как volatile, поэтому сделать запись в буфер после выхода из обработчика прерывания компилятор тоже не имеет права. Компилятор может лишь только вообще не писать в буфер, если обращений к нему больше нигде нет, но порядок следования команд, запись -> разрешение прерываний, на другой, он поменять не может!..
|
|
|
|
|
Oct 11 2011, 06:27
|

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

|
QUOTE (defunct @ Oct 11 2011, 00:39)  Потому что разрешение прерывания - есть volatile инструкция, и компилятор ни при каких условиях (если в нем нет багов) не имеет права изменять ее порядок появления в коде. Он не может перенести запись после разрешения прерываний как вы говорите, т.к. поменяется порядок volatile инструкции "sei". Вы не правы - он не может изменить ее порядок относительно других volatile-инструкций (или выражений с побочными эффектами). В противном случае он обязан был бы перед этой инструкцией выгрузить в ОЗУ содержимое всех регистров, в которых закешированы любые переменные. Но этого не происходит - достаточно посмотреть листинг. А вот если мы буфер сделаем volatile - он уже будет обязан сгрузить его в ОЗУ перед sei. QUOTE (defunct @ Oct 11 2011, 00:39)  Компилятор может лишь только вообще не писать в буфер, если обращений к нему больше нигде нет, но порядок следования команд, запись -> разрешение прерываний, на другой, он поменять не может!.. Мне кажется в этом вы ошибаетесь. Обратите внимание на пример ReAl в конце сообщения №36 той ветки.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 16 2011, 23:04
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Много всего написал, потом удалил, потому как не хочу втягиваться в бесконечный спор. Оставлю только выжимку. 1. Компилятор не должен скидывать временные адреса/индексы, не должен скидывать автоматические переменные и т.д. Скидывать требуется ровно то что требуется, - переменную (или группу переменных) которая находится в защищенном блоке из volatile инструкций. 2. Примеры ReAl'а на мой взгляд непоказательны, в первый вставьте printf("%d",i); и всё станет на свои места, во втором - баг определенной одной версии компилятора. 3. Кто прав, кто неправ рассудит время. Если уж совсем по логике, - volatile перед переменной нужен только для тех переменных, которые не на 100% контроллируются кодом "видимым" компилятору, - а именно, изменяются другой программой, другим процессом, процессором, аппаратным/периферийным модулем. Переменные же которые изменяются кодом который компилятор генерит (в пределах одной программы), в т.ч. и изменяемые в прерываниях, - должны четко обрабатываться и без volatile.
PS: а почему же в той ветке нет продолжения? Никто на последний пост zltigo не ответил. За полтора года так и не удалось найти компилятор который бы выносил запись в буфер за пределы sei()? Стало быть вот и доказательство того, что таких компиляторов нет.
|
|
|
|
|
Oct 17 2011, 06:07
|

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

|
QUOTE (defunct @ Oct 17 2011, 02:04)  Переменные же которые изменяются кодом который компилятор генерит (в пределах одной программы), в т.ч. и изменяемые в прерываниях, - должны четко обрабатываться и без volatile. Ну это вы что-то сильно загнули. Тут за примером далеко ходить не нужно - очень много компиляторов выкидывают в основном цикле проверку не-volatile флага, который взводится в прерывании. QUOTE (defunct @ Oct 17 2011, 02:04)  За полтора года так и не удалось найти компилятор который бы выносил запись в буфер за пределы sei()? Стало быть вот и доказательство того, что таких компиляторов нет. Да никто просто не искал. Я, например, использую volatile и спокоен, что подобного выноса не будет. Не использовать volatile рискуя нарваться на грабли ради того, чтобы найти такой компилятор как-то желания не возникает. Потому ветка и заглохла. И эта заглохнет.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 17 2011, 12:03
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Сергей Борщ @ Oct 17 2011, 09:07)  Ну это вы что-то сильно загнули. Тут за примером далеко ходить не нужно - очень много компиляторов выкидывают в основном цикле проверку не-volatile флага, который взводится в прерывании. Должны, не значит что это делается. В примерах за которыми "далеко ходить не надо" мы наблюдаем результат недалекости разработчиков компилятора. Компилятор прексрасно видит все обработчики прерываний, и технически нет никаких препятствий собрать список переменных используемых в них. Вопрос в том почему мало кто это делает, - видать просто не хватает мозгов у разработчиков, пробежаться по собственным же прагмам. А вот способ выкинуть потребность в volatile - работать по указателю: Код typedef struct tagRING_BUFFER { int put; int get; int size; U8 *storage; } TRING, *PRING;
struct { TRING RxRing; TRING TxRing; } uart_ctrl;
static void ring_put( PRING pRing, U8 ch) { U8 iMask = ILock(); pRing->storage[ pRing->put++] = ch; if (pRing->put >= pRing->size) pRing->put = 0; IUnlock(iMask); }
static U8 ring_get(PRING pRing, U8 *ch) { U8 retval = FALSE; U8 iMask = ILock(); if (pRing->put != pRing->get) { *ch = pRing->storage[pRing->get++]; if (pRing->get >= pRing->size) pRing->get = 0; retval = TRUE; } IUnlock(iMask); return retval; }
RX_ISR() { ring_put( &uart_ctrl.RxRing, UDR); }
TX_ISR() { U8 ch; if ( ring_get( &uart_ctrl.TxRing, &ch)) UDR = ch; ... }
main() { U8 ch; ... while(TRUE) { if (ring_get(&uart_ctrl.RxRing, &ch)) ring_put(&uart_ctrl.TxRing, ch); } }
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|