Я работаю с Zynq-7000 SoC - разрабатываю двухъядерное приложение (CPU0, CPU1). Я хочу использовать общую встроенную память (OCM) с отключенным кешем для двунаправленного обмена данными между ядрами. Моя идея состоит в том, чтобы установить обмен данными следующим образом:
typedef struct
{
uint8_t mstatus;
uint8_t[10] mdata;
} mailbox;
mailbox core0mbox;
mailbox core1mbox;
Структура mailbox
содержит буфер для хранения данных (mdata
) и его состояния (mstatus
). Статус может быть равен 0
или 1
(в общем случае - нулевое значение указывает на то, что данные были обработаны приемником и новые данные могут быть записаны в буфер; ненулевое значение указывает на то, что данные не были обработаны приемником. еще ресивер). Есть два почтовых ящика — core0mbox
(хранит данные, полученные ядром 0 от ядра 1) и core1mbox
(хранит данные, полученные ядром 1 от ядра 0), оба хранятся в OCM.
Когда ядро 0 хочет отправить данные, оно опрашивает флаг состояния core1mbox.mstatus
- если он равен нулю, ядро заполняет буфер, связанный с
core1mbox
, данными, а затем устанавливает флаг, связанный сcore1mbox
, на1
- если он имеет ненулевое значение, ядро не может отправить данные
Когда ядро 1 хочет отправить данные, оно опрашивает флаг состояния core0mbox.mstatus
.
- если он равен нулю, ядро заполняет буфер, связанный с
core0mbox
, данными, а затем устанавливает флаг, связанный сcore0mbox
, на1
- если он имеет ненулевое значение, ядро не может отправить данные
Ядро 0 периодически опрашивает core0mbox.mstatus
— если оно имеет ненулевое значение, то ядро 0 обрабатывает данные и после завершения устанавливает core0mbox.mstatus
в 0
.
Ядро 1 периодически опрашивает core1mbox.mstatus
- если оно имеет ненулевое значение, то ядро 1 обрабатывает данные и после завершения устанавливает core1mbox.mstatus
в 0
.
Мой вопрос: может ли эта схема привести к неопределенному поведению системы (например, повреждению данных) из-за проблем, вызванных одновременным доступом? Я знаю, что эта схема не могла бы работать, если бы флаг состояния мог иметь больше значений (проблемы из-за неатомарной операции записи/чтения) или если бы в системе было бы большее количество ядер, но, похоже, она хорошо работает для описанная ситуация.
uint8_t
атомарными. Обычно наint
они есть, но я не знаю насчетuint8_t
в вашей системе. - person yyny   schedule 16.11.2016uint8_t
не будут атомарными (поскольку нам важно только, равен ли статус нулю или нет). - person Steven   schedule 16.11.2016mstatus == 1
до тех пор, пока все данные не будут записаны? Вам нужны хотя бы некоторые барьеры памяти, если не полный мьютексный подход. - person twalberg   schedule 16.11.2016volatile
наmstatus
. Однако, как я объяснил, это бесполезно, если операции надuint8_t
не являются атомарными. - person yyny   schedule 18.11.2016uint8_t
(по крайней мере, чтение и запись) являются атомарными, и ваш код будет работать должным образом (если вы определитеmstatus
volatile
), так что все должно быть в порядке. В противном случае вам придется использовать C11 или, если это невозможно, что-то специфичное для платформы, напримерfutex
в Linux или__atomic
в GCC. - person yyny   schedule 18.11.2016