Notes about cmpxchg/cmpxchg64 in Linux kernel
本文将mark下Linux kernel中cmpxchg/cmpxchg64的相关笔记。对于底层实现的硬件原理,待有空了再分析。
本文参考的内核版本为v5.0。
基本原理
cmpxchg(void* ptr, int old, int new) 将old和ptr指向的内容比较
- 如果相等,则将new写入到ptr中,返回old
- 如果不相等,则返回ptr指向的内容
整个过程中操作是原子的。
From the point of view of a Linux kernel programmer, compare-and-swap has the following prototype:1
T cmpxchg(T *ptr, T old, T new);
where T
can be either an integer type that is at most as wide as a pointer, or a pointer type. In order to support such polymorphism, cmpxchg()
is defined as a macro rather than a function, but the macro is written carefully to avoid evaluating its arguments multiple times. Linux also has a cmpxchg64()
macro that takes 64-bit integers as the arguments, but it may not be available on all 32-bit platforms.
Example
1 | /* Posted-Interrupt Descriptor */ |
值得注意的是:ndst
和nv
field均属于pi_desc的control
。
在上述代码片段中,old.control的类型是u64,在第31行到43行执行过程中,IOMMU硬件是有可能更改 on
(Outstanding Notification)bit的,也就是说pi_desc->control的内容可能会发生变化。
因此会在第44行到45行检测pi_desc->control与old.control是否相等:
- 如果相等(说明过程中IOMMU硬件没有更改
on
),就将new.control写入到&pi_desc->control中,并返回old.control,则会跳出do while循环 - 如果不相等(说明过程中IOMMU硬件更改了
on
),就会返回pi_desc->control,则继续进入do while循环
参考资料: