欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于 atomic 的话题

程序员文章站 2022-03-06 13:01:03
...

这里有一个很重要的概念:boundary (边界)

常见的 boundary:

★ word boundary(16 位)
★ doubleword boundary(32 位)
★ quadword boundary(64 位)

---------------------------------------------------------------------------------

1、造成这些 boundary 的原因是:data bus width (数据线的宽度)

  对于 processor 这里有一个很重要的分界点,以 Pentium 处理器为分界,在 Pentium 之前的 data bus 是 32 位,而 Pentiume 之后的 data bus 有 64 位。

  每 8 bits 分成一组 byte,由信号 BE# 来控制 read/write,被称为 data path

  所以,Pentiume 之后的 processor 有 8 个 data path(BE0 ~ BE7)

  就是由这些 data path 造成了 多种 boundary,这 8 个 data path 造成了可以有 quadword boundary 的出现

  但是 address bus 还是 32,以及后来的 48 位


2、 data path 是影响 boundary 和 atomic 的最主要的因素,

而造成 非 atomic 的成因就是:跨 bounday,实际上是跨了 8 data path

   因此:跨了 8 个 data path 就会造成 非 atomic 的情况

   在 Pentium 之后的 processor 只要在不是跨 8 data path,即:quadword boudary 的情况下都能保证是 atomic


3、 何为跨 8 data path ?

BE0# ----> 0
BE1# ----> 1
BE2# ----> 2
BE3# ----> 3
BE4# ----> 4
BE5# ----> 5
BE6# ----> 6
BE7# ----> 7
-------------------------------------------
每个 data path 对应控制 1 个 byte

跨 quadword boudary 产生的情形:
  例如:当从 BE3#(3 data path) read/write 一个 quadword(64位),这时就属于跨 quadword boudary
  这时,processor 需要做 2 次 read/write 操作,这样,就不能保证 atomic

又例如:
  从 BE3# (3 data path) read/write 一个 word 操作,不会跨过 8 data path,它的 atomic 得到保证。



4、 另一些很坏的情况是:跨 cache line boundary,甚至是:跨 page boundary

  cache line boundary 是:大多数 processor 的 cache line 是 64 bytes(0 ~ 63 byte),如果一个 read/write 是跨过了 64 bytes 这个边界的话,若使用 lock 来保证它的 atomic 的话,processor 会先做 fill cache line 动作。

  page bundary 是:以 4K page 为例,同样若跨了 4K bytes 边界,processor 会做两次读 page




5、 以指令来说明“跨 boundary“

指令: mov eax, dword ptr [5]

  这条指令从 地址 5 开始读 doubleword 到 eax 寄存器

那么:
  (1) processor 先将 BE5# = 0,BE6# = 0,BE7# = 0,其它置 1,使用 data path 5、6、7 有效,其它 data path 无效,先读 24 位,放到 eax 的低 24 位

  (2) 接着 processor 再置 BE0# = 0,其它置1,使 data path 0 有效,其它 data path 无效,
   读 byte 放到 eax 的高 8 位

------------------------------------------------------------
  以这样来完成 doubleword 的读,这样 processor 实际上做了 2 次 read 工作。

  所以,手机号购买atomic 将不能得到保证。

不能保证 atomic 的第二个因素是:processor 做 read-modify-write 类交易

典型的如:执行 add dword ptr [eax], eax 指令


对于这条指令:

1、processor 是 read 从内存 [eax] 一个 dword 放到 temp registers

2、processor 做 add 工作,temp registers 与 eax 相加结果放 temp registers

3、processor 写内存 [eax],从 temp registers

-------------------------------------------------------------

这样,就是 read-modify-write 操作不能保证 atomic


需要 lock 进行 atomic 


int b = a;

代码的目的是令 b = a

(1) movl a, %eax // atomic
(2) movl %eax, -4(%ebp) // atomic

-------------------------------------------------------------
虽然是2条指令,每条指令都是原子的。

(1) 中 a 已经 load 到 eax 中,即使读完后 a 被改变,不会影响 eax
(2) 中 eax 已经 store 到 -4(%ebp) 中,这个 eax 就是 a 值

>>> 即使 write 后,-4(%ebp) 被改写,那也是 write 完之后的事。

所以:int b = a; 这条语句是原子的,这样已经足够了

即使之后 b 被改写,但 b = a 语句来说,是原子的。


又例如:

b = a;

----------------------------------------------

如果,编译器是这样编译的话:

movl a, -4(%ebp) // a ---> temp
movl -4(%ebp), %eax // temp ---> eax
movl %eax, -8(%ebp) // eax ---> b

--------------------------------------------------------------------

中间,多了一个 memory 读/写,这就不能保证其原子性了。