0

プリエンプティブな Linux 3.0 カーネルを搭載した Android 組み込みプラットフォーム (Exynos5dual ベース) での wait_event と wake_up の奇妙な動作について質問があります。非プリエンプティブ カーネル (すべてのバージョン) を使用する通常の SMP ラップトップでは発生しません。

従来のスリーパー/ウェイカー シナリオの Linux デバイス ドライバーがあり、次のようになります。

T0: taskA:
    if(!flag)
        wait_event_interruptible_timeout(wq, flag==true, timeout=0.5sec)

T1: (after a few msec) taskB: 
    atomic set flag
    wake_up_interruptible()

T2: (after timeout msec) taskA: 
    wait_event_interruptible_timeout expires (ret 0) instead of waking up at T1

フラグのすべての読み取りと書き込みはアトミックであり、アトミック bitops (カーネル セット/テスト ビット) から揮発性の atom_t まで、atomic_t vars を使用した各読み取り/書き込み用のメモリ バリアの使用に移行しました (これによると)

TaskA が実際に待機を開始した場合 (wait_event_* カーネル関数が最初に条件をチェックするため、常にそうであるとは限りません)、フラグの値が変更され、wake_up() が呼び出されたときに taskB によってウェイクアップされるのではなく、完全なタイムアウトを待機します。

2 つのタスクが異なるコアで発生していると思われます。Core1 は、wait_event_..() の後にディープ スリープし、Core2 で発生する wake_up_interruptible() によってウェイクアップできません。

これが本当なのか、それとも他の何かが原因なのか、誰か知っていますか?

: スリーパーのタスク構造体 ptr を保存してから、wake_up_interruptible() の前に (およびそれに加えて) wake_up_process (saved_ptr) を実行すると、この問題は解決するようです。これは最適とは言えず、もっと良い方法はないかと考えています。

4

0 に答える 0