📄 timer.cpp
字号:
//********************************************************************
// 日期: 2004/08/24 - 24:8:2004 19:15
// 名前: tiamo
// 描述: timer routine
//*********************************************************************
#include "Stdafx.h"
// timer
TIMER g_timer;
namespace
{
// intenal use
LARGE_INTEGER _s_ZeroTime = {0,0};
}
#pragma alloc_text(PAGE,InitializeTimerSystem)
#pragma alloc_text("TIMER",ShutdownTimerSystem)
#pragma alloc_text("TIMER",ShutdownTimerSystem)
#pragma alloc_text("TIMER",ScheduleTimerItem)
#pragma alloc_text("TIMER",CancelTimerItem)
#pragma alloc_text("TIMER",CommonTimerRoutine)
#pragma alloc_text("TIMER",SetTimer)
// init timer system,you should call it in your driver entry
VOID InitializeTimerSystem()
{
PAGED_CODE();
NdisInitializeListHead(&g_timer.m_ltTimerItemsHead);
g_timer.m_ulSig = TIMER_SIG;
NdisAllocateSpinLock(&g_timer.m_lockSelf);
NdisInitializeTimer(&g_timer.m_ndisTimer,CommonTimerRoutine,&g_timer);
}
// shut down timer system,you should call it in your driver unload
VOID ShutdownTimerSystem()
{
ASSERT(g_timer.m_ulSig == TIMER_SIG);
NdisFreeSpinLock(&g_timer.m_lockSelf);
}
// init timer item
VOID InitializeTimerItem(PTIMER_ITEM pItem)
{
ASSERT(pItem);
NdisInitializeListHead(&pItem->m_ltTimerItemAnchor);
}
// schedule time call
VOID ScheduleTimerItem(PTIMER_ITEM pItem,TIMER_ROUTINE pRoutine,ULONG ulMsDelay,PVOID pContext)
{
ASSERT(g_timer.m_ulSig == TIMER_SIG && pItem && pRoutine);
pItem->m_pContext = pContext;
pItem->m_pTimerRoutine = pRoutine;
LARGE_INTEGER curTime;
KeQuerySystemTime(&curTime);
pItem->m_ullExecuteTime.QuadPart = curTime.QuadPart + ulMsDelay * 10000;
NdisAcquireSpinLock(&g_timer.m_lockSelf);
if(!IsListEmpty(&g_timer.m_ltTimerItemsHead))
{
PLIST_ENTRY pEntry = g_timer.m_ltTimerItemsHead.Blink;
for(;;)
{
PTIMER_ITEM pCurItem = CONTAINING_RECORD(pEntry,TIMER_ITEM, m_ltTimerItemAnchor);
if(pCurItem->m_ullExecuteTime.QuadPart < pItem->m_ullExecuteTime.QuadPart || pEntry == &g_timer.m_ltTimerItemsHead)
{
InsertHeadList(pEntry,&pItem->m_ltTimerItemAnchor);
if(&pItem->m_ltTimerItemAnchor == g_timer.m_ltTimerItemsHead.Flink)
SetTimer(curTime);
break;
}
pEntry = pEntry->Blink;
}
}
else
{
InsertHeadList(&g_timer.m_ltTimerItemsHead,&pItem->m_ltTimerItemAnchor);
SetTimer(curTime);
}
NdisReleaseSpinLock(&g_timer.m_lockSelf);
}
// cancel timer call
VOID CancelTimerItem(PTIMER_ITEM pItem,PVOID pCancelContext)
{
ASSERT(pItem);
// not in the timer list
if(IsListEmpty(&pItem->m_ltTimerItemAnchor))
return;
NdisAcquireSpinLock(&g_timer.m_lockSelf);
// next item
PLIST_ENTRY pEntry = g_timer.m_ltTimerItemsHead.Flink;
BOOLEAN bCanceled = TRUE;
// if next item is that we want to cancel
BOOLEAN bNextItem = pEntry == &pItem->m_ltTimerItemAnchor;
if(pEntry != &g_timer.m_ltTimerItemsHead)
{
if(bNextItem)
{
// cancel
NdisCancelTimer(&g_timer.m_ndisTimer,&bCanceled);
}
if(bCanceled)
{
// remove from list
RemoveEntryList(pEntry);
// reinit it
NdisInitializeListHead(pEntry);
// request another timer call
if(bNextItem)
SetTimer(_s_ZeroTime);
}
}
NdisReleaseSpinLock(&g_timer.m_lockSelf);
// call the routine with the cancel context
if(!bNextItem || bCanceled)
{
pItem->m_pTimerRoutine(pItem,pItem->m_pContext,pCancelContext);
}
}
// ndis timer routine
VOID CommonTimerRoutine(PVOID pSystem1,PVOID pContext,PVOID pSystem3,PVOID pSystem4)
{
PTIMER pTimer = static_cast<PTIMER>(pContext);
ASSERT(pTimer && pTimer->m_ulSig == TIMER_SIG);
ASSERT(DISPATCH_LEVEL == KeGetCurrentIrql());
// acquire spinlock
NdisDprAcquireSpinLock(&pTimer->m_lockSelf);
// remove head
PLIST_ENTRY pEntry = RemoveHeadList(&pTimer->m_ltTimerItemsHead);
if(pEntry)
{
InitializeListHead(pEntry);
// set next timer
SetTimer(_s_ZeroTime);
}
// release lock
NdisDprReleaseSpinLock(&pTimer->m_lockSelf);
if(pEntry)
{
PTIMER_ITEM pTimerItem = CONTAINING_RECORD(pEntry,TIMER_ITEM,m_ltTimerItemAnchor);
// call the routine normal fire
pTimerItem->m_pTimerRoutine(pTimerItem,pTimerItem->m_pContext,NULL);
}
}
// set timer
VOID SetTimer(LARGE_INTEGER ullCurrentTime)
{
ASSERT(g_timer.m_ulSig == TIMER_SIG);
ASSERT(DISPATCH_LEVEL == KeGetCurrentIrql());
// check
if(IsListEmpty(&g_timer.m_ltTimerItemsHead))
return;
// get current time
if(ullCurrentTime.QuadPart == 0)
{
KeQuerySystemTime(&ullCurrentTime);
}
PTIMER_ITEM pTimerItem = CONTAINING_RECORD((g_timer.m_ltTimerItemsHead.Flink),TIMER_ITEM, m_ltTimerItemAnchor);
ullCurrentTime.QuadPart = (pTimerItem->m_ullExecuteTime.QuadPart - ullCurrentTime.QuadPart) / 10000;
if(ullCurrentTime.QuadPart < 0)
return;
NdisSetTimer(&g_timer.m_ndisTimer,ullCurrentTime.LowPart);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -