Partager via


Mutex rapides et Mutex protégés

À compter de Windows 2000, les pilotes ont la possibilité d'utiliser des mutex rapides s'ils nécessitent une forme d'exclusion mutuelle à faible surcharge pour le code exécuté à 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 gardés. Les mutex gardés sont des remplacements interchangeables pour les mutex rapides, mais fournissent de meilleures performances. Comme 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 surveillé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 protégés sont implémentés différemment des mutex rapides. Le chemin d’accès au code protégé par un mutex rapide s’exécute à un niveau IRQL égal à APC_LEVEL. Un chemin de code protégé par un mutex surveillé s’exécute à IRQL <= APC_LEVEL, mais avec tous les APC 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 façon identique et sont soumis aux mêmes restrictions. En particulier, les routines de noyau qui sont illégales à appeler lorsque IRQL = APC_LEVEL ne doivent pas être appelées depuis un chemin de code protégé par un fast mutex ou un guarded mutex.

À partir de Windows 8, les mutex protégés sont implémentés sous forme de mutex rapides. Dans un chemin d'exécution protégé par un mutex gardé ou un mutex rapide, Driver Verifier considère les appels aux routines du noyau comme se produisant à IRQL = APC_LEVEL. Comme dans les versions antérieures de Windows, les appels qui sont illégaux à APC_LEVEL sont illégaux dans un chemin de code protégé par un mutex gardé 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, indépendamment du fait que le mutex ait été acquis. ExTryToAcquireFastMutex retourne TRUE s’il a acquis 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 au niveau de IRQL = APC_LEVEL. ExAcquireFastMutex et ExTryToAcquireFastMutex élèvent l’IRQL actuel à APC_LEVEL, et ExReleaseFastMutex rétablit l’IRQL d’origine. Ainsi, tous les APC sont désactivés pendant que le thread détient un mutex rapide.

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

Les mutex rapides ne peuvent pas être acquis de manière récursive. Si un thread qui détient déjà un mutex rapide tente de l’acquérir de nouveau, il se retrouvera dans un état de deadlock. Les mutex rapides peuvent être utilisés uniquement dans le code s'exécutant au niveau IRQL <= APC_LEVEL.

Mutex protégés

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

À compter de Windows 8, les mutex surveillés et les mutex rapides sont implémentés de façon identique.

Dans les versions de Windows antérieures à Windows 8, les mutex protégé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é permet d’entrer dans une région protégée, ce qui est une opération plus rapide. Pour plus d’informations sur les régions protégé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 fil 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 tenter d’acquérir le mutex protégé sans suspendre le thread actuel. La routine retourne immédiatement, indépendamment du fait que le mutex ait été acquis. KeTryToAcquireGuardedMutex retourne TRUE si elle a acquis le mutex pour l’appelant ; sinon, elle retourne FALSE.

Un thread appelle KeReleaseGuardedMutex pour libérer un mutex protégé 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 APC sont désactivés pendant que le thread détient un mutex protégé.

Si un chemin de code est garanti pour s’exécuter avec tous les APC 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 quittent 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 à IRQL = APC_LEVEL.

Les mutex gardés ne peuvent pas être acquis de manière récursive. Si un thread qui détient déjà un mutex protégé tente de l’acquérir, ce thread provoquera un interblocage. Les mutex protégés peuvent être utilisés uniquement dans le code qui s'exécute à un niveau IRQL >= APC_LEVEL.