2012-02-15 56 views
13

最近、私は原子の読み書きのLinuxカーネル実装を検討し、いくつかの質問が出ました。 IA64アーキテクチャからLinuxカーネルでの原子操作の読み込みと書き込み

第1の関連コード:読み取りと書き込みの両方の動作について

typedef struct { 
    int counter; 
} atomic_t; 

#define atomic_read(v)  (*(volatile int *)&(v)->counter) 
#define atomic64_read(v) (*(volatile long *)&(v)->counter) 

#define atomic_set(v,i)  (((v)->counter) = (i)) 
#define atomic64_set(v,i) (((v)->counter) = (i)) 
  1. は、直接的なアプローチは、読み取りまたは変数への書き込みをしたと思われます。どこか別の仕掛けがない限り、私は、この操作がアセンブリドメイン内で原子的であることが保証されていることを理解していません。私は明らかな答えは、そのような操作は、1つのアセンブリopcodeに変換されますが、そのように、どのように考慮する別のメモリキャッシュレベル(または他の最適化)を考慮する保証はありますか?

  2. 読み取りマクロでは、キャストトリックで揮発性タイプが使用されます。誰もが、これがここでどのように原子性に影響するかを手がかりにしていますか?あなたが特定のアーキテクチャのために書く場合、あなたはそれに仮定を特定することができます

答えて

13

ここでは、「原子」と「揮発性」という言葉の使い方を誤解していると思います。 Atomicは、実際には、ワードが原子的に読み書きされることを意味します(1つのステップで、このメモリ位置の内容が常に1つの書き込みまたは他のものであり、その中間のものではないことを保証します)。そしてvolatileキーワードは、以前の読み込み/書き込み(基本的に読み込みを最適化しないでください)のために、その場所のデータを決して使用しないようにコンパイラに指示します。

"アトミック"と "揮発性"という単語がここで意味するのは、どのような形式のメモリ同期でもありません。また、いずれの読み書きバリアやフェンスも意味しません。メモリとキャッシュの一貫性に関しては何も保証されていません。これらの関数は、基本的にソフトウェアレベルでのみアトミックであり、ハードウェアは最適と判断することができますが、最適と判断されます。

ここで、単に読み込みが十分である理由について、各アーキテクチャのメモリモデルが異なります。多くのアーキテクチャでは、特定のバイトオフセットまたはxワードの長さなどにアライメントされたデータのアトミック読み取りまたは書き込みが保証され、CPUごとに異なります。 Linuxカーネルには、(実際には実際には実際には実際には保証されていないと言われているが実際には実際には)原子的な読み取り/書き込みを保証するプラットフォーム上で原子コール(基本的にCMPXCHG)書きます。 volatileについては

あなたはメモリマップドIOにアクセスしている場合を除き、それ一般的にのための必要はないが、それはすべて/なぜatomic_readatomic_writeマクロが呼び出されている場所時に/によって異なります。多くのコンパイラ(C仕様では設定されていませんが)は揮発性変数のメモリバリア/フェンスを生成します(GCC、私の頭の上から外れています、MSVCは確かです)。この場合、は通常を意味します。すべてこの変数の読み込み/書き込みは、仮想的な揮発性変数を作成することで、ほぼすべてのコンパイラの最適化から正式に除外されています最適化と再注文のための制限。

2

(それは書き込み操作で使用されていないことに注意してください)。
私はIA-64がこれらのことを単一の命令にコンパイルすると思います。

カウンタがキャッシュライン境界を超えていない限り、キャッシュは問題ではありません。しかし、4/8バイトアラインメントが必要な場合、これは起こり得ません。

機械命令が2つのメモリアクセスに変換する場合、「実」アトミック命令が必要です。インクリメント(読み込み、インクリメント、ライト)または比較&スワップの場合です。

volatileは、コンパイラが実行できる最適化に影響します。
たとえば、コンパイラが複数の読み込みを1つの読み込みに変換しないようにします。
しかし、マシンの命令レベルでは何もしません。

3

読み取りは、ほとんどの主要なアーキテクチャー上でアトミックであり、サイズの倍数に揃えられていれば(与えられたタイプの読み取りサイズよりも大きくない場合)、インテルのアーキテクチャーのマニュアルを参照してください。 Intelは、x86では、シングルバイト書き込みとアライメント書き込みはIPF(IA64)の下ではアトミックであり、すべてが獲得と解放のセマンティクスを使用しており、アトミック性を保証すると述べています。thisを参照してください。

volatileは、コンパイラが値をローカルにキャッシュしないようにします。そのため、コンパイラは値をローカルにキャッシュしないようにします。

+0

現代のカーネルでは、ここでは 'volatile'は' READ_ONCE() '/' WRITE_ONCE'と呼ばれるマクロを通して使用されます。私の頭の中の解釈は、コンパイラが技術的に値*複数*回の読み書きが許可されていることです。例えば。コードが読み取り値をローカル変数にコピーし、それを別の場所で使用する場合したがって、値をローカルにキャッシュされないようにするだけでは不十分です。完全な説明:https://lwn.net/Articles/508991/ – sourcejedi

関連する問題