repstosw 2 August 23, 2021 Posted August 23, 2021 · Report post Совсем недавно вышла новая версия компилятора от Texas Instruments для DSP семейства C6000+ : TI CGT C6000 8.3.11 Есть вопрос - как сделать в нём барьер памяти для компилятора? В GCC барьер памяти делается так: asm volatile ("" ::: "memory"); Нужны аналогичные действия в C6745. Чтобы компилятор не переставил местами строки кода, критичные к последовательности выполнения. Наглядная иллюстрация: https://blog.regehr.org/archives/28 Quote Take this simple example (which originated with Arch Robison): volatile int ready; int message[100]; void foo (int i) { message[i/10] = 42; ready = 1; } The purpose of foo() is to store a value into the message array and then set the ready flag so that another interrupt or thread can see the value. From this code, GCC, Intel CC, Sun CC, and Open64 emit very similar assembly: $ gcc -O2 barrier1.c -S -o - foo: movl 4(%esp), %ecx movl $1717986919, %edx movl $1, ready movl %ecx, %eax imull %edx sarl $31, %ecx sarl $2, %edx subl %ecx, %edx movl $42, message(,%edx,4) ret Obviously the programmer’s intent is not respected here, since the flag is stored prior to the value being written into the array. Quote Share this post Link to post Share on other sites More sharing options...
Связист 0 August 24, 2021 Posted August 24, 2021 · Report post А если отключить оптимизацию для одной функции? SPRUI04C: 7.9.20 The FUNCTION_OPTIONS Pragma Quote Share this post Link to post Share on other sites More sharing options...
repstosw 2 August 26, 2021 Posted August 26, 2021 (edited) · Report post On 8/25/2021 at 12:11 AM, bee said: А если отключить оптимизацию для одной функции? SPRUI04C: 7.9.20 The FUNCTION_OPTIONS Pragma Можно. Но это значит "сдаться без боя". Если барьеры компилятора невозможны, то предлагаю рассмотреть задачу с другой стороны - получение 100% гарантии, что оптимизатор не переставит местами куски кода на максимальной оптимизации. Или отключение специальным флагом оптимизатора возможность такого переупорядочивания. В нуль-посте я привёл ссылку результата работы GCC. Может быть, это только он так делает. Остальные компиляторы, возможно, не переставляют. В любом случае анализ асм-листинга будет полезен. Edited August 26, 2021 by repstosw Quote Share this post Link to post Share on other sites More sharing options...
jcxz 52 August 26, 2021 Posted August 26, 2021 · Report post 2 минуты назад, repstosw сказал: Можно. Но это значит "сдаться без боя". Если барьеры компилятора невозможны, то предлагаю рассмотреть задачу с другой стороны - получение 100% гарантии, что оптимизатор не переставит местами куски кода на максимальной оптимизации. Или отключение специальным флагом оптимизатора возможность такого переупорядочивания. А если в качестве такого барьера использовать чтение (или запись) volatile-переменной? Вроде как компилятор не должен переносить куски кода, обращающиеся к памяти, через участки volatile-доступа. Конечно будет лишнее обращение к памяти. Но лучше что-то чем ничего. PS: Отключение оптимизации - это как лечение головной боли с помощью топора. Quote Share this post Link to post Share on other sites More sharing options...
AlexRayne 1 August 26, 2021 Posted August 26, 2021 · Report post volatile asm доступен у компилера техаса? Quote Share this post Link to post Share on other sites More sharing options...
Связист 0 August 26, 2021 Posted August 26, 2021 · Report post 12 hours ago, repstosw said: Можно. Но это значит "сдаться без боя". ... Ну если хочется повоевать, то мануал по техасскому компилятору в помощь. Как я писал выше, мануал SPRUI04C (отлично гуглится). 12 hours ago, jcxz said: А если в качестве такого барьера использовать чтение (или запись) volatile-переменной? Плохая идея. Вот по этому поводу цитата из мануала: Quote The TI compiler does not shrink or grow volatile accesses. It is the user's responsibility to make sure the access size is appropriate for devices that only tolerate accesses of certain widths. The TI compiler does not change the number of accesses to a volatile variable unless absolutely necessary. This is significant for read-modify-write expressions such as += ; for an architecture which does not have a corresponding read-modify-write instruction, the compiler will be forced to use two accesses, one for the read and one for the write. Even for architectures with such instructions, it is not guaranteed that the compiler will be able to map such expressions to an instruction with a single memory operand. It is not guaranteed that the memory system will lock that memory location for the duration of the instruction. In a multi-core system, some other core may write the location after a RMW instruction reads it, but before it writes the result. The TI compiler will not reorder two volatile accesses, but it may reorder a volatile and a non-volatile access, so volatile cannot be used to create a critical section. Use some sort of lock if you need to create a critical section. 12 hours ago, jcxz said: PS: Отключение оптимизации - это как лечение головной боли с помощью топора. Это кто ж вам внушил такую дикую мысль? Неужели для всего кода сплошняком необходима полнейшая оптимизация, особенно для кода выставляющего разного рода флажки? Quote Share this post Link to post Share on other sites More sharing options...
repstosw 2 August 27, 2021 Posted August 27, 2021 · Report post 7 hours ago, bee said: Неужели для всего кода сплошняком необходима полнейшая оптимизация, особенно для кода выставляющего разного рода флажки? Единственное, что приходит на ум - сделать части в виде функций и вызывать их. Функции компилятор уж точно не переставит. Опции оптимизации работают только с точностью до функции. 7 hours ago, bee said: The TI compiler will not reorder two volatile accesses, but it may reorder a volatile and a non-volatile access, so volatile cannot be used to create a critical section. Сузим поиск. У меня 1 задача: основной main() и обработчик прерывания по завершению пересылки EDMA, который подпитывает декодер на McASP новыми данными. Необходимо по завершению пересылки в обработчике ставит волатильный флажок готовности для main(). Где гарантии, что компилятор вначале оставит код по пересылке данных, а лишь только потом установит флажок готовности для main() ? А может переставит местами? Можно в асм листинг глядеть постоянно и следить. Но мне нужны гарантии. И у TI как я понял, решения нет, кроме снижения уровня оптимизации. Quote Share this post Link to post Share on other sites More sharing options...
jcxz 52 August 27, 2021 Posted August 27, 2021 · Report post 9 часов назад, bee сказал: Плохая идея. Вот по этому поводу цитата из мануала: И что? Эта ваша цитата как раз и подтверждает возможность такого использования volatile-обращений. Сами своё же и прочитайте: 9 часов назад, bee сказал: The TI compiler will not reorder two volatile accesses Одна volatile-операция - это как раз "барьер", другая - та, которую нельзя передвигать. А она именно наверняка volatile, так как нет никакой необходимости "прибивать гвоздями" обычные операции, а только те - порядок выполнения которых важен. А это как правило операции с регистрами периферии и т.п. Цитата Это кто ж вам внушил такую дикую мысль? Неужели для всего кода сплошняком необходима полнейшая оптимизация, особенно для кода выставляющего разного рода флажки? Вы серьёзно думаете, что не бывает задач, где необходимо производить тяжёлые вычисления, синхронизируя этот процесс с некоей периферией (DMA и т.п.) или другими ядрами в многоядерной системе? Или синхронизация этих вычислений с какими-то временными интервалами (всякого рода эмуляторы чужих CPU, отрисовка видео и т.п.)? Или вы просто с такими не сталкивались и судите со своей колокольни? 2 часа назад, repstosw сказал: Единственное, что приходит на ум - сделать части в виде функций и вызывать их. Функции компилятор уж точно не переставит. Опции оптимизации работают только с точностью до функции. Не факт. Если внутри них нет volatile-доступов - запросто: заинлайнит и переставит. Вы же не сказали ему, что он не может переставлять. А значит даже если текущая версия компилятора не переставляет, то следующая может решить иначе (раз ей никто явно не запретил). PS: Можно ещё попробовать посмотреть реализацию критических секций в какой-нить РТОС типа uCOS/FreeRTOS/etc. Точнее в её порте для целевого CPU. Как там сделано. Quote Share this post Link to post Share on other sites More sharing options...
jcxz 52 August 27, 2021 Posted August 27, 2021 · Report post 2 часа назад, repstosw сказал: У меня 1 задача: основной main() и обработчик прерывания по завершению пересылки EDMA, который подпитывает декодер на McASP новыми данными. Необходимо по завершению пересылки в обработчике ставит волатильный флажок готовности для main(). Где гарантии, что компилятор вначале оставит код по пересылке данных, а лишь только потом установит флажок готовности для main() ? А может переставит местами? Здесь ничего не понятно... Что с чем переставит? Пересылка у вас - через EDMA, ISR вызывается в её конце. Значит там и будет поставлен флажок. Как он может быть поставлен до пересылки? Если вы говорите про какие-то пересылки внутри ISR + установка флажка там же, то какая разница в каком порядке они будут выполнены, если для main() они всё равно будут единой (атомарной) операцией? Quote Share this post Link to post Share on other sites More sharing options...
repstosw 2 August 28, 2021 Posted August 28, 2021 · Report post Пока веду контроль по асм-листингу, что всё как надо мне. Это конечно большой минус, что их компилятор не имеет никаких директив управления кодом (кроме снижения оптимизации). Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 36 August 28, 2021 Posted August 28, 2021 · Report post Судя по различным источникам, нет у них таких директив или команд для компилятора. Рекомендуют вместо этого дендрофекальные __disable_interrupts() и __restore_interrupts() и все переменные внутри этой секции сделать volatile. Quote Share this post Link to post Share on other sites More sharing options...