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).

  1. spin_lock_irq* не выключают основную обработку прерываний, после которой вызов назначенного обработчика вызывается на каком-то процессоре. Функция spin_lock_irq* выключают обработку на том процессоре, на котором её вызвали, до вызова spin_unlock_irq*. Прерывания никуда не теряются, они помещаются в очередь, из очереди будет всё выполнено после spin_unlock_irq* (если процессор 1, иначе задачи распределятся по остальным процессорам сразу).

  2. * Есть вариант использовать 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 драйверов еще не залазил). В общем сложную цель выбрал для тестов. Это не ответ, возможно я в чем-то ошибаюсь, поправьте если не прав, спасибо.


Ответы (0 шт):