spin_lock_irqsave vs spin_lock_irq
-
23-09-2019 - |
質問
上で機械を使用 spin_lock_irqsave
ない spin_lock_irq
から割り込みコンテキスト
なぜうま保存したいるフラッグを含有の場合)?
しおりを付けることができ割込みルーチンを中断すか?
解決
私は、カーネルではなくから新しいです方法。あなたはフラグを保存し、フラグとそれを解放した場合、関数spin_lock_irqsaveはちょうど以前の状態に割り込みを返します。
spin_lock_irqsave
と例
spinlock_t mLock = SPIN_LOCK_UNLOCK;
unsigned long flags;
spin_lock_irqsave(&mLock, flags); // save the state, if locked already it is saved in flags
// Critical section
spin_unlock_irqrestore(&mLock, flags); // return to the formally state specified in flags
例(irqsaveなし)spin_lock_irq
と
spinlock_t mLock = SPIN_LOCK_UNLOCK;
unsigned long flags;
spin_lock_irq(&mLock); // Does not know if already locked
// Critical section
spin_unlock_irq(&mLock); // Could result in an error unlock...
他のヒント
spin_lock_irqsave
基本的には保存用の中断前の状態のスピンロックと、スピンロックを無効に割り込みの場合、ロックが割り込み処理の中のコンテキストの再可能にする場合が解除.そのため、割り込み状態が保存されるべきである復の割り込みます。
例:
- せん断x無効にしていた前にスピンロックが取得された
spin_lock_irq
今を無効に割り込みxのロックspin_unlock_irq
るように、割り込み。
このように3段階上解放後にロックして中断xを有効になった先に無効に以前のロックを取得しました。
その場合のみしたがって、これらの割り込みは無効にします spin_lock_irq
その他を使用 spin_lock_irqsave
.
spin_lock_irqsave
以外spin_lock_irq
の必要性がlocal_irq_save(flags)
がlocal_irq_disable
以外に必要とされる理由と非常によく似ています。ここではロバート・ラブによってLinuxカーネル開発の第二版から取られ、この要件の良い説明がある。
local_irq_disable()ルーチンは、割り込みがあった場合に危険です すでに前の呼び出しに無効。に対応するコール local_irq_enable()無条件にもかかわらず、割り込みを可能にします 彼らが開始するためにオフにしたという事実。代わりに、メカニズムが必要とされています 以前の状態に割り込みを復元します。これは共通の関心事であります カーネル内の指定されたコード・パスは、の両方に到達することができるためと 割り込みなしでコールチェーンに応じて、有効。例えば、 大きな機能の一部であるスニペット前のコードを想像してみてください。 一つは、この機能は他の二つの関数によって呼び出されることを想像してみて 割り込みを無効にしてないもの。それはなってきているので 難しいカーネルは、すべてのコードを知っているサイズと複雑になるにつれて パスが機能に至るまで、その状態を保存するためにはるかに安全です それを無効にする前に割り込みシステム。次に、あなたがする準備ができたら、 再度有効に割り込み、あなたは、単に元の状態に復元ます:
unsigned long flags;
local_irq_save(flags); /* interrupts are now disabled */ /* ... */
local_irq_restore(flags); /* interrupts are restored to their previous
state */
これらの方法はしたがって、マクロとして少なくとも部分的に実装されていること注 (unsigned long型として定義されなければならない)flagsパラメータであります 一見値渡し。このパラメータには含まれてい 割り込みの状態を含むアーキテクチャ固有のデータ システム。少なくとも一つのサポートアーキテクチャが組み込まれているので 値にスタック情報(エヘン、SPARC)、フラグを渡すことができません 別の関数に(具体的には、同じスタック上に残っている必要があります フレーム)。このため、保存するための呼び出しと呼び出しが復元します 割り込みは、同じ関数内で発生する必要があります。
以前のすべての機能は、両方の割り込みからと呼ばれることができ、 プロセスのコンテキストます。
読書 なぜカーネルコード実行中のスレッドに割り込みキです。 クロバート大好き 第, ようこ:
一部割り込みハンドラー( Linuxの場として早割り込みハンドラー)を実行 すべての障害の プロセッサー無効になります。を行います 確かに、割り込みハンドラ運行 なしに中断、早 可能です。では、すべての割り込み ハンドラの実行を現在の 割り込み線障害者すべての プロセッサです。これにより、二 割込みハンドラと同じ 割り込みラインを実行しません。 同時に行います。でも防止装置 ドライバーの作家を取り扱 再帰的障害、複雑な プラグインです。
は以下のLinuxカーネル4.15.18、内のコードの一部であるspiin_lock_irq()__raw_spin_lock_irq呼び出すことを示しています()。あなたは、コードの一部が、割り込み禁止の下に見ることができるようにしかし、それはすべてのフラグを保存しません。
static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)
{
local_irq_disable();
preempt_disable();
spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}
コードの下ショーはspin_lock_irqsave()現在のフラグの段階とプリエンプト無効を保存します。
static inline unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock)
{
unsigned long flags;
local_irq_save(flags);
preempt_disable();
spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
/*
* On lockdep we dont want the hand-coded irq-enable of
* do_raw_spin_lock_flags() code, because lockdep assumes
* that interrupts are not re-enabled during lock-acquire:
*/
#ifdef CONFIG_LOCKDEP
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
#else
do_raw_spin_lock_flags(lock, &flags);
#endif
return flags;
}
この質問は誤った主張から開始します。
On an SMP machine we must use spin_lock_irqsave and not spin_lock_irq from interrupt context.
どちらもこれらの割り込みから使用する必要がありますの
コンテキスト、SMP上またはUPに。いえ、spin_lock_irqsave()
ののより普遍的なものとして、割り込みコンテキストから使用することができます
(それは、割り込みや通常のコンテキストの両方で使用することができる)が、
あなたは、割り込みコンテキストからspin_lock()
を使用することになっています
通常の文脈からspin_lock_irq()
またはspin_lock_irqsave()
。
spin_lock_irq()
の使用はほとんど常に間違ったことです
このSMPまたはUPされ、割り込みコンテキストで実行します。それは働くこと
IRQを使用して実行ほとんどの割り込みハンドラは、ローカルで有効になっているので、
しかし、あなたはそれを試してみるべきではありません。