Правильный способ удаления kthread, ожидающего, пока семафор будет поднят - PullRequest
0 голосов
/ 14 марта 2020

Я пишу модуль ядра, который использует потоки ядра и семафоры.

Я вызываю up(...) функцию для семафора из обработчика прерываний, и затем мой kthread начинает выполняться.

static int interrupt_handler_thread(void *data)
{
    /* duty cycle */
    while (!kthread_should_stop()) {
        /*
         * If semaphore has been uped in the interrupt, we will
         * acquire it here, else thread will go to sleep.
         */
        if (!down_interruptible(mysem)) {
            /* proccess  gpio interrupt */
            dev_info(dev, "gpio interrupt detected\n"); 
        }
    }

    do_exit(0);

    return 0;
}

Семафор и нить инициализируются в функции module_init. Проверка ошибок была пропущена.

...
sema_init(mysem, 0);

thread = kthread_create(interrupt_handler_thread,client,"my_int_handler");
wake_up_process(thread);
...

И во время выгрузки модуля семафор и нить удаляются:

/*
* After this call kthread_should_stop() in the thread will return TRUE.
* See https://lwn.net/Articles/118935/
*/
kthread_stop(thread);

/*
* Release the semaphore to return
* from down_interruptible() function
*/
up(mysem);

Когда я пытаюсь выгрузить мой модуль, он замирает в нить в down_interruptible() функция, потому что она ждет, пока семафор поднимается в обработчике прерываний. И мой код никогда не возвращается из kthread_stop().

Кажется, мне нужно отключить прерывание от моего gpio, поднять семафор вручную и вызвать функцию kthread_stop(). Но это потенциальная ошибка, потому что после того, как семафор восстановлен вручную, поток начинает выполняться и после его рабочего цикла можно снова down_interruptible().

Может кто-нибудь помочь мне, пожалуйста?

PS: я знаю про этот вопрос , но, похоже, это не мой случай.

1 Ответ

1 голос
/ 15 марта 2020

Для правильной работы ваш kthread должен проверять состояние "остановки" потока при ожидании на семафоре. К сожалению, не существует «остановки» версии функции down.

Вместо kthread используйте механизм workqueue . Работы уже имеют все необходимые функции:

  • Вы можете добавить работу внутри обработчика прерываний (queue_work),
  • Одновременно может быть запущена только одна работа,
  • Используя destroy_workqueue, вы можете безопасно завершить все работы.

На самом деле рабочие очереди реализуются с использованием kthreads. См., Например, реализацию функции kthread_worker_fn .

...