Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
As seções críticas podem ser exibidas no modo de usuário por uma variedade de métodos diferentes. O significado exato de cada campo depende da versão do Microsoft Windows que você está usando.
Exibindo seções críticas
As seções críticas podem ser apresentadas pela extensão !ntsdexts.locks, a extensão !critsec, a extensão !cs e o comando dt (Tipo de Exibição).
A extensão !ntsdexts.locks exibe uma lista de seções críticas associadas ao processo atual. Se a opção -v for usada, todas as seções críticas serão exibidas. Aqui está um exemplo:
0:000> !locks
CritSec ntdll!FastPebLock+0 at 77FC49E0
LockCount 0
RecursionCount 1
OwningThread c78
EntryCount 0
ContentionCount 0
*** Locked
....
Scanned 37 critical sections
Se você souber o endereço da seção crítica que deseja exibir, você pode usar a extensão !critsec . Isso exibe a mesma coleção de informações que !ntsdexts.locks. Por exemplo:
0:000> !critsec 77fc49e0
CritSec ntdll!FastPebLock+0 at 77FC49E0
LockCount 0
RecursionCount 1
OwningThread c78
EntryCount 0
ContentionCount 0
*** Locked
A extensão !cs pode exibir uma seção crítica com base em seu endereço, pesquisar um intervalo de endereços para seções críticas e até mesmo exibir o rastreamento de pilha associado a cada seção crítica. Alguns desses recursos exigem símbolos completos do Windows para funcionar corretamente. Se o Application Verifier estiver ativo, !cs -t pode ser usado para exibir a árvore de seção crítica. Consulte a página de referência !cs para obter detalhes e exemplos.
As informações exibidas por !cs são ligeiramente diferentes das mostradas por !ntsdexts.locks e !critsec. Por exemplo:
## 0:000> !cs 77fc49e0
Critical section = 0x77fc49e0 (ntdll!FastPebLock+0x0)
DebugInfo = 0x77fc3e00
LOCKED
LockCount = 0x0
OwningThread = 0x00000c78
RecursionCount = 0x1
LockSemaphore = 0x0
SpinCount = 0x00000000
O comando dt (Display Type) pode ser usado para exibir o conteúdo literal da estrutura RTL_CRITICAL_SECTION. Por exemplo:
0:000> dt RTL_CRITICAL_SECTION 77fc49e0
+0x000 DebugInfo : 0x77fc3e00
+0x004 LockCount : 0
+0x008 RecursionCount : 1
+0x00c OwningThread : 0x00000c78
+0x010 LockSemaphore : (null)
+0x014 SpinCount : 0
Interpretando campos de seção crítica no Windows XP e Windows 2000
Os domínios mais importantes da estrutura da secção crítica são os seguintes:
No Microsoft Windows 2000 e Windows XP, o campo LockCount indica o número de vezes que qualquer thread chamou a rotina EnterCriticalSection para essa seção crítica, menos uma. Este campo começa em -1 para uma seção crítica desbloqueada. Cada chamada de EnterCriticalSection incrementa esse valor; cada chamada de LeaveCriticalSection diminui isso. Por exemplo, se LockCount for 5, essa seção crítica será bloqueada, um thread a adquiriu e cinco threads adicionais aguardarão esse bloqueio.
O campo RecursionCount indica o número de vezes que o thread proprietário chamou EnterCriticalSection para essa seção crítica.
O campo EntryCount indica o número de vezes que um thread diferente do thread proprietário chamou EnterCriticalSection para essa seção crítica.
Uma seção crítica recém-inicializada tem esta aparência:
0:000> !critsec 433e60
CritSec mymodule!cs+0 at 00433E60
LockCount NOT LOCKED
RecursionCount 0
OwningThread 0
EntryCount 0
ContentionCount 0
O depurador exibe "NOT LOCKED" como o valor para LockCount. O valor real deste campo para uma seção crítica desbloqueada é -1. Você pode verificar isso com o comando dt (Display Type):
0:000> dt RTL_CRITICAL_SECTION 433e60
+0x000 DebugInfo : 0x77fcec80
+0x004 LockCount : -1
+0x008 RecursionCount : 0
+0x00c OwningThread : (null)
+0x010 LockSemaphore : (null)
+0x014 SpinCount : 0
Quando o primeiro thread chama a rotina EnterCriticalSection , os campos LockCount, RecursionCount, EntryCount e ContentionCount da seção crítica são incrementados por um e OwningThread se torna a ID do thread do chamador. EntryCount e ContentionCount nunca são diminuídos. Por exemplo:
0:000> !critsec 433e60
CritSec mymodule!cs+0 at 00433E60
LockCount 0
RecursionCount 1
OwningThread 4d0
EntryCount 0
ContentionCount 0
Neste ponto, quatro coisas diferentes podem acontecer.
O thread proprietário chama EnterCriticalSection novamente. Isso incrementará LockCount e RecursionCount. EntryCount não é incrementado.
0:000> !critsec 433e60 CritSec mymodule!cs+0 at 00433E60 LockCount 1 RecursionCount 2 OwningThread 4d0 EntryCount 0 ContentionCount 0Um thread diferente chama EnterCriticalSection. Isso incrementará LockCount e EntryCount. RecursionCount não é incrementado.
0:000> !critsec 433e60 CritSec mymodule!cs+0 at 00433E60 LockCount 1 RecursionCount 1 OwningThread 4d0 EntryCount 1 ContentionCount 1O thread proprietário chama LeaveCriticalSection. Isso diminuirá LockCount (para -1) e RecursionCount (para 0) e redefinirá OwningThread para 0.
0:000> !critsec 433e60 CritSec mymodule!cs+0 at 00433E60 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 0Outro thread chama LeaveCriticalSection. Isso produz os mesmos resultados que o thread proprietário chamando LeaveCriticalSection -- ele diminuirá LockCount (para -1) e RecursionCount (para 0) e redefinirá OwningThread para 0.
Quando qualquer thread chama LeaveCriticalSection, o Windows diminui LockCount e RecursionCount. Esta característica tem aspetos bons e maus. Ele permite que um driver de dispositivo entre em uma seção crítica em um thread e deixe a seção crítica em outro thread. No entanto, também torna possível chamar acidentalmente LeaveCriticalSection no thread errado, ou chamar LeaveCriticalSection muitas vezes e fazer com que LockCount atinja valores inferiores a -1. Isso corrompe a seção crítica e faz com que todos os threads esperem indefinidamente na seção crítica.
Interpretando campos de seção crítica no Windows Server 2003 SP1 e posterior
No Microsoft Windows Server 2003 Service Pack 1 e versões posteriores do Windows, o campo LockCount é analisado da seguinte forma:
O bit mais baixo mostra o estado do bloqueio. Se esse bit for 0, a seção crítica será bloqueada; se for 1, a secção crítica não está bloqueada.
O próximo bit mostra se um thread foi acordado para esse bloqueio. Se este bit for 0, então um thread foi acordado para este bloqueio; se for 1, nenhum fio foi acordado.
Os bits restantes são o complemento do número de threads à espera do bloqueio.
Como exemplo, suponha que o LockCount seja -22. O bit mais baixo pode ser determinado desta forma:
0:009> ? 0x1 & (-0n22)
Evaluate expression: 0 = 00000000
O próximo bit mais baixo pode ser determinado desta forma:
0:009> ? (0x2 & (-0n22)) >> 1
Evaluate expression: 1 = 00000001
Os complementos dos bits restantes podem ser determinados desta forma:
0:009> ? ((-1) - (-0n22)) >> 2
Evaluate expression: 5 = 00000005
Neste exemplo, o primeiro bit é 0 e, portanto, a seção crítica está bloqueada. O segundo bit é 1 e, portanto, nenhum thread foi despertado para esta trava. O complemento dos bits restantes é 5, e por isso há cinco threads esperando por esse bloqueio.
Informações adicionais
Para obter informações sobre como depurar tempos limite de seção crítica, consulte Tempo limite de seção crítica. Para obter informações gerais sobre seções críticas, consulte o SDK do Microsoft Windows, o Kit de Driver do Windows (WDK) ou Microsoft Windows Internals de Mark Russinovich e David Solomon.