2016-03-03 37 views
5

Derleyicim hala C++ 11 ve std :: atomic'i desteklemediğinden, ldrex-strex çifti aracılığıyla manuel olarak uygulamak zorunda kaldım.ARM Cortex M3 üzerinde atomik int64_t

Soruma şudur: ldrex ve strex ile int64_t 'atomik olarak okuma-değiştir-yazmanın doğru yolu nedir?

böyle

Basit çözüm işe görünmüyor (STREXW biri 1'e her zaman döndürür):

volatile int64_t value; 
int64_t temp; 

do 
{ 
    int32_t low = __LDREXW((uint32_t *)&value); 
    int32_t high = __LDREXW(((uint32_t *)&value)+1); 

    temp = (int64_t)low | ((int64_t)high<<32); 
    temp++;  

} while(__STREXW(temp, (uint32_t *)&value) | __STREXW(temp>>32, ((uint32_t *)&value)+1)); 
Ben farklı adreslerde işaret birkaç sıralı LDREX veya STREX talimatlar hakkında bir şey bulamadık

Kılavuz ama bana izin verilmesi gerektiğini bana görünüyordu. Aksi takdirde, birden fazla iş parçacığı, bazı senaryolarda iki farklı atom değişkenini değiştiremezdi.

+1

Bu GCC nedir? GCC dahili atomlarını düşünün? ARM için – user3528438

+0

GCC şimdi std :: atomic için destek var. Hayır, GCC değil, Keil armcc. – Amomum

+0

Bakın: [ARM AN321 - Cortex-M bellek engelleri] (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHEADII.html). Atomik aşırı yüklü bir kelimedir. Evrendeki şeyler atomik olarak gerçekleşemez. Bir takım elektronikler karşısında atomiktirler; Ana hat/kesintiler, SMP, otobüste cihaz vb. Probleminiz tam olarak nedir? Daha iyi tarif etmelisin. –

cevap

4

Bu asla işe yaramaz, çünkü münhasıranları bu şekilde yuvalayamazsınız. Uygulama-bilge, Cortex-M3 yerel özel monitör bile bir adresi takip etmez - the exclusive reservation granule is the entire address space - böylece her kelimeyi ayrı ayrı izleme varsayımı zaten geçersizdir. mimari zaten açıkça dışladı Ancak, hatta herhangi bir uygulama ayrıntılarını dikkate almak gerekmez arka arkaya strex:

If two STREX instructions are executed without an intervening LDREX the second STREX returns a status value of 1. This means that:

  • Every STREX must have a preceding LDREX associated with it in a given thread of execution.
  • It is not necessary for every LDREX to have a subsequent STREX .

Cortex-M3 (ve genel olarak ARMv7-M) kokan yana ARMv7-A gibi ldrexd var, ya değişkenin tüm girişlerini kontrol etmek için ayrı bir kilit kullanmanız ya da sadece okuma-değiştirme-yazma çevresindeki kesintileri devre dışı bırakmanız gerekecek. Eğer mümkün olursa, atomik 64 bit türüne ihtiyaç duymayacak şeyleri yeniden tasarlamak gerçekten daha iyi olacaktır, çünkü aynı çekirdek üzerindeki diğer parçacıklara göre sadece atomikliği elde edersiniz. -bit işlem atomik bir DMA denetleyicisi gibi bir dış ajan bakış açısından.

+0

Bundan korkuyordum. Yani şimdi anlıyorum, _any_ ldrex _every other_ ldrex için özel monitörü sıfırlayacak? – Amomum

+0

Teşekkürler, şimdi anladım! – Amomum

+0

@Amomum V7-M, yerel/global monitör ayırımına sahip değil - v7-A yerel monitör durum makinesinin kırpılmış bir versiyonu gibi görünüyor. Uygulamada donanımın muhtemelen bir adresi takip etmeyi bile zahmetsizce yapması ve herhangi bir bellek erişimindeki münhasır durumu temizlemesini beklemekteyim. – Notlikethat

1

Sadece gcc'nin nasıl çalıştığına bakıp aynı komut dizilerini kullanın.

gcc 4.8.2 iddialaris_lock_free() ile std::atomic<int64_t> bile -mcpu=cortex-m3 ile gerçek dönen uygulamaktır. Maalesef, gerçekten çalışmıyor.'u kullanmaya çalışan yardımcı işlevlerin hiçbir uygulaması olmadığından, bağlantı kuramayan veya çalışmayan kodlar yapar. (Denemek için @Notlikethat teşekkürler.)

Here's the test code I tried. Bu bağlantı kesilirse, bu cevabın eski bir sürümüne bakın. Bu sorunun cevabını, ilgili durumlarda, gcc 'un'un yararlı bir kod oluşturduğu herkes için yararlı olması durumunda bırakıyorum.

+0

Kol için gcc 5.2.1 ile önerdiğin şeyi denedim ve linker hatası aldım: "e: \ gcc-arm-none-eabi-5_2-2015q4-20151219-win32 \ arm-none-eabi \ include \ C++ \ 5.2. 1 \ bits/atomic_base.h: 514: std :: atomic 'u oluştururken "__atomic_fetch_add_8" için tanımlanmamış başvuru; std :: atomic beklendiği gibi çalıştı. Mantıklı gibi. – Amomum

+0

@Amomum: gcc kurulumunuz normalde 'libgcc.a'dan yardım fonksiyonlarına ihtiyaç duyduğunda çalışır mı? Bu bir gcc hatası veya yanlış yüklenmiş bir derleyici sorunudur. 64bit bölümünün benzer bir yardımcı işlevini çağırması olasıdır. Uint64_t'nin –

+0

bölümü, beklendiği gibi __aeabi_uldivmod çağırır. Bunun bir hata olduğunu düşünmüyorum, belki atom uint64_t uygulamak gerçekten mümkün değil mi?Bazı mimarların örneğin uint8_t içermemesi normaldir (eğer CHAR_BITS 8'den büyükse); Bu yüzden __atomic_fetch_add_8 'un bu kadar büyük bir sorun olmadığını düşünmüyorum. – Amomum

İlgili konular