Linux kernel中list.h中 链表的初始化函数如下
static inline void INIT_LIST_HEAD(struct list_head *list)
{
WRITE_ONCE(list->next, list);
list->prev = list;
}
上面一段代码的作用是初始化链表,使前向指针和后向指针分别指向list自己。
不理解WRITE_ONCE()函数是干嘛的
转到WRITE_ONCE()函数,如下
#define WRITE_ONCE(var, val) \
(*((volatile typeof(val) *)(&(var))) = (val))
volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。这与上篇的mesi协议有关
国外网站的回答是这样的
The ACCESS_ONCE macro is used in situations where a value is being retrieved from a storage location that is known (or suspected) to be volatile, but is not typed as such. The purpose is to retrieve the current value of the storage location in such a way as to defeat an optimising compiler that might otherwise cache the value in a register, or not even provide a storage location at all.
The construct as written applies the 'volatile' to the storage location indirectly by declaring a suitably typed pointer to that location. As per the C standard, this mandates that the object be evaluated strictly according to the rules of the abstract machine.
Your proposed modification would not apply volatile to the storage location, so it would not achieve this purpose. The value retrieval could be subject to optimisation.
Incidentally, I regard this as a model of conciseness for the stated purpose. I reserve complex for far worse things than this.
大概是这么个意思,*((volatile typeof(val) *)(&(var))可以保证var在多线程下被其它函数调用变量时不会出错。具体详情可以参考我前面一篇文章 缓存一致性协议(MESI协议)