web-dev-qa-db-ja.com

ARM=

DSB、DMB、およびISBが命令の順序変更を防ぐための障害であることを理解しています。また、それぞれについて非常に優れた説明をたくさん見つけることができますが、それらを使用しなければならないケースを想像するのはかなり困難です。

また、オープンソースのコードから、時々それらの障壁を見かけますが、なぜそれらが使用されているのか理解するのは非常に困難です。例として、Linuxカーネル3.7のtcp_rcv_synsent_state_process関数には、次のような行があります。

    if (unlikely(po->origdev))
            sll->sll_ifindex = orig_dev->ifindex;
    else
            sll->sll_ifindex = dev->ifindex;

    smp_mb();

    if (po->tp_version <= TPACKET_V2)
            __packet_set_status(po, h.raw, status);

ここで、smp_mb()は基本的にDMBです。実際の例をいくつか教えていただけますか?障壁について理解を深めるのに役立ちます。

22
jaeyong

申し訳ありませんが、あなたが尋ねているような簡単な例を提供するつもりはありません。すでにLinuxのソースコードを調べているので、十分に検討する必要があり、それらは役に立たないようです。その点で恥はありません-すべての正気な人は、少なくとも最初はメモリアクセスの順序付けの問題によって混乱しています:)

あなたが主にアプリケーション開発者であるなら、あなたはそれについてあまり心配する必要がないあらゆる機会があります-あなたが使うどんな並行性フレームワークでもあなたのためにそれを解決します。

あなたが主にデバイスドライバーの開発者である場合、例は見つけるのがかなり簡単です-コードに以前のアクセスへの依存関係が影響を及ぼした場合(割り込みソースをクリアし、DMA =記述子)他のアクセスが実行される前に(割り込みを再度有効にして、DMAトランザクションを開始)。

並行性フレームワークを開発している(またはデバッグしている)場合は、おそらくもう少しトピックを読む必要があります-しかし、質問は、即時の必要性ではなく表面的な好奇心を示唆していますか?並行性フレームワークによって提供されるプリミティブに基づいていない、スレッド間でデータを渡すための独自のメソッドを開発している場合、それはすべての意図と目的のための並行性フレームワークです。

Paul McKenneyは、メモリバリアの必要性、およびプロセッサに実際にどのような影響があるかについて優れた論文を書いています。 メモリバリア:ソフトウェアハッカーのハードウェアビュー

それが少しハードコアすぎる場合は、もう少し軽量な3部構成のブログシリーズを書き、最後にARM固有のビューを示します。最初の部分は メモリアクセスの順序付け-はじめに です。

ただし、特にARMアーキテクチャの場合)、具体的な例のリストの場合は、 バリアリトマステストとクックブック よりもはるかに悪い結果になる可能性があります。

非常に軽量なプログラマーの見方であり、完全にアーキテクチャ的に正しいバージョンではないものは次のとおりです。

  • DMB-メモリアクセスが別のメモリアクセスに関して順序付けを必要とする場合。
  • DSB-プログラムの実行が進む前にメモリアクセスを完了する必要がある場合。
  • ISB-メモリマップの更新後や実行するコードの記述後など、プログラムの特定のポイントの後で命令フェッチを明示的に行う必要がある場合。 (実際には、これは「この時点でプリフェッチされた命令を破棄する」ことを意味します。)
35
unixsmurf

通常、メモリアクセスが特定の順序で発生することを確認する必要がある場合は、メモリバリアを使用する必要があります。これは多くの理由で必要になる場合があります。通常、2つ以上のプロセス/スレッドまたはハードウェアコンポーネントが同じメモリ構造にアクセスする場合に必要です。

DMA転送でよく使用されます。単純なDMA制御構造は次のようになります。

struct dma_control {
  u32 owner;
  void * data;
  u32 len;
};

所有者は通常、OWNER_CPUやOWNER_HARDWAREなどに設定され、2人の参加者の誰が構造での作業を許可されるかを示します。

これを変更するコードは通常次のようになります

dma->data = data;
dma->len  = length;
smp_mb();
dma->owner = OWNER_HARDWARE;

したがって、所有権がDMAハードウェアに転送される前に、lenのデータが常に設定されます。それ以外の場合、CPUがメモリアクセス。

同じことが、異なるコアで実行されているプロセスやスレッドにも当てはまります。は同様の方法で通信できます。

5
Nico Erfurth

バリア要件の簡単な例の1つは、スピンロックです。バリアなしで、compare-and-swap(またはARM上のLDREX/STREX)を使用してスピンロックを実装する場合、プロセッサはメモリから値を投機的にロードし、計算された値をメモリに遅延保存することができ、これらのいずれも発生する必要はありません。命令ストリーム内のロード/ストアの順序で。

特にDMBは、DMBを中心としたメモリアクセスの並べ替えを防ぎます。 DMBがない場合、スピンロックが解放された後、プロセッサはスピンロックによって保護されたメモリにストアを並べ替えることができます。または、プロセッサは、スピンロックが実際にロックされる前に、または別のコンテキストによってロックされている間に、スピンロックによって保護されたメモリを読み取ることができます。

unixsmurfはすでに指摘していますが、 バリアリトマステストとクックブック についても指摘します。バリアを使用する場所と理由のかなり良い例がいくつかあります。

3
rsaxvc