Introdução às Travas de Rotação
Os bloqueios de rotação são mecanismos de sincronização definidos pelo kernel, somente no modo kernel, exportados como um tipo opaco: KSPIN_LOCK. Um bloqueio giratório pode ser usado para proteger dados ou recursos compartilhados contra acesso simultâneo. Ao executar em IRQL <= DISPATCH_LEVEL, um driver pode usar KeAcquireInStackQueuedSpinLock e KeReleaseInStackQueuedSpinLock para adquirir e liberar o bloqueio de rotação como um bloqueio de rotação em fila.
Como alternativa, os chamadores em execução em IRQL >= DISPATCH_LEVEL podem chamar KeAcquireSpinLockAtDpcLevel e KeReleaseSpinLockFromDpcLevel para obter melhor desempenho do driver.
Muitos componentes usam bloqueios de rotação, incluindo drivers. Qualquer tipo de motorista pode usar uma ou mais travas de giro executivas. Por exemplo, a maioria dos sistemas de arquivos usa uma fila de trabalho intertravada na extensão de dispositivo do driver do sistema de arquivos (FSD) para armazenar IRPs que são processados pelas rotinas de retorno de chamada de thread de trabalho do sistema de arquivos e pelo FSD. Uma fila de trabalho intertravada é protegida por um bloqueio de rotação executivo, que resolve a contenção entre o FSD tentando inserir IRPs na fila e quaisquer threads simultaneamente tentando remover IRPs. Como outro exemplo, o driver do controlador de disquete do sistema usa dois bloqueios de rotação executivos. Um bloqueio de rotação executivo protege uma fila de trabalho intertravada compartilhada com o thread dedicado ao dispositivo deste driver; o outro protege um objeto de timer compartilhado por três rotinas de driver.
Os bloqueios de rotação em fila fornecem melhor desempenho do que os bloqueios de rotação comuns para bloqueios de alta contenção em máquinas com vários processadores. Para obter mais informações, consulte Bloqueios de rotação em fila. Os drivers também podem usar KeAcquireSpinLock e KeReleaseSpinLock para adquirir e liberar um bloqueio de rotação como um bloqueio de rotação comum.
Para sincronizar o acesso a estruturas de dados simples, os drivers podem usar qualquer uma das rotinas ExInterlockedXxx para garantir o acesso atômico à estrutura de dados. Os motoristas que utilizam essas rotinas não precisam adquirir ou liberar o bloqueio de giro explicitamente.
Cada driver que tem um ISR usa um bloqueio de rotação de interrupção para proteger quaisquer dados ou hardware compartilhados entre seu ISR e suas rotinas SynchCritSection que geralmente são chamadas de suas rotinas StartIo e DpcForIsr. Um bloqueio de rotação de interrupção está associado ao conjunto de objetos de interrupção criados quando o driver chama IoConnectInterrupt, conforme descrito em Registrando um ISR.
Siga estas diretrizes para usar bloqueios de rotação em drivers:
Forneça o armazenamento para quaisquer dados ou recursos protegidos por um bloqueio de rotação e para o bloqueio de rotação correspondente na memória de espaço do sistema residente (pool não paginado, conforme mostrado na figura Espaços de memória virtual e memória física). Um driver deve fornecer o armazenamento para quaisquer bloqueios de rotação executivos que ele usa. No entanto, um driver de dispositivo não precisa fornecer o armazenamento para um bloqueio de rotação de interrupção, a menos que ele tenha um ISR multivetor ou tenha mais de um ISR, conforme descrito em Registrando um ISR.
Chame KeInitializeSpinLock para inicializar cada bloqueio de rotação para o qual o driver fornece armazenamento antes de usá-lo para sincronizar o acesso aos dados compartilhados ou ao recurso que ele protege.
Chame todas as rotinas de suporte que usam um bloqueio de rotação em um IRQL apropriado, geralmente em <= DISPATCH_LEVEL para bloqueios de rotação executivos ou em <= DIRQL para um bloqueio de rotação de interrupção associado aos objetos de interrupção do driver.
Implemente rotinas para executar o mais rápido possível enquanto elas mantêm um bloqueio de rotação. Nenhuma rotina deve manter um bloqueio de rotação por mais de 25 microssegundos.
Nunca implemente rotinas que façam o seguinte enquanto mantém um bloqueio de rotação:
Causar exceções de hardware ou gerar exceções de software.
Tente acessar a memória paginável.
Faça uma chamada recursiva que causaria um bloqueio ou poderia fazer com que um bloqueio de rotação fosse mantido por mais de 25 microssegundos.
Tente adquirir outro bloqueio de rotação se isso puder causar um impasse.
Chame uma rotina externa que viole qualquer uma das regras anteriores.