Функция NdisAllocateSpinLock (ndis.h)

Функция NdisAllocateSpinLock инициализирует переменную типа NDIS_SPIN_LOCK, используемую для синхронизации доступа к ресурсам, совместно используемым функциями драйверов, не относящихся к ISR.

Синтаксис

void NdisAllocateSpinLock(
  [out] PNDIS_SPIN_LOCK SpinLock
);

Параметры

[out] SpinLock

Указатель на непрозрачную переменную, представляющую блокировку спина.

Возвращаемое значение

None

Remarks

Прежде чем драйвер вызывает NdisAcquireSpinLock, NdisDprAcquireSpinLock или любую из функций NdisInterlockedXxx , он должен вызвать NdisAllocateSpinLock , чтобы инициализировать блокировку спина, переданную в качестве обязательного параметра для этих функций NdisXxx . Вызывающий объект должен предоставить непагрегированное хранилище для переменной в SpinLock .

После вызова NdisAllocateSpinLock драйвер может вызвать NdisAcquireSpinLock , чтобы получить монопольное использование ресурсов, защищаемых спин-блокировкой. После завершения доступа к ресурсам драйвер вызывает NdisReleaseSpinLock , чтобы другие функции драйвера могли получить доступ к ресурсам, защищенным этой блокировкой спина.

Как правило, для повышения производительности драйвер должен использовать различные блокировки для защиты разных критически важных разделов. Таким образом, драйвер может инициализировать несколько спиновых блокировок с помощью NdisAllocateSpinLock.

Каждая блокировка спина, выделяемая драйвером, защищает дискретный набор общих ресурсов от одновременного доступа функций драйвера, которые выполняются в IRQL <= DISPATCH_LEVEL. Например, драйвер, поддерживающий внутреннюю очередь пакетов, может инициализировать одну блокировку спина для защиты очереди, а другую — для защиты набора переменных состояния, которые выполняют несколько функций драйвера, не включая MiniportInterrupt илиФункция MiniportDisableInterruptEx— доступ, пока драйвер обрабатывает пакеты.

NdisAcquireSpinLock вызывает IRQL для DISPATCH_LEVEL и сохраняет старый IRQL в спин-блокировке. При освобождении блокировки спина в irQL устанавливается значение, хранящееся в спин-блокировке. Так как NDIS иногда входит в драйверы в PASSIVE_LEVEL, могут возникнуть проблемы со следующим кодом:

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

Драйвер не должен получать доступ к блокировкам спина в этой последовательности по следующим причинам:

  • Между NdisReleaseSpinLock(A) и NdisReleaseSpinLock(B) код выполняется на PASSIVE_LEVEL вместо DISPATCH_LEVEL и может быть неправильно прерван.
  • После NdisReleaseSpinLock(B) код выполняется в DISPATCH_LEVEL что может привести к сбою вызывающего объекта гораздо позже с ошибкой IRQL_NOT_LESS_OR_EQUAL stop.
Драйвер никогда не должен использовать две блокировки спина для защиты одного и того же (под)набора ресурсов, так как вложенная блокировка спина так часто вызывает взаимоблокировки. Даже если драйвер может быть разработан для предотвращения взаимоблокировок, вложенная блокировка спина негативно сказывается на производительности драйвера и пропускной способности ввода-вывода.

Драйвер мини-порта не может использовать спиновую блокировку для защиты ресурсов, которые его функции, не относящиеся к ISR, совместно используются с miniportInterrupt илиФункция MiniportDisableInterruptEx. Для доступа к ресурсам, совместно используемым с помощью функции MiniportInterrupt или MiniportDisableInterruptEx , драйвер мини-порта должен вызвать NdisMSynchronizeWithInterruptEx , чтобы иметь свой Функция MiniportSynchronizeInterrupt обращается к этим ресурсам в DIRQL.

Если драйверу больше не требуется защита ресурсов, например когда сетевой адаптер удаляется и драйвер освобождает ресурсы, выделенные для этой сетевой карты, драйвер вызывает NdisFreeSpinLock.

Освобождение спиновой блокировки и освобождение спин-блокировки могут быть запутанными. NdisFreeSpinLock очищает память в SpinLock , чтобы она больше не представляла спиновую блокировку. Освобождение полученной спиновой блокировки с помощью NdisReleaseSpinLock просто позволяет другому потоку выполнения получить ее.

Дополнительные сведения о получении и освобождении спиновых блокировок NDIS см. в статье Синхронизация и уведомление в сетевых драйверах.

Вызывающие функции NdisAllocateSpinLock могут выполняться в любом irQL. Обычно вызывающий объект выполняется в irQL = PASSIVE_LEVEL во время инициализации.

Требования

Требование Значение
Минимальная версия клиента Поддерживается для драйверов NDIS 6.0 и NDIS 5.1 (см. раздел NdisAllocateSpinLock (NDIS 5.1)) в Windows Vista. Поддерживается для драйверов NDIS 5.1 (см. раздел NdisAllocateSpinLock (NDIS 5.1)) в Windows XP.
Целевая платформа Универсальное
Верхняя часть ndis.h (включая Ndis.h)
Библиотека Ndis.lib
IRQL Любой уровень (см. раздел "Примечания")
Правила соответствия DDI SpinLockDpr(ndis), SpinLockDprRelease(ndis), SpinlockRelease(ndis)

См. также раздел

DriverEntry of NDIS Protocol Drivers

MiniportDisableInterruptEx

MiniportHaltEx

MiniportInitializeEx

MiniportInterrupt

NdisAcquireSpinLock

NdisDprAcquireSpinLock

NdisDprReleaseSpinLock

NdisFreeSpinLock

NdisInterlockedAddUlong

NdisInterlockedInsertHeadList NdisInterlockedInsertTailList NdisInterlockedRemoveHeadList NdisMSynchronizeWithInterruptEx

NdisReleaseSpinLock

NetTimerCallback