Перейти к содержанию
    

C, GCC. Компилятор выбрасывает код при оптимизации

Пишу задачу для второго ядра. Кодер Рида-Соломона.  Данные в буфере. Они читаются в задаче, далее производятся манипуляции с данными, и они обратно читаются в тот же буфер.

Эти данные использует другой процессор. Ядро другой архитектуры, не как архитектура первого ядра. И компилятор уже другой.

На оптимизации -Ofast,  компилятор выкидывает процедуру обработки данных. Справедливо полагая, что результат вычислений нигде не используется.

Выкидывается функция  encode_rs(RSC);

void FEC_Encode(void)
{
 if(rsc==0)
 {
  cache_inv_range((u32)RSC,((u32)RSC)+fsize);
  
  encode_rs(RSC);

  cache_flush_range((u32)RSC,((u32)RSC)+fsize);
  
  UART_putc('^');

  rsc=1; //ready flag for first CPU
 }

}

 

Вопрос, как сделать так, чтобы код не выкидывался и выполнялся?

Вариант вывести результат функции через printf() - не рассматривается.

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

volatile и used  - это все полумеры. сделайте функцию пустую (непременно глобальную), которой передайте аргументом результат обработки

Изменено пользователем AlexRayne

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, AlexRayne said:

volatile и used  - это все полумеры

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, vov4ick said:

extern volatile ?

vloatile сделал. Но это указатель.  И ещё когда mamcpy, memset, то требует убрать volatile.

Как сделать массив volatile?  Чтобы компилятор имел ввиду - каждый элемент массива может быть volatile.

Ну ещё и барьер памяти, потому что важна последовательность действий - вызов encode_rs() не раньше инвалидации и не позже flush. rsc=1 - в самом конце - это флаг другому ядру:

void FEC_Encode(void)
{
 if(rsc==0)
 {
  cache_inv_range((u32)RSC,((u32)RSC)+fsize);

  __asm__ __volatile__ ("" ::: "memory");
  
  encode_rs(RSC);

  __asm__ __volatile__ ("" ::: "memory");

  cache_flush_range((u32)RSC,((u32)RSC)+fsize);

  __asm__ __volatile__ ("" ::: "memory");
  
  UART_putc('^');

  __asm__ __volatile__ ("" ::: "memory");

  rsc=1; //ready flag for first CPU
 }

}

rsc - это некешируемая ячейка памяти, хранящая флаг - volatile : оба ядра могут её читать-писать.   RSC - указатель на буфер данных, тоже volatile.

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/17/2023 at 5:03 PM, repstosw said:

rsc - это некешируемая ячейка памяти, хранящая флаг - volatile : оба ядра могут её читать-писать.

опять поллинг 🙂 там ведь есть аппапртные спинлоки с генерацией прерываний

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, repstosw сказал:

Как сделать массив volatile?  Чтобы компилятор имел ввиду - каждый элемент массива может быть volatile.

u32 volatile buffer[10];

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, repstosw сказал:

RSC - указатель на буфер данных, тоже volatile.

Если сам указатель не меняется - ему совершенно незачем быть volatile. Он должен быть указателем на volatile. Вы бы показали его объявление, тогда вам бы посоветовали правильный вариант.

1 час назад, repstosw сказал:

Как сделать массив volatile

volatile int a1[10];
int volatile a2[10];	// эти два объявления эквивалентны, выбирайте по вкусу.

int * pa;			// указатель на int
int * volatile pb;	// volatile-указатель на int
volatile int * pc1;	// указатель на volatile int
int volatile * pc2; // тоже указатель на volatile int
int volatile * volatile pd; // volatile-указатель на volatile-int

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, repstosw сказал:

И ещё когда mamcpy, memset, то требует убрать volatile.

Тривиальное приведение типа спасёт предводителя дворянства и отца демократии от козней mamcpy.  :wink:

1 час назад, repstosw сказал:

rsc - это некешируемая ячейка памяти, хранящая флаг - volatile : оба ядра могут её читать-писать.   RSC - указатель на буфер данных, тоже volatile.

Барьер перед rsc=1, и сама запись - с volatile.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, repstosw said:
__asm__ __volatile__ ("" ::: "memory");

В многопроцессорной системе барьеры вероятно посложнее делаются, здесь только для компилятора указания.

Изменено пользователем amaora

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/17/2023 at 6:38 PM, jcxz said:

Барьер перед rsc=1, и сама запись - с volatile.

насколько я понял речь про t113-s3, там есть аппаратные спинлоки, достаточно просто прочитать его и если прочитал 0 значит твоё ядро захватило блокировку. Тут пример со стороны arm ядра

https://elixir.bootlin.com/linux/latest/source/drivers/hwspinlock/sun6i_hwspinlock.c#L67

в readl есть барьер после чтения

https://elixir.bootlin.com/linux/latest/source/arch/arm/include/asm/io.h#L286

для armv7 и выше он такой

https://elixir.bootlin.com/linux/latest/source/arch/arm/include/asm/barrier.h#L20

volatile естественно но это тоже только для компилятора, от переупорядочивания вызовов в спекулятивных архитектурах он не спасёт

на стороне ядра xtensa насколько я понял барьер не нужен

Изменено пользователем sasamy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 hours ago, Сергей Борщ said:

Если сам указатель не меняется - ему совершенно незачем быть volatile. Он должен быть указателем на volatile. Вы бы показали его объявление, тогда вам бы посоветовали правильный вариант.

#define FEC_CODER_CONTROL   0x47E00000 //контроль кодера (не кеширован)
#define rsc (*(volatile unsigned int*)FEC_CODER_CONTROL)

#define FEC_CODER_DATA      0xC7D00000 //адрес буфера кодера (кеширован)
volatile dtype *RSC=(volatile unsigned short*)FEC_CODER_DATA;

 

9 hours ago, Сергей Борщ said:
volatile int a1[10];
int volatile a2[10];	// эти два объявления эквивалентны, выбирайте по вкусу.

Это точно, что в этих случаях каждый элемент массива будет volatile? Или только имя массива?

 

9 hours ago, jcxz said:

Тривиальное приведение типа спасёт предводителя дворянства и отца демократии от козней mamcpy.  :wink:

Так и сделал.

 

10 hours ago, sasamy said:

опять поллинг 🙂 там ведь есть аппапртные спинлоки с генерацией прерываний

В настоящий момент не до конца раскурил эти спинлоки.

Они тормозят ядро?  Тогда не подходит.  То, что флаг установился/сбросился, это ещё недостаточно, чтобы тормозить ядро. Потому что оно кроме этого ещё некоторые вещи делает.

 

8 hours ago, amaora said:

В многопроцессорной системе барьеры вероятно посложнее делаются, здесь только для компилятора указания.

Для компилятора и предназначалось. Чтобы не переставил местами несвязанные между собой конструкции.

Для DSP барьер памяти :  memw,   для CPU - инструкция DSB

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...