163 lines
3.6 KiB
C
163 lines
3.6 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
backpack.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the package for pseudo polling. When a caller
|
|||
|
requests the same operation and gets the same error return the rdr
|
|||
|
must prevent flooding the network by backing off requests. Examples
|
|||
|
of when this is desirable are receiving 0 bytes on consequtive reads
|
|||
|
and consequtive fails on a file lock.
|
|||
|
|
|||
|
If the caller is flooding the network, the rdr will return the 0 bytes
|
|||
|
for a pipe read or lock fail to the user until NextTime is reached.
|
|||
|
When NextTime is reached BackOff will indicate that the network should
|
|||
|
be used.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Colin Watson (colinw) 02-Jan-1991
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
Typical usage would be demonstrated by rdr\npipe.c on the peek request.
|
|||
|
|
|||
|
1) Each time peek is called it calls backoff.
|
|||
|
When backoff returns true, RdrNpPeek returns to the caller a response
|
|||
|
indicating there is no data at the other end of the pipe.
|
|||
|
|
|||
|
When backoff returns false a request is made to the network.
|
|||
|
|
|||
|
2) If the reply from the server to the peek in step 1 indicates that
|
|||
|
there is no data in the pipe then RdrNpPeek calls RdrBackPackFailure.
|
|||
|
|
|||
|
3) Whenever there is data in the pipe or when this workstation may
|
|||
|
unblock the pipe (eg. the workstation writing to the pipe)
|
|||
|
RdrBackPackSuccess is called.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
24-Dec-1990 ColinW
|
|||
|
|
|||
|
Created
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
//
|
|||
|
// BackPackSpinLock is used to protect all Time entries in
|
|||
|
// the BACK_PACK structures from being accessed simultaneously.
|
|||
|
//
|
|||
|
|
|||
|
KSPIN_LOCK BackPackSpinLock = {0};
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE3FILE, RdrBackOff)
|
|||
|
#pragma alloc_text(PAGE3FILE, RdrBackPackFailure)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
RdrBackOff (
|
|||
|
IN PBACK_PACK pBP
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called each time a request is made to find out if a the
|
|||
|
request should be sent to the network or a standard reply should be
|
|||
|
returned to the caller.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pBP - supplies back pack data for this request.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE when caller should not access the network.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LARGE_INTEGER CurrentTime;
|
|||
|
KIRQL OldIrql;
|
|||
|
|
|||
|
DISCARDABLE_CODE(RdrFileDiscardableSection);
|
|||
|
|
|||
|
// If the previous request worked then we should access the network.
|
|||
|
|
|||
|
if ( pBP->CurrentIncrement == 0 ) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// If the delay has expired then access the network.
|
|||
|
|
|||
|
KeQuerySystemTime(&CurrentTime);
|
|||
|
|
|||
|
ACQUIRE_SPIN_LOCK(&BackPackSpinLock, &OldIrql);
|
|||
|
|
|||
|
if (CurrentTime.QuadPart < pBP->NextTime.QuadPart) {
|
|||
|
RELEASE_SPIN_LOCK(&BackPackSpinLock, OldIrql);
|
|||
|
return TRUE; // Not time to access the network yet.
|
|||
|
} else {
|
|||
|
RELEASE_SPIN_LOCK(&BackPackSpinLock, OldIrql);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
RdrBackPackFailure (
|
|||
|
IN PBACK_PACK pBP
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called each time a request fails.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pBP - supplies back pack data for this request.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LARGE_INTEGER CurrentTime;
|
|||
|
KIRQL OldIrql;
|
|||
|
|
|||
|
DISCARDABLE_CODE(RdrFileDiscardableSection);
|
|||
|
|
|||
|
KeQuerySystemTime(&CurrentTime);
|
|||
|
|
|||
|
ACQUIRE_SPIN_LOCK(&BackPackSpinLock, &OldIrql);
|
|||
|
|
|||
|
if (pBP->CurrentIncrement < pBP->MaximumDelay ) {
|
|||
|
|
|||
|
//
|
|||
|
// We have reached NextTime but not our maximum delay limit.
|
|||
|
//
|
|||
|
|
|||
|
pBP->CurrentIncrement++;
|
|||
|
}
|
|||
|
|
|||
|
// NextTime = CurrentTime + (Interval * CurrentIncrement )
|
|||
|
|
|||
|
pBP->NextTime.QuadPart = CurrentTime.QuadPart + (pBP->Increment.QuadPart * pBP->CurrentIncrement);
|
|||
|
|
|||
|
RELEASE_SPIN_LOCK(&BackPackSpinLock, OldIrql);
|
|||
|
|
|||
|
}
|
|||
|
|