91 lines
2.2 KiB
C
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;
|
|
}
|
|
|