windows-nt/Source/XPSP1/NT/net/tcpip/driver/common/9x/locks.c
2020-09-26 16:20:57 +08:00

91 lines
2.2 KiB
C

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
locks.c
Abstract:
Millennium locks. See below for details of the WHY you might
do this.
Author:
Scott Holden (sholden) 2/10/2000
Revision History:
--*/
#include "tcpipbase.h"
//
// The TCP/IP stacks makes a number of assumptions about the receive indication
// path being at DPC. Since Millennium indicates receives up on a global event
// at PASSIVE level, we need to take extra precautions in this path to return
// the thread to the correct IRQL upon releasing a spin lock.
//
// Since TCP/IP will grab locks and release in a different order and in some
// situations CTEGetLockAtDPC will not save the previous IRQL, there were many
// issues with leaving threads at the wrong IRQL when enabling spin locks.
//
// This implementation solves this issue -- since we are on a uniproc machine.
// When we enter the first lock, we can raise IRQL to DISPATCH to ensure
// that we are not pre-empted. Each additional lock will increment the count.
// When the last lock is released, the old IRQL is restored.
//
//
LONG gTcpipLock = 0;
KIRQL gTcpipOldIrql;
VOID
TcpipMillenGetLock(
CTELock *pLock
)
{
#if DBG
KIRQL OldIrql;
#endif // DBG
ASSERT(gTcpipLock >= 0);
// First spinlock acquire raises DPC.
if (gTcpipLock++ == 0) {
KeRaiseIrql(DISPATCH_LEVEL, &gTcpipOldIrql);
}
// Verify that our individual locks are somehow not reentrant.
// KeAcquireSpinLock will do that for us on Millennium.
ASSERT((KeAcquireSpinLock(pLock, &OldIrql),OldIrql==DISPATCH_LEVEL) && ((*pLock)&1));
ASSERT(gTcpipLock >= 1);
return;
}
VOID
TcpipMillenFreeLock(
CTELock *pLock
)
{
ASSERT(gTcpipLock >= 1);
// Verify that our individual locks are somehow not reentrant.
// KeReleaseSpinLock on Millennium does that and more for us.
ASSERT(KeGetCurrentIrql()==DISPATCH_LEVEL &&
(KeReleaseSpinLock(pLock, DISPATCH_LEVEL),TRUE));
// Last release lowers IRQL to original.
if (--gTcpipLock == 0) {
KeLowerIrql(gTcpipOldIrql);
}
ASSERT(gTcpipLock >= 0);
return;
}