c - 禁用 DCache 将阻止设置atomic_flag

标签 c caching arm atomic zynq

我们使用的是基于 zynq-7000 的 CPU,因此是 cortex-a9,并且在使用我们正在使用的库 (open-amp) 内的atomic_flags 时遇到了以下问题。

我们使用 SoC 上的第二个 CPU 来执行裸机代码。
禁用 dcache 时,无法再设置原子整数,这是一个为我们触发问题的简单代码:

#define XREG_CONTROL_DCACHE_BIT (0X00000001U<<2U)
#define XREG_CP15_SYS_CONTROL   "p15, 0, %0,  c1,  c0, 0"
#define mfcp(rn)    ({uint32_t rval = 0U; \
             __asm__ __volatile__(\
               "mrc " rn "\n"\
               : "=r" (rval)\
             );\
             rval;\
             })
#define mtcp(rn, v) __asm__ __volatile__(\
             "mcr " rn "\n"\
             : : "r" (v)\
            );

static void DCacheDisable(void) {
    uint32_t CtrlReg;
    /* clean and invalidate the Data cache */
    CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);

    CtrlReg &= ~(XREG_CONTROL_DCACHE_BIT);
    /* disable the Data cache */
    mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
}

int main(void) {
    DCacheDisable();

    atomic_int flag = 0;
    printf("Before\n");
    atomic_flag_test_and_set(&flag);
    printf("After\n");
}

CPU 对 atomic_flag_test_and_set 执行以下循环:

dmb     ish
ldrexb  r1, [r3] ; bne jumps here
strexb  r0, r2, [r3]
cmp     r0, #0
bne     -20     ; addr=0x1f011614: main + 0x00000060
dmb     ish

但是寄存器r0始终保持1 。 当省略对 DCacheDisable 的函数调用时,代码完美运行。

我真的找不到任何有关禁用 dcache 和原子标志的信息。

有人知道吗?

工具链:我们使用的是 vitis 2022.2,它附带 arm-xilinx-eabi-gcc.exe (GCC) 11.2.0 。编译器选项为-O2 -std=c11 -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard

最佳答案

这在支持缓存的 ARM 平台上很常见。高速缓存行被用作排他锁的临时存储。 ARM 中的术语是 exclusive reserve granule或锁定内存的大小。在具有缓存的系统上,您会发现颗粒是缓存行大小。

因此,在内部,ldrexstrex 是作为缓存解析策略的一部分实现的。您可以compare it to cortex-m systems ,其中整个内存空间是一个保留颗粒。

ldrex/strex 对对于与不属于 AXI 结构的外部设备进行同步是没有用的。如果您想禁用缓存以与 FPGA 接口(interface)一起使用,我认为这行不通。您需要在 FPGA 中实现缓存协议(protocol)。

对于 Cortex-M 系统,没有缓存结构,自定义逻辑实现“全局监视器”。

缓存机制实际上似乎很有用,因为缓存行可以用作事务内存。即,要么整条线都 promise 不 promise 。似乎可以为具有多个指针的结构创建无锁算法。该节点不会锁定整个列表,而只会锁定一个条目。不过,我还没有见过它被这样使用过。我认为主要是因为 ARM 文档建议不要这样做(不要依赖 ERG 大小)。

关于c - 禁用 DCache 将阻止设置atomic_flag,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76207164/

相关文章:

printing - ARM 汇编以十进制形式打印寄存器值

linux - ARM 工具链在错误的库目录中查找

c - 需要算法来解决C中的移位问题

c - 通过 C 中的文件使用 crypt 函数进行身份验证(段错误)

caching - Varnish :如何将命中/未命中统计信息发送到后端

php - 使用 PHP + MySQL 缓存大量内容

java - JNA 内存泄漏

c++ - 最小化进程之间的上下文切换时间

python - 我可以让我所有的 python 脚本都缓存字节码吗?在我的主目录的中央目录树下?

ARM NEON SIMD 版本 2