1

メモリバリアの使用について理解できないことがあり、明確化を望んでいます。

したがって、Treibers スタックがあり、SMR を使用しているとします。したがって、各ポインターに関連付けられたカウンターはありません。アトミック操作でポインターを正しく取得する必要があります (これは ABA に関するものではありません。SMR を使用しています。それはABAを扱っていますが、それは問題の一部ではありません)。

ここで、Intel (x86/x64) で作業していると仮定して、すべての CAS に完全なメモリ バリアが付属しているとします。キャッシュラインがロックされ、読み取りバリアが発行され、無効化キューがクリアされ、キャッシュラインがロードされ、そのキャッシュラインの最新バージョンが読み込まれ、比較が行われ、書き込みバリアが発行されると、CASing が発生すると思います発行し、ストア バッファをフラッシュし、最後にキャッシュ ライン ロックを解放します。

したがって、次の pop のコードがあります。

BARRIER_PROCESSOR_READ;

original_top = stack_state->top;

do
{
  if( original_top == NULL )
    return( 0 );

  copy_of_original_top = original_top;

  original_top = compare_and_swap( &stack_state->top, original_top->next, original_top );
}
while( copy_of_original_top != original_top );

*user_data = original_top->user_data;

したがって、最初に読み取りバリアを発行します。これにより、無効化キューを確実にフラッシュします。しかし、そうすることと、state_state->top を読み取ることの間にギャップがあります。無効化キューをクリアしてから state_stack->top を読み取るまでの間に、何かが起こる可能性があります。コアは割り込みを処理し、バスの競合が発生し、非常に遅くなる可能性があります。名前を付けると、無効化されたキャッシュラインが再ロードされる可能性があります (別のプロセッサによって再度無効化される可能性があります)。基本的に - 無効化キューは補充できます。つまり、original_top の値を実際に信頼することはできません。実際には間違っているローカル キャッシュ ラインを読み取っている可能性があり (まだ無効化していません)、そうすることで、その値が NULL であると誤って認識し、0 を返します。

したがって、基本的に、読み取りバリアがどのように役立つかはわかりません。バリアの後でも、実行したい実際の読み取りの前に何かが起こる可能性があるためです。

ここで何が欠けていますか?

4

2 に答える 2

1

私はあなたの質問を完全には理解していませんが、詳細が抜けているのではないかと強く思っています。

メモリ フェンシングは、プロセスを同期するためではなく、変更の可視性を保証するために使用されます。フェンシングだけでは、データへのアクセスはロックされません。

一方、アトミック操作とロック (ミューテックス、クリティカル セクション、セマフォ、その他の同期プリミティブなど) の両方は、特定のメモリ領域に 1 つのスレッドのみがアクセスすることを保証します (すべてのアクセスは、「所有」しているときに発生するようにコード化されていると仮定します)。そのようなロックまたはアトミックに)。ただし、順序付けされた可視性は保証されません。

両方が必要な場合は、排他的アクセスフェンシングの両方が必要です (注意: フェンシングは通常、mutex などの高レベルの同期プリミティブの一部として既に実装されているため、それらを使用する場合は、フェンシングについて明示的に心配する必要はありません)。

于 2012-09-21T11:50:24.963 に答える
0

あなたの質問を完全に理解しているかどうかはわかりませんが、読み取りバリアを発行した後、後続の読み取りは、バリアの前に発生した読み取りの後に確実に順序付けられます。BARRIER_PROCESS_READ がどのように定義されているかによっては、後続の読み取りで、プロセッサ固有のキャッシュ ラインではなく、共有メモリからデータをプルするように強制することもできます。これにより、他のプロセッサで実行された書き込みが表示されるようになります (これらの書き込みの後に適切な書き込みバリア!)。

これらのことは、割り込みが存在する場合でも当てはまります。読み取りバリアの直後に割り込みハンドラー内からキャッシュ ラインがいっぱいになった場合でも、それらのキャッシュ ラインからの読み取りによって、読み取りバリアのセマンティクスに関して有効な値が得られます。

あなたが提供したコードサンプルでは、​​読み取りバリアの目的は、実際には他のプロセッサによる書き込みを可視化し、次の行original_top = stack_state->top; が読み取り後にローカルにキャッシュされた値ではなく、新しい値を取得することであると思われますバリアの前に発生しました。割り込みハンドラが同じアドレスを読み取った場合でも、この制約は当てはまります。読み取られた値は「新鮮」ではありませんが、少なくとも無制限にキャッシュされた値ではありません。

于 2012-09-21T11:47:49.177 に答える