ARM CM3 islemcilerde CLREX, LDREX ve STREX komutlari

Mikro Step

Kıdemli Üye
Katılım
25 Eylül 2022
Mesajlar
3,846
Bu komutlari faydali bir iste kullanmak istiyorum fakat olayi tam kavrayamadim.

Cok cekirdekli islemciler beni ilgilendirmiyor ve tek cekirdekte bu komutu kullanmak istiyorum.

CLREX isletildiginde senkronizasyonu bozuyor.

LDREX R1, [Adres] ; ile Adresdeki veriyi okuyoruz. Ardindan
....
....
STREX R0, R2, [Adres] ; Adrese R2 icerigini yaziyoruz.

Eger bu yazma islemi sonucunda R0=0 olduysa islem basarili, 1 olduysa hata var anlamina geliyor.
LDREX ardindan STREX kullaninca zaten hata olusmuyor.

Tamam adamlar boyle bir mekanizma kurmuslar.

Fakat LDREX ile okudugum adresden farkli bir adrese STREX ile erisim yaparsam da sonuc basarili oluyor.

Yani basarili olmak icin LDREX ardindan STREX isletmek yeterli. Adresin ayni olup olmamasi onemli degil. Hatta dokumanlarda yazilanin aksine okuma ve yazma komutlarinin ayni boyutta veri islemesi de onemli degil. (Byte okuduysan byte yaz, word okuduysan word yaza da gerek yok)

STREX ardindan bir daha STREX isletirsek hata aliyoruz.

Ya da LDREX CLREX STREX dizilimi da hataya neden oluyor.

Dolayisi ile bu 3 lu komutu cok ise yarar bulmadim ve faydali bir amac icin kullanamiyorum.

Anladigim kadariyla bir flag var. Hedef adresden okunacak yada yazilacak veriyi dusunmezsek,

LDREX bu flagi temizliyor.
CLREX flagi set ediyor.
STREX Flag temiz ise gozleme registerine 0, flag set ise gozleme registerine 1 atiyor. Flagi tekrar set ediyor.

Tamam da bunlarla nerede nasil ise yarar bir kod yazabiliriz?
 
Soyle bir ornek kod buldum. Fakat nerede isime yarar anlamadim.

Ana programla int program arasinda kullanilan ortak bir degisken uzerinde maniplasyon yapmak istesem de nasil isime yarayacak?

Lock address : LockAddr
Lock free : 0x00
Lock taken : 0xFF

MOV R1, #0xFF ; load the 'lock taken' value
try LDREX R0, [LockAddr] ; load the lock value
CMP R0, #0 ; is the lock free?
STREXEQ R0, R1, [LockAddr] ; try and claim the lock
CMPEQ R0, #0 ; did this succeed?
BNE try ; no - try again . . . .
; yes - we have the lock
 
Son düzenleme:
multithreaded programlamada kullanılan mutex yapısına karşılık gelen komutlar bunlar. Yani birden fazla paralel program çalışıyor iken, atomik olarak set/clear edilebilen bir flag gibi düşünülebilir. Veya ana program ve bir kesme de olabilir, neticede burada da paralel iki program çalışmış oluyor.

Örnek bir uygulama: Programda iki thread çalışıyor. İkisinin paylaştığı bir queue var. Queue eğer bu xxxEX ile gerçekleştirilmiş bir flag ile korunursa, belli bir anda sadece bir thread'in queue yu değiştirebildiğini garanti edebilirsin.
 
Su siralar iki threadden olusan bir program yaziyorum. Baslikta gecen komutlarin bu tip islere yarayacagini dusunuyordum fakat ilk kez simdi kullanmak istedim fakat halen nasil kullanacagim konusunda tereddutlerim var.

Siradan ram uzerine verilerimi yazip bir flag ile diger threadi bilgilendirmek varken bu clrex, ldrex, strex bana ciddi bir kolaylik getirecekse de halen bu kolayligi goremedim.
 
Eğer böyle bir flag kullanmadan iki thread çalıştırırsan, "race condition" denen durumlar ortaya çıkıyor. Mesela şu senaryonu düşünelim:

İki thread var, T1, T2. Bir tana queue var, Q. Q nun içinde kaç mesaj olduğunu ifade eden de count değişkeni var, Q.count.

T1, Q ya mesajı yazıyor, Q.count bir arttırılıyor. T2, Q.count'un sıfırdan farklı olduğunu görüyor, mesajı işliyor ve Q.count'u bir azaltıyor. Böyle bir programı gerçekleştirip çalıştırınca, özellikle de birden fazla çekirdeğe sahip işlemcilerde, bir süre sonra saçmalamaya başladığı görülüyor, Q yapısı bozulur ve birşeyler sapıtır, çünkü Q yu iki thread de aynı anda kurcalıyor.

