只是想知道哪些CPU架构支持比较和交换原子原语?
Answer 1:
PowerPC的拥有更强大的原语可用:“lwarx”和“stwcx”
lwarx从内存中加载一个值,但记住的位置。 触及该位置将导致“stwcx”,条件存储指令的任何其它线程或CPU,失败。
所以lwarx / stwcx组合可以让你实现单位递增/递减,比较和交换,而像“单位递增循环缓冲区指数”更强大的原子操作
Answer 2:
一个不同的,更简单的方式来回答这个问题可能会列出不支持比较和多处理器平台交换(或负载链接/条件存储,可以用来写一个)。
我知道的只有一个是PARISC,其中只有一个原子清晰字指令。 这可用于构建一个互斥(提供的一个对准的16字节边界上的字)。 有这个archetecture没有CAS(不像X86,IA64,PPC,SPARC,MIPS,S390,...)
Answer 3:
有几个人评论/被问及是否需要对CMPXCHG在x86 / x64“锁定”前缀。 答案是肯定的多核机器。 该指令是用于无锁单核机器完全原子。
它已经有一段时间,因为我研究过这个东西,深深的,但是我似乎记得指令是技术上重新启动 - 它可以中止指令飞行中段(如果它没有任何副作用还),以避免延迟中断处理过长。
Answer 4:
英特尔的x86有这种支持。 IBM在它的Solaris到Linux移植指南给出了这样的例子:
bool_t My_CompareAndSwap(IN int *ptr, IN int old, IN int new)
{
unsigned char ret;
/* Note that sete sets a 'byte' not the word */
__asm__ __volatile__ (
" lock\n"
" cmpxchgl %2,%1\n"
" sete %0\n"
: "=q" (ret), "=m" (*ptr)
: "r" (new), "m" (*ptr), "a" (old)
: "memory");
return ret;
}
Answer 5:
与ARMv6体系结构ARM开始就可以用于实现原子比较交换操作的LDREX / STREX指令。
Answer 6:
对不起,很多信。 :(
几乎在x86 ISA的所有指令(除了所谓的字符串指令,和其他人也许很少),包括CMPXCHG,在单核CPU的情况下原子。 这是因为,根据x86架构,CPU检查每条指令的执行完成后赶到中断,从来没有在中间。 其结果是,中断请求可以被检测和处理它可以仅在两个连续的指令的执行之间边界启动。 由于该单一的指令的执行期间通过CPU采取的所有存储器引用分离并不能由任何其他活动交错。 这种行为是单核和多核CPU常见。 但是,如果在单核CPU的上下文中只有一个有其同时执行对存储器的访问的系统的一个以上的单元,其执行对存储器的访问,在多核CPU的上下文中,系统的单元。 指令隔离是不够的在这样的环境的一致性,因为存储器访问由不同的CPU在同一时间可以交织彼此制成。 由于这种额外的保护层必须被施加到数据改变协议。 用于x86这层是锁定前缀,即在系统总线上启动的原子事务。
总结:它是安全的,成本更低的使用像CMPXCHG,XADD,BTS等同步指令而不锁定前缀,如果你放心,通过该指令访问的数据可以通过一个内核只访问。 如果您没有在此保证,适用锁定前缀通过权衡性能,以提供安全性。
有通过CPU硬件同步支持两个主要的方法:
- 原子事务为主。
- 高速缓存一致性协议为主。
没有人是万能的。 这两种方法都有其优点和缺点。
基于原子事务的方法依赖于内存总线上的特殊类型交易的支撑。 在连接到总线的此类交易仅一个代理(CPU核)有资格访问存储器。 作为结果,在一方面,原子事务期间由总线所有者的所有存储器引用是保证能够制备为单个不间断事务。 在另一只手的所有其他总线代理(CPU内核)将被强制执行等基本交易完成后,要回访问内存的能力。 没关系,他们希望获得什么样的存储单元,即使他们想访问不是由总线所有者原子事务中引用的内存区域。 作为结果,大量使用锁前缀说明将系统显著放缓。 在另一方面,由于该总线仲裁器可以访问总线根据轮询调度各总线代理,有保证每个总线代理将有相对公平的访问内存和所有代理会能够取得进展,并以相同的速度做到了。 此外,ABA问题进入戏中的原子事务的情况下,由于其性质,原子事务很短(几个内存引用由单指令制造)和事务处理过程中对内存采取的所有行动只能靠记忆区域的价值,没有考虑到帐户,是存储区域是由两笔交易之间的一些其他人访问。 基于同步支持原子事务的很好的例子是x86架构,其中锁定指令前缀执行CPU中的原子事务执行它们。
高速缓存一致性协议为基础的方法依赖于一个事实,即存储器行只能在一个L1缓存在时间的一个瞬间缓存。 在高速缓存一致性的系统存储器访问协议类似于动作下一个序列:
- CPU A存储在L1高速缓存存储器线X。 在相同的时间CPU B期望访问存储器线X(X - > CPU A L1)
- 在总线上CPU B问题内存行X访问事务。 (X - > CPU A L1)
- 所有的总线(CPU内核)具有监听总线上的所有交易和检查,如果被交易请求的存储器行访问存储在它的主人CPU的L1缓存所谓的探听。 所以,CPU A探听代理检测到CPU A拥有由CPU B.请求的存储器线(X - > CPU A L1)
- CPU A暂停由CPU B.发出的存储器访问事务(X - > CPU A L1)
- CPU A冲洗从其L1高速缓存中箭头B所请求的存储器行。 (X - >存储器)
- CPU简历之前暂停交易。 (X - >存储器)
- CPU B从存储器中取出存储线X。 (X - > CPU B L1)
感谢该协议CPU核心总是访问在存储器中的实际数据,并访问所述存储器在严格的顺序被序列,在一个时间访问。 高速缓存一致性协议的基于同步支持依赖这样的事实,即CPU可以容易地检测,该特定存储器线在两个时间点之间的访问。 在第一存储器存取的线X必须打开交易,CPU可以标记在L1高速缓存该存储器行必须通过监听剂来控制。 反过来探听剂可以除了高速缓存行冲洗期间执行检查,以确定的是,线被标记为控制,并提高内部标志,如果控制线冲洗。 作为结果,如果CPU会期间关闭交易存储器存取检查内部标志,它会知道被控制内存行之所以能够被别人改变,并得出结论是交易必须成功完成或者为失败,必须加以考虑。 这是LL \ SC指令类实现的方式。 这种方法更简单的是原子事务并提供同步了更多的灵活性,因为更多的数量不同的同步原语可以在其上与原子事务的方法相比,可以建群。 这种方式更加灵活有效,因为它不会阻止访问内存为系统的其他部分。 正如你可以看到它解决了ABA问题,因为它的基础上的内存区域访问检测的事实,但不是在存储区域变化的检测值。 作为交易失败对内存区域的任何访问参与正在进行的交易将被考虑。 这样就可以在同一时间有好有坏,因为特定的算法有兴趣的可以只在内存区域的价值,并在该帐户不被采取该位置被人在中间访问,直到访问更改内存。 在这种情况下,中间读取内存值会导致假阴性的交易失败。 另外这种方法会导致contenting在同一内存行控制流的巨大的性能下降,因为他们能够从彼此不断钢材内存行,并以此阻止对方从完成交易成功。 这确实是显著的问题,因为在终端情况下,它可以在活锁打开系统。 高速缓存一致性协议的基于同步支持通常RISC CPU使用,因为它的简单性和灵活性。 但必须指出的是,英特尔公司决定支持x86架构的同步支持这样的做法太。 在去年英特尔宣布的事务性同步扩展到x86架构,将在新一代的Haswell的英特尔处理器来实现。 在结果,它看起来像,在x86将拥有最有力的支持同步,并允许系统开发人员可以使用两种方法的优点。
Answer 7:
只是为了完成列表中,MIPS已经加载所关联(LL)和条件存储(SC),它从内存中加载一个值,如果没有其他的CPU已经访问了位置以后有条件存储指令。 它真实的,你可以使用这些指令来执行交换,增加等操作。 不过它的缺点是具有大量的CPU行使锁非常严重你进入活锁:在有条件的商店经常会失败,并且需要另一个循环再次尝试,这将失败,等等。
该软件的mutex_lock实现将变得非常复杂试图执行一个指数退避,如果这些情况被认为是重要的,足以担心。 在一个系统,我曾与128个内核,他们是。
Answer 8:
在x86和Itanium有CMPXCHG(比较和交换)
Answer 9:
比较和交换加入IBM大型机在1973年它(和双比较和交换)对IBM大型机仍(与像巴解组织最近的多处理器功能一起 - 进行锁定操作)。
Answer 10:
SPARC V9具有CAS指令。 在SPARC V9 体系结构手册讨论了使用在附件J中CAS指令的,在实施例和J.11具体J.12看。
我相信指令的名称实际上是“卡萨”,因为它可以访问无论是当前的地址空间或备用。 “CAS”是访问当前ASI汇编宏。
还有上一篇文章developers.sun.com讨论哪些Sparc处理器多年来实施的各种原子指令,其中包括CAS。