windows-nt/Source/XPSP1/NT/net/rras/ipx/ipxwan/timer.c
2020-09-26 16:20:57 +08:00

196 lines
3.2 KiB
C

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
timer.c
Abstract:
Work Items Timer
Author:
Stefan Solomon 07/20/1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#define TimerHandle hWaitableObject[TIMER_HANDLE]
LIST_ENTRY TimerQueue;
/*++
Function: StartWiTimer
Descr: Inserts a work item in the timer queue for the specified time
Remark: has to take and release the queues lock
--*/
VOID
StartWiTimer(PWORK_ITEM reqwip,
ULONG timeout) // milliseconds
{
PLIST_ENTRY lep;
PWORK_ITEM timqwip;
ULONG delay;
LONGLONG to;
BOOL rc;
reqwip->DueTime = GetTickCount() + timeout;
ACQUIRE_QUEUES_LOCK;
lep = TimerQueue.Blink;
while(lep != &TimerQueue)
{
timqwip = CONTAINING_RECORD(lep, WORK_ITEM, Linkage);
if(IsLater(reqwip->DueTime, timqwip->DueTime)) {
break;
}
lep = lep->Blink;
}
InsertHeadList(lep, &reqwip->Linkage);
reqwip->WiState = WI_WAITING_TIMEOUT;
if(lep == &TimerQueue) {
delay = reqwip->DueTime - GetTickCount();
if(delay > MAXULONG/2) {
// already happened
to = 0;
}
else
{
to = ((LONGLONG)delay) * (-10000);
}
rc = SetWaitableTimer(TimerHandle,
(PLARGE_INTEGER)&to,
0, // signal once
NULL, // no completion routine
NULL,
FALSE);
if(!rc) {
Trace(TIMER_TRACE, "Cannot start waitable timer %d\n", GetLastError());
}
}
RELEASE_QUEUES_LOCK;
}
/*++
Function: ProcessTimerQueue
Descr: called when the timer queue due time has come.
Dequeues all wi with expired timeout and queues them in the
workers work items queue
Remark: has to take and release the queues lock
--*/
VOID
ProcessTimerQueue(VOID)
{
ULONG currTime = GetTickCount();
ULONG dueTime = currTime + MAXULONG/2;
PWORK_ITEM wip;
FILETIME filetime;
LONGLONG to;
DWORD rc;
ACQUIRE_QUEUES_LOCK;
while(!IsListEmpty(&TimerQueue))
{
// check the first in the list
wip = CONTAINING_RECORD(TimerQueue.Flink, WORK_ITEM, Linkage);
if(IsLater(currTime, wip->DueTime)) {
RemoveEntryList(&wip->Linkage);
wip->WiState = WI_TIMEOUT_COMPLETED;
EnqueueWorkItemToWorker(wip);
}
else
{
dueTime = wip->DueTime;
break;
}
}
to = ((LONGLONG)(dueTime - currTime)) * (-10000);
rc = SetWaitableTimer(
TimerHandle,
(PLARGE_INTEGER)&to,
0, // signal once
NULL, // no completion routine
NULL,
FALSE);
if(!rc) {
Trace(TIMER_TRACE, "Cannot start waitable timer %d\n", GetLastError());
}
RELEASE_QUEUES_LOCK;
}
/*++
Function: StopWiTimer
Descr: remove from the timer queue all the work items referencing this adapter
and insert them in the workers queue
Remark: takes the queues lock
--*/
VOID
StopWiTimer(PACB acbp)
{
PWORK_ITEM wip;
PLIST_ENTRY lep;
ACQUIRE_QUEUES_LOCK;
lep = TimerQueue.Flink;
while(lep != &TimerQueue) {
wip = CONTAINING_RECORD(lep, WORK_ITEM, Linkage);
lep = lep->Flink;
if(wip->acbp == acbp) {
RemoveEntryList(&wip->Linkage);
wip->WiState = WI_TIMEOUT_COMPLETED;
EnqueueWorkItemToWorker(wip);
}
}
RELEASE_QUEUES_LOCK;
}