Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9464167
  • 博文数量: 1750
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 20091
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1750)

文章存档

2024年(26)

2023年(26)

2022年(112)

2021年(217)

2020年(157)

2019年(192)

2018年(81)

2017年(78)

2016年(70)

2015年(52)

2014年(40)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: LINUX

2010-11-24 15:47:01

I/O 寄存器和常规内存

  1. 硬件寄存器和内存之间的强相似性, 存取 I/O 寄存器的程序员必须小心避免被 CPU(或者编译器)优化所戏弄, 它可能修改希望的 I/O 行为.
  2. I/O 寄存器和 RAM 的主要不同是 I/O 操作有边际效果, 而内存操作没有: 一个内存写的唯一效果是存储一个值到一个位置, 并且一个内存读返回最近写到那里的值. 因为内存存取速度对 CPU 性能是至关重要的, 这种无边际效果的情况已被多种方式优化: 值被缓存, 并且 读/写指令被重编排.
  3. 编译器能够缓存数据值到 CPU 寄存器而不写到内存, 并且即便存储它们, 读和写操作都能够在缓冲内存中进行而不接触物理 RAM. 重编排也可能在编译器级别和在硬件级别都发生: 如果它以不同于在程序文本中出现的顺序来执行,常常换一种指令序列能够执行得更快。所以重编派后执行序列可能和我们的预期不相同。
  4. 所以当使用内存的访问方式来操作IO寄存器的时候,可能会造成无法预见的错误。因为他们(编译器或CPU)干扰了那些“边际效果”
  5. 对编译器优化和硬件重编排的解决方法是在必须以一个特殊顺序对硬件(或者另一个处理器)可见的操作之间安放一个内存屏障


#include <linux/kernel.h>
void barrier(void)
/*

* 告知编译器插入一个内存屏障,但对硬件没有影响。 即把当前驻留在CPU寄存器的值存储到内存,并重新读取他们。 但对于硬件的代码重编派不做处理,保留硬件处理的自由度,而仅仅阻止编译器的优化。

*/

#include <asm/system.h>
void rmb(void); //read memory barrier
void wmb(void);
void mb(void)
/*

* 插入硬件内存屏障,rmb保证任何此代码之前的读操作执行完成,而wmb保证此代码之前的写操作正确完成。 mb则是rmb/wmb的超集。

*/

范例

writel(dev->registers.addr, io_destination_address);
writel(dev->registers.size, io_size);
writel(dev->registers.operation, DEV_READ);
wmb(); /*保证写下面的control寄存器之前,其他的三个寄存器正确执行而没有被优化掉或进行寄存器设置顺序的重新编排*/
writel(dev->registers.control, DEV_GO);



因为内存屏障影响性能, 它们应当只用在确实需要它们的地方.
阅读(2731) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~