linux kernel module. Сон во время spin_lock_irq включает прерывания?
SMP система с 1 процессором (ядром) запущена в VirtualBox.
Я пытаюсь понять почему прерывания все таки происходят и соответствующая реакция графической оболочки выполнена, если они отключены.
В определенном месте кода модуля ядра выполняю следующий код:
spin_lock_irq(&lock);
mdelay(10000);
spin_unlock_irq(&lock);
Перед тем как выполнить код, я запоминаю кол-во прерываний мыши в /proc/stat, пусть будет 18500.
После того как код запустился и ушел в сон, на экране ничего не происходит (спин же держим) и никакой реакции на клавиатуру/мышь. После того как код вышел из блокировки на экране всплывает всё, что случайно было запущено (мышью или клавиатурой), но, в /proc/stat по прежнему счетчик мыши прерываний 18500. Что происходит если внутри спин блокировки вызвать sleep подобные функции или любую функцию которая может уснуть? Кругом ответы только о "deadlock" - не этот ответ я ожидаю.
Я думаю что аппаратные прерывания включаются во время sleep (но как, они же выключены) и вытесняют этот sleep процесс. Или я неправильно понял spin_lock_irq.
UPD:
mdelay - не сон, а цикл который выжидает время по jiffiers. Изменил lock функции и аргументы в соответствие заголовку.
UPD_2:
Говоря процессор имею ввиду ядро (cpu0, cpu1, cpu2, cpu3 и т.д. из /sys/devices/system/cpu).
spin_lock_irq*
не выключают основную обработку прерываний, после которой вызов назначенного обработчика вызывается на каком-то процессоре. Функцияspin_lock_irq*
выключают обработку на том процессоре, на котором её вызвали, до вызоваspin_unlock_irq*
. Прерывания никуда не теряются, они помещаются в очередь, из очереди будет всё выполнено послеspin_unlock_irq*
(если процессор 1, иначе задачи распределятся по остальным процессорам сразу).* Есть вариант использовать
disable_irq(irq_number)
для отключения основной обработки конкретного прерывания, но этот вызов не сработает, еслиrequest_irq(...)
для этого прерывания был вызван с флагомSA_SHIRQ
(shared irq - общее прерывание, то есть может быть назначено много обработчиков), даже если обработчик один на всю систему.
Теперь я загрузился с ubuntu (не виртуальная машина), оставил один процессор: echo 0 > /sys/devices/cpu/cpu[1-n]/online
. Далее вижу что прерывания за движение мышью обрабатывает xhci_hcd и запрос за прерывание указан с флагом 0 (то есть не SA_SHIRQ), код из репозитория Linux:
ret = request_irq(pci_irq_vector(pdev, 0), xhci_msi_irq, 0, "xhci_hcd",
xhci_to_hcd(xhci));
Далее делаю то же самое:
spin_lock_irq(&lock);
mdelay(10000);
spin_unlock_irq(&lock);
Вожу мышью (много), после unlock позиция мыши изменилась (далеко), а значение из /proc/stat
для этого преравния изменилось не на 1, а на 4, но обработчики после основной функции обработки прерывания должны быть в очереди, куда делись остальные как минимум 100? Или там предел? Тогда почему нет предела на очередь обработки прерываний с клавиатуры (драйвер i8042, если во время блокировки нажимать клавиатуру, значение кол-ва прерываний этого драйвера увеличивается как надо, 50 раз нажал, значение на 100 увеличится (отпустить клавишу - тоже прерывание). Хорошо, спишем это на то, что i8042 делает запрос с SA_SHIRQ флагом). Окей, пытаюсь сделать так:
disable_irq_nosync(126);
spin_lock_irq(&lock);
mdelay(10000);
spin_unlock_irq(&lock);
enable_irq(126);
(из /proc/interrupts видно что xhci_hcd берет прерывание 126) и происходит то же самое: значение меняется на 4, но по моим ожиданиям и судя по тому что запрос на обработку прерывания был с флагом 0, оно вообще не должно было поменяться.
Либо документация неправильно написана (не верю конечно же в это), либо я не понимаю: что именно я понял не так.
Что-то явно происходит непрозрачное, помогите разобраться.
UPD_3:
Не обязательно меняется на 4 (может быть больше, может меньше, в основном 3-5, бывает и больше если еще и флешка вставлена).
disable_irq правда работает для xhci, ибо если выключить и не включать, мышь так и не работает (irq не shared), а если выключить i8042 (прерывание 1) для клавиатуры, то она все равно работает: там shared флаг установлен. Всё как по документации. А то что мышь оказывается после включения не пойми где и после включения оказывается инкремент кол-ва прерываний на небольшое кол-во, я думаю это уже связано с протоколами usb/pci (acknowledge, повторная отправка и прочее). Не стоит забывать что прерывания может включить кто-то еще, даже если Вы отключили явно, может быть из-за флешки это и происходит, вот оно и тикает больше, даже если выключить (в такие дебри реализации usb драйверов еще не залазил). В общем сложную цель выбрал для тестов. Это не ответ, возможно я в чем-то ошибаюсь, поправьте если не прав, спасибо.