Mutex veloci e Mutex sorvegliati

A partire da Windows 2000, i driver possono usare mutex veloci se richiedono una forma di esclusione reciproca a basso sovraccarico per il codice eseguito in IRQL <= APC_LEVEL. Un mutex veloce può proteggere un percorso di codice che deve essere immesso da un solo thread alla volta. Per immettere il percorso del codice protetto, il thread acquisisce il mutex. Se un altro thread ha già acquisito il mutex, l'esecuzione del thread corrente viene sospesa fino al rilascio del mutex. Per uscire dal percorso del codice protetto, il thread rilascia il mutex.

A partire da Windows Server 2003, i driver possono anche usare mutex sorvegliati. I mutex sorvegliati sono sostituzioni di mutex veloci, ma offrono prestazioni migliori. Come un mutex veloce, un mutex protetto può proteggere un percorso di codice che deve essere immesso da un solo thread alla volta. Tuttavia, il codice che usa i mutex sorvegliati esegue più rapidamente del codice che usa mutex veloci.

Nelle versioni di Windows prima di Windows 8, i mutex sorvegliati vengono implementati in modo diverso da mutex veloci. Percorso di codice protetto da un mutex rapido eseguito in IRQL = APC_LEVEL. Percorso di codice protetto da un mutex sorvegliato eseguito in IRQL <= APC_LEVEL ma con tutte le API disabilitate. In queste versioni precedenti di Windows, l'acquisizione di un mutex sorvegliato è un'operazione più veloce rispetto all'acquisizione di un mutex veloce. Tuttavia, questi due tipi di mutex si comportano in modo identico e sono soggetti alle stesse restrizioni. In particolare, le routine del kernel che sono illegali da chiamare in IRQL = APC_LEVEL non devono essere chiamate da un percorso di codice protetto da un mutex veloce o da un mutex protetto.

A partire da Windows 8, i mutex sorvegliati vengono implementati come mutex veloci. In un percorso di codice protetto da un mutex sorvegliato o da un mutex veloce, Driver Verifier considera le chiamate alle routine del kernel come avviene in IRQL = APC_LEVEL. Come nelle versioni precedenti di Windows, le chiamate illegali in APC_LEVEL sono illegali in un percorso di codice protetto da un mutex protetto o da un mutex veloce.

Mutex veloci

Un mutex veloce è rappresentato da una struttura FAST_MUTEX . Il driver alloca la propria risorsa di archiviazione per una struttura FAST_MUTEX e quindi chiama la routine ExInitializeFastMutex per inizializzare la struttura.

Un thread acquisisce un mutex rapido eseguendo una delle operazioni seguenti:

  • Chiamata alla routine ExAcquireFastMutex . Se il mutex è già stato acquisito da un altro thread, l'esecuzione del thread chiamante viene sospesa fino a quando il mutex non diventa disponibile.

  • Chiamata alla routine ExTryToAcquireFastMutex per provare a acquisire il mutex veloce senza sospendere il thread corrente. La routine restituisce immediatamente, indipendentemente dal fatto che il mutex sia stato acquisito. ExTryToAcquireFastMutex restituisce TRUE se ha acquisito correttamente il mutex per il chiamante; in caso contrario, restituisce FALSE.

Un thread chiama ExReleaseFastMutex per rilasciare un mutex veloce acquisito da ExAcquireFastMutex o ExTryToAcquireFastMutex.

Percorso di codice protetto da un mutex rapido eseguito in IRQL = APC_LEVEL. ExAcquireFastMutex e ExTryToAcquireFastMutex generano l'irQL corrente in APC_LEVEL e ExReleaseFastMutex ripristina l'irQL originale. Pertanto, tutte le API sono disabilitate mentre il thread contiene un mutex veloce.

Se è garantito che un percorso di codice venga sempre eseguito in APC_LEVEL, il driver può invece chiamare ExAcquireFastMutexUnsafe e ExReleaseFastMutexUnsafe per acquisire e rilasciare un mutex veloce. Queste routine non modificano l'IRQL corrente e possono essere usate in modo sicuro solo quando il irQL corrente è APC_LEVEL.

I mutex veloci non possono essere acquisiti in modo ricorsivo. Se un thread che sta già tenendo un mutex veloce tenta di acquisire, tale thread verrà deadlock. I mutex veloci possono essere usati solo nel codice eseguito in IRQL <= APC_LEVEL.

Mutex sorvegliati

I mutex sorvegliati, disponibili a partire da Windows Server 2003, eseguono la stessa funzione dei mutex veloci, ma con prestazioni superiori.

A partire da Windows 8, i mutex sorvegliati e i mutex veloci vengono implementati in modo identico.

Nelle versioni di Windows prima di Windows 8, i mutex sorvegliati vengono implementati in modo diverso da mutex veloci. L'acquisizione di un mutex veloce genera l'irQL corrente per APC_LEVEL, mentre acquisisce un mutex protetto entra in una regione protetta, che è un'operazione più veloce. Per altre informazioni sulle aree protette, vedere Aree critiche e aree protette.

Un mutex sorvegliato è rappresentato da una struttura KGUARDED_MUTEX . Il driver alloca la propria risorsa di archiviazione per una struttura KGUARDED_MUTEX e quindi chiama la routine KeInitializeGuardedMutex per inizializzare la struttura.

Un thread acquisisce un mutex sorvegliato eseguendo una delle operazioni seguenti:

  • Chiamata di KeAcquireGuardedMutex. Se il mutex è già stato acquisito da un altro thread, l'esecuzione del thread chiamante viene sospesa fino a quando il mutex non diventa disponibile.

  • Chiamando KeTryToAcquireGuardedMutex per provare a acquisire il mutex sorvegliato senza sospendere il thread corrente. La routine restituisce immediatamente, indipendentemente dal fatto che il mutex sia stato acquisito. KeTryToAcquireGuardedMutex restituisce TRUE se ha acquisito correttamente il mutex per il chiamante; in caso contrario, restituisce FALSE.

Un thread chiama KeReleaseGuardedMutex per rilasciare un mutex sorvegliato acquisito da KeAcquireGuardedMutex o KeTryToAcquireGuardedMutex.

Un thread che contiene un mutex sorvegliato viene eseguito in modo implicito all'interno di un'area protetta. KeAcquireGuardedMutex e KeTryToAcquireGuardedMutex entrano nell'area protetta, mentre KeReleaseGuardedMutex lo chiude. Tutte le API sono disabilitate mentre il thread contiene un mutex sorvegliato.

Se un percorso di codice è garantito per l'esecuzione con tutte le API disabilitate, il driver può invece usare KeAcquireGuardedMutexUnsafe e KeReleaseGuardedMutexUnsafe per acquisire e rilasciare il mutex sorvegliato. Queste routine non entrano o escono da un'area protetta e possono essere usate solo all'interno di un'area protetta già esistente o in IRQL = APC_LEVEL.

I mutex sorvegliati non possono essere acquisiti in modo ricorsivo. Se un thread che sta già tenendo un mutex sorvegliato tenta di acquisirlo, tale thread verrà deadlock. I mutex sorvegliati possono essere usati solo nel codice eseguito in IRQL <= APC_LEVEL.