Présentation des verrous de rotation
Les verrous de rotation sont des mécanismes de synchronisation définis par le noyau, en mode noyau uniquement, exportés sous la forme d’un type opaque : KSPIN_LOCK. Un verrou de rotation peut être utilisé pour protéger les données partagées ou les ressources contre l’accès simultané. Lorsqu'il fonctionne à IRQL <= DISPATCH_LEVEL, un pilote peut utiliser KeAcquireInStackQueuedSpinLock et KeReleaseInStackQueuedSpinLock pour acquérir et libérer le verrou de spin en tant que verrou de spin mis en file d'attente.
Par ailleurs, les appelants fonctionnant à IRQL >= DISPATCH_LEVEL peuvent appeler KeAcquireSpinLockAtDpcLevel et KeReleaseSpinLockFromDpcLevel pour améliorer les performances du pilote.
De nombreux composants utilisent des verrous de rotation, y compris des pilotes logiciels. Tout type de pilote peut utiliser un ou plusieurs verrous exécutifs. Par exemple, la plupart des systèmes de fichiers utilisent une file d'attente de travail verrouillée dans l'extension de périphérique du pilote de système de fichiers (FSD) pour stocker les IRP traités à la fois par les routines de rappel des threads de travail du système de fichiers et par le FSD. Une file d'attente interverrouillée est protégée par un verrou exécutif, qui résout les conflits entre la FSD qui tente d'insérer des IRP dans la file d'attente et tous les threads qui tentent simultanément de retirer des IRP. Autre exemple, le pilote du contrôleur de disquette du système utilise deux verrous exécutifs. L'un d'eux protège une file d'attente interverrouillée partagée avec le thread dédié à l'appareil de ce pilote ; l'autre protège un objet de temporisation partagé par trois routines du pilote.
Les verrous de rotation mis en file d’attente offrent de meilleures performances que les verrous de rotation ordinaires pour les verrous de contention élevés sur les machines multiprocesseurs. Pour plus d'informations, reportez-vous à la section Verrous de spin en file d'attente. Les pilotes peuvent également utiliser KeAcquireSpinLock et KeReleaseSpinLock pour acquérir et libérer un verrou de rotation en tant que verrou de rotation ordinaire.
Pour synchroniser l’accès à des structures de données simples, les pilotes peuvent utiliser l’une des routines ExInterlockedXxx pour garantir l’accès atomique à la structure de données. Les pilotes qui utilisent ces routines n’ont pas besoin d’acquérir ou de libérer explicitement le verrou de rotation.
Chaque pilote disposant d'un ISR utilise un verrou d'interruption pour protéger les données ou le matériel partagés entre son ISR et ses routines SynchCritSection appelées à partir de ses routines StartIo et DpcForIsr. Un verrou d'interruption est associé à l'ensemble des objets d'interruption créés lorsque le pilote appelle IoConnectInterrupt, comme décrit dans Enregistrement d'un ISR.
Respectez les consignes suivantes pour l'utilisation des spin locks dans les pilotes :
Fournissez le stockage pour toute donnée ou ressource protégée par un spin lock et pour le spin lock correspondant dans la mémoire résidente de l'espace système (pool non paginé, comme indiqué dans la figure Espaces de mémoire virtuelle et mémoire physique). Un pilote doit fournir l'espace de stockage pour tous les verrous exécutifs qu'il utilise. Toutefois, un pilote d'appareil n'a pas besoin de fournir le stockage pour un verrou d'interruption à moins qu'il ne dispose d'un ISR multivecteur ou qu'il ait plus d'un ISR, comme décrit dans la section Enregistrement d'un ISR.
Appelez KeInitializeSpinLock pour initialiser chaque verrou de rotation pour lequel le pilote fournit un stockage avant de l’utiliser pour synchroniser l’accès aux données partagées ou à la ressource qu’il protège.
Appelez chaque routine de support qui utilise un spin lock à un IRQL approprié, généralement à <= DISPATCH_LEVEL pour les spin locks exécutifs ou à <= DIRQL pour un spin lock d'interruption associé aux objets d'interruption du pilote.
Implémentez des routines pour qu'elles s'exécutent aussi rapidement que possible lorsqu'elles détiennent un spin lock. Aucune routine ne doit contenir de verrou de rotation pendant plus de 25 microsecondes.
N’implémentez jamais les routines qui effectuent l’une des opérations suivantes lors de la conservation d’un verrou de rotation :
Provoquez des exceptions matérielles ou déclenchez des exceptions logicielles.
Essayez d’accéder à la mémoire paginable.
Effectuez un appel récursif qui provoquerait un interblocage ou pourrait entraîner la tenue d’un verrou de rotation pendant plus de 25 microsecondes.
Essayez d'acquérir un autre spin lock si cela risque de provoquer un blocage.
Appelez une routine externe qui enfreint l’une des règles précédentes.