|
|
/*++
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; }
|