繁体   English   中英

ARM Cortex-M4 Mutex锁。 DMB指令

[英]ARM Cortex-M4 Mutex Lock. DMB Instruction

我阅读了以下文档:ARM的Barrier_Litmus_Tests_and_Cookbook

第7.2节显示了获取互斥锁/信号量的代码。

Loop
   LDREX R5, [R1] ; read lock
   CMP R5, #0 ; check if 0
   STREXEQ R5, R0, [R1] ; attempt to store new value
   CMPEQ R5, #0 ; test if store suceeded
   BNE Loop ; retry if not
   DMB

LDREX指令请求对存储器地址进行独占访问。 如果处理器具有独占访问权限,则仅使用STREX写入成功。 它们使用DMB指令确保独占写入与所有处理器同步。

我有一个小问题。 假设处理器具有对内存地址的独占访问权并将其锁定。 完成STREX指令后,将删除独占访问。 从现在开始,其他处理器可以访问此内存。 但是,写入仍然在处理器的缓存中,直到DMB完成。 如果另一个处理器在第一个处理器已锁定但尚未同步到RAM时尝试获取对锁的访问权限,会发生什么情况。 存储器地址不是专门锁定到第一个处理器,而是写入未完成。

任何人都可以解释,为什么这确实有效并且是安全的。 我有我的问题。

我认为你过于复杂了。 看看amba / axi规范(以及你在哪里找到了多核心皮质-m4?)。 ldrex / strex用于在多处理器芯片中跨处理器共享资源。 他们一段时间以来被错误地用于其他事情。 不幸的是,ARM在正确记录所有这些方面做得非常糟糕。

ldr的独有部分是processorid和地址(范围)保存在表中。 当strex发生时,检查该地址(范围)的processorid是否与EXOKAY匹配,如果不是OKAY则不进行存储。 Strex没有清除任何东西,他们有趣地拥有这个clrex指令,我假设将processorid设置为某个不会命中的值,或者取决于他们如何构建表,他们释放了一个表项。

我可以在写完之后尝试这个,但你可以像ldrex一样轻松然后strex然后strex,相当肯定我已经在全尺寸的手臂上做了int,将尝试在皮质-m4 ldrex,strex,strex,clrex,strex上看看是什么发生。

在单处理器系统中,ldrex / strex预计可以在ARM的逻辑中工作,但芯片供应商不需要支持它,可能只是返回OKAY(而不是EXOKAY)。 L1当然也可能是L2是超出芯片供应商的臂逻辑。 (皮质有没有l2?)。 通常情况下,您不必担心触及芯片供应商代码,如果不是无限期地运行很长时间而不知道任何此类代码,因为您将保留在其中一个缓存中。 例如,禁用Linux中的两个缓存是皇家PITA,它们可能使它看起来像是编译时选项,但是深入挖掘并看到现实。 只有一个处理器,您如何获得不同的处理器ID?

在多处理器芯片中,芯片供应商应该在缓存之外正确支持它,如果你甚至可以通过独占访问,如何正常使用ldrex / strex,你最有可能在你的L1缓存中,永远不会得到暴露于芯片供应商提供的内容,但如果你在两者之间中断并且你很可能被L2保存,就会发生这种情况。 在这种情况下,芯片中有多个处理器ID是有意义的,因为有多个处理器。

这很好

Cortex-M4处理器实现了本地专用监视器。 处理器内的本地监视器已构造成不保存任何物理地址,而是将任何访问视为与先前LDREX的地址匹配。 这意味着实现的独占预留粒度是整个内存地址范围。

m7 trm也说了同样的话。

没有多个核心怎么可能/会产生不同的ID? 文档使用术语processorid来指示正在使用哪个处理器。 皮质中有多少个处理器? 也许它在其他地方使用不同的字符串/名称进行了记录,但是此时我不知道如何生成cortex-m中的processorid并且单个处理器是多于一个? 我无法访问核心以确定。

因此,即使逻辑不支持每地址独占访问,他们也没有说他们没有检查处理器ID,他们只是考虑对标记为共享的内存的所有strex访问与最后ldrex的处理器ID进行检查,而与其地址无关。

编辑

PUT32(0x01000600,0x600);
PUT32(0x01000700,0x700);
PUT32(0x01000800,0x800);
CLREX();
hexstring(STREX(0x20000600,0x12345678));
hexstring(STREX(0x20000700,0x12345678));
hexstring(STREX(0x20000800,0x12345678));
hexstring(LDREX(0x20000600));
hexstring(STREX(0x20000600,0x6666));
hexstring(STREX(0x20000700,0x12345678));
hexstring(STREX(0x20000800,0x12345678));
hexstring(LDREX(0x20000600));
hexstring(STREX(0x20000700,0x7777));
hexstring(STREX(0x20000800,0x12345678));
hexstring(GET32(0x20000600));
hexstring(GET32(0x20000700));
hexstring(GET32(0x20000800));
CLREX();
hexstring(0xAABBCCDD);
hexstring(LDREX(0x20000600));
CLREX();
hexstring(STREX(0x20000600,0x2222));
hexstring(GET32(0x20000600));

生产

00000001 
00000001 
00000001 
00000600 <-- ldrex
00000000 <-- strex pass
00000001 <-- strex fail
00000001 
00006666 
00000000 
00000001 
00006666 
00007777 
00000800 
AABBCCDD 
00006666 
00000001 
00006666 

因此看起来他们在这里做的是在ldrex独立于地址后传递的下一个strex。 所以使用你的术语strex“清除锁定”。

请注意,在ldrex和strex之间放置一个clrex确实会使strex失败。

没有命中相同的地址并不重要一个ldrex到一个strex

hexstring(LDREX(0x20000900));
hexstring(STREX(0x20000900,0x2222));
hexstring(STREX(0x20000900,0x2222));

3EEDCC1B 
00000000 
00000001 

打开数据缓存并没有改变结果。

测试功能:

.thumb_func
.globl LDREX
LDREX:
    ldrex r0,[r0]
    bx lr

.thumb_func
.globl CLREX
CLREX:
    clrex
    bx lr

.thumb_func
.globl STREX
STREX:
    strex r0,r1,[r0]
    bx lr

与大哥ARM不同:

CLREX();
hexstring(STREX(0x20000600,0x12345678));
hexstring(LDREX(0x20000600));
hexstring(STREX(0x20000600,0x6666));
hexstring(LDREX(0x20000600));
PUT32(0x20000600,0x11);
hexstring(STREX(0x20000600,0x6666));

00000001 
00000600 
00000000 
00006666 
00000000 

strex在两者之间存在非独占访问权限,至少基于您发布的非独占商店的文档应该破坏之前的ldrex(在armv7-a上)。

注意以上是在cortex-m4 r0p1 CPUID 0x410FC241上

这是安全的,因为芯片设计师使其安全。 Test_and_Set指令的全部内容将由操作系统用于semaphone和mutex命令。 在多核/多处理器环境中,除了内置的汇编命令之外,没有其他方法可以准确地实现此功能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM