1

このことを考慮

ユーザープログラムのスレッド1:

buf = malloc(9000);
memset(buf, 0xee, 9000);
read(buf, 9000); //for example gives pages [part of 7, 8, 9, part of 10]

ユーザープログラムのスレッド2:

buf = malloc(9000); //for example gives pages [part of 4, 6, 5, part of 7]
memset(buf, 0xee, 9000);
read(buf, 9000);

ドライバーの読み取り:

get_user_pages();

//build dma sg list from pages
//...

//the platform demands a cachesync
for(all pages) {
    dma_cache_wback_inv();
}

//start dma and wait for it to be done
//...
wait_event_interruptible_timeout(); //blocks calling thread until dma done

for(all pages) {
    if(read) SetPageDirty();
    page_cache_release();
}

7ページは両方の転送で使用されることに注意してください。これは大きな問題であり、データが不良になることがありました(0xeeは1つのbufの最後にあります)。明確にするために、2つの読み取りは異なるDMAチャネルで実行されるため、同時に実行できます。

私の解決策は、2つのドライバーDMAが同じページの一部を共有しないように、ユーザープログラムのバッファーをページアラインすることでした。

これに対する別の解決策があるのだろうか?また、なぜこれが大きな問題だったのか疑問に思います。

4

1 に答える 1

1

これは、組み込みプロセッサの制限であり、キャッシュコヒーレントではないDMAです。ハイエンドのPowerPCチップでは、この問題は解消されます。

2つのバッファは、それらが出会うポイントでキャッシュラインを共有します。1つのスレッドがRAMにキャッシュを書き込むドライバーにあると同時に、2番目のスレッドはまだmemsetにあり、キャッシュラインを0xeeで埋めています。

DMA 1はデータをRAMに書き込みますが、プロセッサは0xeeを含むそのデータのダーティキャッシュラインを保持しています。2番目のスレッドがキャッシュを書き出すとき、DMA1から来たデータの上に0xeeを置きます。

解決策は次のとおりです。

  1. バッファをキャッシュアラインします(最高のパフォーマンス)。
  2. カーネルドライバーでバウンスバッファーを使用します(既存のユーザースペースコードと最も互換性があります)。

ここget_user_pages()での問題の一部ではありません-これはハードウェアとタイミングに関するものです。

于 2012-03-02T11:02:46.660 に答える