前提:私はARM組み込み(ほとんどベアメタル)環境で作業していますが、C ++ 11(も)さえ使用できないので、「標準のC ++のみを使用する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)
}
また、私はいくつかのコードの再利用を実現しようとしています。そのため、プラットフォーム固有のコード(add()
内のメソッドarm/atomic_int.cpp
)に実装する基本的な関数を1つだけ分離しました。
あるatomic_int.h
本当にポータブルそれは、異なるプラットフォーム/アーキテクチャ/コンパイラを越えていると?このアプローチは実行可能ですか?(実現可能とは、すべてのプラットフォームがadd()
メソッドのみを実装することによって原子性を保証することが実現可能であることを意味します)。
これは、同じ関数の対応するARM GCC 8.3.1実装です。どうやら、唯一の本当の違いは、dmb
前と後の存在です。私の場合は本当に必要ですか?どうして?AtomicInt
(なしでdmb
)私が失敗する例はありますか?
更新:修正された実装、削除 get()
原子性と整列の問題を解決するためのメソッドの。これでadd()
標準のように動作しますfetchAndAdd()
。
使用しているarmアーキテクチャのバージョンは何ですか?armv-7?
—
マイクヴァンダイク
これは質問には対応していませんが、2つの連続したアンダースコア(
—
ピートベッカー
__ATOMIC_INT_H_
)を含む名前と、アンダースコアで始まり、その後に大文字が続く名前は、実装で使用するために予約されています。コードでそれらを使用しないでください。
メンバー名
—
クリフォード
atomic
はstd::atomic
、との混同を避けるためにおそらく使用しないのが最善ですが、どのような場合でもそれを単に使用しない理由を疑います。
ARMアーキテクチャが追加さ
—
gentooise
__ATOMIC_INT_H_
れ、識別子の名前が変更されました。
volatile
C ++のキーワードは、変数を介して最適化しないことを意味します。したがって、get()
メソッドはその恩恵を受けます。ただし、一般的に、C ++ではvolatileが廃止されようとしています。システムが32ビットデータを組み込みで同期できない場合は、ミューテックスを使用する以外に選択肢はほとんどありません-少なくともスピンロック。