加载中…
个人资料
行者无疆-超越
行者无疆-超越
  • 博客等级:
  • 博客积分:0
  • 博客访问:23,328
  • 关注人气:1
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
正文 字体大小:

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

(2014-02-13 14:57:06)
标签:

android

内存屏障

编译屏障

同步

it

分类: 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不对写内存的指令重新排序。所以不需要内存屏蔽指令。

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有