Ama ATOMİK olarak set/clear/test edilebilen bir flag olursa o zaman her thread güvenli bir şekilde bu flag'ı test edebilir ve izin varsa Q yu kurcalar. Ve kurcalarken de, aynı flag'dan geçen başka hiçbir thread'in Q yu kurcalayamayacağından emin olur.

Race condition konusunu daha iyi anlamak için paralel programlama ile ilgili google'da "dining philosophers problem" araştırabilirsin. Biz personel alımlarında potansiyel yazılımcılar ile interview yaparken benim sorduğun sorulardan birisiydi bu :)
 
Bu 3 komut hakkinda derli toplu bir anlatim yok. Benim gibi bu komutlara takmis kisilerin tartistigi ortamlarda context saving isleminde resetleniyor vs denmisti.

Gercekten de main rutinde ldrex ile okuyup yazma isini int rutinine birakirsam yazma islemi basarisiz oluyor. Bu da buyuk bir ip ucu oldu.
 
LDREX ardindan STREX ile yazma islemi yapilmak istensin.
Yani hey diger Task ben bu flagi okudum simdide degerini degistirecegim demek istensin.

Fakat STREX isletilemeden daha once algilanmis int cevaplansin. int rutininden geri gelindiginde STREX basarisiz oluyor.

Burdan sunu anliyoruz. Ben flagi okudum tam yazacaktim araya bir baska task girdi artik bu okudugum degere guvenem bir daha okuyum ardindan degerini degistireyim. Belkide task bana bir sey demek istedi yorumunu yapmama imkan taniyor.

Eger bu mekanizma olmamis olsaydi bir adresdeki veriyi okuyup degerini degistiremeden int gelse ve cevaplansaydi ve int rutini de bu adresi degistirseydi int dan geri donuste bundan haberdar olamayacaktik cunku adresi degistirme komutu henuz isletememistik.

Guzel bir uclu imis. Hakkiyla kullanabilmek icin biraz pratik yapmak gerekecek.

Yalniz cok yetersiz bir mekanizma. Cunku kod denemelerimden anladigim kadariyla koskoca programda sadece bu is icin tek bir flag kullanabiliyoruz.

Yani koskoca memory alaninda sadece bir adres icin gozetim yapabiliyoruz. (Umarim yaniliyorumdur)
 
openchat dan rica ettim bana asagidaki kodu yazdi.

.section .text
.syntax unified
.thumb

// Global variable shared between tasks
.global shared_var
.type shared_var, %object
shared_var:
.word 0x00000000

// Task 1: increment shared variable
.task1:
mov r0, #1 // Load value to increment
mov r1, #1 // Loop counter
loop1:
ldrex r2, [shared_var] // Load exclusive
add r2, r0 // Increment value
strex r3, r2, [shared_var] // Store exclusive
cmp r3, #0 // Check store success
bne loop1 // Try again if failed
subs r1, #1 // Decrement loop counter
bne loop1

// Task 2: read shared variable
.task2:
mov r1, #10 // Loop counter
loop2:
ldrex r0, [shared_var] // Load exclusive
cmp r0, #0 // Check value
beq loop2 // Retry if zero
mov r2, #1 // Signal success
clrex // Clear exclusive
b end2
loop2_fail:
mov r2, #0 // Signal failure
end2:
subs r1, #1 // Decrement loop counter
bne loop2

// Endless loop
endless:
b endless
 

Forum istatistikleri

Konular
5,883
Mesajlar
100,318
Üyeler
2,491
Son üye
djkop

Son kaynaklar

Son profil mesajları

gruptaki arkadaşlara selamlar. sıteyi bu gün fark ettim. Asansör için 2x7 segment LCD gösterge üretmek istiyorum. acaba bu sayfadaki arkadaşlardan destek alabilirmiyim. LCD nin mantık açılımı ektedir.
deneyci wrote on TA3UIS's profile.
Selam.
Amatör telsiz lisansı nasıl alınıyor?
Lisansı olmayanı forumlarına almıyorlar. :)
Bilgi alamıyoruz.
cemalettin keçeci wrote on HaydarBaris's profile.
barış kardeşim bende bu sene akıllı denizaltı projesine girdim ve sensörleri arastırıyorum tam olarak hangi sensör ve markaları kullandınız yardımcı olabilir misin?
m.white wrote on Altair's profile.
İyi akşamlar.Arabanız ne marka ve sorunu nedir.Ben araba tamircisi değilim ama tamirden anlarım.
* En mühim ve feyizli vazifelerimiz millî eğitim işleridir. Millî eğitim işlerinde mutlaka muzaffer olmak lâzımdır. Bir milletin hakikî kurtuluşu ancak bu suretle olur. (1922)
Back
Top