Използвам проста софтуерна опашка, базирана на индекс за запис и индекс за четене.
Подробности за въведението; Език: C, Компилатор: GCC Оптимизация: -O3 с допълнителни параметри, Архитектура: Armv7a, CPU: Многоядрен, 2 Cortex A-15, L2 Cache: Споделен и активиран, L1 Cache: Всеки CPU, активиран, Архитектурата трябва да бъде кеш съгласуван.
CPU 1 извършва писане, а CPU 2 чете. По-долу е много опростен примерен код. Можете да приемете, че първоначалните стойности на индексите са нула.
ЧЕСТО СРЕЩАНИ:
#define QUE_LEN 4
unsigned int my_que_write_index = 0; //memory
unsigned int my_que_read_index = 0; //memory
struct my_que_struct{
unsigned int param1;
unsigned int param2;
};
struct my_que_struct my_que[QUE_LEN]; //memory
CPU 1 работи:
void que_writer
{
unsigned int write_index_local;
write_index_local = my_que_write_index; //my_que_write_index is in memory
my_que[write_index_local].param1 = 16; //my_que is my queue and stored in memory also
my_que[write_index_local].param2 = 32;
//similar writing stuff
++write_index_local;
if(write_index_local == QUE_LEN) write_index_local = 0;
my_que_write_index = write_index_local;
}
CPU 2 работи:
void que_reader()
{
unsigned int read_index_local, param1, param2;
read_index_local = my_que_read_index; //also in memory
while(read_index_local != my_que_write_index)
{
param1 = my_que[read_index_local].param1;
if(param1 == 0) FATAL_ERROR;
param2 = my_que[read_index_local].param2;
//similar reading stuff
my_que[read_index_local].param1 = 0;
++read_index_local;
if(read_index_local == QUE_LEN) read_index_local = 0;
}
my_que_read_index = read_index_local;
}
Добре, в нормален случай никога не трябва да възниква фатална грешка, защото param1 на опашката винаги се съхранява с постоянна стойност 16. Но по някакъв начин param1 на опашката се случва 0 и възниква фатална грешка.
Ясно е, че това по някакъв начин е проблем със състоянието на състезанието, но не мога да разбера как се случва. Индексите се актуализират отделно от процесорите.
Не искам да запълвам кода си с бариери на паметта, без да разбирам същината на проблема. Имате ли идея как става това?
Подробности: Това е baremetal система, тези кодове са забранени за прекъсване и няма превключване или превключване на задачи.
stdatomic.h
. Има доста статии, включително кодови фрагменти за прилагане на безопасни за нишки буфери; Горещо препоръчвам първо да ги прочетете внимателно. Например: защо кодът за четене всъщност трябва да препрочита индекса за запис, след като той не се променя от негова гледна точка? - person too honest for this site   schedule 09.10.2015