Condividi tramite


Rilevamento di deadlock

Il rilevamento dei deadlock monitora l'uso delle risorse del driver che devono essere bloccate, ovvero spinlock, mutex e mutex veloci. Questa opzione Driver Verifier rileverà la logica del codice che potrebbe causare un deadlock a un certo punto.

L'opzione Rilevamento deadlock di Driver Verifier, insieme all'estensione del debugger del kernel !deadlock , è uno strumento efficace per assicurarsi che il codice eviti un uso insufficiente di queste risorse.

Il rilevamento dei deadlock è supportato solo in Windows XP e versioni successive di Windows.

Cause di deadlock

Un deadlock si verifica quando due o più thread vengono in conflitto su alcune risorse, in modo che non sia possibile eseguire alcuna esecuzione.

La forma più comune di deadlock si verifica quando due o più thread attendono una risorsa di proprietà dell'altro thread. Questo è illustrato come segue:

Thread 1 Thread 2
Prende il blocco A Prende blocco B
Blocco richieste di accesso B Richieste di blocco A

Se entrambe le sequenze si verificano contemporaneamente, il thread 1 non otterrà mai Il blocco B perché è di proprietà del thread 2 e il thread 2 non otterrà mai il blocco A perché è di proprietà del thread 1. In questo modo, i thread coinvolti si arrestano e, nel peggiore dei casi, il sistema smette di rispondere.

I deadlock non sono limitati a due thread e due risorse. I deadlock con tre vie tra tre thread e tre lucchetti sono comuni; inoltre, si verificano occasionalmente anche quelli a cinque o sei parti. Questi deadlock richiedono un certo grado di "sfortuna" perché si basano su una serie di cose che si verificano simultaneamente. Tuttavia, quanto più distanti sono le acquisizioni dei blocchi, tanto più è probabile che si verifichino.

I deadlock a thread singolo possono verificarsi quando un thread tenta di acquisire un blocco che possiede già.

Il denominatore comune tra tutti i deadlock è che la gerarchia di blocchi non viene rispettata. Ogni volta che è necessario acquisire più lock contemporaneamente, ogni lock deve avere una precedenza ben definita. Se A viene preso prima di B a un punto e B prima di C in un altro, la gerarchia è A-B-C. Ciò significa che A non deve mai essere acquisito dopo B o C e B non deve essere acquisito dopo C.

La gerarchia di blocchi deve essere seguita anche quando non esiste alcuna possibilità di deadlock, perché nel processo di gestione del codice sarà facile introdurre accidentalmente un deadlock.

Risorse che possono causare deadlock

I deadlock più inequivocabili sono il risultato delle risorse di proprietà. Questi includono blocchi di rotazione, mutex, mutex veloci e ERESOURCEs.

Le risorse segnalate anziché acquisite (ad esempio eventi e porte LPC) tendono a causare deadlock molto più ambigui. È naturalmente possibile, e fin troppo comune, che il codice faccia un uso improprio di queste risorse, al punto che due thread finiscono per aspettare indefinitamente che si completino a vicenda. Tuttavia, poiché queste risorse non sono effettivamente di proprietà di un thread, non è possibile identificare il thread delinquente con qualsiasi grado di certezza.

L'opzione Rilevamento deadlock di Driver Verifier cerca potenziali deadlock che coinvolgono spin lock, mutex e mutex veloce. Non monitora l'uso di ERESOURCEs, né monitora l'uso di risorse non gestite.

Effetti del rilevamento dei deadlock

Le routine di rilevamento dei deadlock di Driver Verifier rilevano violazioni della gerarchia di blocchi che non sono necessariamente simultanee. Nella maggior parte dei casi, queste violazioni identificano i percorsi di codice che si bloccheranno quando si presenti l'occasione.

Per trovare potenziali deadlock, Driver Verifier crea un grafico dell'ordine di acquisizione delle risorse e verifica la presenza di cicli. Se si dovesse creare un nodo per ogni risorsa e disegnare una freccia ogni volta che un blocco viene acquisito prima di un altro, i cicli di percorso rappresentano violazioni della gerarchia di blocchi.

Driver Verifier genererà un controllo del bug quando viene individuata una di queste violazioni. Ciò si verifica prima che si verifichino eventuali deadlock effettivi.

