Я разрабатываю драйвер устройства Linux, работающий на встроенном CPU. Этот драйвер устройства управляет некоторыми внешними устройствами. Внешнее оборудование имеет собственный DDR-контроллер и внешнюю DDR. Аппаратный DDR отображается на встроенном CPU через окно с подвижным ядром (поэтому я получил доступ к внешней DDR из драйвера Linux). Я использую ядро 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
@ qbert220: Посмотрите на реализацию вашей архитектуры 'copy_from_user()' - эта функция обязательно устанавливает вещи так, чтобы неустранимые ошибки страницы возвращали «EFAULT» вызывающему абоненту, а не вызывали панику (вам также нужно будет увидеть как обработчик ошибок страницы выполняет свою часть задания). – caf
Это довольно простая архитектура. Реализация copy_to_user вызывает access_ok (который проверяет адрес в ожидаемом диапазоне) и возвращает -EFAULT, если это возвращает false. Во всех остальных случаях он вызывает memcpy и возвращает количество байтов, которые были запрошены для копирования (возвращаемое значение memcpy игнорируется). – qbert220