此C ++ AtomicInt实现正确吗?

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

前提:我正在使用甚至没有C ++ 11(带有std::atomic<int>)的ARM嵌入式(几乎是裸机)环境,因此请避免使用诸如<std::atomic<int>“:我不能。

此AtomicInt的ARM实现正确吗? (假设ARM体系结构为

ARMv7-A

您是否看到一些同步问题?

特别是,定义get()方法是否正确? volatile是否必需/有用?

实施1

// 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 get(void) { return atom; } void add(int32_t value); // Implement 'add' method in platform-specific file void sub(int32_t value) { add(-value); } void inc(void) { add(1); } void dec(void) { add(-1); } private: volatile int32_t atom; }; #endif
// File: arm/atomic_int.cpp

#include "atomic_int.h"

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

    asm volatile(

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

    : "=&r" (res), "=&r" (tmp), "+&r" (&atom) // output (atom is both in-out)
    : "r" (value)                             // input
    : "cc");                                  // clobbers: condition code register changed (CPSR)
}
而且,我正在尝试实现一些代码重用,这就是为什么我只隔离了一个要在平台特定代码(add())中实现的基本功能的原因。这种方法

可行吗? (对于feasible,我的意思是对于仅通过实现add()方法来保证原子性的每个平台都是可行的)。更新:我看到一个可能的问题可能是

内存对齐

。特别是,似乎不能保证在每个平台上都加载原子int32_tget()方法)是原子的(例如,如果变量未对齐4个字节,或者该平台不是基于32位的)。我对么?我还应该在特定于平台的文件中保留get()方法吗?

UPDATE2:我添加了第二个实现,该实现应该解决我对get()同步的疑问,并且还应该解决对齐问题。基本上,这个想法是将add()实现为一种addAndGet(),并删除get()方法。

实施2

// 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, tmp;

    asm volatile(

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

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

    return res; // safe to return res (local variable cannot be changed by other execution contexts)
}
前提:我正在使用甚至没有C ++ 11(带有std :: atomic 

)的ARM嵌入式(几乎是裸机)环境,因此请避免使用诸如“仅使用标准C ++ std:...

c++ arm embedded atomic volatile
1个回答
0
投票
© www.soinside.com 2019 - 2024. All rights reserved.