Bus Locking

Intel 64和IA-32处理器提供了LOCK#信号,在某些关键的访存操作时会自动地激活assert这个信号,用于封锁系统总线或类似的链接。当这个输出信号被激活时,就会阻塞来自于其他的处理器或总线代理的总线控制请求。在其他情况下,如果软件业务逻辑需要封锁总线,可以在相应的指令前放置一个LOCK指令前缀。

对于Intel386,Intel486,和Pentium处理器,显示地指定LOCK前缀,会使处理器激活LOCK#信号。硬件设计人员有责任在设计硬件时,提供LOCK#信号的接收机制,用来控制处理器间的访存操作。

对于P6及其后代处理器,如果访存操作命中处理器的内部缓存,在LOCK#信号通常不会被激活;而且,“加锁操作”只会发生在处理器的内部缓存中。

Automatic Locking

在以下操作中,处理器自动遵循“加锁的”的语义(即执行原子操作):

  • 当执行XCHG指令时,有操作数引用存储器数据。
  • 当设置TSS描述符中的B(busy)标志位时 – 当切换任务时,处理器会测试并设置(test and set)TSS描述符的TYPE域的B标志位。为了确保两个处理器不会同时切换到同一个任务,处理器在处理B标志位时,会遵循“加锁的”语义。
  • 当更新段描述符时 – 当载入一个段描述符时,如果段描述符的A(accessed)标志位没有被设置,则处理器会将其置1。在这个操作中,处理器也遵循加锁语义,这样段描述符在被更新时,就不会被其他的处理器修改。为了让这个过程更加高效,用于更新描述符的操作系统程序应该遵守如下的步骤:
    • 使用加锁的操作修改段描述符的访问权限字节,指示描述符不存在,在描述符的TYPE域设定一个值,指示描述符正在被更新。
    • 更新段描述符的域(这个操作可能需要多次访存操作;因此,不能使用加锁的操作)
    • 使用加锁的操作修改段描述符的访问权限字节,指示描述符有效而且可用。

注:参看下图,以数据段描述符为例。

  • 不管段描述符的访问标志位是否被设置,Intel386处理器总是会更新这个标志位。但是在Intel486,Pentium,P6 family,Pentium 4,Intel Xeon处理器上,会先测试这个标志位,只有当没有设置时,才会将其置1。
  • 当更新页目录和页表条目时,处理器使用加锁的操作来设置页目录和页表条目的访问标志位A与脏标志位D。

  • 中断确认 – 在中断请求发出后,中断控制器可能使用数据总线给处理器发送中断向量。处理器使用加锁语义,确保在中断向量传输时,没有其他的数据会出现在数据总线上。

Software Controlled Bus Locking

