1

次の抜粋は、Web サイトhttps://lwn.net/Articles/262464/からの抜粋であり、共有データ構造 (作成された RCU 用) の読み取りの不一致を扱っています。

p = gp;
if (p != NULL) {
  do_something_with(p->a, p->b, p->c);
}

このコード フラグメントは、誤った順序付けの影響を受けないように見えるかもしれませんが、残念ながら、DEC Alpha CPU [PDF] と値推測コンパイラの最適化により、信じられないかもしれませんが、p->a、p->b、および p- の値が生じる可能性があります。 >c は p の値の前にフェッチされます! これはおそらく、コンパイラーが p の値を推測し、p->a、p->b、および p->c をフェッチし、次に p の実際の値をフェッチする、値推測コンパイラーの最適化の場合に最も簡単に確認できますその推測が正しかったかどうかを確認するために。この種の最適化は非常にアグレッシブで、おそらくめちゃくちゃですが、実際にはプロファイル駆動型の最適化のコンテキストで発生します。

上記のコードが、へのアクセスで誤った (*) 値を生成することを意図しているのかどうかは不明ですp->a書かれた(ソース内の)順序」は、まったく、当然のことながら、私にとっては問題ありません。

最初の解釈が正しければ、この種の動作を許容するシステム (コンパイラ) が壊れていると考えます。私の質問は、普及しているアーキテクチャ (アルファ) が既に消滅している可能性がある場合でも、これがまだ存在するかどうかです。

(*)p->aある記録とp->b別の記録、またはもっと悪いものに由来するという意味での誤った値

PS: チェックはしていませんが、gp変数が正しく装飾されていると想定していますatomic

4

1 に答える 1

1

C++

この記事は 2007 年に書かれたものなので、C++11 より前の日付です。

C++11 は、標準でスレッドに関するものを定義した最初のものであり、データ競合を構成するものと構成しないものを1定義しています。

現在のルールの下では、あなたの結論は基本的に正しいと思います-引用されたコード、評価p->ap->bおよび/または標準の要件に違反する場合p->c。NULL ポインターであっp==NULLても、目に見える効果はありませんでした)。p

C

ここでの話はほとんど同じです。C11 標準は、スレッド化と、それらを使用するときのシーケンス処理の仕組みを最初に定義したものです。したがって、この記事が書かれた時点では、標準にはそれに関する規則はありませんでした。彼らは同じ用語を使用していませんが、C と C++ の委員会はこれについて調整しているので、少なくとも 2 つの言語のルールがこの点で同じになるように意図していると思います。


1. とにかく、それはしようとします-メモリが機能する場合、2011 規格での定義方法にいくつかの穴が見つかったため、新しい規格で更新が行われました. しかし要点は、2011 年の標準より前は、試行さえしなかったということです。
于 2021-02-12T17:51:09.883 に答える