原子操作是不可分割的操作,在执行完成时不会被事件中断。 在单处理器系统(UniProcessor,UP )中,中断只发生在指令和指令之间,所以一个指令可以执行的操作都可以被认为是原子操作。
多处理器系统(Symmetric Multi-Processor,简称SMP )的情况不同,系统中的多个处理器独立工作,因此一个指令可以执行的操作也可能受到干扰。
所有X86 CPU都具有锁定特定内存地址的功能,如果该特定内存地址被锁定,其他系统总线将无法读取或更改该内存地址。 这个能力是通过在LOCK指令前缀中添加以下汇编指令来实现的。 使用LOCK命令前缀时,CPU会声明LOCK#信号,以便在与多处理器系统或多线程冲突的环境中独占使用该内存地址。 命令执行完成后,该锁定动作也将消失。
LOCK命令可以与前缀一起使用的命令包括:
BT,BTS,BTR,BTC (毫米,红色/英寸) )。
XCHG,xadd (红,米/米,红) )。
添加、或、添加、删除、删除(毫米、红色/英寸) )。
“与”、“辅”和“或”(毫米,红色/英寸) )。
非、耐克、偶、德克(毫米)
注意:以“XCHG”、“XADD”和“x”开头的所有指令都保证在多处理器系统中进行原子操作。 它们总是声明“锁定#”信号。 LOCK前缀的有无没有关系。
以下是原子操作的简单例子。
void _ fastcall原子_ Inc (volatile int * pnum ) { _ ASM _ ASM _ lockincdwordptr [ ecx ] ret } }
上,__fastcall关键字可以保证参数通过寄存器传递,从而提高原子指令的性能。
另外,linux内核有一组原子操作函数。 例如,其中之一:
satic _ inline _ void atomic _ add (整数,原子_ t * v ) ) ) ) ) ) ) ) )。) ) ) ) )但) ) ) ) ) ) ) ) ) ) ) ) )中) ) ) )。而
{
__asm__ __volatile__ (
锁定前缀'地址% 1,%0'
360 ' m ' (v -计数器) )。
();
}
在上面,LOCK_PREFIX宏定义了LOCK命令前缀,如#ifdef CONFIG_SMP
# #定义锁定_前缀
'.section .smp_locks,'a'n'
'.align 4n'
' .长661 fn '/*地址*/
' .预览 n '
' 661:ntlock;'
#else /*! 配置_ SMP * /
# #定义锁定_首选项'
# # endif
综上所述,在单处理器系统中,LOCK_PREFIX宏为空。 在这种情况下,不需要LOCK指令前缀,因此处理器如果可能的话,会将原子操作编译为单一的机器指令。
某些处理器(如P6系列、奔腾4系列和至强处理器)在锁定操作中可能不会声明锁定#信号。 从P6系列处理器开始,当处理器将通过LOCK指令访问的内存加载到高速缓存中时,通常不声明LOCK#信号。 相反,它只是锁定了处理器的缓存。 在这里,处理器缓存的相干性(coherency )机制保证了可以原子性地操作存储器。