2012-03-02 40 views
1

考慮這個同時DMA到用戶存儲器

線程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在一個buf的末尾被發現)。爲了清楚起見,這兩個讀取運行在不同的DMA通道上,因此它們可以同時運行。

我的解決方案是頁面對齊用戶程序中的緩衝區,以便2驅動程序DMA永遠不會共享相同頁面的部分。

我想知道是否還有其他解決方案? 我也想知道爲什麼這是一個大問題。

+1

這可能是相當具體的平臺 - 緩存失效的要求表明你正在嵌入式系統上運行。兩個緩衝區足夠接近以共享緩存線,還是在平臺勘誤中還存在其他限制? – 2012-03-02 09:49:44

+0

是的,這是一個ppc440ep,並且緩衝區可能足夠接近。緩存行是32個字節,我只看到4-12個字節被破壞/不變。緩存中是否存在2個不同版本的相同物理內存?當我在一個線程中執行wback時,它是否可以銷燬另一個線程的數據?據我所知沒有任何錯誤。但是get_user_pages呢?當它返回2個不同版本的同一頁面時會發生什麼?如果來自不同線程的get_user_pages和page_cache_release變爲交織。 – Ronnie 2012-03-02 10:43:39

+0

我不完全清楚get_user_pages/page_cache_release是幹什麼的,除非給予頁面的物​​理地址。在這個系統上沒有光盤緩存或任何東西,只有內存和cpu-cache。 – Ronnie 2012-03-02 10:50:58

回答

1

這是您的嵌入式處理器的侷限性,而DMA不是緩存一致的。在高端PowerPC芯片上,這個問題消失了。

您的兩個緩衝區在它們相遇的地方共享一個緩存行。在驅動程序將緩存寫入RAM的同時,第二個線程仍處於memset填充緩存行的0xee。

DMA 1將數據寫入RAM,但處理器仍爲該數據保留一條髒緩存行,其中包含0xee。當第二個線程寫出緩存時,它將0xee放在來自DMA1的數據上。

的解決方案是:

  1. 緩存調整您的緩衝區(最高性能)。
  2. 在內核驅動程序中使用反彈緩衝區(與現有的用戶空間代碼最兼容)。

get_user_pages()這裏不是問題的一部分 - 這是關於硬件和時間。

+0

我認爲你對緩存問題是正確的,但我也認爲我已經看到錯誤,而不使用memset,因爲在調試此問題之前沒有memset ...但是可能在DMA 1完成後讀取緩衝區,可以使在DMA 2完成之前,緩存將0xee讀回緩存? – Ronnie 2012-03-02 11:18:19

+0

'malloc'還會觸及緩衝區末端周圍的數據以進行堆維護。這可能就足夠了。 – 2012-03-02 11:20:21

+0

是的,這聽起來像一個解釋。 – Ronnie 2012-03-02 11:23:21