CherieLi Student

x86和arm架构原子操作原理

2019-10-08
CherieLi

CPU指令集分为两种:

CISC:复杂指令集,指令多,功能多,一条指令可以完成很复杂的逻辑或者算数运算。

RISC:简单指令集,指令少,功能也少,但是基本上都是常用的指令,对于复杂的问题,需要通过N多个条指令才能完成,执行效率没有CISC高。

x86架构基于CISC,arm架构基于RISC。

1.X86架构

1.1 单处理器

在单处理器系统中,中断只会发生在指令与指令之间,能够在单条指令中完成的操作都可以认为是原子操作。X86使用CISC指令集,允许在一条指令里进行两次内存操作,因此,对于i++,i–这类操作在单处理器中可视为原子操作(必须显示使用addl r,%1命令)。

1.2 多处理器

在多处理器系统中,多个处理器独立运行,在单条指令中能完成的操作也可能受到干扰,这种情况下,CPU提供了在指令执行期间对总线加锁的手段,使得同一总线上别的CPU就暂时不能通过总线访问内存了,保证了这条指令在多处理器环境中的原子性。

实现时使用了C内嵌汇编语言。

内嵌汇编语法:

__asm__:内嵌汇编关键字,告知编译器下述语句为汇编代码
__volatile__:告知编译器不要优化(比如重组优化)下述汇编语句

变量列表中常见符号:

“+”:操作数可读可写

“=”: 操作数只写

“&”:常用于输出操作,表示输出操作不能使用输入操作使用过的寄存器,只能+&或=&方式使用

“r”: 操作数是任何可用的通用寄存器

“m”: 操作数是内存变量

“p”: 操作数是一个合法的内存地址

“l”: 操作数是立即数

“Q”: A memory address which uses a single base register with no offset

“V”: 操作数是内存变量,但其寻址方式非偏移量类型

static __inline__ void atomic_ad(int i, atomic_t *v)
{
    __asm__ __volatile__(
    	LOCK “addl %1,%0”
    	:"+m" (v->counter)
    	:"ir" (i),"m"(v->counter));
}

0% —–i

1% —–v->counter

2.ARM架构

1.1 单处理器

ARM使用RISC指令集,在一次指令执行期间只能有一次内存操作,因此在单处理器系统中,i++, i–等也不能视为原子操作,ARM使用关中断来实现原子操作。

1.2 多处理器

1.2.1 实现

在ARM多核处理器中,使用专门的指令ldrex和strex实现原子操作。

static inline int atomic_add_return(int i, atomic_t *v)
{
    unsigned long tmp;
    int result;
    __asm__ __volatile__("@ atomic_add_return\n"
          "1: ldrex %0, [%3]\n"
          "   add %0,%0,%4\n"
          "   strex  %1,%0,[%3]\n"
          "   teq %1, #0\n"
          "   bne 1b"
          : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
          : "r" (&v->counter), "Ir"(i)
          : "cc");
     return result;
}

%0 —— result

%1 —— tmp

%3 —— v->counter的地址

%4 —– i

(1)ldrex %0,[%3]

独占式地加载(Load-Exclusive)v->counter的地址,把它的值放到result中,并更新exclusive monitor(s)

用C描述就是:

result = v->counter

(2)add %0,%0,%4

result = result + i

(3) strex %1, %0, [%3]

独占式地保存(Store-Exclusive)数据至v->counter的地址,数据来自result, 操作结果(成功/失败)保存在tmp中

“cc”是一个特殊的参数,用来标明汇报代码会修改标志寄存器(flags register),在某些机器平台上,GCC通过一个特殊的硬件寄存器表征条件类型的代码,“cc”就是这个特殊寄存器的名字,某些机器平台没有上述功能,“cc”会被忽略,不起作用。

1.2.2 多线程原子操作


下一篇 google benchmark

Comments

Content