首页 文章

ARM Cortex-M4 Mutex锁 . DMB指令

提问于
浏览
1

我阅读了以下文档: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时尝试获取对锁的访问权限,会发生什么情况 . 存储器地址不是唯一地锁定到第一个处理器,但写入没有完成 .

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

2 回答

  • 3

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

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

    我可以在写完之后尝试这个,但你可以轻松ldrex然后strex然后strex,相当肯定我已经在全尺寸武器上完成int,将尝试在cortex-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上

  • 0

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

相关问题