Partager via


Mutex rapides et mutex surveillés

À compter de Windows 2000, les pilotes peuvent utiliser des mutex rapides s’ils nécessitent une forme d’exclusion mutuelle à faible surcharge pour le code qui s’exécute à IRQL <= APC_LEVEL. Un mutex rapide peut protéger un chemin de code qui doit être entré par un seul thread à la fois. Pour entrer le chemin du code protégé, le thread acquiert le mutex. Si un autre thread a déjà acquis le mutex, l’exécution du thread actuel est suspendue jusqu’à ce que le mutex soit libéré. Pour quitter le chemin du code protégé, le thread libère le mutex.

À compter de Windows Server 2003, les pilotes peuvent également utiliser des mutex surveillés. Les mutex surveillés sont des remplacements par dépôt pour les mutex rapides, mais offrent de meilleures performances. À l’instar d’un mutex rapide, un mutex protégé peut protéger un chemin de code qui doit être entré par un seul thread à la fois. Toutefois, le code qui utilise des mutex sauvegardés s’exécute plus rapidement que le code qui utilise des mutex rapides.

Dans les versions de Windows antérieures Windows 8, les mutex surveillés sont implémentés différemment des mutex rapides. Un chemin de code protégé par un mutex rapide s’exécute à IRQL = APC_LEVEL. Un chemin de code protégé par un mutex protégé s’exécute à IRQL <= APC_LEVEL, mais avec tous les API désactivés. Dans ces versions antérieures de Windows, l’acquisition d’un mutex protégé est une opération plus rapide que l’acquisition d’un mutex rapide. Toutefois, ces deux types de mutex se comportent de la même façon et sont soumis aux mêmes restrictions. En particulier, les routines de noyau qui ne peuvent pas être appelées à IRQL = APC_LEVEL ne doivent pas être appelées à partir d’un chemin de code protégé par un mutex rapide ou un mutex protégé.

À compter de Windows 8, les mutex surveillés sont implémentés en tant que mutex rapides. Dans un chemin de code protégé par un mutex protégé ou un mutex rapide, driver Verifier traite les appels aux routines du noyau comme se produisant à IRQL = APC_LEVEL. Comme dans les versions antérieures de Windows, les appels non conformes à APC_LEVEL sont non conformes dans un chemin de code protégé par un mutex protégé ou un mutex rapide.

Mutex rapides

Un mutex rapide est représenté par une structure FAST_MUTEX . Le pilote alloue son propre stockage pour une structure FAST_MUTEX , puis appelle la routine ExInitializeFastMutex pour initialiser la structure.

Un thread acquiert un mutex rapide en effectuant l’une des opérations suivantes :

  • Appel de la routine ExAcquireFastMutex . Si le mutex a déjà été acquis par un autre thread, l’exécution du thread appelant est suspendue jusqu’à ce que le mutex soit disponible.

  • Appel de la routine ExTryToAcquireFastMutex pour essayer d’acquérir le mutex rapide sans interrompre le thread actuel. La routine retourne immédiatement, que le mutex ait été acquis ou non. ExTryToAcquireFastMutex retourne TRUE s’il a réussi à acquérir le mutex pour l’appelant ; sinon, elle retourne FALSE.

Un thread appelle ExReleaseFastMutex pour libérer un mutex rapide acquis par ExAcquireFastMutex ou ExTryToAcquireFastMutex.

Un chemin de code protégé par un mutex rapide s’exécute à IRQL = APC_LEVEL. ExAcquireFastMutex et ExTryToAcquireFastMutex déclenchent l’IRQL actuel en APC_LEVEL, et ExReleaseFastMutex restaure l’IRQL d’origine. Ainsi, tous les API sont désactivés pendant que le thread contient un mutex rapide.

Si un chemin de code est garanti pour s’exécuter toujours à APC_LEVEL, le pilote peut à la place appeler ExAcquireFastMutexUnsafe et ExReleaseFastMutexUnsafe pour acquérir et libérer un mutex rapide. Ces routines ne modifient pas l’IRQL actuel et ne peuvent être utilisées en toute sécurité que lorsque l’IRQL actuel est APC_LEVEL.

Les mutex rapides ne peuvent pas être acquis de manière récursive. Si un thread qui contient déjà un mutex rapide tente de l’acquérir, ce thread se bloquera. Les mutex rapides peuvent être utilisés uniquement dans le code qui s’exécute à IRQL <= APC_LEVEL.

Mutex surveillés

Les mutex guarded, qui sont disponibles à partir de Windows Server 2003, exécutent la même fonction que les mutex rapides, mais avec des performances plus élevées.

À compter de Windows 8, les mutex sauvegardés et les mutex rapides sont implémentés de manière identique.

Dans les versions de Windows antérieures Windows 8, les mutex surveillés sont implémentés différemment des mutex rapides. L’acquisition d’un mutex rapide élève l’IRQL actuel à APC_LEVEL, tandis que l’acquisition d’un mutex protégé entre dans une région protégée, ce qui est une opération plus rapide. Pour plus d’informations sur les régions surveillées, consultez Régions critiques et Régions surveillées.

Un mutex protégé est représenté par une structure KGUARDED_MUTEX . Le pilote alloue son propre stockage pour une structure KGUARDED_MUTEX , puis appelle la routine KeInitializeGuardedMutex pour initialiser la structure.

Un thread acquiert un mutex protégé en effectuant l’une des opérations suivantes :

  • Appel de KeAcquireGuardedMutex. Si le mutex a déjà été acquis par un autre thread, l’exécution du thread appelant est suspendue jusqu’à ce que le mutex soit disponible.

  • Appel de KeTryToAcquireGuardedMutex pour essayer d’acquérir le mutex protégé sans suspendre le thread actuel. La routine retourne immédiatement, que le mutex ait été acquis ou non. KeTryToAcquireGuardedMutex retourne TRUE s’il a réussi à acquérir le mutex pour l’appelant ; sinon, elle retourne FALSE.

Un thread appelle KeReleaseGuardedMutex pour libérer un mutex protégé qui a été acquis par KeAcquireGuardedMutex ou KeTryToAcquireGuardedMutex.

Un thread qui contient un mutex protégé s’exécute implicitement à l’intérieur d’une région protégée. KeAcquireGuardedMutex et KeTryToAcquireGuardedMutex entrent dans la région protégée, tandis que KeReleaseGuardedMutex la quitte. Tous les API sont désactivés alors que le thread contient un mutex protégé.

Si l’exécution d’un chemin de code est garantie avec tous les API désactivés, le pilote peut utiliser KeAcquireGuardedMutexUnsafe et KeReleaseGuardedMutexUnsafe pour acquérir et libérer le mutex protégé. Ces routines n’entrent pas ou ne sortent pas d’une région protégée et peuvent être utilisées uniquement à l’intérieur d’une région protégée déjà existante ou à l’adresse IRQL = APC_LEVEL.

Les mutex gardés ne peuvent pas être acquis de manière récursive. Si un thread qui contient déjà un mutex protégé tente de l’acquérir, ce thread se bloquera. Les mutex guarded ne peuvent être utilisés que dans le code qui s’exécute à IRQL <= APC_LEVEL.