web-dev-qa-db-ja.com

x86で自然にアラインされた変数アトミックの整数割り当てはなぜですか?

私はこれを読んでいます 記事 アトミック操作について、変数が自然にアラインされている限り、x86では32ビット整数の割り当てがアトミックであると述べています。

自然な配置が原子性を保証するのはなぜですか?

31
timlyo

32ビット以下のオブジェクトがメモリの「通常の」部分内で自然にアラインされる場合、80386または80386sx以外の互換プロセッサが、1回の操作でオブジェクトの32ビットすべてを読み書きすることが可能になります。プラットフォームが迅速かつ便利な方法で何かを実行できることは、必ずしも何らかの理由でプラットフォームが他の方法で実行できないことを必ずしも意味しませんが、すべてではないにしても多くのx86プロセッサでそれが可能であると私は信じています一度に8ビットまたは16ビットのみにアクセスできるメモリ領域がある場合、メモリの「通常の」領域への32ビットアクセスの整列を要求すると、システムに読み取りが発生するような条件をIntelが定義したことはないと思います全体を読み書きせずに値の一部を書き込む場合、私はインテルがそのようなものをメモリの「通常の」領域に対して定義するつもりはないと思います。

6
supercat

自然に整列するとは、型のアドレスが型のサイズの倍数であることを意味します。

たとえば、バイトは任意のアドレスに配置でき、short(16ビットと想定)は2の倍数でなければならず、int(32ビットと想定)は4の倍数でなければならず、long(64ビットと想定)は8の倍数である。

自然にアライメントされていないデータにアクセスした場合、CPUはフォールトを発生させるか、メモリの読み取り/書き込みを行いますが、アトミック操作としては行いません。 CPUが実行するアクションは、アーキテクチャによって異なります。

たとえば、以下のメモリレイアウトの画像です。

01234567
...XXXX.

そして

int *data = (int*)3;

*dataを読み取ろうとすると、値を構成するバイトが2つのintサイズのブロックに分散され、1バイトはブロック0-3にあり、3バイトはブロック4-7にあります。さて、ブロックが論理的に隣接しているからといって、物理的に隣接しているとは限りません。たとえば、ブロック0〜3はCPUキャッシュラインの最後にあり、ブロック3〜7はページファイルにあります。 3バイトを取得するためにCPUがブロック3-7にアクセスすると、ブロックがメモリ内にないことがわかり、メモリをページインする必要があることを通知します。これにより、OSの呼び出しプロセスがブロックされる可能性があります。メモリをページインします。

メモリがページインされた後、プロセスが再開する前に別のプロセスが発生し、Yをアドレス4に書き込む場合があります。次に、プロセスが再スケジュールされ、CPUが読み取りを完了しますが、期待したXXXXではなくXYXXを読んでください。

2
Sean

なぜそれがそのように設計されているのかと尋ねたなら、私はそれがCPUアーキテクチャの設計からの良い副産物だと思います。

486時代に戻ると、マルチコアCPUまたはQPIリンクがないため、その時点では原子性は実際には厳密な要件ではありません(DMAがそれを必要とする場合がありますか?)。

X86では、データ幅は32ビット(またはx86_64の場合は64ビット)です。つまり、CPUは最大1回のショットでデータ幅を読み書きできます。また、メモリデータバスは通常、この数と同じかそれ以上です。整列されたアドレスの読み取り/書き込みがワンショットで行われるという事実と組み合わせると、読み取り/書き込みが非アトミックになるのを妨げるものは当然ありません。同時にスピード/アトミックを獲得します。

1
Wei Shen

最初の質問に答えるために、変数は、そのサイズの倍数であるメモリアドレスに存在する場合、自然にアラインされます。

リンクした記事と同様に割り当て手順のみを考慮した場合、MOV(割り当て手順)は設計上のアラインメント上のアトミックであるため、アラインメントはアトミック性を保証しますデータ。

他の種類の命令、たとえばINCは、[〜#〜] lock [〜#〜] edである必要があります(期間中、現在のプロセッサに共有メモリへの排他的アクセスを提供するx86プレフィックス)接頭辞付きの操作の場合)複数のステップ(=命令、つまりロード、インク、ストア)を介して実際に実行されるため、データが整列されている場合でも.

0