我知道这可能是一个奇怪的用法。我只是想知道我是否可以在SCU禁用的情况下使用LDREX/STREX。
我使用的是双核Cortext-A9 SoC。这两个内核在AMP模式下运行:每个内核都有自己的操作系统。虽然内存控制器是共享资源,但每个核心都有自己的内存空间。一方无法访问另一方的内存空间。因为不需要缓存一致性,所以SCU没有启用。同时,我还有一个共享内存区域,两个核心都可以访问。共享内存区域是非缓存的,以避免缓存一致性问题。
我在这个共享内存区域中定义了一个旋转锁。此旋转锁用于保护共享资源访问。现在,旋转锁定的实现方式很简单:
void spin_lock(uint32_t *lock)
{
while(*lock);
*lock = 1;
}
void spin_unlock(uint32_t *lock)
{
*lock = 0;
}
其中,lock是共享内存中的一个变量,因此两个核心都可以访问该锁。
此实现的问题在于访问锁不是独占的。这就是为什么我想使用LDREX/STREX来实现旋转锁定。请允许我重申我的问题:
我可以在没有启用SCU的情况下使用LDREX/STREX吗?
谢谢!
所以。。。你的问题的直接答案是,是的,这是可能的——只要内存系统中的其他东西实现了共享内存区域的独占监视器。如果没有,那么STREX将始终返回OK(而不是EXOK),在结果寄存器中可观察到失败。
但是,为什么不启用SCU?显然,您所要做的工作需要至少在该区域的两个操作系统之间有一个一致的内存视图。使用PIPT数据缓存,根据缓存线在每个图像中的映射方式,您不会看到缓存线的任何混叠。
总的来说,答案是否定的。这里有两个问题:
1) 不能对未缓存的内存使用独占加载/存储。互斥运算只对"正常"幂等内存进行操作。
2) ARM手册没有具体说明独占监视器如何与内存一致性协同工作,但任何合理的实现本质上都会将监视器置于缓存线获取机制中。如果您禁用了缓存线窥探,则很可能会使芯片上的监视器无法工作。
您唯一的(格式不正确的)问题,
我可以在不启用SCU的情况下使用LDREX/STREX吗?
在理想的ARM宇宙中,是的,这是可能的。也就是说,有可能在某个地方,某一天你能做到这一点。我想你是说
在我的系统中,如果不启用SCU,我可以使用LDREX/STREX吗?
不幸的是,ARM ARM有点像政治/官僚文件。阅读"强烈建议"、"不可预测"、"未知"和可以时,必须格外小心。所有程序员都希望ldrex/strex
应用于所有内存。事实上,如果总线控制器(通常是AXI-NIC)实现了监视器,那么支持备受喜爱的swp
指令就不会有问题。StackOverflow上有很多帖子,人们希望用ldrex/strex
替换swp
。
在您阅读并重新阅读ARM ARM的双声道(它是为程序员编写的,也是为硅实现者编写的)之后,很明显监视器逻辑可能是在缓存中实现的。缓存控制器必须实现脏线广播。脏线广播与"监视器"非常相似,而您的"保留颗粒"很可能是缓存线大小(这是一个多大的关联)。
ARM ARM是为那些可能希望实现Cortex-a CPU的人编写的通用文档。它的编写是为了让他们的手(创造力)不被束缚来实现缓存中的监视器。
因此,您需要阅读特定Cortex-A9 SOC的特定文档。它可能只支持带有缓存内存的ldrex/strex
。事实上,在执行ldrex
之前,建议发出pld
以确保内存在缓存中,这意味着您需要激活系统中的SCU。我想你担心SCU会增加延迟的一些额外周期?
我认为这些信息中的一些让许多非常聪明的人感到困惑。注意可能和之间的差异是。StackOverflow上的每个人可能都希望监视器在总线控制器(或核心内存芯片)中实现。然而,对于大多数真正的芯片来说,情况并非如此。
可以肯定的是,如果你想将代码/OS移植到更新或不同的Cortex-A CPU,即使你的芯片组支持缓存子系统之外的"全局监视器",你也不应该做出这种假设。