2017-03-09 162 views
0

私は以下の文書を読む:Barrier_Litmus_Tests_and_Cookbook、ARM。ARM Cortex-M4ミューテックスロック。 DMB命令

セクション7.2では、ミューテックス/セマフォを取得するコードを示します。

Loop 
    LDREX R5, [R1] ; read lock 
    CMP R5, #0 ; check if 0 
    STREXEQ R5, R0, [R1] ; attempt to store new value 
    CMPEQ R5, #0 ; test if store suceeded 
    BNE Loop ; retry if not 
    DMB 

LDREX命令は、メモリアドレスに対する排他アクセスを要求します。 STREXによる書き込みは、プロセッサに排他アクセス権がある場合にのみ成功します。 DMB命令を使用して、排他書き込みがすべてのプロセッサに確実に同期されるようにします。

私はそれに小さな問題があります。プロセッサがメモリアドレスへの排他的アクセスを有し、それをロックしていると仮定する。 STREX命令が終了すると、排他アクセスが削除されます。他のプロセッサは今からこのメモリにアクセスできます。ただし、書き込みはDMBが終了するまでプロセッサのキャッシュに残ります。最初のプロセッサがすでにロックしていて、まだRAMに同期されていないときに、別のプロセッサがロックへのアクセスを取得しようとするとどうなりますか?メモリアドレスは、最初のプロセッサに排他的にロックされているわけではありませんが、書き込みは完了していません。

誰でも説明できますが、なぜこれが機能し安全です。私はそれに私の問題があります。

+0

「DMB」は、メモリ階層(すなわちキャッシュ)内の様々な点までそれらを見えるようにすることによって、メモリアクセスを順序付ける。プロセッサが別のキャッシュをスヌーピングできるようにするには、キャッシュコヒーレンスメカニズムが必要です。仮定した状況は非常にうまくいく可能性があります。 ARMキャッシュは一貫しています。さらにオプションのない「DMB」はフルシステム同期を行いますが、私はそれが何を意味するのかはわかりませんが、私はメモリに書き込むことができます。 –

+3

「DMB」は、リード・モディファイ・ライトのアトミック性には必要ありません。 「DMB」は、*他の*メモリ操作がRMW操作に関して順序付けされることを保証する。 – EOF

+0

DMBは荷物を押して保管しておき、荷物を完成させてください。他の荷物を観察する前に、すべてのオブザーバーによってロックが成功していることを確認してください。他のメモリバリアを使用して、書き込みバッファやキャッシュなどをフラッシュするのと同じように。 –

答えて

2

私はあなたがそれを複雑にしていると思います。 amba/axiの仕様を見てください(また、マルチコアの皮質-m4はどこにありますか?)。 ldrex/strexは、マルチプロセッサチップ内のプロセッサ間でリソースを共有するためのものです。彼らはしばらくの間、他のものに間違って使われてきました。 ARMは残念なことに、これを正しく文書化するのは異常に悪い仕事でした。

ldrの排他的な部分は、processoridとアドレス(範囲)がテーブルに保存されていることです。 strexが起こると、そのアドレス(range)のprocessoridがEXOKAYと一致するかどうかチェックされ、OKAYではない場合はストアを実行してください。 Strexは何もクリアしていません。彼らは興味深いことに、このclrex命令を持っています。プロセッサIDは、ヒットしなかったり、テーブルを作成する方法によって、テーブルエントリを解放します。

私はこれを書いた後にこれを試してもよいが、あなたはldrexとstrexとstrexを、かなり確かに私は完全な大きさの腕にintした、皮質-m4 ldrex、strex、strex、clrex、ストリートと何が起こるか見る。

ldrex/strexはARMのロジックで動作することが期待されていますが、チップベンダーはサポートする必要はなく、(EXOKAYの代わりに)OKAYを返すだけです。 L1は確かにそしておそらくL2はあなたがチップベンダーに入ることを超える腕の論理です。 (cortex-msにはl2がありますか?)通常は、チップベンダのコードを叩くことを心配する必要はありません。キャッシュの1つに残るので、無期限に実行すると長時間実行できます。例えば、Linuxで両方のキャッシュを無効にすることはロイヤルPITAです。コンパイル時のオプションのように思えるかもしれませんが、現実を掘り下げて見てください。そして、1つのプロセッサだけでは、どのように異なるプロセッサIDを取得しますか?

マルチプロセッサチップでは、チップベンダーは排他的アクセス権を持っていてもキャッシュを超えて正しくサポートするはずです。ldrex/strexが通常どおりに使用されているか、L1チップベンダーが提供したものにさらされることはありませんが、途中で中断され、L2によって保存される可能性があります。この場合、複数のプロセッサが存在するため、チップ内に複数のプロセッサIDを持つことは理にかなっています。

