Mutexes rápidos e mutexes protegidos

A partir do Windows 2000, os drivers poderão usar mutexes rápidos se exigirem uma forma de exclusão mútua de baixa sobrecarga para o código executado em IRQL <= APC_LEVEL. Um mutex rápido pode proteger um caminho de código que deve ser inserido por apenas um thread por vez. Para inserir o caminho de código protegido, o thread adquire o mutex. Se outro thread já tiver adquirido o mutex, a execução do thread atual será suspensa até que o mutex seja liberado. Para sair do caminho de código protegido, o thread libera o mutex.

A partir do Windows Server 2003, os drivers também podem usar mutexes protegidos. Os mutexes protegidos são substituições suspensas para mutexes rápidos, mas fornecem melhor desempenho. Como um mutex rápido, um mutex protegido pode proteger um caminho de código que deve ser inserido por apenas um thread por vez. No entanto, o código que usa mutexes protegidos é executado mais rapidamente do que o código que usa mutexes rápidos.

Em versões do Windows antes de Windows 8, os mutexes protegidos são implementados de forma diferente dos mutexes rápidos. Um caminho de código protegido por um mutex rápido é executado em IRQL = APC_LEVEL. Um caminho de código protegido por um mutex protegido é executado em IRQL <= APC_LEVEL mas com todas as APCs desabilitadas. Nessas versões anteriores do Windows, a aquisição de um mutex protegido é uma operação mais rápida do que a aquisição de um mutex rápido. No entanto, esses dois tipos de mutex se comportam de forma idêntica e estão sujeitos às mesmas restrições. Em particular, rotinas de kernel que são ilegais de chamar em IRQL = APC_LEVEL não devem ser chamadas de um caminho de código protegido por um mutex rápido ou um mutex protegido.

Começando com Windows 8, os mutexes protegidos são implementados como mutexes rápidos. Em um caminho de código protegido por um mutex protegido ou um mutex rápido, o Verificador de Driver trata chamadas para rotinas de kernel como ocorrendo em IRQL = APC_LEVEL. Como em versões anteriores do Windows, chamadas que são ilegais em APC_LEVEL são ilegais em um caminho de código protegido por um mutex protegido ou um mutex rápido.

Mutexes rápidos

Um mutex rápido é representado por uma estrutura de FAST_MUTEX . O driver aloca seu próprio armazenamento para uma estrutura FAST_MUTEX e chama a rotina ExInitializeFastMutex para inicializar a estrutura.

Um thread adquire um mutex rápido fazendo um dos seguintes procedimentos:

  • Chamando a rotina ExAcquireFastMutex . Se o mutex já tiver sido adquirido por outro thread, a execução do thread de chamada será suspensa até que o mutex fique disponível.

  • Chamar a rotina ExTryToAcquireFastMutex para tentar adquirir o mutex rápido sem suspender o thread atual. A rotina retorna imediatamente, independentemente de o mutex ter sido adquirido. ExTryToAcquireFastMutex retornará TRUE se tiver adquirido com êxito o mutex para o chamador; caso contrário, retornará FALSE.

Um thread chama ExReleaseFastMutex para liberar um mutex rápido que foi adquirido por ExAcquireFastMutex ou ExTryToAcquireFastMutex.

Um caminho de código protegido por um mutex rápido é executado em IRQL = APC_LEVEL. ExAcquireFastMutex e ExTryToAcquireFastMutex aumentam o IRQL atual para APC_LEVEL e ExReleaseFastMutex restaura o IRQL original. Assim, todas as APCs são desabilitadas enquanto o thread mantém um mutex rápido.

Se for garantido que um caminho de código sempre seja executado em APC_LEVEL, o driver poderá chamar ExAcquireFastMutexUnsafe e ExReleaseFastMutexUnsafe para adquirir e liberar um mutex rápido. Essas rotinas não alteram o IRQL atual e só podem ser usadas com segurança quando o IRQL atual é APC_LEVEL.

Mutexes rápidos não podem ser adquiridos recursivamente. Se um thread que já está segurando um mutex rápido tentar adquiri-lo, esse thread será deadlock. Mutexes rápidos só podem ser usados em código executado em IRQL <= APC_LEVEL.

Mutexes protegidos

Os mutexes protegidos, que estão disponíveis a partir do Windows Server 2003, executam a mesma função que os mutexes rápidos, mas com maior desempenho.

Começando com Windows 8, mutexes protegidos e mutexes rápidos são implementados de forma idêntica.

Em versões do Windows antes de Windows 8, os mutexes protegidos são implementados de forma diferente dos mutexes rápidos. Adquirir um mutex rápido eleva o IRQL atual para APC_LEVEL, enquanto a aquisição de um mutex protegido entra em uma região protegida, o que é uma operação mais rápida. Para obter mais informações sobre regiões protegidas, consulte Regiões críticas e regiões protegidas.

Um mutex protegido é representado por uma estrutura de KGUARDED_MUTEX . O driver aloca seu próprio armazenamento para uma estrutura KGUARDED_MUTEX e chama a rotina KeInitializeGuardedMutex para inicializar a estrutura.

Um thread adquire um mutex protegido fazendo um dos seguintes procedimentos:

  • Chamando KeAcquireGuardedMutex. Se o mutex já tiver sido adquirido por outro thread, a execução do thread de chamada será suspensa até que o mutex fique disponível.

  • Chamar KeTryToAcquireGuardedMutex para tentar adquirir o mutex protegido sem suspender o thread atual. A rotina retorna imediatamente, independentemente de o mutex ter sido adquirido. KeTryToAcquireGuardedMutex retornaráTRUE se tiver adquirido com êxito o mutex para o chamador; caso contrário, retornará FALSE.

Um thread chama KeReleaseGuardedMutex para liberar um mutex protegido que foi adquirido por KeAcquireGuardedMutex ou KeTryToAcquireGuardedMutex.

Um thread que contém um mutex protegido é executado implicitamente dentro de uma região protegida. KeAcquireGuardedMutex e KeTryToAcquireGuardedMutex entram na região protegida, enquanto KeReleaseGuardedMutex sai dela. Todas as APCs são desabilitadas enquanto o thread contém um mutex protegido.

Se for garantido que um caminho de código seja executado com todas as APCs desabilitadas, o driver poderá usar KeAcquireGuardedMutexUnsafe e KeReleaseGuardedMutexUnsafe para adquirir e liberar o mutex protegido. Essas rotinas não entram ou saem de uma região protegida e só podem ser usadas dentro de uma região protegida já existente ou em IRQL = APC_LEVEL.

Mutexes protegidos não podem ser adquiridos recursivamente. Se um thread que já está segurando um mutex protegido tentar adquiri-lo, esse thread será deadlock. Os mutexes protegidos só podem ser usados no código executado em IRQL <= APC_LEVEL.