適用範囲:DS-5, RealView Development Suite (RVDS), ARM Developer Suite (ADS)
SWPおよびLDREX/STREX命令とは?
SWP(ARMv6アーキテクチャ以前)およびLDREX/STREX(ARMv6以降)はマルチマスタシステムサポートのために設計された命令です。例えば、DMAコントローラのような他のバスマスタを伴うシステムやマルチコアシステムなどです。これらの基本的用途は、同時に2つのマスタによる競合アクセスを避けることによってマスタ間の通信中にデータ共有の完全性を管理することにあります。例:共有メモリの同期
SWPはmutexやセマフォのための基本構成ブロックとして使用することができるアトミックなロードおよびストア処理を提供します。
ARMv6は同期の基礎となるペアを持ちます。LDREXとSTREXはバスマスタに他のマスタが排他アクセスを要求されるアドレスに対して書き込みを行ったかを検知させることができます。様々な高度なロックを構成するために使うこともできます。LDREX/STREXの利点は、バス上の他のトランザクションを妨げないことです。これに対して、SWPを実行するコアはHLOCK信号のアサートによって、命令が完了するまでバスを保持します。
これらの命令は割り込みの無効を必要とすることなく、mutex、セマフォなどを実装したシングルマスタシステム上でも有用です。同様にマルチスレッドシステムでも有用です。
SWPはアーキテクチャARMv6以降では非推奨です。v6およびそれ以前のコア(ARM11以前)では代わりにLDREX/STREX命令を使うべきです。ARMv7では、byte、harfwordおよびdoubleバージョンの同期の命令が追加されました:
LDREXB/STREXB
LDREXH/STREXH
LDREXD/STREXD
より詳細については、ARM Architecture Reference ManualおよびAMBAのドキュメントを参照してください。
Cコンパイラの振舞い
Cコンパイラは純粋なCソースコードをコンパイルした場合、SWPおよびLDREX/STREXのいずれも生成しません。これは、C(およびC++)の言語仕様では、このような処理について触れていませんし、これらの命令に割り当てられた言語の演算子がない為です。
しかしながら、以下の方法でこれらの命令にプログラム中からアクセスすることができます:
コンパイラ組み込み関数を使用した例:
__ldrex(); __strex();
組み込みアセンブラを使用した例:
/* Embedded assembler to access the SWP instruction */ __asm atomic_swap(unsigned int read, unsigned int write, unsigned int addr) { SWP r0,r1,[r2] }
__ldrexと__strex組み込み関数は第2パラメータのサイズによってLDREXB/STREXB, LDREXH/STREXHまたはLDREX/STREXを生成します。
例:
__ldrex( (char *) ptr ) // generates LDREXB __ldrex( (short *) ptr) // generates LDREXH __ldrex( (int *) ptr ) // generates LDREX
RVCT v3.1以降は新しい組み込み関数__swp, __ldrexおよび__strexが、RVCT v4.0以降のバージョンでは、同じく新しい組み込み関数__ldrexdおよび&color(blue__strexd};が追加されました。
もし__ldrexと__strexがLDREXおよびSTREX命令をサポートしていないCPUターゲット用に使用されると、エラーが生成されます。
インラインアセンブラもSWPおよびLDREX/STREXをサポートします。