0

を使用している IRQ がありhandle_level_irq()ます。ほとんどの場合、ISR は下位半分をスケジュールする必要がありますが、場合によっては、それが偽であると判断でき、(パフォーマンス上の理由から) 下位半分をスケジュールしたくない場合があります。問題は、後者の場合、競合状態が発生することです。ISR がスプリアスであると判断した場合、割り込みのマスクを解除し、終了する準備をします (desc->lockこの時点では、ISR は によって保護されていないことに注意してください)。handle_level_irq()しかし、その後、2 番目の CPU で割り込みがトリガーされます。2 番目の CPU は、グラブに従ってdesc->lockIRQ をマスクし、1 番目の CPU で ISR が進行中であると判断するため、ロックを解除desc->lockして終了します。最初の CPU の元の ISR も終了し、割り込みは常にマスクされたままになります。

必要がない限り、下半分をスケジュールできないようにしたいので、上記の競合状態を回避しながら、ISR がマスクを解除する方法はありますか?

4

1 に答える 1

0

問題は、IRQ がレベル トリガーであり、スプリアス値があることです。偽の割り込みを受信して​​いる場合、レベル値はどのように解決されると考えられますか? つまり、スプリアスの性質上、割り込みは現在アクティブ レベルにあります。これが、偽の割り込みによる CPU のデッドロックを防ぐために、Linux が割り込みをマスクしている理由です。

割り込みレベルをエッジ トリガーに変更し、次のエッジでレベル トリガーに戻すことができます。これにより、ハードウェアがデアサートするまで、スプリアスレベルが無視されます。ハードウェアが割り込みを再度アサートすると、エッジが発生し、この時点でレベルのトリガーを再インストールできます。

このため、割り込みラインが共有されていない限り、ほとんどのペリフェラルはエッジ トリガーになります。この問題は、コードではなく、割り込みコントローラーにある可能性がありhandle_level_irq()ます。バージョンを指定していないか、使用するドライバーを提供していません。

回線が共有されておらず、コントローラーがエッジ トリガーをサポートしている場合は、エッジを使用するようにコードを変換します。ウィキペディアで詳細を参照してください。

于 2013-11-29T16:10:10.433 に答える