曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4679|回复: 0
打印 上一主题 下一主题

[Macro] barrier()

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2010-12-29 22:01:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
定义

#define barrier() __asm__ __volatile__("": : :"memory")

说明
__volatile__ 告诉编译器,严禁将此处的汇编语句与其它的语句重组合优化。即:原原本本按原来的样子处理这这里的汇编。

在内嵌汇编中,指令部分为空,输出位置为空,输入位置为空,但它用 memory 强制gcc编译器假设 RAM 所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将作废。cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存。。这个用法就是防止内存屏障

内核的 kernel/sched.c 中的 context_switch() 函数里有一处用法:

* Here we just switch the register state and the stack. */
switch_to(prev, next, prev);
barrier();
/*
* this_rq must be evaluated again because prev may have moved
* CPUs since it called schedule(), thus the 'rq' on its stack
* frame will be invalid.
*/
finish_task_switch(this_rq(), prev);

context_switch() 函数负责从当前进程切换到另一个进程环境,但当前进程需要修改某些内核数据结构,而这些修改也需要反映到另外一个进程中,因此这里插入 barrier()  ,以保证内存变量和对应的寄存器的一致。

switch_to 代码
#define switch_to(prev,next,last) do {     \
unsigned long esi,edi;      \
asm volatile("pushfl\n\t"  /* Save flags */ \
       "pushl %%ebp\n\t"     \
       "movl %%esp,%0\n\t" /* save ESP */  \
       "movl %5,%%esp\n\t" /* restore ESP */ \
       "movl $1f,%1\n\t"  /* save EIP */  \
       "pushl %6\n\t"  /* restore EIP */ \
       "jmp __switch_to\n"    \
       "1:\t"      \
       "popl %%ebp\n\t"     \
       "popfl"      \
       :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \     
        "=a" (last),"=S" (esi),"=D" (edi)   \
       :"m" (next->thread.esp),"m" (next->thread.eip), \
        "2" (prev), "d" (next));    \
} while (0)




补充:
CPU越过内存屏障后,将刷新自己对存储器的缓冲状态。这条语句(barrier())实际上不生成任何代码,但可使gcc在 barrier()之后刷新寄存器对变量的分配。 也就是说,barrier()宏只约束gcc编译器,不约束运行时的CPU行为。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-6 10:00 , Processed in 0.079162 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表