2017-03-09 226 views
0

我看了下面的文档:ARM的Barrier_Litmus_Tests_and_CookbookARM Cortex-M4互斥锁。 DMB指令

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时尝试获取锁的访问权限,会发生什么情况。内存地址不是专门锁定到第一个处理器,但写入没有完成。

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

+0

'DMB'通过使内存访问直到内存层次结构中的各个点(即缓存)来指令内存访问。高速缓存一致性机制对于允许处理器侦听另一个高速缓存是必需的,否则您假设的情况可能会发生。 ARM缓存是一致的。没有选项的'DMB'会进行全系统同步,我不知道它是什么意思,但我可以写一个内存。 –

+3

对于读取 - 修改 - 写入的原子性而言,'DMB'不是必需的。 'DMB'确保*其他*内存操作按照RMW操作进行排序。 – EOF

+0

的DMB是推动负载和存储出去,让他们完成这样其他看到它... ...“确保锁的成功要求由所有观察者观察到他们所观察到的任何后续加载或存储之前。”就像您使用其他内存障碍,刷写写入缓冲区和缓存等一样。 –

回答

2

我认为你已经过分复杂化了。看看amba/axi规范(以及你在哪里找到了多核cortex-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逻辑逻辑。 (cortex-ms是否有l2?)。通常情况下,您不必担心触及芯片供应商代码,如果不是无限期地运行很长时间,您可能会停留在其中一个缓存中,但不知道这些情况。例如,在Linux中禁用这两个缓存就是一个皇家PITA,它们可能会使它看起来像是编译时选项,但可以深入了解现实。只有一个处理器,你如何获得不同的处理器ID?

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

这是很好

了Cortex-M4处理器实现本地监控独家。处理器内的本地监视器已被构建,以使其 不包含任何物理地址,而是将任何访问视为与先前LDREX的地址匹配的 。这意味着 实施的独占预留颗粒是整个内存 地址范围。

m7 trm说同样的事情。

没有多核心怎么会/会产生一个不同的ID? 该文档使用术语processorid来指示正在使用哪个处理器。 cortex-m中有多少处理器?也许它在其他地方使用不同的字符串/名称进行记录,但此时我不知道cortex-m中的processorid是如何生成的,并且单处理器是否存在多个?我没有获得核心知道肯定。

所以即使逻辑不支持每个地址的独占访问,他们并没有说他们没有检查processorid,他们只是考虑所有标记为共享的内存的strex访问与最后一个独立于ldrex的processorid进行检查的地址。

编辑

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 

所以看起来他们在这里做什么是下一个STREX LDREX通过独立的地址后。因此,使用你的条款strex“清除锁定”。

请注意,在ldrex和strex之间加入clre会导致strex失败。

不打相同的地址事项的一个LDREX一个STREX

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

3EEDCC1B 
00000000 
00000001 

开启数据高速缓存上didnt并没有改变结果。

测试功能:

.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 

不像大哥哥怀里:

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上)。

注意上面是一个皮质-M4 r0p1 CPUID 0x410FC241

0

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