Я реализую однопользовательскую очередь с одним производителем, при которой один поток ожидает заполнения глобальной очереди другим потоком, например так:
while (queue.head == queue.tail);
Когда я скомпилировал программу gcc -O0, она работала хорошо. Но когда он был скомпилирован с gcc -O1, произошел тупик. Затем я посмотрел код ассемблера и обнаружил, что последняя версия проверяла (queue.head == queue.tail) только один раз, если это не так, затем переходила к мертвому циклу и больше никогда не проверялась.
Я также пытался объявить очередь как изменчивую, но она не работала. Как заставить gcc знать, что очередь распределяется между потоками, и перестать так оптимизировать? Большое спасибо.
приписка
1 В однопоточной программе можно оптимизировать таким образом. Но в моей программе queue.tail можно изменить другим потоком.
2 Моя очередь была объявлена так:
typedef struct {
struct my_data data[MAX_QUEUE_LEN];
int head;
int tail;
} my_queue_t;
volatile my_queue_t queue;
3 Я также пытался объявить голову и хвост (но не всю структуру) как изменчивые, это не сработало. Но после того, как я объявляю очередь, голову, хвост все как изменчивые, это работает. Таким образом, volatile должно быть объявлено всем связанным переменным, как это?