Compartilhar via


Detecção de deadlock

A Detecção de Deadlock monitora o uso de recursos do driver que precisam ser bloqueados : bloqueios de rotação, mutexes e mutexes rápidos. Essa opção do Verificador de Drivers detectará a lógica de código que tem o potencial de causar um deadlock no futuro.

A opção de Detecção de Deadlock do Verificador de Driver, juntamente com a extensão do depurador de kernel !deadlock , é uma ferramenta eficaz para garantir que seu código evite o mau uso desses recursos.

A Detecção de Deadlock tem suporte apenas no Windows XP e versões posteriores do Windows.

Causas de deadlocks (bloqueios)

Um deadlock é causado quando dois ou mais threads entram em conflito sobre algum recurso, de modo que nenhuma execução é possível.

A forma mais comum de deadlock ocorre quando dois ou mais threads esperam por um recurso que pertence ao outro thread. Isso é ilustrado da seguinte maneira:

Thread 1 Thread 2
Usa o bloqueio A Obtém o bloqueio B
Bloqueio de solicitações B Solicitações bloqueiam A

Se ambas as sequências ocorrerem ao mesmo tempo, o Thread 1 nunca obterá o Bloqueio B porque ele pertence ao Thread 2 e o Thread 2 nunca obterá o Bloqueio A porque ele pertence ao Thread 1. Na melhor das hipóteses, isso faz com que os threads envolvidos interrompam e, na pior das hipóteses, faz com que o sistema pare de responder.

Deadlocks não se limitam a dois threads e dois recursos. Os deadlocks de três partes entre três threads e três bloqueios são comuns, e até mesmo deadlocks de cinco ou seis partes ocorrem ocasionalmente. Esses deadlocks exigem um certo grau de "má sorte", pois dependem de várias coisas acontecendo simultaneamente. No entanto, quanto mais distantes forem as aquisições de bloqueio, maior a probabilidade de ocorrerem problemas.

Deadlocks de thread único podem ocorrer quando um thread tenta obter um bloqueio que ele já possui.

O denominador comum entre todos os deadlocks é que a hierarquia de bloqueio não é respeitada. Sempre que for necessário ter mais de um bloqueio ao mesmo tempo, cada bloqueio deve ter uma precedência clara. Se A for levado antes de B em um ponto e B antes de C em outro, a hierarquia será A-B-C. Isso significa que A nunca deve ser adquirido após B ou C, e B não deve ser adquirido após C.

A hierarquia de bloqueio deve ser seguida mesmo quando não há possibilidade de um deadlock, pois no processo de manutenção do código será fácil para um deadlock ser introduzido acidentalmente.

Recursos que podem causar deadlocks

Os deadlocks mais inequívocos são o resultado de recursos proprietários. Isso inclui bloqueios de rotação, mutexes, mutexes rápidos e ERESOURCEs.

Recursos que são sinalizados em vez de serem adquiridos (como eventos e portas LPC) tendem a causar bloqueios muito mais ambíguos. É claro que é possível, e muito comum, que o código abuse desses recursos de forma que duas threads acabem aguardando indefinidamente um pelo outro para serem concluídos. No entanto, como esses recursos não pertencem de fato a nenhum thread, não é possível identificar o thread delinquente com qualquer grau de certeza.

A opção Detecção de Deadlock do Verificador de Driver busca por possíveis deadlocks envolvendo bloqueios de rotação, mutexes e mutexes rápidos. Ele não monitora o uso de ERESOURCEs nem monitora o uso de recursos não proprietários.

Efeitos da detecção de deadlock

As rotinas de Detecção de Deadlock do Driver Verifier encontram violações da hierarquia de bloqueio que não são necessariamente simultâneas. Na maioria das vezes, essas violações identificam caminhos de código que bloquearão quando tiverem a oportunidade.

Para encontrar possíveis deadlocks, o Verificador de Driver cria um gráfico de ordem de aquisição de recursos e verifica se há ciclos. Se você criar um nó para cada recurso e desenhar uma seta sempre que um bloqueio for adquirido antes de outro, os ciclos no caminho representarão violações da hierarquia de bloqueio.

