В последнее время я читаю некоторые коды пространства ядра Linux, я вижу это
uint64_t used;
uint64_t blocked;
used = atomic64_read(&g_variable->used); //#1
barrier(); //#2
blocked = atomic64_read(&g_variable->blocked); //#3
Какова семантика этого фрагмента кода? Обеспечивает ли он выполнение # 1 перед # 3 на # 2. Но я немного помешал, потому что
#A В 64-битной платформе макрос Atom64_read расширяется до
used = (&g_variable->used)->counter // where counter is volatile.
В 32-битной платформе она была преобразована для использования блокировки cmpxchg8b. Я предполагаю, что эти два имеют одинаковую семантику, а для 64-битной версии, я думаю, это означает:
- all-or-nothing, мы можем исключить случай, когда адрес не выравнивается и размер слова больше, чем размер родного слова процессора.
- не оптимизировать, заставить процессор считывать данные из памяти.
atomic64_read не имеет семантики для сохранения порядка чтения!!! см. this
#B макрос барьера определяется как
/* Optimization barrier */
/* The "volatile" is due to gcc bugs */
#define barrier() __asm__ __volatile__("": : :"memory")
Из wiki this просто запрещает gcc компилятор переупорядочивать чтение и запись.
Что меня путают, так это то, как отключить оптимизацию переупорядочения для CPU? Кроме того, могу ли я думать, что барьерный макрос является полным забором?