2011-01-19 8 views
6

Understanding the Linux kernel (Bovet & Cesati),て読んでいたカーネル同期の章では、スピンロックの取得コードがに沸くと述べている:Linux/SMPスピンロックが不必要に遅くなっていますか?

1: lock: 
    btsl $0, slp 
    jnc  3 
2: testb $1, slp 
    jne  2 
    jmp  1 
3: 

今、私はもともとループを入れ子にしているために、あなたのようなものを実装することができ、無駄なように見えたと思いました:

1: lock: 
    btsl $0, slp 
    jc  1 

これはずっと簡単です。しかし、lockが他のCPUに影響を及ぼし、btslのタイミングが単純なtestbのタイミングよりも大きいため、なぜ彼らはそれを行ったのか分かりません。

私がを持っていないことの1つは、が私の頭を浮かべることができなかったことです。その後のスピンロックのリリースです。この本は、それは次のように得られることを述べて:

lock: 
    btrl $0, slp 

私の質問は基本的になぜですか?lock/mov-immediateのコンボは高速です。

カーネルがバグフリー(カーネル内の他の多くの場所であることが前提)の規則に従って、古い状態は1になるので、キャリーフラグに古い状態を取得する必要はありませんあなたがまだそれを取得していなければそれをリリースしようとはしません)。

そしてmovbtrlよりもはるかに高速である、少なくとも386

にだから私は何をしないのですか?

後のチップでこれらの命令のタイミングが変更されましたか?

本の印刷以降にカーネルが更新されましたか?

本は間違っている(または簡略化された説明を表示していますか?

私は、より速い命令が満足しないCPU間の同期を含むいくつかの面を見逃しましたか?

答えて

10

まあ、Understanding the Linux Kernelは古いです。書かれて以来、Linuxカーネルは、いわゆるチケットスピンロックを使用するように更新されました。ロックは、基本的に2バイトで16ビットの数量に分割されます:Next(ディスペンサーの次のチケットのようなもの)と他のOwner(カウンター上の「現在のサービング」番号のようなもの)を呼び出しましょう。スピンロックは、両方の部分をゼロに設定して初期化されます。ロックは、スピンロックの値に注意して、アトミックに次の値をインクリメントします。増分前の次の値が所有者と等しい場合、ロックが取得されています。それ以外の場合は、所有者が正しい値に増分されるまでスピンします。

関連するコードはasm/spinlock.h(x86用)です。ロック解除操作が実際にはるかに高速かつシンプルなブックよりもこう述べています。

static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock) 
{ 
    asm volatile(UNLOCK_LOCK_PREFIX "incb %0" 
     : "+m" (lock->slock) 
     : 
     : "memory", "cc"); 
} 

incは約8または9倍高速btrよりからです。

希望します。もしそうでなければ、私はもっと深く掘り下げることができます。

関連する問題