我有一个简单的裸机Raspberry Pi项目,我在其中尝试实现自旋锁。这是我的代码:

spinlock_lock:
    push {r4, r5, lr}

    mov r5, #0x1
1:
    ldrex r4, [r0]
    teq r4, #0
    strexeq r4, r5, [r0]
    teqeq r4, #0
    bne 1b

    pop {r4, r5, pc}


问题是ldrex导致数据中止。我传递的指针是页面对齐的,并且ARM在系统模式下运行。奇怪的是,将代码替换为使用非排他性加载/存储的版本即可。使用独家加载和存储时,我需要记住什么?

最佳答案

[为了清楚起见,忽略非MMU架构]

排他访问指令仅保证可在普通内存上使用。在ARMv7-A中,实现定义了它们将在强序内存还是在设备内存上工作-除非系统文档明确声明支持,否则将无法预测强序内存或设备内存的排他性。适用于此的ARMv6更加严格:


LDREX和STREX操作只能在支持“普通”内存属性的内存上执行。


当MMU关闭时,指令访问被视为普通访问,而数据访问被视为强顺序访问。因此,尝试在MMU关闭的情况下使用排他性很可能会失败-为了使用它们,我认为除了为正确的属性设置身份映射设置一些最小页面表外,别无选择。

08-15 23:07