Реализация атомарной операции чтения и записи в ядре Linux
Недавно я заглянул в реализацию ядра Linux для атомарного чтения и записи, и возникло несколько вопросов.
Сначала соответствующий код из архитектуры ia64:
typedef struct {
int counter;
} atomic_t;
#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic64_read(v) (*(volatile long *)&(v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
#define atomic64_set(v,i) (((v)->counter) = (i))
Похоже, что для операций чтения и записи был выбран прямой способ чтения или записи в переменную. Если где-то нет другого трюка, я не понимаю, какие существуют гарантии, что эта операция будет атомарной в области сборки. Я предполагаю, что очевидным ответом будет то, что такая операция преобразуется в один код операции сборки, но даже в этом случае, как это гарантируется, принимая во внимание различные уровни кэша памяти (или другие оптимизации)?
В макросах чтения тип volatile используется в фокусе приведения. Кто-нибудь знает, как это влияет на атомарность здесь? (Обратите внимание, что он не используется в операции записи)