⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timer.cpp

📁 pppoe client
💻 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 + -