Jump to content

    
repstosw

TI CGT C6000 8.3.11 барьер памяти для компилятора. Как?

Recommended Posts

Совсем недавно вышла новая версия компилятора от 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.

 

Share this post


Link to post
Share on other sites
On 8/25/2021 at 12:11 AM, bee said:

А если отключить оптимизацию для одной функции?

SPRUI04C:           7.9.20 The FUNCTION_OPTIONS Pragma

 

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

 

В нуль-посте я привёл ссылку результата работы GCC. Может быть, это только он так делает.  Остальные компиляторы, возможно, не переставляют.  В любом случае анализ асм-листинга будет полезен.

Edited by repstosw

Share this post


Link to post
Share on other sites
2 минуты назад, repstosw сказал:

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

А если в качестве такого барьера использовать чтение (или запись) volatile-переменной?

Вроде как компилятор не должен переносить куски кода, обращающиеся к памяти, через участки volatile-доступа.

Конечно будет лишнее обращение к памяти. Но лучше что-то чем ничего.

 

PS: Отключение оптимизации - это как лечение головной боли с помощью топора.

Share this post


Link to post
Share on other sites
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: Отключение оптимизации - это как лечение головной боли с помощью топора.

Это кто ж вам внушил такую дикую мысль? Неужели для всего кода сплошняком необходима полнейшая оптимизация, особенно для кода выставляющего разного рода флажки?

 

Share this post


Link to post
Share on other sites
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 как я понял, решения нет, кроме снижения уровня оптимизации.

 

Share this post


Link to post
Share on other sites
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. Как там сделано.

Share this post


Link to post
Share on other sites
2 часа назад, repstosw сказал:

У меня 1 задача:  основной main() и обработчик прерывания по завершению пересылки EDMA, который подпитывает декодер на McASP новыми данными.

Необходимо по завершению пересылки в обработчике ставит волатильный флажок готовности для main().

Где гарантии, что компилятор вначале оставит код по пересылке данных, а лишь только потом установит флажок готовности для main() ?  А может переставит местами?

Здесь ничего не понятно... :wacko2:  Что с чем переставит? Пересылка у вас - через EDMA, ISR вызывается в её конце. Значит там и будет поставлен флажок. Как он может быть поставлен до пересылки?

Если вы говорите про какие-то пересылки внутри ISR + установка флажка там же, то какая разница в каком порядке они будут выполнены, если для main() они всё равно будут единой (атомарной) операцией?

Share this post


Link to post
Share on other sites

Пока веду контроль по асм-листингу, что всё как надо мне.

Это конечно большой минус, что их компилятор не имеет никаких директив управления кодом (кроме снижения оптимизации).

Share this post


Link to post
Share on other sites

Судя по различным источникам, нет у них таких директив или команд для компилятора.

Рекомендуют вместо этого дендрофекальные __disable_interrupts() и __restore_interrupts() и все переменные внутри этой секции сделать volatile.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.