Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
3.2 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. timer.c
  5. Abstract:
  6. Work Items Timer
  7. Author:
  8. Stefan Solomon 07/20/1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #define TimerHandle hWaitableObject[TIMER_HANDLE]
  14. LIST_ENTRY TimerQueue;
  15. /*++
  16. Function: StartWiTimer
  17. Descr: Inserts a work item in the timer queue for the specified time
  18. Remark: has to take and release the queues lock
  19. --*/
  20. VOID
  21. StartWiTimer(PWORK_ITEM reqwip,
  22. ULONG timeout) // milliseconds
  23. {
  24. PLIST_ENTRY lep;
  25. PWORK_ITEM timqwip;
  26. ULONG delay;
  27. LONGLONG to;
  28. BOOL rc;
  29. reqwip->DueTime = GetTickCount() + timeout;
  30. ACQUIRE_QUEUES_LOCK;
  31. lep = TimerQueue.Blink;
  32. while(lep != &TimerQueue)
  33. {
  34. timqwip = CONTAINING_RECORD(lep, WORK_ITEM, Linkage);
  35. if(IsLater(reqwip->DueTime, timqwip->DueTime)) {
  36. break;
  37. }
  38. lep = lep->Blink;
  39. }
  40. InsertHeadList(lep, &reqwip->Linkage);
  41. reqwip->WiState = WI_WAITING_TIMEOUT;
  42. if(lep == &TimerQueue) {
  43. delay = reqwip->DueTime - GetTickCount();
  44. if(delay > MAXULONG/2) {
  45. // already happened
  46. to = 0;
  47. }
  48. else
  49. {
  50. to = ((LONGLONG)delay) * (-10000);
  51. }
  52. rc = SetWaitableTimer(TimerHandle,
  53. (PLARGE_INTEGER)&to,
  54. 0, // signal once
  55. NULL, // no completion routine
  56. NULL,
  57. FALSE);
  58. if(!rc) {
  59. Trace(TIMER_TRACE, "Cannot start waitable timer %d\n", GetLastError());
  60. }
  61. }
  62. RELEASE_QUEUES_LOCK;
  63. }
  64. /*++
  65. Function: ProcessTimerQueue
  66. Descr: called when the timer queue due time has come.
  67. Dequeues all wi with expired timeout and queues them in the
  68. workers work items queue
  69. Remark: has to take and release the queues lock
  70. --*/
  71. VOID
  72. ProcessTimerQueue(VOID)
  73. {
  74. ULONG currTime = GetTickCount();
  75. ULONG dueTime = currTime + MAXULONG/2;
  76. PWORK_ITEM wip;
  77. FILETIME filetime;
  78. LONGLONG to;
  79. DWORD rc;
  80. ACQUIRE_QUEUES_LOCK;
  81. while(!IsListEmpty(&TimerQueue))
  82. {
  83. // check the first in the list
  84. wip = CONTAINING_RECORD(TimerQueue.Flink, WORK_ITEM, Linkage);
  85. if(IsLater(currTime, wip->DueTime)) {
  86. RemoveEntryList(&wip->Linkage);
  87. wip->WiState = WI_TIMEOUT_COMPLETED;
  88. EnqueueWorkItemToWorker(wip);
  89. }
  90. else
  91. {
  92. dueTime = wip->DueTime;
  93. break;
  94. }
  95. }
  96. to = ((LONGLONG)(dueTime - currTime)) * (-10000);
  97. rc = SetWaitableTimer(
  98. TimerHandle,
  99. (PLARGE_INTEGER)&to,
  100. 0, // signal once
  101. NULL, // no completion routine
  102. NULL,
  103. FALSE);
  104. if(!rc) {
  105. Trace(TIMER_TRACE, "Cannot start waitable timer %d\n", GetLastError());
  106. }
  107. RELEASE_QUEUES_LOCK;
  108. }
  109. /*++
  110. Function: StopWiTimer
  111. Descr: remove from the timer queue all the work items referencing this adapter
  112. and insert them in the workers queue
  113. Remark: takes the queues lock
  114. --*/
  115. VOID
  116. StopWiTimer(PACB acbp)
  117. {
  118. PWORK_ITEM wip;
  119. PLIST_ENTRY lep;
  120. ACQUIRE_QUEUES_LOCK;
  121. lep = TimerQueue.Flink;
  122. while(lep != &TimerQueue) {
  123. wip = CONTAINING_RECORD(lep, WORK_ITEM, Linkage);
  124. lep = lep->Flink;
  125. if(wip->acbp == acbp) {
  126. RemoveEntryList(&wip->Linkage);
  127. wip->WiState = WI_TIMEOUT_COMPLETED;
  128. EnqueueWorkItemToWorker(wip);
  129. }
  130. }
  131. RELEASE_QUEUES_LOCK;
  132. }