Öncül: C ++ 11 (ile std::atomic<int>
) bile bulunmayan bir ARM gömülü (neredeyse çıplak metal) ortamla çalışıyorum , bu yüzden lütfen " sadece standart C ++ kullanstd::atomic<int>
" gibi cevaplardan kaçının : Yapamam .
AtomicInt'in bu ARM uygulaması doğru mu? (ARM mimarisinin ARMv7-A olduğunu varsayalım )
Bazı senkronizasyon sorunları görüyor musunuz? Öyle mi volatile
gerekli / yararlı?
// 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)
}
Ayrıca, ben bazı kod yeniden elde etmeye çalışıyorum, bu yüzden platforma özgü kod ( add()
içindeki yöntem arm/atomic_int.cpp
) uygulamak için sadece bir temel işlevi izole .
Mı atomic_int.h
gerçekten taşınabilir farklı platformları / mimariler / derleyici genelinde olduğu gibi? Bu yaklaşım uygulanabilir mi? (With uygulanabilir Yani sadece uygulayarak garanti bölünmezlik her platform için uygun add()
bir yöntem ).
İşte aynı fonksiyonun karşılık gelen ARM GCC 8.3.1 uygulaması. Görünüşe göre, tek gerçek fark, dmb
öncesi ve sonrası varlığıdır . Benim durumumda gerçekten gerekli mi? Neden? Benim AtomicInt
(olmadan dmb
) başarısız olduğu bir örneğiniz var mı?
GÜNCELLEME: sabit uygulama, get()
atomisite ve hizalama sorunlarını çözmek için kaldırılan yöntem. Şimdi add()
bir standart gibi davranıyor fetchAndAdd()
.
__ATOMIC_INT_H_
) içeren adlar ve alt çizgi ile başlayan ve büyük harfle başlayan adlar uygulama tarafından ayrılmıştır. Bunları kodunuzda kullanmayın.
atomic
muhtemelen en iyisi std::atomic
, karışıklığı önlemek için kullanılmaz , ancak her halükarda neden sadece kullanmamanız gerektiği sorusuna neden olur.
__ATOMIC_INT_H_
tanımlayıcı yeniden adlandırıldı .
volatile
C ++ içindeki anahtar kelime, değişken üzerinden optimizasyon yapılmaması anlamına gelir. Böyleceget()
yöntem bundan faydalanır. Bununla birlikte, genel olarak, uçucu C ++ 'da mahrum etmek üzeredir. Sisteminiz 32 bit verileri yerleşik olarak senkronize edemiyorsa, muteksleri kullanmaktan başka bir seçeneğiniz yoktur - en azından spinlock.