前提:我正在使用甚至没有C ++ 11(带有std::atomic<int>
)的ARM嵌入式(几乎是裸机)环境,因此请避免使用诸如<std::atomic<int>“:我不能。
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)
}
而且,我正在尝试实现一些代码重用,这就是为什么我只隔离了一个要在平台特定代码(UPDATE2:我添加了第二个实现,该实现应该解决我对add()
)中实现的基本功能的原因。这种方法可行吗? (对于feasible,我的意思是对于仅通过实现
add()
方法来保证原子性的每个平台都是可行的)。更新:我看到一个可能的问题可能是内存对齐
。特别是,似乎不能保证在每个平台上都加载原子int32_t
(get()
方法)是原子的(例如,如果变量未对齐4个字节,或者该平台不是基于32位的)。我对么?我还应该在特定于平台的文件中保留get()
方法吗?
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:...