Недавно я читаю некоторые коды пространства ядра 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-битной платформе макрос atomic64_read расширяется до
used = (&g_variable->used)->counter // where counter is volatile.
В 32-битной платформе он был преобразован для использования блокировки cmpxchg8b . Я предполагаю, что эти два имеют одинаковую семантику, и для 64-битной версии, я думаю, это означает:
- все или ничего , мы можем исключить случай, когда адрес не выровнен и размер слова больше, чем собственный размер слова процессора.
- без оптимизации , принудительное чтение CPU из области памяти.
atomic64_read не имеет семантики для сохранения порядка чтения !!! см. this
# B барьер * Макрос 1034 * определяется как
/* Optimization barrier */
/* The "volatile" is due to gcc bugs */
#define barrier() __asm__ __volatile__("": : :"memory")
Из вики это просто запрещает компилятору gcc переупорядочивать чтение и запись.
Что меня смущает, так это как отключить оптимизацию переупорядочения для процессора? Кроме того, могу ли я считать, что барьерный макрос является полным забором?