“Чужие” spinlock’и
Иногда приходится делать хаки при написании драйверов, для того чтобы иметь возможность работать со какими-то недокументированными фичами ядра. И для того чтобы обеспечить синхронизацию, приходится использовать чужие объекты синхронизации. Это, как оказалось, вместо стабильности может наоборот привнести хаоса в код. Я хочу рассказать как я обжегся на спинлоках.
Для работы со спинлоком есть целый набор функций:
Before calling any support routine that requires access to a caller-supplied executive spin lock, a driver must call KeInitializeSpinLock to initialize the corresponding executive spin lock. Support routines that require an initialized executive spin lock include the following:
KeAcquireSpinLock and, subsequently, KeReleaseSpinLock
KeAcquireSpinLockAtDpcLevel and, subsequently, KeReleaseSpinLockFromDpcLevel
KeAcquireInStackQueuedSpinLock and, subsequently, KeReleaseInStackQueuedSpinLock
KeAcquireInStackQueuedSpinLockAtDpcLevel and, subsequently, KeReleaseInStackQueuedSpinLockFromDpcLevel
Но не пишется о том, что будет если вы используете разные функции на одном и том же спинлоке. Как показал опыт, ничего не будет, ровно до того момента пока не будет захвачен спинлок и начнется ожидание.
Например, ОС инициализирует спинлок через KeInitializeSpinLock, и дальше использует пару KeAcquireSpinLock/KeReleaseSpinLock для работы с ним. Тут вы своим кодом начинаете пытаться лочить его через KeAcquireInStackQueuedSpinLock/KeReleaseInStackQueuedSpinLock. И вот если лок был уже захвачен через KeAcquireSpinLock, KeAcquireInStackQueuedSpinLock рухнет, потому что KeAcquireSpinLock хранит в SPIN_LOCK просто DWORD равный 0 или 1. А KeAcquireInStackQueuedSpinLock хранит там указатель на очередь. Спинлок один и тот же данные абсолютно разные. Соответственно, в спинлоке, залоченом через KeAcquireSpinLock хранится число 1, а KeAcquireInStackQueuedSpinLock попытается прочитать по указателю = 1.
В моем случае все оказалось еще веселее, в одних версии ОС для этого спинлока использовались KeAcquireSpinLock/KeReleaseSpinLock, а в других KeAcquireInStackQueuedSpinLock/KeReleaseInStackQueuedSpinLock. Баг получился плавающим.
Вывод: при использовании чужих спинлоков обязательно проверьте какими функциями пользуется ОС.
А возможно ли узнать какой программой вызывается этот ntoskrnl.exe!KeReleaseInStackQueuedSpinLock+0x1e0
У меня такая проблема: с некоторых пор 50% процессора отжирает процесс system
Сейчас через process explorer определил что основные виновники это именно эти threads. вот картинка. http://clip2net.com/s/1JIu0
Может вам известно в каком направлении можно начать действовать?
А что выводится по нажатию на кнопку “stack” в Process Explorer’e Имею в виду как раз то окно что на скиншоте. Вообще если жрет System, то это значит что не программа, а какой-то драйвер виноват.
кнопка “stack” говорит что “unable to access thread” так же и по кнопкам внизу.
http://clip2net.com/s/1JUFo
И как бы этот драйвер тогда выследить?
а то достала уже ситуация с загрузкой проца
ноут постоянно шумит на повышенных. для охлаждения
В каком направлении еще можно покапать?
Нужно запускать Process Explorer от админа. Если все равно не дает стек – тогда лезть через windbg.
Похоже что дело было в virtualBox. даже не используемом.
Либо они с Vmware что то поделить не могли. После unistalla virtulaBox перезагрузки system больше так ресурсы не жрет
Буду еще экспериментировать.