- 浏览: 208903 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
Prepared:
Hadoop的几个明显缺点 -
CSunDNan:
...
openjdk jvm 方法字节码执行过程 -
幻影之蚀:
...
mysql 源码分析2 源码调试环境建立 -
shukongchengje:
紧急呼唤楼主,mysql代码从哪里弄?官网wiki上看的一头雾 ...
mysql源码分析 整体架构 -
yeshaoting:
好文章.不介意的话转载了.
jvm 字节码中文含义
来自于在CU的一个讨论:
http://linux.chinaunix.net/bbs/thread-713279-1-1.html
讨论完了给一个总结,有些话是别人说的,有的还是clf的网友的,为了不使文档显得杂乱,都不具名了。
欢迎批评指正!
内核中定义的内存屏障原语有:
#define barrier() __asm__ __volatile__("": : :"memory")
#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
#ifdef CONFIG_SMP
#define smp_mb() mb()
#define smp_rmb() rmb()
#define smp_wmb() wmb()
#define smp_read_barrier_depends() read_barrier_depends()
#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
#else
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#define smp_read_barrier_depends() do { } while(0)
#define set_mb(var, value) do { var = value; barrier(); } while (0)
#endif
1). smp_xxx()和xxx()的区别
为了给其它CPU也提供相关的barrier宏。 例如x86的rmb()是用了lfence指令,但其它CPU不能用这个指令。
2). 关于barrier()宏,jkl大师是这么说的:
CPU越过内存屏障后,将刷新自己对存储器的缓冲状态。这条语句实际上不生成任何代码,但可使gcc在
barrier()之后刷新寄存器对变量的分配。
也就是说,barrier()宏只约束gcc编译器,不约束运行时的CPU行为。 举例:
1 int a = 5, b = 6;
2 barrier();
3 a = b;
在line 3,GCC不会用存放b的寄存器给a赋值,而是invalidate b的Cache line,重新读内存中的b值,赋值给a。
3). mb() vs. rmb() vs. wmb()
rmb()不允许读操作穿过内存屏障;wmb()不允许写操作穿过屏障;而mb()二者都不允许。
看IA32上wmb()的定义:
#ifdef CONFIG_X86_OOSTORE
#define wmb() alternative("lock;addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM);
#else
#define wmb() __asm__ __volatile__ ("": : :"memory");
#endif
Intel和AMD都没有在IA32 CPU中实现乱序写(Out-Of-Order Store),所以wmb()定义为空操作,不约束CPU行为;但
有些IA32 CPU厂商实现了OOO Store,所以就有了使用sfence的那个wmb()实现。
4). 内存屏障的体系结构语义
4.1) 只有一个主体(CPU或DMA控制器)访问内存时,无论如何也不需要barrier;但如果有两个或更多主体访问内存,且
其中有一个在观测另一个,就需要barrier了。
4.2) IA32 CPU调用有lock前缀的指令,或者如xchg这样的指令,会导致其它的CPU也触发一定的动作来同步自己的Cache。
CPU的#lock引脚链接到北桥芯片(North Bridge)的#lock引脚,当带lock前缀的执行执行时,北桥芯片会拉起#lock
电平,从而锁住总线,直到该指令执行完毕再放开。 而总线加锁会自动invalidate所有CPU对 _该指令涉及的内存_
的Cache,因此barrier就能保证所有CPU的Cache一致性。
4.3) 接着解释。
lock前缀(或cpuid、xchg等指令)使得本CPU的Cache写入了内存,该写入动作也会引起别的CPU invalidate其Cache。
IA32在每个CPU内部实现了Snoopying(BUS-Watching)技术,监视着总线上是否发生了写内存操作(由某个CPU或DMA控
制器发出的),只要发生了,就invalidate相关的Cache line。 因此,只要lock前缀导致本CPU写内存,就必将导致
所有CPU去invalidate其相关的Cache line。
两个地方可能除外:
-> 如果采用write-through策略,则根本不存在缓存一致性问题(Linux对全部内存采用write-back策略);
-> TLB也是Cache,但它的一致性(至少在IA32上)不能通过Snoopying技术解决,而是要发送
INVALIDATE_TLB_VECTOR这个IPI给其它的CPU。
4.4) 进一步解释,MESI协议
包括IA32的许多体系结构的CPU,为了保证缓存一致性,实现了MESI协议。
M: Modified,已修改
E: Exclusive,排他
S: Shared,共享
I: Invalid,无效
IA32 的CPU实现了MESI协议来保证Cache coherence。 CPU的总线监测单元,始终监视着总线上所有的内存写操作,
以便随时调整自己的Cache状态。
-> Modified。 本CPU写,则直接写到Cache,不产生总线事物;其它CPU写,则不涉及本CPU的Cache,其它CPU
读,则本CPU需要把Cache line中的数据提供给它,而不是让它去读内存。
-> Exclusive。只有本CPU有该内存的Cache,而且和内存一致。 本CPU的写操作会导致转到Modified状态。
-> Shared。 多个CPU都对该内存有Cache,而且内容一致。任何一个CPU写自己的这个Cache都必须通知其它
的CPU。
-> Invalid。 一旦Cache line进入这个状态,CPU读数据就必须发出总线事物,从内存读。
5) 考虑到DMA
5.1). Wirte through策略。 这种情形比较简单。
-> 本CPU写内存,是write through的,因此无论什么时候DMA读内存,读到的都是正确数据。
-> DMA写内存,如果DMA要写的内存被本CPU缓存了,那么必须Invalidate这个Cache line。下次CPU读它,就
直接从内存读。
5.2). Write back策略。 这种情形相当复杂。
-> DMA读内存。被本CPU总线监视单元发现,而且本地Cache中有Modified数据,本CPU就截获DMA的内存读操作,
把自己Cache Line中的数据返回给它。
-> DMA写内存。而且所写的位置在本CPU的Cache中,这又分两种情况:
a@ Cache Line状态未被CPU修改过(即cache和内存一致),那么invalidate该cache line。
b@ Cache Line状态已经被修改过,又分2种情况:
<1> DMA写操作会替换CPU Cache line所对应的整行内存数据,那么DMA写,CPU则invalidate
自己的Cache Line。
<2> DMA写操作只替换Cache Line对应的内存数据的一部分,那么CPU必须捕获DMA写操作的新
数据(即DMA想把它写入内存的),用来更新Cache Line的相关部分。
----
天吖度绱耍疫M杯中物!
[Original] [Print] [Top]
Subject: [精华] Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-07-25 12:12 Length: 25 byte(s)
[Original] [Print] [Top]
毛哥书的下册SMP有介绍啊。
----
kscope 很好用的。和source insight 差不多了 。
[Original] [Print] [Top]
Subject: [精华] Re: 尝试总结memory barrier
Author: leviathan Posted: 2007-07-25 18:21 Length: 31 byte(s)
[Original] [Print] [Top]
《情景分析》讲barrier部分太少了
----
天吖度绱耍疫M杯中物!
[Original] [Print] [Top]
Subject: [精华] Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-07-25 19:06 Length: 47 byte(s)
[Original] [Print] [Top]
呵呵,这个东西,讨论来讨论去就会到BNN的地盘了。
----
kscope 很好用的。和source insight 差不多了 。
[Original] [Print] [Top]
Subject: [精华] Re: 尝试总结memory barrier
Author: wheelz Posted: 2007-07-25 19:19 Length: 50 byte(s)
[Original] [Print] [Top]
内核Documentation下有一篇非常好的文档.可以作为补充
----
http://www.kernelchina.org/
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: sky3452 Posted: 2007-07-26 10:21 Length: 14 byte(s)
[Original] [Print] [Top]
好文,受益匪浅
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: leviathan Posted: 2007-07-26 12:31 Length: 166 byte(s)
[Original] [Print] [Top]
才看到,谢谢:) 这个文档估计就是去年他们的讨论结果,居然有2k多行
主楼不能排版,一排版就出乱码,在这层上传个txt试试:)
----
天吖度绱耍疫M杯中物!
--
Attached file: 653878-%B3%A2%CA%D4%D7%DC%BD%E1memory%20barrier.txt.gz
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-10-12 12:03 Length: 335 byte(s)
[Original] [Print] [Top]
“在line 3,GCC不会用存放b的寄存器给a赋值,而是invalidate b的Cache line,重新读内存中的b值,赋值给a。”
感觉这个是不对的。上面都说了“barrier()宏只约束gcc编译器,不约束运行时的CPU行为”,
而invalidate Cache line要调用wbinvd命令,我对GCC的代码进行grep 没有发现使用wbinvd的地方。
----
应用程序是LINUX的软肋。
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-10-12 13:18 Length: 1,661 byte(s)
[Original] [Print] [Top]
“
4.2) IA32
CPU调用有lock前缀的指令,或者如xchg这样的指令,会导致其它的CPU也触发一定的动作来同步自
己的Cache。
CPU的#lock引脚链接到北桥芯片(North
Bridge)的#lock引脚,当带lock前缀的执行执行时,北桥芯片会拉起#lock
电平,从而锁住总线,直到该指令执行完毕再放开。 而总线加锁会自动invalidate所有CPU对
_该指令涉及的内存_
的Cache,因此barrier就能保证所有CPU的Cache一致性。 ”
总线加锁的功能是保证程序执行的顺序不乱掉,
一旦加LOCK指令了,CPU会将此指令前的读写操作都串行完成,这最主要的作用是使CPU的预取等无
效了。
在这个串行操作中,MESI协议会起作用。
但保证所有CPU的Cache一致性的是MESI协议,这是硬件上保证的。
barrier是对GCC编译器做约束,是软件层次上的。
“因此barrier就能保证所有CPU的Cache一致性”这种说法是不对的。
“4.3) 接着解释。
lock前缀(或cpuid、xchg等指令)使得本CPU的Cache写入了内存,该写入动作也会引起别的CPU
invalidate其Cache。
IA32在每个CPU内部实现了Snoopying(BUS-Watching)技术,监视着总线上是否发生了写内存操作(?
赡掣鯟PU或DMA控
制器发出的),只要发生了,就invalidate相关的Cache line。
因此,只要lock前缀导致本CPU写内存,就必将导致
所有CPU去invalidate其相关的Cache line。 ”
lock指令保证程序执行的顺序不乱掉,没有将“本CPU的Cache写入了内存”的功能。
总线监视功能是由各个CPU的CACHE完成的,
这个功能可以算是MESI协议的实现。MESI保证了SMP下的CACHE一致性。
----
应用程序是LINUX的软肋。
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-10-12 13:34 Length: 632 byte(s)
[Original] [Print] [Top]
memory barrier的实质是对内存的操作施加顺序上的约束。
Memory barrier, also known as membar or memory fence, is a class of instructions which
cause a central processing unit (CPU) to enforce an ordering constraint on memory
operations issued before and after the barrier instruction.
上文源于:http://www.answers.com/topic/memory-barrier
至于“SMP情况下CACHE的一致性”只是memory
barrier在执行lock,sfence,lfence等指令时的副作用 !!!!,
“SMP情况下CACHE的一致性”是由MESI来做的。
----
应用程序是LINUX的软肋。
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: leviathan Posted: 2007-10-12 14:29 Length: 257 byte(s)
[Original] [Print] [Top]
这里的说法的确有问题,应该修正为:
“在line 3,GCC不会用存放b的寄存器给a赋值,而是读内存中的b值,赋值给a。”
至于读内存中的b是否会引发cache invalidate,那就是CPU的事了。
谢谢指正。
----
天吖度绱耍疫M杯中物!
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-10-13 17:13 Length: 230 byte(s)
[Original] [Print] [Top]
"一旦加LOCK指令了,CPU会将此指令前的读写操作都串行完成,这最主要的作用是使CPU的预取等无效了。"
仔细看了一下INTEL的手册,LOCK不能使CPU的预取无效,所以这句是不对的。CPUID这种串行语句才会使CPU的预取无效。
----
应用程序是LINUX的软肋。
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: crspo Posted: 2007-10-20 12:27 Length: 427 byte(s)
[Original] [Print] [Top]
这个问题与体系结构密切相关
首先要明白cache coherence能解决什么问题?
coherence与consistency的区别?
在IA-32上 rmb()/wmb()/mb() 与在多处理器下IA-32遵循的Processor Consistency密切相关,
大家不但可以参考IA-32的手册,有兴趣的话可以参考一下AMD64的手册,那里的解释更完善.
另外wmb()/MFENCE的语义与体系结构中的write buffer/write-combining buffer功能和作用密切相关.
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: asand Posted: 2007-10-22 16:23 Length: 3,194 byte(s)
[Original] [Print] [Top]
4.1) 只有一个主体(CPU或DMA控制器)访问内存时,无论如何也不需要barrier;但如果有两个或更多主体访问内存,且
其中有一个在观测另一个,就需要barrier了
这个好像不大对吧?下面的文字来自<<LDD3>>
I/O 寄存器和常规内存
不管硬件寄存器和内存之间的强相似性, 存取 I/O 寄存器的程序员必须小心避免被 CPU(或者编译器)优化所戏弄, 它可能修改希望的 I/O 行为.
I/O 寄存器和 RAM 的主要不同是 I/O 操作有边际效果, 而内存操作没有: 一个内存写的唯一效果是存储一个值到一个位置, 并且一个内存读返回最近写到那里的值. 因为内存存取速度对 CPU 性能是至关重要的, 这种无边际效果的情况已被多种方式优化: 值被缓存, 并且 读/写指令被重编排.
编译器能够缓存数据值到 CPU 寄存器而不写到内存, 并且即便它存储它们, 读和写操作都能够在缓冲内存中进行而不接触物理 RAM. 重编排也可能在编译器级别和在硬件级别都发生: 常常一个指令序列能够执行得更快, 如果它以不同于在程序文本中出现的顺序来执行, 例如, 为避免在 RISC 流水线中的互锁. 在CISC 处理器, 要花费相当数量时间的操作能够和其他的并发执行, 更快的.
当应用于传统内存时(至少在单处理器系统)这些优化是透明和有益的, 但是它们可能对正确的 I/O 操作是致命的, 因为它们干扰了那些"边际效果", 这是主要的原因为什么一个驱动存取 I/O 寄存器. 处理器无法预见这种情形, 一些其他的操作(在一个独立处理器上运行, 或者发生在一个 I/O 控制器的事情)依赖内存存取的顺序. 编译器或者 CPU 可能只尽力胜过你并且重编排你请求的操作; 结果可能是奇怪的错误而非常难于调试. 因此, 一个驱动必须确保没有进行缓冲并且在存取寄存器时没有发生读或写的重编排.
硬件缓冲的问题是最易面对的:底层的硬件已经配置(或者自动地或者通过 Linux 初始化代码)成禁止任何硬件缓冲, 当存取 I/O 区时(不管它们是内存还是端口区域).
对编译器优化和硬件重编排的解决方法是安放一个内存屏障在必须以一个特殊顺序对硬件(或者另一个处理器)可见的操作之间. Linux 提供 4 个宏来应对可能的排序需要:
#include <linux/kernel.h>
void barrier(void)
这个函数告知编译器插入一个内存屏障但是对硬件没有影响. 编译的代码将所有的当前改变的并且驻留在 CPU 寄存器的值存储到内存, 并且后来重新读取它们当需要时. 对屏障的调用阻止编译器跨越屏障的优化, 而留给硬件自由做它的重编排.
#include <asm/system.h>
void rmb(void);
void read_barrier_depends(void);
void wmb(void);
void mb(void);
这些函数插入硬件内存屏障在编译的指令流中; 它们的实际实例是平台相关的. 一个 rmb ( read memory barrier) 保证任何出现于屏障前的读在执行任何后续读之前完成. wmb 保证写操作中的顺序, 并且 mb 指令都保证. 每个这些指令是一个屏障的超集.
read_barrier_depends 是读屏障的一个特殊的, 弱些的形式. 而 rmb 阻止所有跨越屏障的读的重编排, read_barrier_depends 只阻止依赖来自其他读的数据的读的重编排. 区别是微小的, 并且它不在所有体系中存在. 除非你确切地理解做什么, 并且你有理由相信, 一个完整的读屏障确实是一个过度地性能开销, 你可能应当坚持使用 rmb.
void smp_rmb(void);
void smp_read_barrier_depends(void);
void smp_wmb(void);
void smp_mb(void);
屏障的这些版本仅当内核为 SMP 系统编译时插入硬件屏障; 否则, 它们都扩展为一个简单的屏障调用.
[Original] [Print] [Top]
« Previous thread
应用层要支持connect函数的正确连接,2.6内核make menuconfig需哪些选项支持?
http://linux.chinaunix.net/bbs/thread-713279-1-1.html
讨论完了给一个总结,有些话是别人说的,有的还是clf的网友的,为了不使文档显得杂乱,都不具名了。
欢迎批评指正!
内核中定义的内存屏障原语有:
#define barrier() __asm__ __volatile__("": : :"memory")
#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
#ifdef CONFIG_SMP
#define smp_mb() mb()
#define smp_rmb() rmb()
#define smp_wmb() wmb()
#define smp_read_barrier_depends() read_barrier_depends()
#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
#else
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#define smp_read_barrier_depends() do { } while(0)
#define set_mb(var, value) do { var = value; barrier(); } while (0)
#endif
1). smp_xxx()和xxx()的区别
为了给其它CPU也提供相关的barrier宏。 例如x86的rmb()是用了lfence指令,但其它CPU不能用这个指令。
2). 关于barrier()宏,jkl大师是这么说的:
CPU越过内存屏障后,将刷新自己对存储器的缓冲状态。这条语句实际上不生成任何代码,但可使gcc在
barrier()之后刷新寄存器对变量的分配。
也就是说,barrier()宏只约束gcc编译器,不约束运行时的CPU行为。 举例:
1 int a = 5, b = 6;
2 barrier();
3 a = b;
在line 3,GCC不会用存放b的寄存器给a赋值,而是invalidate b的Cache line,重新读内存中的b值,赋值给a。
3). mb() vs. rmb() vs. wmb()
rmb()不允许读操作穿过内存屏障;wmb()不允许写操作穿过屏障;而mb()二者都不允许。
看IA32上wmb()的定义:
#ifdef CONFIG_X86_OOSTORE
#define wmb() alternative("lock;addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM);
#else
#define wmb() __asm__ __volatile__ ("": : :"memory");
#endif
Intel和AMD都没有在IA32 CPU中实现乱序写(Out-Of-Order Store),所以wmb()定义为空操作,不约束CPU行为;但
有些IA32 CPU厂商实现了OOO Store,所以就有了使用sfence的那个wmb()实现。
4). 内存屏障的体系结构语义
4.1) 只有一个主体(CPU或DMA控制器)访问内存时,无论如何也不需要barrier;但如果有两个或更多主体访问内存,且
其中有一个在观测另一个,就需要barrier了。
4.2) IA32 CPU调用有lock前缀的指令,或者如xchg这样的指令,会导致其它的CPU也触发一定的动作来同步自己的Cache。
CPU的#lock引脚链接到北桥芯片(North Bridge)的#lock引脚,当带lock前缀的执行执行时,北桥芯片会拉起#lock
电平,从而锁住总线,直到该指令执行完毕再放开。 而总线加锁会自动invalidate所有CPU对 _该指令涉及的内存_
的Cache,因此barrier就能保证所有CPU的Cache一致性。
4.3) 接着解释。
lock前缀(或cpuid、xchg等指令)使得本CPU的Cache写入了内存,该写入动作也会引起别的CPU invalidate其Cache。
IA32在每个CPU内部实现了Snoopying(BUS-Watching)技术,监视着总线上是否发生了写内存操作(由某个CPU或DMA控
制器发出的),只要发生了,就invalidate相关的Cache line。 因此,只要lock前缀导致本CPU写内存,就必将导致
所有CPU去invalidate其相关的Cache line。
两个地方可能除外:
-> 如果采用write-through策略,则根本不存在缓存一致性问题(Linux对全部内存采用write-back策略);
-> TLB也是Cache,但它的一致性(至少在IA32上)不能通过Snoopying技术解决,而是要发送
INVALIDATE_TLB_VECTOR这个IPI给其它的CPU。
4.4) 进一步解释,MESI协议
包括IA32的许多体系结构的CPU,为了保证缓存一致性,实现了MESI协议。
M: Modified,已修改
E: Exclusive,排他
S: Shared,共享
I: Invalid,无效
IA32 的CPU实现了MESI协议来保证Cache coherence。 CPU的总线监测单元,始终监视着总线上所有的内存写操作,
以便随时调整自己的Cache状态。
-> Modified。 本CPU写,则直接写到Cache,不产生总线事物;其它CPU写,则不涉及本CPU的Cache,其它CPU
读,则本CPU需要把Cache line中的数据提供给它,而不是让它去读内存。
-> Exclusive。只有本CPU有该内存的Cache,而且和内存一致。 本CPU的写操作会导致转到Modified状态。
-> Shared。 多个CPU都对该内存有Cache,而且内容一致。任何一个CPU写自己的这个Cache都必须通知其它
的CPU。
-> Invalid。 一旦Cache line进入这个状态,CPU读数据就必须发出总线事物,从内存读。
5) 考虑到DMA
5.1). Wirte through策略。 这种情形比较简单。
-> 本CPU写内存,是write through的,因此无论什么时候DMA读内存,读到的都是正确数据。
-> DMA写内存,如果DMA要写的内存被本CPU缓存了,那么必须Invalidate这个Cache line。下次CPU读它,就
直接从内存读。
5.2). Write back策略。 这种情形相当复杂。
-> DMA读内存。被本CPU总线监视单元发现,而且本地Cache中有Modified数据,本CPU就截获DMA的内存读操作,
把自己Cache Line中的数据返回给它。
-> DMA写内存。而且所写的位置在本CPU的Cache中,这又分两种情况:
a@ Cache Line状态未被CPU修改过(即cache和内存一致),那么invalidate该cache line。
b@ Cache Line状态已经被修改过,又分2种情况:
<1> DMA写操作会替换CPU Cache line所对应的整行内存数据,那么DMA写,CPU则invalidate
自己的Cache Line。
<2> DMA写操作只替换Cache Line对应的内存数据的一部分,那么CPU必须捕获DMA写操作的新
数据(即DMA想把它写入内存的),用来更新Cache Line的相关部分。
----
天吖度绱耍疫M杯中物!
[Original] [Print] [Top]
Subject: [精华] Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-07-25 12:12 Length: 25 byte(s)
[Original] [Print] [Top]
毛哥书的下册SMP有介绍啊。
----
kscope 很好用的。和source insight 差不多了 。
[Original] [Print] [Top]
Subject: [精华] Re: 尝试总结memory barrier
Author: leviathan Posted: 2007-07-25 18:21 Length: 31 byte(s)
[Original] [Print] [Top]
《情景分析》讲barrier部分太少了
----
天吖度绱耍疫M杯中物!
[Original] [Print] [Top]
Subject: [精华] Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-07-25 19:06 Length: 47 byte(s)
[Original] [Print] [Top]
呵呵,这个东西,讨论来讨论去就会到BNN的地盘了。
----
kscope 很好用的。和source insight 差不多了 。
[Original] [Print] [Top]
Subject: [精华] Re: 尝试总结memory barrier
Author: wheelz Posted: 2007-07-25 19:19 Length: 50 byte(s)
[Original] [Print] [Top]
内核Documentation下有一篇非常好的文档.可以作为补充
----
http://www.kernelchina.org/
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: sky3452 Posted: 2007-07-26 10:21 Length: 14 byte(s)
[Original] [Print] [Top]
好文,受益匪浅
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: leviathan Posted: 2007-07-26 12:31 Length: 166 byte(s)
[Original] [Print] [Top]
才看到,谢谢:) 这个文档估计就是去年他们的讨论结果,居然有2k多行
主楼不能排版,一排版就出乱码,在这层上传个txt试试:)
----
天吖度绱耍疫M杯中物!
--
Attached file: 653878-%B3%A2%CA%D4%D7%DC%BD%E1memory%20barrier.txt.gz
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-10-12 12:03 Length: 335 byte(s)
[Original] [Print] [Top]
“在line 3,GCC不会用存放b的寄存器给a赋值,而是invalidate b的Cache line,重新读内存中的b值,赋值给a。”
感觉这个是不对的。上面都说了“barrier()宏只约束gcc编译器,不约束运行时的CPU行为”,
而invalidate Cache line要调用wbinvd命令,我对GCC的代码进行grep 没有发现使用wbinvd的地方。
----
应用程序是LINUX的软肋。
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-10-12 13:18 Length: 1,661 byte(s)
[Original] [Print] [Top]
“
4.2) IA32
CPU调用有lock前缀的指令,或者如xchg这样的指令,会导致其它的CPU也触发一定的动作来同步自
己的Cache。
CPU的#lock引脚链接到北桥芯片(North
Bridge)的#lock引脚,当带lock前缀的执行执行时,北桥芯片会拉起#lock
电平,从而锁住总线,直到该指令执行完毕再放开。 而总线加锁会自动invalidate所有CPU对
_该指令涉及的内存_
的Cache,因此barrier就能保证所有CPU的Cache一致性。 ”
总线加锁的功能是保证程序执行的顺序不乱掉,
一旦加LOCK指令了,CPU会将此指令前的读写操作都串行完成,这最主要的作用是使CPU的预取等无
效了。
在这个串行操作中,MESI协议会起作用。
但保证所有CPU的Cache一致性的是MESI协议,这是硬件上保证的。
barrier是对GCC编译器做约束,是软件层次上的。
“因此barrier就能保证所有CPU的Cache一致性”这种说法是不对的。
“4.3) 接着解释。
lock前缀(或cpuid、xchg等指令)使得本CPU的Cache写入了内存,该写入动作也会引起别的CPU
invalidate其Cache。
IA32在每个CPU内部实现了Snoopying(BUS-Watching)技术,监视着总线上是否发生了写内存操作(?
赡掣鯟PU或DMA控
制器发出的),只要发生了,就invalidate相关的Cache line。
因此,只要lock前缀导致本CPU写内存,就必将导致
所有CPU去invalidate其相关的Cache line。 ”
lock指令保证程序执行的顺序不乱掉,没有将“本CPU的Cache写入了内存”的功能。
总线监视功能是由各个CPU的CACHE完成的,
这个功能可以算是MESI协议的实现。MESI保证了SMP下的CACHE一致性。
----
应用程序是LINUX的软肋。
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-10-12 13:34 Length: 632 byte(s)
[Original] [Print] [Top]
memory barrier的实质是对内存的操作施加顺序上的约束。
Memory barrier, also known as membar or memory fence, is a class of instructions which
cause a central processing unit (CPU) to enforce an ordering constraint on memory
operations issued before and after the barrier instruction.
上文源于:http://www.answers.com/topic/memory-barrier
至于“SMP情况下CACHE的一致性”只是memory
barrier在执行lock,sfence,lfence等指令时的副作用 !!!!,
“SMP情况下CACHE的一致性”是由MESI来做的。
----
应用程序是LINUX的软肋。
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: leviathan Posted: 2007-10-12 14:29 Length: 257 byte(s)
[Original] [Print] [Top]
这里的说法的确有问题,应该修正为:
“在line 3,GCC不会用存放b的寄存器给a赋值,而是读内存中的b值,赋值给a。”
至于读内存中的b是否会引发cache invalidate,那就是CPU的事了。
谢谢指正。
----
天吖度绱耍疫M杯中物!
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: zyzii Posted: 2007-10-13 17:13 Length: 230 byte(s)
[Original] [Print] [Top]
"一旦加LOCK指令了,CPU会将此指令前的读写操作都串行完成,这最主要的作用是使CPU的预取等无效了。"
仔细看了一下INTEL的手册,LOCK不能使CPU的预取无效,所以这句是不对的。CPUID这种串行语句才会使CPU的预取无效。
----
应用程序是LINUX的软肋。
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: crspo Posted: 2007-10-20 12:27 Length: 427 byte(s)
[Original] [Print] [Top]
这个问题与体系结构密切相关
首先要明白cache coherence能解决什么问题?
coherence与consistency的区别?
在IA-32上 rmb()/wmb()/mb() 与在多处理器下IA-32遵循的Processor Consistency密切相关,
大家不但可以参考IA-32的手册,有兴趣的话可以参考一下AMD64的手册,那里的解释更完善.
另外wmb()/MFENCE的语义与体系结构中的write buffer/write-combining buffer功能和作用密切相关.
[Original] [Print] [Top]
Subject: Re: 尝试总结memory barrier
Author: asand Posted: 2007-10-22 16:23 Length: 3,194 byte(s)
[Original] [Print] [Top]
4.1) 只有一个主体(CPU或DMA控制器)访问内存时,无论如何也不需要barrier;但如果有两个或更多主体访问内存,且
其中有一个在观测另一个,就需要barrier了
这个好像不大对吧?下面的文字来自<<LDD3>>
I/O 寄存器和常规内存
不管硬件寄存器和内存之间的强相似性, 存取 I/O 寄存器的程序员必须小心避免被 CPU(或者编译器)优化所戏弄, 它可能修改希望的 I/O 行为.
I/O 寄存器和 RAM 的主要不同是 I/O 操作有边际效果, 而内存操作没有: 一个内存写的唯一效果是存储一个值到一个位置, 并且一个内存读返回最近写到那里的值. 因为内存存取速度对 CPU 性能是至关重要的, 这种无边际效果的情况已被多种方式优化: 值被缓存, 并且 读/写指令被重编排.
编译器能够缓存数据值到 CPU 寄存器而不写到内存, 并且即便它存储它们, 读和写操作都能够在缓冲内存中进行而不接触物理 RAM. 重编排也可能在编译器级别和在硬件级别都发生: 常常一个指令序列能够执行得更快, 如果它以不同于在程序文本中出现的顺序来执行, 例如, 为避免在 RISC 流水线中的互锁. 在CISC 处理器, 要花费相当数量时间的操作能够和其他的并发执行, 更快的.
当应用于传统内存时(至少在单处理器系统)这些优化是透明和有益的, 但是它们可能对正确的 I/O 操作是致命的, 因为它们干扰了那些"边际效果", 这是主要的原因为什么一个驱动存取 I/O 寄存器. 处理器无法预见这种情形, 一些其他的操作(在一个独立处理器上运行, 或者发生在一个 I/O 控制器的事情)依赖内存存取的顺序. 编译器或者 CPU 可能只尽力胜过你并且重编排你请求的操作; 结果可能是奇怪的错误而非常难于调试. 因此, 一个驱动必须确保没有进行缓冲并且在存取寄存器时没有发生读或写的重编排.
硬件缓冲的问题是最易面对的:底层的硬件已经配置(或者自动地或者通过 Linux 初始化代码)成禁止任何硬件缓冲, 当存取 I/O 区时(不管它们是内存还是端口区域).
对编译器优化和硬件重编排的解决方法是安放一个内存屏障在必须以一个特殊顺序对硬件(或者另一个处理器)可见的操作之间. Linux 提供 4 个宏来应对可能的排序需要:
#include <linux/kernel.h>
void barrier(void)
这个函数告知编译器插入一个内存屏障但是对硬件没有影响. 编译的代码将所有的当前改变的并且驻留在 CPU 寄存器的值存储到内存, 并且后来重新读取它们当需要时. 对屏障的调用阻止编译器跨越屏障的优化, 而留给硬件自由做它的重编排.
#include <asm/system.h>
void rmb(void);
void read_barrier_depends(void);
void wmb(void);
void mb(void);
这些函数插入硬件内存屏障在编译的指令流中; 它们的实际实例是平台相关的. 一个 rmb ( read memory barrier) 保证任何出现于屏障前的读在执行任何后续读之前完成. wmb 保证写操作中的顺序, 并且 mb 指令都保证. 每个这些指令是一个屏障的超集.
read_barrier_depends 是读屏障的一个特殊的, 弱些的形式. 而 rmb 阻止所有跨越屏障的读的重编排, read_barrier_depends 只阻止依赖来自其他读的数据的读的重编排. 区别是微小的, 并且它不在所有体系中存在. 除非你确切地理解做什么, 并且你有理由相信, 一个完整的读屏障确实是一个过度地性能开销, 你可能应当坚持使用 rmb.
void smp_rmb(void);
void smp_read_barrier_depends(void);
void smp_wmb(void);
void smp_mb(void);
屏障的这些版本仅当内核为 SMP 系统编译时插入硬件屏障; 否则, 它们都扩展为一个简单的屏障调用.
[Original] [Print] [Top]
« Previous thread
应用层要支持connect函数的正确连接,2.6内核make menuconfig需哪些选项支持?
发表评论
-
Linux内存:内存管理的实质
2010-04-13 08:49 10991. 内核初始化: * 内核建立好内核页目录页表数据 ... -
深入C++的new
2010-04-12 10:31 864“new”是C++的一个关键字,同时也是操作符。关于new的话 ... -
Linux 的多线程编程
2010-04-12 09:32 1934本文们针 Linux 线程编程主特性总结出 5 条经验,以改善 ... -
浅析Linux下core文件
2010-04-08 10:32 2159当我们的程序崩溃时,内核有可能把该程序当前内存映射到core文 ... -
Linux下的CPU利用率计算原理详解
2010-04-07 17:13 1639我们在搞性能测试的时 ... -
linux cpu负载原理
2010-04-07 16:41 1253linux cpu负载原理 内核分析 待补 -
从VFS inode到LFS inode的寻址过程
2010-03-30 17:16 1834我们知道Linux是借用虚拟文件系统作为上层抽象的管理者来统一 ... -
CPU学习
2010-03-30 14:16 1464这是作者学习硬件基本知识过程中的笔记,由于以前很少接触这方面的 ... -
Cache Cohernce with Multi-Processor
2010-03-30 13:57 858刚写完一篇关于Cache Coherence的文章,就发现BN ... -
Cache 的write back和write through
2010-03-30 13:54 2305Cache 的write back和write through ... -
linux 2.6 Makefile详解
2010-03-30 13:48 1486熟悉内核的Makefile对开发设备驱动、理解内核代码结构都是 ... -
linux1
2010-03-30 13:38 683linux1 linux1 linux1 -
nfs
2010-03-30 13:29 678nfs文件系统 -
修改Linux内核增加系统调用
2010-03-30 09:44 1226本文修改内核2.4.29,分两部分,第一部分修改内核并测试,第 ... -
Linux内核裁剪的具体步骤
2010-03-29 17:27 1856在menuconfig中配置: 详 ... -
Linux内核修改实验
2010-03-29 17:10 1188Linux内核修改实验 实验 ... -
Linux内核剪裁实验
2010-03-29 17:08 1342实验目的: 1. 配置、编译Linux内核; 2 ... -
c语言深度解析
2010-03-29 15:38 752c语言深度解析 嘿嘿 -
Linux线程实现机制分析
2010-03-29 15:12 933内容: ·基础 ... -
linux 经典进程切换实现代码
2010-03-29 15:10 1236extern _inline void switch_to(i ...
相关推荐
内存屏障是一种在计算机科学中用来控制指令执行顺序和内存读写的同步机制。由于现代计算机系统的CPU处理速度远超过内存访问速度,为了提高性能,CPU会采用缓存(Cache)技术,而这种技术往往会导致内存操作的重新...
优化屏障和内存屏障是内核同步的两种重要手段,用于防止编译器和处理器的优化导致的数据乱序问题。 优化屏障主要用于阻止编译器对源代码指令的重排序。在Linux内核中,`barrier()`宏就是一个典型的优化屏障实现,它...
在JVM中,内存屏障被用来维持语言层并发原语的语义。JVM会在合适的时刻插入内存屏障,以确保多线程程序的正确执行。 六、结论 内存屏障是Java并发编程中的一种重要机制,用于解决多线程程序中的问题。通过了解内存...
但是,对于需要确保有序性的操作,如同步原语,就需要使用内存屏障来强制顺序。 内存屏障是一种强制处理器执行特定内存操作顺序的指令,它确保了之前的所有内存操作在执行屏障操作之前完成,并且之后的内存操作在...
McKenney)是IBM Beaverton Linux Technology Center的一名专家,他深入剖析了内存屏障如何成为确保同步原语正确操作的关键因素之一。 #### 为什么需要内存屏障? 为了理解内存屏障的重要性,我们需要先了解现代...
其中最重要的改进之一是引入了内存屏障指令,用于控制内存访问的顺序和可见性。 - **Load-Acquire (LDAR)**:这是一条加载指令,它保证在该指令之前的所有内存访问都已经完成。 - **Store-Release (STLR)**:这是一...
3. **内存屏障**:内存屏障可以防止编译器和处理器对指令进行重排序,确保特定的内存操作顺序。在多线程中,使用内存屏障可以避免因指令重排序导致的数据不一致性。VC++提供了`_ReadWriteBarrier()`和`_...
2. **内存屏障**:通过提供内存屏障(memory barrier)的概念,C++09允许程序员明确指定哪些内存操作不能被编译器或处理器重新排序。 3. **线程间的同步**:C++09提供了`std::mutex`、`std::lock_guard`等同步原语,...
### 内存屏障:硬件视角下的软件黑客 #### 引言 本文由Paul E. McKenney撰写,他是IBM Beaverton Linux Technology Center的一员。文章深入探讨了内存屏障(Memory Barriers)的概念及其在现代多处理器系统中的...
- ARMv8、PowerPC和MIPS等则采用弱内存模型(Weak Memory Ordering,WMO),允许程序员通过内存屏障指令控制顺序,实现更高的执行效率,但对程序员要求更高。 C11和C++11标准引入了内存顺序的概念,提供了一套标准化...
同时,也会探讨Java内存模型是如何处理内存屏障、重排序以及 Happens-Before 规则等复杂概念。通过阅读《深入理解JAVA内存模型.pdf》和观看38套java高级架构视频教程,你将能更好地理解和应用这些知识,提升你的Java...
内存屏障是一种同步机制,可以保证内存操作在处理器上的执行顺序,确保多线程或进程对共享内存的访问不会发生数据不一致的情况。互斥锁是一种用于控制多个线程对共享资源访问的同步机制,确保同一时刻只有一个线程...
- **内存屏障**(Memory Barrier):防止编译器和处理器对指令进行重排序的一种机制。 - **编译器内存屏障**(Compiler Memory Barrier):防止编译器对指令进行重排序。 - **处理器内存屏障**(Processor Memory ...
这些包括屏障,广播和减少。 参与机器之间的数据传输是抽象的,因此可以随时使用IP,如果可用,则可以使用InifiniBand(或RoCE)。 在后一种情况下,如果使用InfiniBand传输,则可以使用加速跨机器GPU到GPU的内存...
3. **内存屏障**:了解JMM中的内存屏障指令,它们在多核处理器上的重要性,以及如何避免数据竞争。 4. **双重检查锁定**:正确实现单例模式,理解为何需要双重检查锁定,以及volatile在此中的作用。 5. ** Happens...
##### CPU内存屏障 - **定义**:确保内存操作按特定顺序执行。 - **作用**:保证写操作在屏障之前完成,读操作在其之后进行。 - **类比**:如宠物门,确保宠物在通过门前完成所有准备工作。 #### 共同主题:依赖性...
3. **内存屏障**:插入内存屏障指令,防止编译器或CPU对I/O相关指令进行重新排序。 4. **同步原语**:利用信号量、互斥锁等同步机制,保证在多线程环境下对I/O寄存器的访问顺序不被打乱。 在Linux内核中,这些措施...
在Lecture 5之前,学生们需要完成Project 4,其中包括对进程管理的测试,如创建(spawn)、终止(kill)和等待(wait)操作,以及三个同步原语的实现,包括条件变量、信号量和屏障。此外,还需要实现基于邮箱的进程间通信...