組み込みのマシン コード (たとえば、x86 アーキテクチャを想定) を使用して、アトミックな比較と整数値のスワップを行う C の関数をどのように記述しますか? i7 プロセッサ専用に書かれている場合、より具体的に言えますか?
変換はメモリ フェンスとして機能しますか?それとも、比較とスワップに含まれるそのメモリ位置だけで順序付け関係を保証するだけですか? メモリフェンスと比較してどれくらいコストがかかりますか?
ありがとうございました。
組み込みのマシン コード (たとえば、x86 アーキテクチャを想定) を使用して、アトミックな比較と整数値のスワップを行う C の関数をどのように記述しますか? i7 プロセッサ専用に書かれている場合、より具体的に言えますか?
変換はメモリ フェンスとして機能しますか?それとも、比較とスワップに含まれるそのメモリ位置だけで順序付け関係を保証するだけですか? メモリフェンスと比較してどれくらいコストがかかりますか?
ありがとうございました。
アトミック実行にはプレフィックスCMPXCHG
付きの命令を使用できます。LOCK
例えば
lock cmpxchg DWORD PTR [ebx], edx
また
lock cmpxchgl %edx, (%ebx)
これにより、EAXレジスタの値がEBXレジスタに格納されているアドレスの値と比較され、EDXレジスタの値が同じ場合はその場所に格納されます。それ以外の場合は、EBXレジスタに格納されているアドレスの値がにロードされます。 EAX。
この命令を使用するには、486以降が必要です。
これを行う最も簡単な方法は、おそらく_InterlockedCompareExchange()のようなコンパイラ組み込みを使用することです。これは関数のように見えますが、実際には単一のマシン操作に要約されるコンパイラーの特殊なケースです。MSVC x86 組み込みの場合、これは読み取り/書き込みフェンスとしても機能しますが、他のプラットフォームでは必ずしもそうではありません。(たとえば、PowerPC では、lwsyncを明示的に発行して、メモリの並べ替えをフェンスする必要があります。)
一般に、多くの一般的なシステムでは、コンペア アンド スワップ操作は通常、接触している 1 つのアドレスに対してのみアトミック トランザクションを強制します。他のメモリ アクセスは並べ替えることができ、マルチコア システムでは、スワップしたメモリ アドレス以外のメモリ アドレスがコア間で一貫していない可能性があります。
整数値が 64 ビットの場合は、IA32 x86 で cmpxchg8b 8 バイトの比較と交換を使用します。変数は 8 バイトにアラインされている必要があります。
Example:
mov eax, OldDataA //load Old first 32 bits
mov edx, OldDataB //load Old second 32 bits
mov ebx, NewDataA //load first 32 bits
mov ecx, NewDataB //load second 32 bits
mov edi, Destination //load destination pointer
lock cmpxchg8b qword ptr [edi]
setz al //if transfer is succesful the al is 1 else 0
興味深いことに、一部のプロセッサは比較交換を提供していませんが、代わりに、残念ながら名前の付いた比較と交換 (名前は「compare-exchange」に似ているように聞こえますが、実際には「compare-and-store」と呼ばれる必要があります。これは、比較を行い、値が一致した場合に格納し、値が一致して格納が実行されたかどうかを示すためです)。命令は、比較交換セマンティクス (比較が失敗した場合に読み取られた値を提供する) を合成できませんが、場合によっては、比較交換に存在する ABA 問題を回避できます。多くのアルゴリズムは、両方のスタイルの CPU で使用できるため、「CAS」操作に関して説明されています。
「Load Linked」命令は、プロセッサにメモリ位置を読み取り、それが書き込まれる可能性があるかどうかを何らかの方法で監視するように指示します。「Conditional Store」命令は、最後の「Load Linked」操作以降に何も書き込まれなかった場合にのみ、メモリ ロケーションに書き込むようにプロセッサに指示します。決定は悲観的である可能性があることに注意してください。たとえば、割り込みを処理すると、「Load-Linked」/「Conditional Store」シーケンスが無効になる場合があります。同様に、マルチプロセッサ システムでは、監視されている実際の場所に触れていなくても、監視されている場所と同じキャッシュ ライン上の場所にアクセスする別の CPU によって LL/CS シーケンスが無効になる場合があります。通常の使用法では、LL/CS は非常に近くで一緒に使用され、再試行ループがあり、