zoukankan      html  css  js  c++  java
  • Linux IO乱序

    原创翻译,转载请注明出处。

    在一些平台,所谓的内存映射I/O在保序执行这方面是没有保障的。在这些平台,驱动写入器负责保证I/O写操作按照预期的顺序写到设备内存映射地址。

    代表性的做法是通过读取一个安全的设备或桥接寄存器,该寄存器可以导致I/O芯片在任何读操作发生前刷新所有带处理的写操作到设备上。

    驱动通常在一退出由自旋锁保护的临界区代码时就使用这种技术。这就可以保证后发生的写操作只能在之前已有的写操作的后面执行,这个类似只对I/O操作使用一个内存屏障操作,mb()。

    下面举一个具体例子,假设一个设备驱动:

            ...
    CPU A:  spin_lock_irqsave(&dev_lock, flags)
    CPU A:  val = readl(my_status);
    CPU A:  ...
    CPU A:  writel(newval, ring_ptr);
    CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
            ...
    CPU B:  spin_lock_irqsave(&dev_lock, flags)
    CPU B:  val = readl(my_status);
    CPU B:  ...
    CPU B:  writel(newval2, ring_ptr);
    CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
            ...


    以上例子会发生设备可能接收到newval2在newval之前,这样就会引起问题,需要如下修改才能正常:

            ...
    CPU A:  spin_lock_irqsave(&dev_lock, flags)
    CPU A:  val = readl(my_status);
    CPU A:  ...
    CPU A:  writel(newval, ring_ptr);
    CPU A:  (void)readl(safe_register); /* maybe a config register? */
    CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
            ...
    CPU B:  spin_lock_irqsave(&dev_lock, flags)
    CPU B:  val = readl(my_status);
    CPU B:  ...
    CPU B:  writel(newval2, ring_ptr);
    CPU B:  (void)readl(safe_register); /* maybe a config register? */
    CPU B:  spin_unlock_irqrestore(&dev_lock, flags)


    这样,想safe_register读取就会让I/O芯片在收到读操作之前刷新之前的未处理的写操作,从而防止数据污染。

  • 相关阅读:
    一个简易的MySQL性能查询脚本
    pt-osc原理、限制、及与原生online-ddl比较
    Netstat Commands for Linux Network Management
    MySQL 资源大全中文版
    自增表死锁问题分析及处理
    MySQL自带的性能压力测试工具mysqlslap
    iOS in-app purchase详解
    iOS 将Excel导入到SQLite3的过程
    iOS iTuns Connect官方配置教程
    OpenGL 知识二
  • 原文地址:https://www.cnblogs.com/danxi/p/6647425.html
Copyright © 2011-2022 走看看