【问题标题】:make sure one cpu has written a "double" before another cpu read that "double"?确保一个 cpu 在另一个 cpu 读取“double”之前写入了“double”?
【发布时间】:2013-05-23 07:36:22
【问题描述】:

我打算在双核 ARM Cortex-A9 CPU 上运行一个操作系统(一个内核运行 Linux,另一个没有操作系统)。

在无操作系统端,我们将 64 位 double 写入 DDR 内存,然后 Linux 端读取它。

因为 CPU 有一条 32 位总线到 DDR,所以值在两个总线周期内传输,这意味着如果在总线上混合写入和读取,则值可能会被破坏。

我该怎么做才能让它以安全的方式工作?

【问题讨论】:

  • “一个是Linux,另一个没有操作系统”——那么“两个不同的操作系统”在哪里?
  • @H2CO3 我的错误,已编辑
  • 你必须实现一个跨核互斥体。您可能可以查看 Linux 互斥锁的实现并复制它。
  • @Mats Petersson 是的,linux 可以使用 spin_lock,但是其他内核没有操作系统,它无法识别 spin_lock。
  • 这是 ldrex/strex 对的用途,它们不是用于锁定资源(在单个内核中,因为它们在 linux 和其他地方被错误地使用),而是用于保护内核之间的内存多核处理器。

标签: c linux assembly arm cpu


【解决方案1】:

您没有具体说明您的订购要求或您打算如何表示更改 - 所以我将简单地回答所述问题:

如果在 64 位对齐的位置上执行 LDREXD/STREXD 指令,则保证是单副本原子指令(如果该位置不是,它们会中止)。如果您正在做一些无锁的事情,那可能对您有好处。如果没有,只需使用互斥锁实现即可。

当然,LDREXD/STREXD 只有在以下任一情况为真时才能正常工作:

  • Linux 和您的其他软件都启用了缓存,两个 cpu 都设置了“SMP”位,并且都将共享区域映射为可回写缓存。

  • Linux 和您的其他软件都将共享区域视为未缓存,并且您的 SoC 为内存设备实现了一个全局监视器

【讨论】:

    【解决方案2】:

    您的问题还不够清楚,但让我们试一试。

    如果no-Os 部分在读取数据时始终看到一致的值对您很重要,那么您只需要执行原子 操作。如果您将使用 gcc 或类似的工具,则可以使用内置函数(例如 __sync_val_compare_and_swap)来实现这种操作。如果没有,这可以通过几行汇编程序来实现,您很容易找到相关的参考资料。 (但在这个特定的处理器上要小心,这不仅仅是一条指令。)

    如果您想要某种信号表明 Linux 端已写入值,最简单的方法是实现您自己的锁结构。由于您在一侧没有操作系统,因此您将不得不实施繁忙的等待。这同样可以通过原子操作来完成,gcc 内置 __sync_lock_test_and_set 将是学习如何实现这一点的一个很好的起点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-03
      • 2013-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多