要显式地指示加锁语义,软件可以使用LOCK指令前缀。不是所有的指令都可以加LOCK前缀。下列的指令在操作存储器操作数时,可以使用LOCK前缀。当在其他指令前或者下述的指令前但是没有向内存写入数据(即目标操作数是寄存器)时,使用LOCK前缀会导致处理器产生无效操作码异常(#UD)。

  • 比特位测试与修改指令(BTS,BTR,和BTC)
  • 交换指令(XADD,CMPXCHG,和CMPXCHG8B)
  • 对XCHG指令,处理器自动假设LOCK前缀
  • 单操作数算术与逻辑指令:INC,DEC,NOT,和NEG
  • 双操作数算术与逻辑指令:ADD,ADC,SUB,SBB,AND,OR和XOR

对于加锁的指令,处理器提供的保证是目标操作数的内存区域一定是原子性操作;但是系统可能将这个区域解释为更大的范围(注:例如,一个缓存行)。

软降应该使用相同的地址与操作数长度来访问信号量(在多个处理器之间传递信号的共享内存空间)。例如,如果一个处理器使用单字长度访问信号量,其他的处理器就不应该使用字节长度访问信号量。

注意:不要使用WC类型的内存实现信号量。对用来实现信号量的缓存行,不要使用非时效存储操作。

总线封锁操作的完整性不会受到内存区域的对齐方式影响。LOCK语义会一直持续到这个个操作数更新完成。但是,非常推荐将LOCK的操作数放置于它们的自然对齐的地址上,主要是出于性能方面的考虑:

  • 单字节访问可以是任何位置
  • 两字节访问在16位边界上
  • 双字访问在32位边界上
  • 四字访问在64位边界上

相对于其他的访存操作与其他的外部可见事件,加锁的操作时原子性的。只有取指与页表访问可以跨越加锁的指令。因此,加锁的指令可以用于同步一个处理器的数据写入与另一个处理器的数据读取。

对于P6 family处理器,加锁的操作会串行化所有未完成的读存与写存操作(即等待所有的访存指令完成)。这个规则对于Pentium 4与Intel Xeon处理器也适用,只有一个例外:引用弱排序内存类型(例如WC类型的内存)的读操作不会被串行化。

加锁的指令不应该被用来保证写入的数据能被当作指令进行取指。

注意:当前版本的Pentium 4,Intel Xeon,P6 family,Pentium和Intel 486处理器允许写入的数据被当作指令读取。但是,Intel推荐想要使用自修改代码的开发者使用另一种同步机制达到这个目的。参看下节。

Handling Self- and Cross-Modifying Code

TODO

Effects of a Lock Operation on Internal Processor Caches

对于Intel486和Pentium处理器,在执行LOCK操作时,LOCK#信号总是被激活,即使被加锁操作的内存区域已经位于在处理器的缓存中。

对于P6和更新的处理器,如果加锁的指令要操作的数据已经位于处理器的缓存中且完全包含在一个缓存行中,同时数据所在的内存区域属于回写式WB内存,处理器可能不会在总线上激活LOCK#信号。相应的,处理器会修改缓存中的数据,同时使用缓存一致性机制来确保加锁操作的原子性。这个操作叫做缓存封锁(cache locking)。缓存一致性协议自动的阻止两个或多个处理器同时修改它们缓存的相同地址区域里的数据。

Intel 64/x86_64/IA-32/x86处理器 - 锁原子操作(2) - 总线封锁/缓存封锁相关推荐

  1. Intel 64/x86_64/IA-32/x86处理器 - 锁原子操作(1) - 处理器保证的原子操作

    Locked Atomic Operations 32位的IA-32处理器支持对系统内存中的位置执行"加锁的原子操作".这些操作通常用于管理共享的数据结构(例如信号量,段描述符,系 ...

  2. Intel 64/x86_64/IA-32/x86处理器段寄存器 - 32位段寄存器/64位段寄存器

    Segment Registers 本节主要讲述Intel处理器中的段寄存器,用于支持处理器的段式存储器管理机制.16位的8086/Intel286处理器有4个段寄存器CS/DS/SS/ES.32位的 ...

  3. Intel 64/x86_64/IA-32/x86处理器基本执行环境 (1) - 32位执行环境概述

    Basic Execution Environment Overview IA-32处理器提供了一套完整的资源,在处理器上运行的程序/任务可以执行指令,存储代码,数据以及状态信息.这些资源(如下简要的 ...

  4. Intel 64/x86_64/IA-32/x86处理器 - SIMD指令集 - SSE扩展(1) - 概述/历史/新数据类型/XMM寄存器组

    SSE Instructions SSE Overview & History Intel SSE技术的全称是Streaming SIMD Extension,中文译作流式单指令多数据指令扩展 ...

  5. Intel 64/x86_64/x86/IA-32处理器操作模式/运行模式

    Processor Operation Mode IA-32架构支持3种操作模式,和一种类操作模式(quasi-operating mode): 实地址模式/实模式(real-address mode ...

  6. Intel 64/x86_64/IA-32/x86处理器 - SIMD指令集 - SSE扩展(7) - 混洗指令 解组合指令

    SSE Shuffle and Unpack Instructions SSE的混洗指令与解组合指令混洗shuffle或交错interleave单精度浮点操作数,并将结果保存到目标操作数. 指令 描述 ...

  7. Intel 64/x86_64/IA-32/x86处理器 - SIMD指令集 - MMX技术(1) - 概述 传输指令

    MMX™ Instructions IA-32架构引入了4个指令集扩展,使得IA-32处理器可以执行单指令多数据SIMD操作.这些扩展包括MMX技术,SSE扩展,SSE2扩展,SSE3扩展. MMX指 ...

  8. Intel 64/x86_64/IA-32/x86处理器 - 通用指令(1) - 数据传输指令

    General-Purpose Instructions 通用指令执行基本的数据搬移,算术/逻辑计算,程序流控制,字符串操作等.这些指令被频繁地用于运行在IA-32与Intel 64架构的系统软件与应 ...

  9. Intel 64/x86_64/IA-32/x86处理器指令集 - CPUID (1) - 概述

    CPUID指令 Introduction of CPUID instruction 根据Wikipedia,CPUID指令是x86处理器体系结构的补充指令,使得软件可以枚举当前运行的处理器的详细特性, ...

最新文章

  1. mongodb关联查询 和spring data mongodb
  2. [周译见] C# 7 中的模范和实践
  3. php ip 省份,PHP有没有生成国内各省份IP地址的类库?
  4. cstring::replace不区分大小写_Excel VBA之函数篇-3.11订单号千奇百怪,如何按照结构区分来源...
  5. 70 行 Go 代码打败 C!
  6. 网易云音乐推荐中的用户行为序列深度建模
  7. 【无线芯片解读】2.4G专题:(SI24R1简版)Ci24R1
  8. use after free double free利用
  9. matlab地震频谱分析,《基于MATLAB的地震数据的分析》.doc
  10. bam文件测序深度统计-bamdst
  11. 微软2016校园招聘4月在线笔试 总结
  12. 2022-2027年中国发动机行业市场调研及未来发展趋势预测报告
  13. Python-----函数详解(上篇)(附小项目实战)
  14. 图片大小、像素、分辨率之间的关系
  15. MATLAB在Linux上报Warning: Unable to create com.mathworks.mde.explorer.Explorer解决方法
  16. 华为完成首个5G测试;央行搭建区块链平台;苹果将于今夜凌晨举行发布会;蔚来汽车明日在美上市; | 雷锋网9月12日消息...
  17. 在VC中编程实现按钮的启用(enable)和禁用(disable)
  18. iOS小技能:设置tableView的点击事件优先级低于cell的选中事件(场景:比如筛选视图,监听蒙版的点击事件就隐藏筛选视图)
  19. 国密算法的ekey基本使用的说明
  20. gcc-c++安装—使用系统自带的源yum install gcc-c++和本地源进行相应的安装

热门文章

  1. 线性调频信号 matlab
  2. Spark MLlib中的协同过滤
  3. 如何运行python代码
  4. getBoundingClientRect()
  5. day8 java的静态与实例
  6. Java for循环改数据_如何改变arrs数组?当然是需用for循环啦
  7. python清除实例化类_在Python中,如何尝试(和排除)类的实例化?
  8. 同一列两行数据怎么合并成一行_经常加班怎么办?两分钟学会这4招,让同事刮目相看!...
  9. python脚本绘图_python实现画图工具
  10. python中多对多替换_Python对指定文件内容进行全局替换