我正在開發在嵌入式CPU上運行的Linux設備驅動程序。該設備驅動程序控制一些外部硬件。外部硬件有它自己的DDR控制器和外部DDR。硬件的DDR通過可移動內存窗口在嵌入式CPU上可見(所以我可以從Linux驅動程序分頁訪問外部DDR)。我正在使用Linux內核版本2.6.33。當線程終止總線錯誤時,如何防止信號量鎖定
我的驅動程序使用sysfs來允許從用戶空間控制外部硬件。例如,外部硬件會生成一個心跳計數器,用於增加外部DDR中的特定地址。驅動程序讀取它以檢測外部硬件是否仍在運行。
如果外部DDR工作不正常,則訪問外部DDR會在嵌入式CPU上產生總線錯誤。爲了防止同時多線程訪問,驅動程序使用信號量。
現在來解決問題。如果一個線程抓取信號量,然後終止一個總線錯誤,信號量仍然被鎖定。隨後的所有調用都會無限期地獲取信號量塊。我可以使用什麼技術來避免這種情況永久掛斷?
一個例子sysfs的功能(簡體):
static ssize_t running_attr_show(struct device *dev, struct device_attribute *attr, char *buffer)
{
struct my_device * const my_dev = container_of(dev, struct my_device, dev);
int ret;
if(down_interruptible(&my_dev->sem))
{
ret = -ERESTARTSYS;
}
else
{
u32 heartbeat;
int running;
// Following line could cause bus error
heartbeat = mwindow_get_reg(&my_dev->mwindow, HEARTBEAT_COUNTER_ADDR);
running = (heartbeat != my_dev->last_heartbeat) ? 1 : 0;
my_dev->last_heartbeat = heartbeat;
ret = sprintf(buffer, "%d\n", result);
/* unlock */
up(&my_dev->sem);
}
return ret;
}
感謝。當然需要考慮一些事情。對於異常處理程序如何知道總線錯誤的原因是來自mwindow_get_reg的調用,您有任何建議嗎?我們有一些代碼已經做了一些探測,它依賴於在訪問之前設置的靜態變量,在故障期間檢測到,以便可以設置另一個靜態,然後在訪問之後進行檢查。在整個過程中,中斷被禁用。這似乎不太優雅,並且意味着通過內存窗口將大量固件複製到目標DDR時,中斷會被禁用很長時間。 – qbert220 2011-03-29 08:41:29
@ qbert220:看看你的架構中'copy_from_user()'的實現 - 該函數必須設置一些東西,這樣不可恢復的頁面錯誤會將EFAULT返回給調用者而不是引起恐慌(你還必須看到頁面錯誤處理程序如何執行其作業)。 – caf 2011-03-29 23:39:18
這是一個相當簡單的架構。 copy_to_user實現調用access_ok(它檢查地址是否在預期的範圍內),如果返回false,則返回-EFAULT。在所有其他情況下,它調用memcpy並返回請求複製的字節數(忽略memcpy返回值)。 – qbert220 2011-03-30 09:45:20