繁体   English   中英

这个 C++ AtomicInt 实现是否正确?

[英]Is this C++ AtomicInt implementation correct?

前提:我正在使用 ARM 嵌入式(几乎是裸机)环境,我什至没有 C++11 (带有std::atomic<int> )可用,所以请避免像“只使用标准std::atomic<int> ”这样的答案: std::atomic<int> ":我不能

这是 AtomicInt 的 ARM实现正确吗? (假设 ARM 架构是ARMv7-A

你看到一些同步问题吗? volatile需要/有用?

// File: atomic_int.h

#ifndef ATOMIC_INT_H_
#define ATOMIC_INT_H_

#include <stdint.h>

class AtomicInt
{
public:
    AtomicInt(int32_t init = 0) : atom(init) { }
    ~AtomicInt() {}

    int32_t add(int32_t value); // Implement 'add' method in platform-specific file

    int32_t sub(int32_t value) { return add(-value); }
    int32_t inc(void)          { return add(1);      }
    int32_t dec(void)          { return add(-1);     }

private:
    volatile int32_t atom;
};

#endif
// File: arm/atomic_int.cpp

#include "atomic_int.h"

int32_t AtomicInt::add(int32_t value)
{
    int32_t res, prev, tmp;

    asm volatile(

    "try:    ldrex   %1, [%3]\n"     // prev = atom;
    "        add     %0, %1, %4\n"   // res = prev + value;
    "        strex   %2, %0, [%3]\n" // tmp = outcome(atom = res); // may fail
    "        teq     %2, #0\n"       // if (tmp)
    "        bne     try"            //     goto try; /* add failed: someone else modified atom -> retry */

    : "=&r" (res), "=&r" (prev), "=&r" (tmp), "+mo" (atom)  // output (atom is both in-out)
    : "r" (value)                                           // input
    : "cc");                                                // clobbers (condition code register [CPSR] changed)

    return prev; // safe return (local variable cannot be changed by other execution contexts)
}

另外,我正在尝试实现一些代码重用,这就是为什么我只隔离了一个基本的 function 以在特定于平台的代码中实现( arm/atomic_int.cpp中的add()方法)。

atomic_int.h是否真的可移植,因为它可以跨不同的平台/架构/编译器? 这种方法可行吗? 可行我的意思是每个平台都可以通过实现add()方法来保证原子性)。

这里是对应的ARM GCC 8.3.1实现同样的function。 显然,唯一真正的区别是dmb前后的存在。 在我的情况下真的需要它们吗? 为什么? 你有我的AtomicInt (没有dmb )失败的例子吗?

更新:修复了实现,删除了get()方法来解决原子性和 alignment 问题。 现在add()的行为类似于fetchAndAdd() ..

如果您使用gcc可能您可以使用旧版__sync内置函数进行原子 Memory 访问

void add(int volatile& a, int value) {
    __sync_fetch_and_add(&a, value);
}

生成

add(int volatile&, int):
.L2:
        ldxr    w2, [x0]
        add     w2, w2, w1
        stlxr   w3, w2, [x0]
        cbnz    w3, .L2
        dmb     ish
        ret

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM