Partager via


NdisAllocateSpinLock (Compact 2013)

3/26/2014

This function initializes a variable of type NDIS_SPIN_LOCK, used to synchronize access to resources shared among driver functions not related to interrupts.

Syntax

VOID NdisAllocateSpinLock(
  PNDIS_SPIN_LOCK SpinLock
);

Parameters

  • SpinLock
    [in] Pointer to an opaque variable that represents a spin lock.

Return Value

None

Remarks

Before a driver calls NdisAcquireSpinLock, NdisDprAcquireSpinLock, or any of the NdisInterlockedXXX functions, it must call this function to initialize the spin lock passed as a required parameter to these NdisXXX functions. The caller must provide storage for the variable at SpinLock.

After calling this function, the driver can call NdisAcquireSpinLock to obtain exclusive use of the resources that the spin lock protects. When resource access is complete, the driver calls NdisReleaseSpinLock so that other driver functions can access the resources that are protected by that spin lock.

Generally, to improve performance a driver should use different locks to protect different critical sections. Therefore, a driver might initialize more than one spin lock with NdisAllocateSpinLock.

Each spin lock that a driver allocates protects a discrete set of shared resources from simultanous access by driver functions that run at IRQL <= DISPATCH_LEVEL. For example, a driver that maintains an internal queue of packets might initialize one spin lock to protect its queue and another to protect a set of state variables that several driver functions, not including the MiniportInterrupt or MiniportDisableInterruptEx function, access while the driver is processing packets.

NdisAcquireSpinLock raises the IRQL to DISPATCH_LEVEL and stores the old IRQL in the spin lock. Releasing the spin lock sets the IRQL to the value that is stored in the spin lock. Because NDIS sometimes enters drivers at PASSIVE_LEVEL, problems can occur with the following code:

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

A driver should not access spin locks in this sequence for the following reasons:

  • Between NdisReleaseSpinLock(A) and NdisReleaseSpinLock(B) the code is running at PASSIVE_LEVEL instead of DISPATCH_LEVEL and is subject to incorrect interruption.
  • After NdisReleaseSpinLock(B) the code is running at DISPATCH_LEVEL which could cause the caller to fault at much later time with an IRQL_NOT_LESS_OR_EQUAL stop error.

A driver should never use two spin locks to protect the same (sub)set of resources because nested spin lock acquisitions so frequently cause deadlocks. Even if a driver could be designed to prevent deadlocks, nested spin lock acquisitions have an adverse effect on driver performance and I/O throughput.

A miniport driver cannot use a spin lock to protect resources that its non-ISR functions share with its MiniportInterrupt or MiniportDisableInterruptEx function. To access resources shared with a MiniportInterrupt or MiniportDisableInterruptEx function, a miniport driver must call NdisMSynchronizeWithInterruptEx to have its MiniportSynchronizeInterrupt function access those resources at DIRQL.

When a driver no longer requires resource protection, for example, when a network adapter is being removed and the driver is releasing the resources it allocated for that network adapter, the driver calls NdisFreeSpinLock.

Freeing a spin lock and releasing a spin lock are potentially confusing. NdisFreeSpinLock clears the memory at SpinLock so that it no longer represents a spin lock. Releasing an acquired spin lock with NdisReleaseSpinLock just allows another thread of execution to acquire that spin lock.

Callers of NdisAllocateSpinLock can run at any IRQL. Usually a caller is running at IRQL = PASSIVE_LEVEL during initialization.

Requirements

Header

ndis.h

Library

ndis.lib

See Also

Reference

NDIS Spin Lock Interface
DriverEntry of NDIS Protocol Drivers
MiniportHaltEx
MiniportInitializeEx
NetTimerCallback
NdisAcquireSpinLock
NdisDprAcquireSpinLock
NdisDprReleaseSpinLock
NdisFreeSpinLock
NdisInterlockedAddUlong
NdisInterlockedInsertHeadList
NdisInterlockedInsertTailList
NdisInterlockedRemoveHeadList
NdisMSynchronizeWithInterruptEx
NdisReleaseSpinLock