Предотвращение ошибок и взаимоблокировок при использовании спиновых блокировок

Хотя подпрограмма драйвера удерживает спин-блокировку, она не может вызвать аппаратное исключение или вызвать исключение программного обеспечения без отключения системы. Другими словами, ISR драйвера и любая подпрограмма SynchCritSection , которую драйвер предоставляет в вызове KeSynchronizeExecution , не должны вызывать ошибку или ловушку, например сбой страницы или арифметическое исключение, и не могут вызывать исключение программного обеспечения. Подпрограмма, вызывающая KeAcquireSpinLock или KeAcquireInStackQueuedSpinLock , также не может вызвать аппаратное исключение или вызвать исключение программного обеспечения до тех пор, пока она не освободит свою исполнительную спиновую блокировку и больше не будет работать в IRQL = DISPATCH_LEVEL.

Страничные данные и процедуры поддержки

При удержании спин-блокировки драйверы не должны вызывать подпрограммы, которые обращаются к страничным данным. Помните, что драйверы могут вызывать определенные процедуры поддержки, которые обращаются к страничным данным, если и только в том случае, если их вызовы выполняются в IRQL строго менее DISPATCH_LEVEL. Это ограничение IRQL не позволяет вызывать эти процедуры поддержки при удержании спин-блокировки. Требования IRQL для любой конкретной процедуры поддержки см. на странице справочника по подпрограмме.

Рекурсия

Попытка получить спин-блокировку рекурсивно гарантированно вызовет взаимоблокировку: удержание экземпляра рекурсивной процедуры не может освободить спин-блокировку, пока второй экземпляр вращается, пытаясь получить ту же блокировку спина.

В следующих рекомендациях описывается использование спин-блокировок с рекурсивными подпрограммами.

  • Рекурсивная подпрограмма не должна вызывать себя при удержании спин-блокировки или не должна пытаться получить такую же блокировку спина при последующих вызовах.

  • Хотя рекурсивная подпрограмма содержит спин-блокировку, другая подпрограмма драйвера не должна вызывать рекурсивную подпрограмму, если рекурсия может вызвать взаимоблокировку или может привести к тому, что вызывающий объект удерживает спин-блокировку дольше 25 микросекунд.

Дополнительные сведения о рекурсивных подпрограммах драйвера см. в разделе Использование стека ядра.

Получение вложенных спин-блокировок

Попытка получить вторую блокировку спина при удержании другой блокировки спина также может привести к взаимоблокировкам или снижению производительности драйвера.

В следующих рекомендациях описывается, как драйверы должны удерживать спин-блокировки.

  • Драйвер не должен вызывать подпрограмму поддержки, которая использует спин-блокировку, если взаимоблокировка не может возникнуть.

  • Даже если взаимоблокировка не может возникнуть, драйвер не должен вызывать подпрограмму поддержки, которая использует спин-блокировку, если альтернативные методы кодирования не могут обеспечить сравнимую производительность и функциональность драйвера.

  • Если драйвер выполняет вложенные вызовы для получения спин-блокировок, он должен всегда получать спин-блокировки в одном и том же порядке каждый раз при получении. Этот порядок помогает избежать взаимоблокировок.

Как правило, избегайте использования вложенных спиновых блокировок для защиты перекрывающихся подмножеств или дискретных наборов общих данных и ресурсов. Подумайте, что может произойти, если драйвер использует две исполнительные блокировки спина для защиты дискретных ресурсов, таких как пара объектов таймера, которые могут быть заданы по отдельности и совместно различными подпрограммами драйвера. Драйвер периодически взаимоблокировки на компьютере SMP, когда одна из двух процедур, каждая из которых удерживает одну спин-блокировку, пыталась получить другую спин-блокировку.

Дополнительные сведения о получении вложенных спиновых блокировок см. в разделе Блокировки, взаимоблокировки и синхронизация.