Android中的编译屏障和内存屏障

现代 CPU中指令的执行次序并不一定严格按顺序执行的,没有相关性的指令可以打乱次序执行,以充分利用 CPU的指令流水线,提高执行速度。另外,编译器也会对指令进行优化,例如:调整指令顺序来利用CPU的指令流水线。这些优化方式,绝大部分情况工作的很好,但是在一些比较复杂的情况可能出问题,例如执行同步代码时就有可能因为这种优化导致同步原语之后的指令在同步原语前执行。内存屏障和编译屏障就是用来告诉CPU和编译器停止优化的方法。

编译屏障是使用伪指令“memory”告诉编译器不能把“memory”前后的代码混淆在一起,这时“memory”也起到一种优化屏障的作用。内存屏障是在代码中插入特殊指令,如arm中的dmbdsbisb指令,x86中的sfencelfencemfence指令。CPU遇到这些特殊指令,要等待前面指令执行完成了,才执行后面的指令。这些指令的作用好像是一道屏障把前后指令隔开,这样就防止了CPU把前后两段指令颠倒执行。

1.  arm平台的内存屏障指令

  •  dsb:数据同步屏障指令。它的作用是等待所有之前的指令完成后再执行后面的指令。
  • dmb:数据内存屏障指令。它的作用是等待前面访问内存的指令完成后再执行后面访问内存的指令。
  • isb:指令同步屏障。它的作用是等待流水线中所有指令执行完成后再执行后面的指令。

2.  x86平台上的内存屏障指令

  •  sfence:存储屏障指令。它的作用是等待前面写内存的指令完成后再执行后面写内存的指令。
  • lfence:读取屏障指令。它的作用是等待前面读取内存的指令完成后再执行后面读取内存的指令。
  •  mfence:混合屏障指令。它的作用是等待前面读写内存的指令完成后再执行后面读写内存的指令。

 

下面看看Android4.4中内存屏障和编译屏障函数是如何实现的:

1.   arm平台的版本:

1)       编译屏障:

void android_compiler_barrier()

{

    __asm__ __volatile__ ("" : : : "memory");

}

编译屏障的实现只是使用了伪指令memory

2)       内存屏障

void android_memory_barrier()

{

#if ANDROID_SMP == 0

    android_compiler_barrier();

#else

    __asm__ __volatile__ ("dmb" : : : "memory");

#endif

}

 

void android_memory_store_barrier()

{

#if ANDROID_SMP == 0

    android_compiler_barrier();

#else

    __asm__ __volatile__ ("dmb st" : : : "memory");

#endif

}

内存屏障的函数中使用了宏ANDROID_SMP。它的值为0表示是单CPU,这种情况下只使用编译屏障就可以了。在多CPU情况下,同时使用了内存屏障指令“dmb”,和编译屏障的伪指令“memory”。函数android_memory_store_barrier中的dmb指令使用了选项st,表示要等待前面所有存储内存的指令执行完后再执行后面的存储内存的指令。

2.  x86平台下的函数

1)        编译屏障:

void android_compiler_barrier(void)

{

    __asm__ __volatile__ ("" : : : "memory");

}

arm平台下一样,编译屏障的实现只是使用了伪指令memory

2)       内存屏障

#if ANDROID_SMP == 0

void android_memory_barrier(void)

{

    android_compiler_barrier();

}

 

void android_memory_store_barrier(void)

{

    android_compiler_barrier();

}

#else

void android_memory_barrier(void)

{

    __asm__ __volatile__ ("mfence" : : : "memory");

}

void android_memory_store_barrier(void)

{

    android_compiler_barrier();

}

#endif

x86平台也一样,如果是单CPU,内存屏障的实现只使用了编译屏障。在多CPU情况下,函数android_memory_barrier使用了内存屏障指令“mfence”,对读写内存的情况都进行了屏障。但是android_memory_store_barrier函数只使用了编译屏障,只是因为Intelcpu不对写内存的指令重新排序。所以不需要内存屏蔽指令。

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试