- Process the timer event directly from the DPC instead of queuing a work item then raising to DISPATCH_LEVEL later when acquiring a spin lock
- Optimize the spin lock operations in NBTimeout and IPDatagramReassemblyTimeout for being called at DISPATCH_LEVEL

svn path=/trunk/; revision=48833
This commit is contained in:
Cameron Gutman 2010-09-20 19:08:40 +00:00
parent a5a6cf644d
commit 12d05b7eb8
5 changed files with 23 additions and 36 deletions

View file

@ -205,7 +205,6 @@ extern LIST_ENTRY InterfaceListHead;
extern KSPIN_LOCK InterfaceListLock; extern KSPIN_LOCK InterfaceListLock;
extern LIST_ENTRY NetTableListHead; extern LIST_ENTRY NetTableListHead;
extern KSPIN_LOCK NetTableListLock; extern KSPIN_LOCK NetTableListLock;
extern BOOLEAN IpWorkItemQueued;
PIP_PACKET IPCreatePacket( PIP_PACKET IPCreatePacket(
ULONG Type); ULONG Type);
@ -232,7 +231,10 @@ BOOLEAN IPRegisterInterface(
VOID IPUnregisterInterface( VOID IPUnregisterInterface(
PIP_INTERFACE IF); PIP_INTERFACE IF);
VOID NTAPI IPTimeout( PVOID Context ); VOID NTAPI IPTimeoutDpcFn(PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2);
VOID IPDispatchProtocol( VOID IPDispatchProtocol(
PIP_INTERFACE Interface, PIP_INTERFACE Interface,

View file

@ -24,8 +24,6 @@ UDP_STATISTICS UDPStats;
/* Network timers */ /* Network timers */
KTIMER IPTimer; KTIMER IPTimer;
KDPC IPTimeoutDpc; KDPC IPTimeoutDpc;
KSPIN_LOCK IpWorkLock;
WORK_QUEUE_ITEM IpWorkItem;
VOID TiWriteErrorLog( VOID TiWriteErrorLog(
PDRIVER_OBJECT DriverContext, PDRIVER_OBJECT DriverContext,
@ -578,28 +576,6 @@ VOID NTAPI TiUnload(
TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
} }
VOID NTAPI IPTimeoutDpcFn(
PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
/*
* FUNCTION: Timeout DPC
* ARGUMENTS:
* Dpc = Pointer to our DPC object
* DeferredContext = Pointer to context information (unused)
* SystemArgument1 = Unused
* SystemArgument2 = Unused
* NOTES:
* This routine is dispatched once in a while to do maintainance jobs
*/
{
if( !IpWorkItemQueued ) {
ExQueueWorkItem( &IpWorkItem, DelayedWorkQueue );
IpWorkItemQueued = TRUE;
}
}
NTSTATUS NTAPI NTSTATUS NTAPI
DriverEntry( DriverEntry(
PDRIVER_OBJECT DriverObject, PDRIVER_OBJECT DriverObject,
@ -630,7 +606,6 @@ DriverEntry(
/* Initialize our periodic timer and its associated DPC object. When the /* Initialize our periodic timer and its associated DPC object. When the
timer expires, the IPTimeout deferred procedure call (DPC) is queued */ timer expires, the IPTimeout deferred procedure call (DPC) is queued */
ExInitializeWorkItem( &IpWorkItem, IPTimeout, NULL );
KeInitializeDpc(&IPTimeoutDpc, IPTimeoutDpcFn, NULL); KeInitializeDpc(&IPTimeoutDpc, IPTimeoutDpcFn, NULL);
KeInitializeTimer(&IPTimer); KeInitializeTimer(&IPTimer);

View file

@ -63,9 +63,21 @@ PIP_PACKET IPInitializePacket(
} }
void NTAPI IPTimeout( PVOID Context ) { VOID NTAPI IPTimeoutDpcFn(PKDPC Dpc,
IpWorkItemQueued = FALSE; PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
/*
* FUNCTION: Timeout DPC
* ARGUMENTS:
* Dpc = Pointer to our DPC object
* DeferredContext = Pointer to context information (unused)
* SystemArgument1 = Unused
* SystemArgument2 = Unused
* NOTES:
* This routine is dispatched once in a while to do maintainance jobs
*/
{
/* Check if datagram fragments have taken too long to assemble */ /* Check if datagram fragments have taken too long to assemble */
IPDatagramReassemblyTimeout(); IPDatagramReassemblyTimeout();

View file

@ -97,12 +97,11 @@ VOID NBTimeout(VOID)
*/ */
{ {
UINT i; UINT i;
KIRQL OldIrql;
PNEIGHBOR_CACHE_ENTRY *PrevNCE; PNEIGHBOR_CACHE_ENTRY *PrevNCE;
PNEIGHBOR_CACHE_ENTRY NCE; PNEIGHBOR_CACHE_ENTRY NCE;
for (i = 0; i <= NB_HASHMASK; i++) { for (i = 0; i <= NB_HASHMASK; i++) {
TcpipAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql); TcpipAcquireSpinLockAtDpcLevel(&NeighborCache[i].Lock);
for (PrevNCE = &NeighborCache[i].Cache; for (PrevNCE = &NeighborCache[i].Cache;
(NCE = *PrevNCE) != NULL;) { (NCE = *PrevNCE) != NULL;) {
@ -136,7 +135,7 @@ VOID NBTimeout(VOID)
PrevNCE = &NCE->Next; PrevNCE = &NCE->Next;
} }
TcpipReleaseSpinLock(&NeighborCache[i].Lock, OldIrql); TcpipReleaseSpinLockFromDpcLevel(&NeighborCache[i].Lock);
} }
} }

View file

@ -510,11 +510,10 @@ VOID IPDatagramReassemblyTimeout(
* to hold IP fragments that have taken too long to reassemble * to hold IP fragments that have taken too long to reassemble
*/ */
{ {
KIRQL OldIrql;
PLIST_ENTRY CurrentEntry, NextEntry; PLIST_ENTRY CurrentEntry, NextEntry;
PIPDATAGRAM_REASSEMBLY CurrentIPDR; PIPDATAGRAM_REASSEMBLY CurrentIPDR;
TcpipAcquireSpinLock(&ReassemblyListLock, &OldIrql); TcpipAcquireSpinLockAtDpcLevel(&ReassemblyListLock);
CurrentEntry = ReassemblyListHead.Flink; CurrentEntry = ReassemblyListHead.Flink;
while (CurrentEntry != &ReassemblyListHead) while (CurrentEntry != &ReassemblyListHead)
@ -539,7 +538,7 @@ VOID IPDatagramReassemblyTimeout(
CurrentEntry = NextEntry; CurrentEntry = NextEntry;
} }
TcpipReleaseSpinLock(&ReassemblyListLock, OldIrql); TcpipReleaseSpinLockFromDpcLevel(&ReassemblyListLock);
} }
VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket) VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)