Annotazioni

Anche se i percorsi di codice in conflitto non possono mai verificarsi contemporaneamente, devono comunque essere riscritti se comportano violazioni della gerarchia di blocchi. Questo codice è come un "deadlock pronto a verificarsi" che potrebbe portare a deadlock reali se il codice venisse riscritto leggermente.

Quando il rilevamento deadlock rileva una violazione, genera un controllo dei bug 0xC4. Il primo parametro di questo controllo di bug indicherà la violazione esatta. Le possibili violazioni includono:

  • Due o più thread coinvolti in una violazione della gerarchia di blocchi

  • Thread che tenta di acquisire esclusivamente una risorsa di cui è già titolare condiviso (le risorse di proprietà esclusiva possono essere acquisite in modalità condivisa; le risorse condivise non possono essere acquisite in modalità esclusiva).

  • Il thread che tenta di acquisire la stessa risorsa due volte (un deadlock)

  • Una risorsa rilasciata senza essere stata acquisita per prima

  • Una risorsa rilasciata da un thread diverso da quello che l'ha acquisita

  • Una risorsa inizializzata più volte o non inizializzata affatto

  • Un thread eliminato mentre possiede ancora risorse

  • A partire da Windows 7, Driver Verifier può prevedere possibili deadlock. Ad esempio, cercando di usare la stessa struttura di dati KSPIN_LOCK sia come spin lock regolare che come spin lock con coda a pila.

Vedere Controllo bug 0xC4 (DRIVER_VERIFIER_DETECTED_VIOLATION) per un elenco dei parametri di controllo dei bug.

Monitoraggio del rilevamento dei deadlock

Quando il rilevamento deadlock rileva una violazione, è possibile usare l'estensione del debugger del kernel !deadlock per analizzare esattamente ciò che si è verificato. Può visualizzare la topologia della gerarchia di blocchi, nonché gli stack di chiamate per ogni thread al momento dell'acquisizione dei blocchi.

È disponibile un esempio dettagliato dell'estensione !deadlock , nonché informazioni generali sulle estensioni del debugger, nella documentazione del pacchetto Strumenti di debug per Windows. Per informazioni dettagliate, vedere Debug di Windows .

Attivazione di questa opzione

Annotazioni

Questa opzione non è compatibile con la sincronizzazione ritardata del kernel

È possibile attivare la funzionalità Rilevamento Deadlock per uno o più driver utilizzando Driver Verifier Manager o il comando Verifier.exe. Per informazioni dettagliate, vedere Selezione delle Opzioni del Verificatore Driver.

  • Alla riga di comando

    Nella riga di comando, l'opzione Rilevamento deadlock è rappresentata da Bit 5 (0x20).The command line, the Deadlock Detection option is represented by Bit 5 (0x20). Per attivare il rilevamento dei deadlock, usare un valore del flag di 0x20 o aggiungere 0x20 al valore del flag. Per esempio:

    verifier /flags 0x20 /driver MyDriver.sys
    

    La funzionalità sarà attiva dopo l'avvio successivo.

    In Windows Vista e versioni successive di Windows è anche possibile attivare e disattivare Il rilevamento deadlock senza riavviare il computer aggiungendo il parametro /volatile al comando. Per esempio:

    verifier /volatile /flags 0x20 /adddriver MyDriver.sys
    

    Questa impostazione è effettiva immediatamente, ma viene persa quando si arresta o si riavvia il computer. Per informazioni dettagliate, vedere Uso di impostazioni volatili.

    La funzionalità Di rilevamento deadlock è inclusa anche nelle impostazioni standard. Per esempio:

    verifier /standard /driver MyDriver.sys
    
  • Uso del Driver Verifier Manager

    1. Selezionare Crea impostazioni personalizzate (per sviluppatori di codice) e quindi selezionare Avanti.

    2. Selezionare Selezionare le singole impostazioni da un elenco completo.

    3. Selezionare (spunta) Rilevamento di stallo.

La funzionalità Di rilevamento deadlock è inclusa anche nelle impostazioni standard. Per usare questa funzionalità, in Gestione driver verifier selezionare Crea impostazioni standard.