ARM 32 位 MCU 上的原子 64 位计数器,无锁

问题描述 投票:0回答:1

在 ARM Cortex M 32 位上,在 C 下,我需要维护一个 64 位计数器。我想避免竞争条件,例如:

start:
         count = 0x00000000 ffffffff
threadA: increment count_low
         count = 0x00000000 00000000
threadB: increment count_low
         count = 0x00000000 00000001
threadA: if (!count_low) increment count_high
         count = 0x00000000 00000001
threadB: if (!count_low) increment count_high
         count = 0x00000000 00000001

这是一个简单的计数器,只有两种使用方式:1. 读取 val 和 2. 递增。

在 ARM 汇编中,无需引入任何锁即可通过

LDREX
STREX
完成此操作。但是,我想避免汇编并使用 C。

最好的方法是简单地使用

atomic_uint_least64_t
吗?这行得通吗?

当我尝试制作计数器

atomic_uint_least64_t
时,出现链接器错误
undefined reference to
__atomic_load_8'
, and when I try adding 
-latomic
, I get 
找不到“-latomic:”没有这样的文件或目录`。

我在 Linux 上使用

arm-none-eabi-gcc
来交叉编译 Cortex M。

c concurrency embedded atomic race-condition
1个回答
0
投票

只需使用

stdatomic.h
原语。对于任何拱门,他们都会“做正确的事情”。并且,代码将被内联。 对于手臂,他们可能会使用

ldrex

。他们可能会使用

dmb
作为记忆屏障。但是,他们也可能使用
ldaxr

这是一个示例程序:

#include <stdatomic.h> unsigned long long ctr; void ctrinc(void) { atomic_fetch_add(&ctr,1); }

这是组装:

.arch armv8-a .file "atom64.c" .text .comm ctr,8,8 .align 2 .global ctrinc .type ctrinc, %function ctrinc: adrp x0, :got:ctr ldr x0, [x0, #:got_lo12:ctr] .L2: ldaxr x1, [x0] add x1, x1, 1 stlxr w2, x1, [x0] cbnz w2, .L2 nop ret .size ctrinc, .-ctrinc .ident "GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0" .section .note.GNU-stack,"",@progbits

一些资源:

    ARM64:LDXR/STXR 与 LDAXR/STLXR
  1. LDAXR 和 LDREX 有什么区别
© www.soinside.com 2019 - 2024. All rights reserved.