Partilhar via


Deteção de impasse

A Deteção de Deadlock monitora o uso pelo driver de recursos que precisam ser bloqueados -- bloqueios de rotação, mutexes e mutexes rápidos. Esta opção de Verificador de Driver detetará a lógica de código que tem o potencial de causar um impasse em algum ponto futuro.

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

A Deteção de Deadlock é suportada apenas no Windows XP e versões posteriores do Windows.

Causas dos impasses

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

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

Tópico 1 Tópico 2
Obtém o Lock A Toma Bloqueio B
Pedidos Bloqueio B Solicitações de Bloqueio A

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

Os bloqueios não estão limitados a dois encadeamentos e dois recursos. Impasses de três vias entre três threads e três locks são comuns - e até mesmo bloqueios de cinco ou seis partes ocorrem ocasionalmente. Estes impasses exigem um certo grau de "má sorte", uma vez que dependem de uma série de coisas que acontecem simultaneamente. No entanto, quanto mais distantes estiverem as aquisições de bloqueio, maior a probabilidade de ocorrerem.

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

O denominador comum entre todos os impasses é que a hierarquia dos bloqueios não é respeitada. Sempre que for necessário adquirir mais do que uma fechadura de cada vez, cada fechadura deve ter uma precedência clara. Se A é tomado antes de B em um ponto e B antes de C em outro, a hierarquia é A-B-C. Isto significa que A nunca deve ser adquirido depois de B ou C, e B não deve ser adquirido depois de C.

A hierarquia de bloqueios deve ser seguida mesmo quando não há possibilidade de um deadlock, pois, durante a manutenção do código, pode ser fácil introduzir acidentalmente um deadlock.

Recursos que podem causar bloqueios

Os impasses mais inequívocos são o resultado de recursos próprios . Estes incluem bloqueios de rotação, mutexes, mutexes rápidos e ERESOURCEs.

Recursos que são sinalizados em vez de adquiridos (como eventos e portas LPC) tendem a causar impasses muito mais ambíguos. É claro que é possível, e muito comum, que o código use indevidamente esses recursos de tal forma que dois threads acabem esperando indefinidamente um pelo outro para completar. No entanto, como esses recursos não são realmente de propriedade de nenhuma thread, não é possível identificar a thread problemática com qualquer grau de certeza.

A opção Deadlock Detection do Driver Verifier procura possíveis deadlocks envolvendo bloqueios de rotação, mutexes e mutexes rápidos. Não controla a utilização de ERESOURCES, nem a utilização de recursos não pertencentes.

Efeitos da deteçã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 serão bloqueados quando lhes for dada a oportunidade.

Para encontrar possíveis deadlocks, o Driver Verifier cria um gráfico da ordem de aquisição de recursos e verifica se há loops. Se você criasse um nó para cada recurso e desenhasse uma seta sempre que um bloqueio fosse adquirido antes de outro, os loops de caminho representariam violações da hierarquia de bloqueio.

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

Observação

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

Quando a Deteção de Deadlock encontrar uma violação, emitirá a verificação de bug 0xC4. O primeiro parâmetro desta verificação de bug indicará a violação exata. Possíveis violações incluem:

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

  • Um segmento que tenta adquirir exclusivamente um recurso para o qual já é um proprietário compartilhado (recursos de propriedade exclusiva 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 é liberado por um thread diferente daquele que o adquiriu

  • Um recurso que é inicializado mais de uma vez ou não foi 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 bloqueios. Por exemplo, tentar usar a mesma estrutura de dados KSPIN_LOCK tanto como um spin lock regular como um spin lock em fila de pilha.

Consulte Bug Check 0xC4 (DRIVER_VERIFIER_DETECTED_VIOLATION) para obter uma lista dos parâmetros de verificação de erro.

Monitorando a deteção de deadlock

Uma vez que o Deadlock Detection encontre uma violação, a extensão do depurador do kernel !deadlock pode 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 do depurador, na documentação do pacote Debugging Tools for Windows. Consulte Depuração do Windows para obter detalhes.

Ativando esta opção

Observação

Esta opção é incompatível com a difusão do atraso de sincronização do kernel

Você pode ativar o recurso de deteção de deadlock para um ou mais drivers usando o Driver Verifier Manager ou a linha de comando Verifier.exe. Para obter detalhes, consulte Selecionando Opções do Verificador de Controladores.

  • Na linha de comando

    Na linha de comando, a opção Deteção de deadlock é representada pelo bit 5 (0x20). Para ativar a Deteção de Impasse, 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 Deteçã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 entra em vigor imediatamente, mas é perdida quando você desliga ou reinicia o computador. Para obter detalhes, consulte Usando Configuração Volátil.

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

    verifier /standard /driver MyDriver.sys
    
  • Usando o Gestor do Verificador de Drivers

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

    2. Selecione configurações individuais de uma lista completa.

    3. Selecione (verifique) Deteção de deadlock.

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