Intel处理器原子操作支持

概述

Intel处理器支持对系统内存中的位置进行锁定原子操作,这些操作通常用于管理共享数据结构(例如信号量,段描述符,系统段或页表等),其中两个或多个处理器。可以同时尝试修改相同的数据,处理器提供机制保证访问的原子性。
Intel处理器使用三个相互依赖的机制来执行锁定的原子操作:

  • 受保障的原子操作:对于基本的内存事务(例如在系统内存中读取或写入一个字节)始终保证以原子方式处理。即一旦启动,处理器保证在允许另一个处理器或总线代理访问存储器位置之前完成操作
  • 总线锁定:处理器使用LOCK#信号和LOCK指令前缀对总线进行锁定,用于保证执行选定的一系列存储器操作,典型的操作时序如对存储器内的某个变量进行读取-修改-写入
  • 缓存一致性协议:确保可以对高速缓存中的数据结构执行原子操作,被称为缓存锁定(cache lock),此时则无需断言总线锁定

受保障的原子操作

Intel486及其后代处理器确保如下的基本操作总是自动原子性(即无需程序员编写任何指令)的:

  • 读/写单个字节
  • 读/写按16位对齐的单字
  • 读/写按32位对齐的双字

Pentium及其后代处理器确保如下的访存操作总是原子性的:

  • 读/写按64位对齐的四字
  • 访问非缓存类型存储器(uncached memory)中16位宽的数据且数据的16个比特位必须能够容纳在32位的数据总线中。

P6及其后代处理器确保如下的访存操作总是原子性的:

  • 访问缓存的存储器(cached memory)中非对齐的16-,32-,和64-位宽的数据且数据的比特位必须能够容纳在同一个缓存行中。

总线锁定

Intel 处理器(包括32位和64位)提供LOCK#信号,该信号在某些关键存储器操作期间自动置位,以锁定系统总线。当总线锁定时,来自其他处理器或总线代理的用于控制总线的请求会被阻止。软件可以指定在遵循LOCK语义的其他情况下将LOCK前缀添加到指令之前。

自动锁定

处理器自动遵循LOCK语义的操作如下:

  • 执行引用内存的XCHG指令时。

  • 设置TSS描述符的B(忙)标志时 - 处理器在切换到任务时测试并在TSS描述符的类型字段中设置忙标志。为确保两个处理器不会同时切换到同一任务,处理器在测试和设置此标志时遵循LOCK语义。

  • 更新段描述符时 - 加载段描述符时,如果标志清除,处理器将在段描述符中设置访问标志。在此操作期间,处理器遵循LOCK语义,以便在更新时,另一个处理器不会修改描述符。要使此操作生效,更新描述符的操作系统过程应使用以下步骤:

    • 使用锁定操作修改访问权限字节以指示不存在段描述符,并指定类型字段的值,该值指示正在更新描述符。
    • 更新段描述符的字段。 (此操作可能需要多次内存访问;因此,无法使用锁定操作。)
    • 使用锁定操作来修改访问权限字节,以指示段描述符有效并存在。
  • 无论是否清除,Intel386处理器始终更新段描述符中的已访问标志。Pentium 4,Intel Xeon,P6系列,Pentium和Intel486处理器仅在尚未设置时才更新此标志。

  • 更新页面目录和页表条目时 - 更新页面目录和页表条目时,处理器使用锁定周期来设置页面目录和页表条目中的已访问和脏标志。

  • 确认中断 - 中断请求后,中断控制器可以使用数据总线将中断向量发送到处理器。处理器在此期间遵循LOCK语义,以确保在传输向量时数据总线上不会出现其他数据。

软件控制总线锁定

要明确强制LOCK语义,软件可以在用于修改内存位置时使用LOCK前缀和以下说明。 当LOCK前缀与任何其他指令一起使用时或者当没有对存储器进行写操作时(即,当目标操作数在寄存器中时),将生成无效操作码异常(#UD)。

  • 位测试和修改指令(BTS,BTR和BTC)。
  • 交换指令(XADD,CMPXCHG和CMPXCHG8B)。
  • XCHG指令自动采用LOCK前缀。
  • 以下单操作数算术和逻辑指令:INC,DEC,NOT和NEG。
  • 以下双操作数算术和逻辑指令:ADD,ADC,SUB,SBB,AND,OR和XOR。

锁定指令保证仅锁定目标操作数定义的内存区域,但可以被系统解释为更大内存区域的锁定。软件应使用相同的地址和操作数长度访问信号量(用于多个处理器之间的信令的共享存储器)。 例如,如果一个处理器使用字访问访问信号量,则其他处理器不应使用字节访问来访问信号量。

总线锁的完整性不受存储器字段对齐的影响。遵循LOCK语义会获得更新整个操作数所需的多个总线周期。但是,建议锁定访问在其自然边界上对齐,以获得更好的系统性能:

  • 8位访问的任何边界(锁定或其他)。
  • 锁定字访问的16位边界。
  • 锁定双字访问的32位边界。
  • 锁定四字访问的64位边界。

锁定操作相对于所有其他内存操作和所有外部可见事件都是原子操作。只有指令获取和页表访问才能传递锁定的指令。锁定指令可用于同步由一个处理器写入并由另一个处理器读取的数据。

LOCK操作对内部处理器缓存的影响

对于Intel486和Pentium处理器,LOCK#信号在LOCK操作期间始终在总线上置位,即使被锁定的内存区域缓存在处理器中也是如此。

对于P6和更新的处理器系列,如果在LOCK操作期间被锁定的存储器区域被高速缓存在执行LOCK操作作为回写存储器并且完全包含在高速缓存行中的处理器中,则处理器可能不会断言 总线上的LOCK#信号。 相反,它将在内部修改内存位置并允许其缓存一致性机制,以确保以原子方式执行操作。 此操作称为“缓存锁定”。缓存一致性机制自动防止缓存相同内存区域的两个或多个处理器同时修改该区域中的数据。

相关参考

  • 《Intel处理器手册》
posted @ 2020-06-07 00:41  Aspiresky  阅读(52)  评论(0编辑  收藏  举报