📄 wcetimer.c
字号:
TQ_ADDREF(pTimerQueue);
LeaveCriticalSection(&g_csTimerQueueList);
return pTimerQueue;
} // FindAndLockTimerQueue()
///////////////////////////////////////////////////////////////////////////////
// FindTimerQueueTimer()
//
// Routine Description:
//
// Find the pTQT in the given pTQ's TimerQueueTimerList.
//
//
// Return Value:
//
// NULL if it's not found, PTIMER_QUEUE_TIMER if found.
//
//
// Note:
//
// Caller should hold TIMER_QUEUE lock.
//
PTIMER_QUEUE_TIMER
FindTimerQueueTimer(PTIMER_QUEUE pTQ, PTIMER_QUEUE_TIMER pTargetTQT)
{
PTIMER_QUEUE_TIMER pTQT = (PTIMER_QUEUE_TIMER)(pTQ->TimerQueueTimerList.Flink);
while((PLIST_ENTRY)pTQT != &(pTQ->TimerQueueTimerList))
{
if (pTQT == pTargetTQT)
break;
pTQT = (PTIMER_QUEUE_TIMER)pTQT->ListEntry.Flink;
}
if ((PLIST_ENTRY)pTQT == &pTQ->ListEntry)
return NULL;
return pTQT;
} // FindAndLockTimerQueue()
///////////////////////////////////////////////////////////////////////////////
// CE_CreateTimerQueueTimer()
//
// Routine Description:
//
// Implement the CreateTimerQueueTimer() Win32 API.
//
// Return Value:
//
// TRUE if successful, FALSE otherwise..
//
BOOL
CE_CreateTimerQueueTimer(
PHANDLE phNewTimer, // handle to timer
HANDLE TimerQueue, // handle to timer queue
WAITORTIMERCALLBACK Callback, // timer callback function
PVOID Parameter, // callback parameter
DWORD DueTime, // timer due time
DWORD Period, // timer period
ULONG Flags) // options *Ignored*
{
PTIMER_QUEUE_TIMER pTimerQueueTimer;
PTIMER_QUEUE pTimerQueue;
DEBUGMSG (ZONE_TIMER,
(TEXT("ZCF:: CE_CreateTimerQueueTimer(). Due[%d]s Period[%d]s\r\n"),
DueTime/1000,
Period/1000));
pTimerQueueTimer = (PTIMER_QUEUE_TIMER) MALLOC(sizeof(TIMER_QUEUE_TIMER));
if (pTimerQueueTimer == NULL)
{
DEBUGMSG(
ZONE_ERROR,
(TEXT("ZCF:: Failed CE_CreateTimerQueueTimer() OOM.\r\n")));
return FALSE;
}
memset(pTimerQueueTimer, 0x00, sizeof(TIMER_QUEUE_TIMER));
#ifdef DEBUG
pTimerQueueTimer->dwSig = CE_TIMERTIMER_SIG;
#endif
pTimerQueueTimer->Callback = Callback;
pTimerQueueTimer->Parameter = Parameter;
pTimerQueueTimer->DueTime = 0x00; // <-- due time is good for one go only..
pTimerQueueTimer->Period = Period;
InitializeCriticalSection(&pTimerQueueTimer->csTimerQueueTimer);
TQT_ADDREF(pTimerQueueTimer); // For deletion.
TQT_ADDREF(pTimerQueueTimer); // For completion.
CTEInitBlockStruc(&pTimerQueueTimer->TimerBlockStruc);
//
// The TimerQueue better be in our list..
//
if (TimerQueue == NULL)
{
//
// Use default timer queue, create one if there isn't one.
//
if (g_hDefaultTimerQueue == NULL)
{
g_hDefaultTimerQueue = CreateTimerQueue();
if (g_hDefaultTimerQueue == INVALID_HANDLE_VALUE)
goto ErrorReturn;
}
TimerQueue = (HANDLE)g_hDefaultTimerQueue;
}
//
// For each TimerQueueTimer, we'll take a ref in TimerQueue.
// We deref it in CE_DeleteTimerQueueTimer()
//
pTimerQueue = FindAndRefTimerQueue((PTIMER_QUEUE)TimerQueue);
if (pTimerQueue == NULL)
goto ErrorReturn;
EnterCriticalSection(&pTimerQueue->csTimerQueue);
ASSERT(pTimerQueue->dwSig == CE_TIMER_SIG);
//
// Queue TimerQueueTimer..
//
InsertTailList(&pTimerQueue->TimerQueueTimerList, (PLIST_ENTRY)pTimerQueueTimer);
LeaveCriticalSection(&pTimerQueue->csTimerQueue);
//
// Start it..
//
*phNewTimer = (PHANDLE)pTimerQueueTimer;
DEBUGMSG (ZONE_TIMER,
(TEXT("ZCF:: CE_CreateTimerQueueTimer() TQT[0x%x] created. Due[%d]s Period[%d]s. TotalTQT[%d]"),
pTimerQueueTimer,
DueTime/1000,
Period/1000,
InterlockedIncrement(&g_dwTotalTQT)));
pTimerQueueTimer->bTimerRunning = TRUE;
CTEStartTimer(
&(pTimerQueueTimer->hTimer),
DueTime,
(CTEEventRtn)PerformCallback,
pTimerQueueTimer);
return TRUE;
ErrorReturn:
DEBUGMSG(ZONE_ERROR,
(TEXT("ZCF:: Failed CE_CreateTimerQueueTimer().\r\n")));
CTEDeinitBlockStruc(&pTimerQueueTimer->TimerBlockStruc);
FREE(pTimerQueueTimer);
return FALSE;
} // CE_CreateTimerQueueTimer()
///////////////////////////////////////////////////////////////////////////////
// CE_DeleteTimerQueueTimer()
//
// Routine Description:
//
// Implement the CreateTimerQueueTimer() Win32 API.
//
// Return Value:
//
// TRUE if successful, FALSE otherwise..
//
BOOL CE_DeleteTimerQueueTimer(
HANDLE TimerQueue, // handle to timer queue
HANDLE Timer, // handle to timer
HANDLE CompletionEvent) // handle to completion event
{
PTIMER_QUEUE pTimerQueue;
PTIMER_QUEUE_TIMER pTimerQueueTimer;
DEBUGMSG (ZONE_TIMER,
(TEXT("ZCF:: CE_DeleteTimerQueueTimer() TQT[0x%x] TQ[0x%x]\r\n"),
Timer,
TimerQueue));
if (TimerQueue == NULL)
{
if (g_hDefaultTimerQueue == NULL)
{
DEBUGMSG (ZONE_TIMER,
(TEXT("ZCF:: CE_ChangeTimerQueueTimer() Default Timer not started.\r\n")));
return FALSE;
}
TimerQueue = g_hDefaultTimerQueue;
}
//
// FindAndRefTimerQueue() will ref TimerQueue in this function.
//
pTimerQueue = FindAndRefTimerQueue(TimerQueue);
if (pTimerQueue == NULL)
{
//
// This should not happen in ZCF code..
//
ASSERT(0);
return FALSE;
}
EnterCriticalSection(&pTimerQueue->csTimerQueue);
pTimerQueueTimer = FindTimerQueueTimer(
pTimerQueue,
(PTIMER_QUEUE_TIMER)Timer);
if (pTimerQueueTimer == NULL)
{
DEBUGMSG (ZONE_TIMER,
(TEXT("ZCF:: CE_DeleteTimerQueueTimer() invalid TQT[0x%x]\r\n"),
Timer));
//
// This should not happen in IPv6 code..
//
ASSERT(0);
LeaveCriticalSection(&pTimerQueue->csTimerQueue);
TQ_DELREF(pTimerQueue); // Taken in FindAndRefTimerQueue()
return FALSE;
}
//
// Remove it from TimerQueueTimerList list.
//
RemoveEntryList((PLIST_ENTRY)pTimerQueueTimer);
LeaveCriticalSection(&pTimerQueue->csTimerQueue);
TQ_DELREF(pTimerQueue); // Taken in FindAndRefTimerQueue()
TQ_DELREF(pTimerQueue); // Taken in CE_CreateTimerQueueTimer()
//
// By now pTimerQueueTimer is a stand alone cell..
//
EnterCriticalSection(&pTimerQueueTimer->csTimerQueueTimer);
pTimerQueueTimer->hFinishEvent = CompletionEvent;
pTimerQueueTimer->DueTime = 0x00;
pTimerQueueTimer->Period = 0x00;
if (pTimerQueueTimer->bTimerRunning == TRUE)
{
//
// For the timer still running case, completion event will be
// set by the callback function. If caller asks to be blocked
// do it.
//
pTimerQueueTimer->bTimerRunning = FALSE;
if (!CTEStopTimer(&(pTimerQueueTimer->hTimer)))
{
DEBUGMSG(ZONE_TIMER,
(TEXT("ZCF:: CE_DeleteTimerQueueTimer(). TQT[0x%x] pending.\r\n"),
pTimerQueueTimer));
//
// Potentially we may get here from the callback itself.
// So, don't block if that's the case.
//
if (CompletionEvent == INVALID_HANDLE_VALUE &&
pTimerQueueTimer->bTimerInCallBack == FALSE)
{
LeaveCriticalSection(&pTimerQueueTimer->csTimerQueueTimer);
CTEBlock(&pTimerQueueTimer->TimerBlockStruc);
ResetEvent(&pTimerQueueTimer->TimerBlockStruc.cbs_event);
EnterCriticalSection(&pTimerQueueTimer->csTimerQueueTimer);
}
//
// Do not need to deref TQT because the PerformCallBack() must have done
// or will be doing that.
//
}
else
{
DEBUGMSG(ZONE_TIMER,
(TEXT("ZCF:: CE_DeleteTimerQueueTimer(). Timer successfully stopped.\r\n")));
TQT_DELREF(pTimerQueueTimer); // Taken in CE_CreateTimerQueueTimer() for completion.
}
}
else
{
DEBUGMSG(ZONE_TIMER,
(TEXT("ZCF:: CE_DeleteTimerQueueTimer(). Timer was not running.\r\n")));
//
// Ditto here..
// Do not need to deref TQT because the PerformCallBack() must have
// done that.
//
}
LeaveCriticalSection(&pTimerQueueTimer->csTimerQueueTimer);
TQT_DELREF(pTimerQueueTimer); // Taken in CE_CreateTimerQueueTimer() for deletion.
return TRUE;
} // CE_DeleteTimerQueueTimer()
///////////////////////////////////////////////////////////////////////////////
// CE_ChangeTimerQueueTimer()
//
// Routine Description:
//
// Implement the ChangeTimerQueueTimer() Win32 API.
//
// Return Value:
//
// TRUE if successful, FALSE otherwise..
//
BOOL
CE_ChangeTimerQueueTimer(
HANDLE TimerQueue, // handle to timer queue
HANDLE Timer, // handle to timer
ULONG DueTime, // timer due time
ULONG Period) // timer period
{
PTIMER_QUEUE_TIMER pTimerQueueTimer;
PTIMER_QUEUE pTimerQueue;
BOOL bRestartTimer = TRUE;
DEBUGMSG (ZONE_TIMER,
(TEXT("ZCF:: CE_ChangeTimerQueueTimer() TQT[0x%x] TQ[0x%x] Due[%d]s Period[%d]s\r\n"),
Timer,
TimerQueue,
DueTime/1000,
Period/1000));
//
// This will hold REF for TIMER_QUEUE during in this function.
//
if (TimerQueue == NULL)
{
if (g_hDefaultTimerQueue == NULL)
{
DEBUGMSG (ZONE_TIMER,
(TEXT("ZCF:: CE_ChangeTimerQueueTimer() Default Timer not started.\r\n")));
return FALSE;
}
TimerQueue = g_hDefaultTimerQueue;
}
//
// TimerQueue is REFed once here.
//
pTimerQueue = FindAndRefTimerQueue(TimerQueue);
if (pTimerQueue == NULL)
{
//
// This should not happen in ZCF code.
//
ASSERT(0);
return FALSE;
}
EnterCriticalSection(&pTimerQueue->csTimerQueue);
pTimerQueueTimer = FindTimerQueueTimer(
pTimerQueue,
(PTIMER_QUEUE_TIMER)Timer);
if (pTimerQueueTimer == NULL)
{
DEBUGMSG (ZONE_TIMER,
(TEXT("ZCF:: CE_ChangeTimerQueueTimer() invalid TQT[0x%x]\r\n"),
Timer));
//
// Should not happen in ZCF code.
//
ASSERT(0);
LeaveCriticalSection(&pTimerQueue->csTimerQueue);
TQ_DELREF(pTimerQueue); // Taken in FindAndRefTimerQueue()
return FALSE;
}
//
// REF hold during this function only..
//
TQT_ADDREF(pTimerQueueTimer);
LeaveCriticalSection(&pTimerQueue->csTimerQueue);
EnterCriticalSection(&pTimerQueueTimer->csTimerQueueTimer);
//
// Attempt to stop the timer if it is currently ticking..
//
if (pTimerQueueTimer->bTimerRunning == TRUE)
{
if (!CTEStopTimer(&(pTimerQueueTimer->hTimer)))
{
if (pTimerQueueTimer->bTimerInCallBack)
{
bRestartTimer = FALSE;
}
else
{
//
// Timer must have fired..
// And the call back is waiting to get in while we are holding
// the CS.
// Tell it to go away..
//
pTimerQueueTimer->bTimerRunning = FALSE;
LeaveCriticalSection(&pTimerQueueTimer->csTimerQueueTimer);
//
// Wait for it to tell us that it has gone away..
//
CTEBlock(&pTimerQueueTimer->TimerBlockStruc);
ResetEvent(&pTimerQueueTimer->TimerBlockStruc.cbs_event);
//
// Cool, all done we are clear to go..
//
EnterCriticalSection(&pTimerQueueTimer->csTimerQueueTimer);
}
}
else
{
TQT_DELREF(pTimerQueueTimer); // Taken in CE_CreateTimerQueueTimer() for completion.
// Since we now cancel it.
}
}
//
// By now the timer has successfully been stopped.
// Per MSDN,
// If you call ChangeTimerQueueTimer on a one-shot timer (its period is
// zero) that has already expired, the timer is not updated.
//
if (pTimerQueueTimer->Period)
{
pTimerQueueTimer->DueTime = DueTime;
pTimerQueueTimer->Period = Period;
if (bRestartTimer)
{
pTimerQueueTimer->bTimerRunning = TRUE;
TQT_ADDREF(pTimerQueueTimer);
CTEStartTimer(
&(pTimerQueueTimer->hTimer),
pTimerQueueTimer->DueTime,
(CTEEventRtn)PerformCallback,
pTimerQueueTimer);
pTimerQueueTimer->DueTime = 0x00;
}
}
LeaveCriticalSection(&pTimerQueueTimer->csTimerQueueTimer);
TQT_DELREF(pTimerQueueTimer); // REF hold in this function.
TQ_DELREF(pTimerQueue); // REF hold in this function.
return TRUE;
} // CE_ChangeTimerQueueTimer()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -