ア | イ | ウ | エ | オ |
カ | キ | ク | ケ | コ |
サ | シ | ス | セ | ソ |
タ | チ | ツ | テ | ト |
ナ | ニ | ヌ | ネ | ノ |
ハ | ヒ | フ | ヘ | ホ |
マ | ミ | ム | メ | モ |
ヤ | ユ | ヨ | ||
ラ | リ | ル | レ | ロ |
ワ | ヰ | ヴ | ヱ | ヲ |
ン |
A | B | C | D | E |
F | G | H | I | J |
K | L | M | N | O |
P | Q | R | S | T |
U | V | W | X | Y |
Z | 数字 | 記号 |
メモリー操作をする命令の実行順序を維持する、プロセッサーの機能。メモリーフェンスとも。
現在のマイクロプロセッサーは、高速処理のための最適化として、アウトオブオーダー実行を導入するものが多い。この時、命令は並び替えられて処理されるが、この命令にはメモリーのロード命令やストア命令も含まれる。
この命令の入れ替えは、単一のスレッド内では破綻が生じないように動作するが、マルチスレッド環境では支障が出ることがある。そのような命令があった場合は、それらの命令の影響が全て完了した後で、後続の命令が実行されることを保証する動作のシーケンスが必要となる。
そこでこのような場合は、手動で(プログラマーによるプログラムの記述によって)アウトオブオーダー実行を一時的に抑止する必要があり、このような目的のための動作をメモリーバリアという。
x86の場合は、次の3命令が用意されている。
lfence (0F AE /5)
mfence (0F AE /6)
sfence (0F AE /7)
なお、lfenceは50サイクル強、sfenceは50サイクル弱程度の実行レイテンシーがあるが、mfenceは130サイクル程度を要し、非常に遅い命令の一つである。
例えば変数への代入を終えたあとフラグをセットする処理と、フラグがセットされたら変数を読みだして処理する処理があり、マルチスレッドで動作していたとする。この時、フラグのセットは非常に重要である。
フラグをセットする側の処理では、変数への代入とフラグのセットの間にsfenceを置き、確実に書き込まれてからフラグがセットされるようにする。
フラグを確認して処理する側では、フラグ確認と後の処理の間にlfenceを置き、フラグの確認が済む前に後の処理が実行されないようにする。
x86/x64アーキテクチャーにおいては、メモリーアクセスの順序保証が必要な場合でも、殆どの場合は明示的なメモリーバリア命令を使わずに済む。
C++のstd::atomicの実装においても、基本的には単純なmov命令を発行するだけでよい。ただしstd::memory_order_seq_cstだけはxchg命令か、movの後でmfence命令が必要になる。
ARMでは、ISB、DSB、DMBの各命令がある。
ARMの処理系では、例えば、次のような組み込み関数が用意される。動作は、単にDMB/DSB/ISB命令を発行するだけである。
また、より新しいバージョンのARM用C/C++コンパイラーでは、内部的にはchar型の引数を取る、次のような組み込み関数がある。
互換性のため、次のようなdefine文が定義されている。
#define __ISB() __isb(0xf); #define __DSB() __dsb(0xf); #define __DMB() __dmb(0xf);
この引数付きの組み込み関数のパラメータは、バリア命令にある4ビットのオプションフィールドにあてられ、オプションで処理中の制限を定義するために使われる。
命令のオペコードは次の通りである(x=option)。
コメントなどを投稿するフォームは、日本語対応時のみ表示されます