これは

のCortex-M4プロセッサは、ローカル排他モニタを実装していいです。 プロセッサ内のローカルモニタは、 が物理アドレスを保持せず、その代わりに以前のLDREXのアドレスと一致するすべてのアクセスを として扱うように構成されています。これは、 が排他予約顆粒を実装したことがメモリ全体が の範囲であることを意味します。

m7 trmは同じことを言います。

複数のコアを持たない場合どのようにして異なるIDを生成できますか? ドキュメントでは、プロセッサIDという用語を使用して、使用されているプロセッサを示しています。どのように多くのプロセッサが皮質にありますか?他の文字列/名前を使用して別の場所で文書化されているかもしれませんが、現時点では、cortex-mのprocessoridがどのように生成され、ユニプロセッサであるかはわかりません。私は確かに知るためにコアにアクセスできない。

論理がアドレスごとの排他アクセスをサポートしていないにもかかわらず、プロセッサIDをチェックしなかったとは言わず、sharedとしてマークされたメモリのすべてのstrexアクセスを、最後のldrexのprocessoridそのアドレスの。

00000001 
00000001 
00000001 
00000600 <-- ldrex 
00000000 <-- strex pass 
00000001 <-- strex fail 
00000001 
00006666 
00000000 
00000001 
00006666 
00007777 
00000800 
AABBCCDD 
00006666 
00000001 
00006666 

を生産

EDIT

PUT32(0x01000600,0x600); 
PUT32(0x01000700,0x700); 
PUT32(0x01000800,0x800); 
CLREX(); 
hexstring(STREX(0x20000600,0x12345678)); 
hexstring(STREX(0x20000700,0x12345678)); 
hexstring(STREX(0x20000800,0x12345678)); 
hexstring(LDREX(0x20000600)); 
hexstring(STREX(0x20000600,0x6666)); 
hexstring(STREX(0x20000700,0x12345678)); 
hexstring(STREX(0x20000800,0x12345678)); 
hexstring(LDREX(0x20000600)); 
hexstring(STREX(0x20000700,0x7777)); 
hexstring(STREX(0x20000800,0x12345678)); 
hexstring(GET32(0x20000600)); 
hexstring(GET32(0x20000700)); 
hexstring(GET32(0x20000800)); 
CLREX(); 
hexstring(0xAABBCCDD); 
hexstring(LDREX(0x20000600)); 
CLREX(); 
hexstring(STREX(0x20000600,0x2222)); 
hexstring(GET32(0x20000600)); 

は、彼らがここで何をしたかのように見えるLDREXは、アドレスとは独立して通過した後の次のSTREXです。だからあなたの言葉を使って、ストリートは "ロックをクリア"します。

ldrexとstrexの間にclrexを置くと、strexが失敗することに注意してください。同じアドレスを打っていない

は結果を変更問題1 LDREX didntの上のデータキャッシュを回す

hexstring(LDREX(0x20000900)); 
hexstring(STREX(0x20000900,0x2222)); 
hexstring(STREX(0x20000900,0x2222)); 

3EEDCC1B 
00000000 
00000001 

STREX 1にdoesntの。

テスト機能:兄付ARMとは異なり

.thumb_func 
.globl LDREX 
LDREX: 
    ldrex r0,[r0] 
    bx lr 

.thumb_func 
.globl CLREX 
CLREX: 
    clrex 
    bx lr 

.thumb_func 
.globl STREX 
STREX: 
    strex r0,r1,[r0] 
    bx lr 

CLREX(); 
hexstring(STREX(0x20000600,0x12345678)); 
hexstring(LDREX(0x20000600)); 
hexstring(STREX(0x20000600,0x6666)); 
hexstring(LDREX(0x20000600)); 
PUT32(0x20000600,0x11); 
hexstring(STREX(0x20000600,0x6666)); 

00000001 
00000600 
00000000 
00006666 
00000000 

STREXは、少なくともあなたは非排他的な店舗を掲載文書に基づいて、その間の非排他的アクセスを存続以前のldrex(armv7-a上)を台無しにするはずです。上記

注チップ設計者は、それが安全になりますので、それが安全であるのCortex-M4 r0p1 CPUID 0x410FC241に

0

です。 Test_and_Set命令の全体のポイントは、セマフォおよびミューテックスコマンドのためにオペレーティングシステムによって使用される。マルチコア/マルチプロセッサ環境では、組み込みアセンブリコマンド以外の方法でこの機能を正確に実装する方法はありません。