Função NdisAllocateSpinLock (ndis.h)

A função NdisAllocateSpinLock inicializa uma variável do tipo NDIS_SPIN_LOCK, usada para sincronizar o acesso a recursos compartilhados entre funções de driver não ISR.

Sintaxe

void NdisAllocateSpinLock(
  [out] PNDIS_SPIN_LOCK SpinLock
);

Parâmetros

[out] SpinLock

Ponteiro para uma variável opaca que representa um bloqueio de rotação.

Valor retornado

Nenhum

Comentários

Antes que um driver chame NdisAcquireSpinLock, NdisDprAcquireSpinLock ou qualquer uma das funções NdisInterlockedXxx, ele deve chamar NdisAllocateSpinLock para inicializar o bloqueio de rotação passado como um parâmetro necessário para essas funções NdisXxx. O chamador deve fornecer armazenamento nãopagado para a variável no SpinLock .

Depois de chamar NdisAllocateSpinLock, o driver pode chamar NdisAcquireSpinLock para obter o uso exclusivo dos recursos que o bloqueio de rotação protege. Quando o acesso ao recurso é concluído, o driver chama NdisReleaseSpinLock para que outras funções de driver possam acessar os recursos protegidos por esse bloqueio de rotação.

Como regra geral, para melhorar o desempenho, um driver deve usar bloqueios diferentes para proteger diferentes seções críticas. Assim, um driver pode inicializar mais de um bloqueio de rotação com NdisAllocateSpinLock.

Cada bloqueio de rotação alocado por um driver protege um conjunto discreto de recursos compartilhados contra acesso simultâneo por funções de driver que são executadas em IRQL <= DISPATCH_LEVEL. Por exemplo, um driver que mantém uma fila interna de pacotes pode inicializar um bloqueio de rotação para proteger sua fila e outro para proteger um conjunto de variáveis de estado que várias funções de driver, sem incluir a função MiniportInterrupt ou MiniportDisableInterruptEx , acessam enquanto o driver está processando pacotes.

NdisAcquireSpinLock eleva o IRQL para DISPATCH_LEVEL e armazena o IRQL antigo no bloqueio de rotação. A liberação do bloqueio de rotação define o IRQL como o valor armazenado no bloqueio de rotação. Como o NDIS às vezes insere drivers em PASSIVE_LEVEL, podem surgir problemas com o seguinte código:

NdisAcquireSpinLock(A);
NdisAcquireSpinLock(B);
NdisReleaseSpinLock(A);
NdisReleaseSpinLock(B);

Um driver não deve acessar bloqueios de rotação nesta sequência pelos seguintes motivos:

  • Entre NdisReleaseSpinLock(A) e NdisReleaseSpinLock(B), o código está sendo executado em PASSIVE_LEVEL em vez de DISPATCH_LEVEL e está sujeito a interrupção inadequada.
  • Depois de NdisReleaseSpinLock(B), o código está em execução em DISPATCH_LEVEL o que pode fazer com que o chamador seja culpado muito mais tarde com um erro de parada de IRQL_NOT_LESS_OR_EQUAL.
Um driver nunca deve usar dois bloqueios de rotação para proteger o mesmo (sub)conjunto de recursos porque aquisições aninhadas de bloqueio de rotação causam deadlocks com tanta frequência. Mesmo que um driver possa ser projetado para evitar deadlocks, aquisições aninhadas de bloqueio de rotação têm um efeito adverso no desempenho do driver e na taxa de transferência de E/S.

Um driver de miniporto não pode usar um bloqueio de rotação para proteger os recursos que suas funções não ISR compartilham com sua função MiniportInterrupt ou MiniportDisableInterruptEx . Para acessar recursos compartilhados com uma função MiniportInterrupt ou MiniportDisableInterruptEx , um driver de miniport deve chamar NdisMSynchronizeWithInterruptEx para que sua função MiniportSynchronizeInterrupt acesse esses recursos no DIRQL.

Quando um driver não precisa mais de proteção de recursos, por exemplo, quando uma NIC está sendo removida e o driver está liberando os recursos alocados para essa NIC, o driver chama NdisFreeSpinLock.

Liberar um bloqueio de rotação e liberar um bloqueio de rotação são potencialmente confusos. O NdisFreeSpinLock limpa a memória no SpinLock para que ele não represente mais um bloqueio de rotação. Liberar um bloqueio de rotação adquirido com NdisReleaseSpinLock simplesmente permite que outro thread de execução adquira esse bloqueio de rotação.

Para obter mais informações sobre como adquirir e liberar bloqueios de rotação do NDIS, consulte Sincronização e Notificação em Drivers de Rede.

Os chamadores do NdisAllocateSpinLock podem ser executados em qualquer IRQL. Normalmente, um chamador está em execução no IRQL = PASSIVE_LEVEL durante a inicialização.

Requisitos

   
Cliente mínimo com suporte Com suporte para drivers NDIS 6.0 e NDIS 5.1 (consulte NdisAllocateSpinLock (NDIS 5.1)) em Windows Vista. Com suporte para drivers NDIS 5.1 (consulte NdisAllocateSpinLock (NDIS 5.1)) em Windows XP.
Plataforma de Destino Universal
Cabeçalho ndis.h (inclua Ndis.h)
Biblioteca Ndis.lib
IRQL Qualquer nível (consulte a seção Comentários)
Regras de conformidade DDI SpinLockDpr(ndis), SpinLockDprRelease(ndis), SpinlockRelease(ndis)

Confira também

DriverEntry de drivers de protocolo NDIS

MiniportDisableInterruptEx

MiniportHaltEx

MiniportInitializeEx

MiniportInterrupt

NdisAcquireSpinLock

NdisDprAcquireSpinLock

NdisDprReleaseSpinLock

NdisFreeSpinLock

NdisInterlockedAddUlong

NdisInterlockedInsertHeadList

NdisInterlockedInsertTailList

NdisInterlockedRemoveHeadList

NdisMSynchronizeWithInterruptEx

NdisReleaseSpinLock

NetTimerCallback