146 lines
3.5 KiB
C
146 lines
3.5 KiB
C
/*++
|
||
|
||
Copyright (c) 1995 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
timer.c
|
||
|
||
Abstract:
|
||
|
||
Timer thread to monitor connection progress in the
|
||
automatic connection driver (acd.sys).
|
||
|
||
Author:
|
||
|
||
Anthony Discolo (adiscolo) 25-Apr-1995
|
||
|
||
Environment:
|
||
|
||
Kernel Mode
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include <ndis.h>
|
||
#include <cxport.h>
|
||
#include <tdi.h>
|
||
#include <tdikrnl.h>
|
||
#include <tdistat.h>
|
||
#include <tdiinfo.h>
|
||
#include <acd.h>
|
||
|
||
#include "acdapi.h"
|
||
#include "table.h"
|
||
#include "acddefs.h"
|
||
#include "debug.h"
|
||
|
||
//
|
||
// Imported routines.
|
||
//
|
||
VOID
|
||
AcdSignalCompletionCommon(
|
||
IN PACD_CONNECTION pConnection,
|
||
IN BOOLEAN fSuccess
|
||
);
|
||
|
||
//
|
||
// Keep track how long the user-space
|
||
// process has been attempting a connection.
|
||
//
|
||
#define ACD_MAX_TIMER_CALLS 3*60 // 3 minutes
|
||
|
||
//
|
||
// We give the user-space process
|
||
// some slack on missed pings.
|
||
//
|
||
#define ACD_MAX_MISSED_PINGS 40 // 20 seconds
|
||
|
||
|
||
|
||
VOID
|
||
AcdConnectionTimer(
|
||
IN PDEVICE_OBJECT pDeviceObject,
|
||
IN PVOID pContext
|
||
)
|
||
{
|
||
PLIST_ENTRY pEntry;
|
||
PACD_CONNECTION pConnection;
|
||
BOOLEAN bCancel = FALSE;
|
||
|
||
//
|
||
// Acquire the spin lock.
|
||
// We're guaranteed to be at DPC
|
||
// since this is a timer routine.
|
||
//
|
||
KeAcquireSpinLockAtDpcLevel(&AcdSpinLockG);
|
||
//
|
||
// If the user-space process responsible
|
||
// for creating the connection hasn't
|
||
// pinged us in a while, or if it hasn't
|
||
// created a connection in 3 minutes,
|
||
// cancel all the pending requests.
|
||
//
|
||
for (pEntry = AcdConnectionQueueG.Flink;
|
||
pEntry != &AcdConnectionQueueG;
|
||
pEntry = pEntry->Flink)
|
||
{
|
||
pConnection = CONTAINING_RECORD(pEntry, ACD_CONNECTION, ListEntry);
|
||
|
||
IF_ACDDBG(ACD_DEBUG_TIMER) {
|
||
PACD_COMPLETION pCompletion;
|
||
|
||
AcdPrint((
|
||
"AcdConnectionTimer: pConnection=0x%x, fNotif=%d, szAddr=",
|
||
pConnection,
|
||
pConnection->fNotif));
|
||
pCompletion = CONTAINING_RECORD(pConnection->CompletionList.Flink, ACD_COMPLETION, ListEntry);
|
||
AcdPrintAddress(&pCompletion->notif.addr);
|
||
AcdPrint((", nTimerCalls=%d, nMissedPings=%d\n",
|
||
pConnection->ulTimerCalls,
|
||
pConnection->ulMissedPings));
|
||
}
|
||
//
|
||
// If we haven't reported the connection to
|
||
// user space yet, or it is in the process of
|
||
// being completed, then don't time it out.
|
||
//
|
||
if (!pConnection->fNotif || pConnection->fCompleting)
|
||
continue;
|
||
|
||
pConnection->ulTimerCalls++;
|
||
if (pConnection->fProgressPing)
|
||
pConnection->ulMissedPings = 0;
|
||
else
|
||
pConnection->ulMissedPings++;
|
||
if (pConnection->ulTimerCalls >= ACD_MAX_TIMER_CALLS ||
|
||
pConnection->ulMissedPings >= ACD_MAX_MISSED_PINGS)
|
||
{
|
||
IF_ACDDBG(ACD_DEBUG_TIMER) {
|
||
AcdPrint((
|
||
"AcdConnectionTimer: canceling pConnection=0x%x\n",
|
||
pConnection));
|
||
}
|
||
//
|
||
// Set the completion-in-progress flag so
|
||
// this request cannot be completed after
|
||
// we release the spin lock.
|
||
//
|
||
pConnection->fCompleting = TRUE;
|
||
bCancel = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
//
|
||
// Release the spin lock.
|
||
//
|
||
KeReleaseSpinLockFromDpcLevel(&AcdSpinLockG);
|
||
//
|
||
// We now process all the canceled requests.
|
||
//
|
||
if (bCancel)
|
||
AcdSignalCompletionCommon(pConnection, FALSE);
|
||
} // AcdConnectionTimer
|
||
|
||
|