LINUX.ORG.RU

linux driver: wake_up_interruptible from tasklet


0

1

Предыдущая тема похоже забыта уже, решил написать ещё раз. Почему не работает wake_up_interruptible() из такслета? (в обработчике прерывания процесс просыпается когда нужно.)
Трассирую запрос, обработчик прерывания и такслет. Единственный процесс делает ioctl запрос с периодом 10 сек. процесс вызывает wait_event_interruptible_timeout(), имитирую прерывание (на входном канале появляется единственный передний фронт сигнала). Вызывается обработчик прерывания, изменяет условие (флаг обнуляется, вижу это через printk()), вызывается такслет (вижу через printk()), такслет вызывает wake_up_interrubtible(), процесс просыпается через 10 секунд (как будто wake_up_... просто игнорируется) значение флага равно 0 !!! (то есть планировщик должен был разбудить поток, но не сделал этого.)
В чём проблема, может чего-то не хватает? (ядро 2.6.35)
Ещё раз код, относящийся к тасклету:

// обработчик для тасклета
static void do_tasklet(unsigned long param)
{
   struct daq_device *dev = (struct daq_device*)param;
   struct dev_priv *dp    = (struct dev_priv*)dev->private;
   printk(KERN_INFO "from tasklet\n");
   wake_up_interruptible(&dp->wait_queue); 

}

// объявление такслета
static DECLARE_TASKLET(dev_tasklet, do_tasklet, 0);

// в коде инициализации устройства
int dev_init(struct daq_device* dev)
{
   ...
   // сохраняю указатель на устройство в структуре тасклета
   dev_tasklet.data = (unsigned long)dev;
   ...
}

Ты что-то набыдлокодил. Предлагаю следущее: пишешь юнит-тест, с минимальной функциональностью, где проявляется описанный тобой баг. Выкладываешь его общественности и ждёшь комментариев.

anonymous
()
Ответ на: комментарий от Murr

Код я уже приводил (в этом разделе форума сейчас на 4-ой странице, в теме «linux driver: wake_up_interruptible»).
В самом простом случае при имитации одного внешнего события обработчик прерывания и тасклет выполняются, тем не менее процесс получает управление только спустя таймаут.

linux__user
() автор топика
Ответ на: комментарий от linux__user

> самом простом случае при имитации одного внешнего события

Этот текст и опубликуй.

tailgunner ★★★★★
()
Ответ на: комментарий от linux__user

> У меня из тасклета в убунте 10.04 (не помню какое ядро там было) тоже работало, а вот в 10.10 не работает...

Вероятно ты внёс какие-то баги. Я не вижу причин, по которым твой use case не должен работать.

Показывай код, на котором воспроизводится твоя проблема.

ky-san
()
Ответ на: комментарий от ky-san

Код я уже приводил (тема «linux driver: wake_up_interruptible»). Там есть функция запроса, обработчик прерывания и код тасклета. Там не всё (нет вычисления значений для записи в аппаратные регистры, чтения и изменения которых выполняются при блокировках и запрете прерываний), но это не нужно, поскольку будет слишком много кода. Сейчас попробовал собрать старый драйвер на убунте 10.10 - валятся ошибки по поводу некоторых определений. Пришлось явно подключить <linux/sched.h>, раньше он был в <linux/interrupt.h>, который я подключаю и в старой и в новой версиях. Может здесь загвоздка? Остальной код почти такой же (код тасклета и обработчика одинаковые).
Логика запроса:

1. Проверка параметров запроса
2. Захват блокировки, запрет прерываний
3. Чтение и запись в порты ввода/вывода, изменение условия (флаг == 1)
4. Отпускание блокировки, разрешение прерываний
5. Вызов wake_up_interruptible_timeout(), (условие - флаг == 0)
6. Захват блокировки, запрет прерываний
7. Явное обнуление флага (флаг == 0) (сохранение нек-ых данных)
8. Отпускание блокировки, разрешение прерываний
9. Завершение запроса

Ещё раз, когда процесс просыпается по таймауту флаг равен 0 (он изменился в обработчике прерывания) это видно через printk().

linux__user
() автор топика

>Почему не работает wake_up_interruptible() из такслета? (в обработчике прерывания процесс просыпается когда нужно.)

Распечатай и сравни адрес &dp->wait_queue в обработчике и в тасклете, помоему просто с параметрами тасклета накосячено. wake_up_interruptible прекрасно работает из тасклета - пример в LDD есть.

anonymous
()
Ответ на: комментарий от anonymous

Я выяснил в чём проблема, всем огромное спасибо. Надо было сразу написать, что устройств 2 штуки (а старый драйвер я тестировал лишь с одной платой, там ошибка не проявлялась), моя ошибка, что не сказал об этом раньше.
Адреса устройств в тасклете и обработчике наверняка будут разные (проверю точно завтра).
Спасибо последнему анонимусу, что напомнил ещё раз про адреса очередей, это натолкнуло меня на правильную мысль :)

linux__user
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.