__asm__ __volatile__ ("" :: : "memory") 的工作 [英] Working of __asm__ __volatile__ ("" : : : "memory")

查看:30
本文介绍了__asm__ __volatile__ ("" :: : "memory") 的工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

__asm__ __volatile__ () 的基本作用是什么,内存" 对 ARM 架构有什么意义?

What basically __asm__ __volatile__ () does and what is significance of "memory" for ARM architecture?

推荐答案

asm volatile("" ::: "memory");

创建编译器级别的内存屏障,强制优化器不重新排序跨屏障的内存访问.

creates a compiler level memory barrier forcing optimizer to not re-order memory accesses across the barrier.

例如,如果您需要以特定顺序访问某个地址(可能是因为该内存区域实际上由不同的设备而不是内存支持),您需要能够将此告诉编译器,否则它可能只是优化您的步骤是为了效率.

For example, if you need to access some address in a specific order (probably because that memory area is actually backed by a different device rather than a memory) you need to be able tell this to the compiler otherwise it may just optimize your steps for the sake of efficiency.

假设在这种情况下,您必须在地址中增加一个值,读取某些内容并在相邻地址中增加另一个值.

Assume in this scenario you must increment a value in address, read something and increment another value in an adjacent address.

int c(int *d, int *e) {
        int r;
        d[0] += 1;
        r = e[0];
        d[1] += 1;
        return r;
}

问题是编译器(在本例中为gcc)可以重新安排您的内存访问以获得更好的性能(-O).可能会导致如下指令序列:

Problem is compiler (gcc in this case) can rearrange your memory access to get better performance if you ask for it (-O). Probably leading to a sequence of instructions like below:

00000000 <c>:
   0:   4603        mov r3, r0
   2:   c805        ldmia   r0, {r0, r2}
   4:   3001        adds    r0, #1
   6:   3201        adds    r2, #1
   8:   6018        str r0, [r3, #0]
   a:   6808        ldr r0, [r1, #0]
   c:   605a        str r2, [r3, #4]
   e:   4770        bx  lr

同时加载 d[0]d[1] 的上述值.让我们假设这是您想要避免的事情,然后您需要告诉编译器不要重新排序内存访问,即使用 asm volatile("" ::: "memory").

Above values for d[0] and d[1] are loaded at the same time. Lets assume this is something you want to avoid then you need to tell compiler not to reorder memory accesses and that is to use asm volatile("" ::: "memory").

int c(int *d, int *e) {
        int r;
        d[0] += 1;
        r = e[0];
        asm volatile("" ::: "memory");
        d[1] += 1;
        return r;
}

所以你会得到你想要的指令序列:

So you'll get your instruction sequence as you want it to be:

00000000 <c>:
   0:   6802        ldr r2, [r0, #0]
   2:   4603        mov r3, r0
   4:   3201        adds    r2, #1
   6:   6002        str r2, [r0, #0]
   8:   6808        ldr r0, [r1, #0]
   a:   685a        ldr r2, [r3, #4]
   c:   3201        adds    r2, #1
   e:   605a        str r2, [r3, #4]
  10:   4770        bx  lr
  12:   bf00        nop

应该注意,这只是编译时内存屏障,以避免编译器重新排序内存访问,因为它没有放置额外的硬件级指令来刷新内存或等待加载或存储完成.如果 CPU 具有架构能力并且内存地址为 normal 类型而不是 stronglyordereddevice(ref).

It should be noted that this is only compile time memory barrier to avoid compiler to reorder memory accesses, as it puts no extra hardware level instructions to flush memories or wait for load or stores to be completed. CPUs can still reorder memory accesses if they have the architectural capabilities and memory addresses are on normal type instead of strongly ordered or device (ref).

这篇关于__asm__ __volatile__ ("" :: : "memory") 的工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