O Verificador de Driver emitirá uma verificação de bugs quando uma dessas violações for descoberta. Isso ocorrerá antes que ocorram deadlocks reais.

Observação

Mesmo que os caminhos de código conflitantes nunca possam acontecer simultaneamente, eles ainda deverão ser reescritos se envolverem violações de hierarquia de bloqueio. Esse código é um "deadlock aguardando para acontecer" que pode causar deadlocks reais se o código for reescrito ligeiramente.

Quando a Detecção de Deadlock encontrar uma violação, ela emitirá o código de verificação de erro 0xC4. O primeiro parâmetro dessa verificação de bug indicará a violação exata. As possíveis violações incluem:

  • Dois ou mais threads envolvidos em uma violação de hierarquia de bloqueio

  • Um thread que tenta adquirir exclusivamente um recurso para o qual ele já é um proprietário compartilhado (recursos exclusivos podem ser adquiridos compartilhados; recursos compartilhados não podem ser adquiridos exclusivamente).

  • Uma thread que tenta adquirir o mesmo recurso duas vezes (um auto-bloqueio)

  • Um recurso que é liberado sem ter sido adquirido primeiro

  • Um recurso que é lançado por um thread diferente daquele que o adquiriu

  • Um recurso que é inicializado mais de uma vez ou que não é inicializado de forma alguma

  • Um thread que é excluído enquanto ainda possui recursos

  • A partir do Windows 7, o Verificador de Driver pode prever possíveis deadlocks. Por exemplo, tentar usar a mesma estrutura de dados KSPIN_LOCK tanto como um spin lock regular quanto como um spin lock enfileirado em pilha.

Consulte Verificação de Bug 0xC4 (DRIVER_VERIFIER_DETECTED_VIOLATION) para obter uma lista dos parâmetros do bug check.

Monitoramento da detecção de deadlock

Depois que a Detecção de Deadlock encontrar uma violação, a extensão do depurador de kernel !deadlock poderá ser usada para investigar exatamente o que ocorreu. Ele pode exibir a topologia da hierarquia de bloqueio, bem como as pilhas de chamadas para cada thread no momento em que os bloqueios foram originalmente adquiridos.

Há um exemplo detalhado da extensão !deadlock , bem como informações gerais sobre extensões de depurador, na documentação do pacote Ferramentas de Depuração para Windows. Consulte a Depuração do Windows para obter detalhes.

Ativando essa opção

Observação

Essa opção é incompatível com o atraso de sincronização do Kernel

Você pode ativar o recurso Detecção de Deadlock para um ou mais drivers usando o Driver Verifier Manager ou a linha de comando Verifier.exe. Para obter detalhes, consulte Selecionar opções do Verificador de Driver.

  • Na linha de comando

    Na linha de comando, a opção Detecção de Deadlock é representada pelo Bit 5 (0x20). Para ativar a Detecção de Deadlock, use um valor de sinalizador de 0x20 ou adicione 0x20 ao valor do sinalizador. Por exemplo:

    verifier /flags 0x20 /driver MyDriver.sys
    

    O recurso estará ativo após a próxima inicialização.

    No Windows Vista e versões posteriores do Windows, você também pode ativar e desativar a Detecção de Deadlock sem reinicializar o computador adicionando o parâmetro /volatile ao comando. Por exemplo:

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

    Essa configuração é efetivada imediatamente, mas é perdida quando você desliga ou reinicializa o computador. Para obter detalhes, consulte Como usar configurações voláteis.

    O recurso detecção de deadlock também está incluído nas configurações padrão. Por exemplo:

    verifier /standard /driver MyDriver.sys
    
  • Usando o Gerenciador de Verificador de Driver

    1. Selecione Criar configurações personalizadas (para desenvolvedores de código) e selecione Avançar.

    2. Selecione Selecionar configurações individuais em uma lista completa.

    3. Selecione (verificar) a detecção de deadlock.

O recurso detecção de deadlock também está incluído nas configurações padrão. Para usar esse recurso, no Gerenciador do Verificador de Driver, selecione Criar Configurações Padrão.