gcc 内联汇编实现一个 x86 上的原子加法操作

0, gcc 内联汇编的格式

0.1 GCC 内联汇编的格式:

asm (assemble template

              : output operands                    (optional)

              : input  operands                     (optional)

              : list of clobbered registers      (optional) );

例如:

读取

__asm__ __volatile__("rdtsc" : "=a"(low),"=d"(high))

x86 的RDTSC指令,是指 Real Time Stamp Counter 读取时间计数器的指令。
这个指令读取cpu时间计数器的值,返回一个unsigned 64bit 整数;
通过edx eax 寄存器返回 cpu 被引导后,时钟所走的圈数。这个指令可以用于测量两次调用之间的时间间隔;这里的代码将时间计数器的64bit值存储进了 edx:eax的组合中。

0.2 AT&T asm 的特点

1, 寄存器前边 加%   %eax

2, 源操作数与目的操作数的顺序: movl  src   dest

3,

movb  1byte

movw  2bytes 一个字

movl   4bytes  两个字

4, 立即数前边加$

movl $0xff77, %eax

5,内存间接引用加括号()

movb  (%esi), %al

0.3 gcc 内联汇编的语法变形

寄存器前边加两个 %

%%eax

未完再补。。。

 

1,先上代码

 __volatile__ 告诉编译器,不要对内部的asm代码做优化,原封不动地搬进程序中即可。

#include <iostream>
#include <omp.h>

int atomicAdd(int* ptr, int value) {
    int result;
    __asm__ __volatile__(
        "lock xaddl %0, %1\n"
        : "=r" (result), "=m" (*ptr)
        : "0" (value), "m" (*ptr)
        : "memory"
    );
    return result;
}

int main() {
    int sharedValue = 0;

    // 原子加法操作
//    int increment = 10;
#pragma omp parallel
{
        for(int i=0; i<900000; i++)
                atomicAdd(&sharedValue, 10);
                //atomicAdd(&sharedValue, increment);
}
    std::cout << "New value: " << sharedValue << std::endl;

    return 0;
}

Makefile:


EXE := hello_atomic
all: $(EXE)

%: %.cpp
	g++ -fopenmp $< -o $@


.PHONY: clean
clean:
	-rm -rf $(EXE)

2,实验运行效果

18核36线程,每个线程做1W次加法,没有加丢:

3,原理

        在 x86 架构的 CPU 中,原子操作通常是通过特殊的 CPU 指令来实现的,这些指令能够确保在多线程并发执行时,线程或进程使用这类指令对共享内存的操作是原子的,即不会被中断或打断。以下是一些常见的 x86 CPU 中用于实现原子操作的指令:


1. XCHG 指令:XCHG 指令用于交换内存中的值和寄存器中的值。在多线程编程中,可以使用 XCHG 指令来实现原子的读-修改-写操作。


2. CMPXCHG 指令:CMPXCHG 指令用于比较首操作数与 XAX的值,如果相等则将第二操作数的值复制给首操作数。这个指令通常用于实现原子的比较并交换操作(Compare and Swap)。


3. LOCK 前缀:LOCK 前缀可以与其他指令一起使用,用于将指令执行过程中的内存访问变为原子操作。例如,LOCK XCHG 或 LOCK CMPXCHG。


4. 内存屏障指令:MFENCE、SFENCE 和 LFENCE 指令用于确保内存操作的顺序性和可见性,以避免乱序执行带来的问题。


这些指令和前缀可以确保在多线程并发执行时,对共享内存的操作是原子的,从而避免竞态条件和数据不一致性问题。在编写并发程序时,可以利用这些原子操作来实现线程安全的共享内存访问。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值