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.

328 lines
7.7 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\routing\ipx\sap\timermgr.c
  5. Abstract:
  6. Timer queue manager for SAP agent.
  7. Author:
  8. Vadim Eydelman 05-15-1995
  9. Revision History:
  10. --*/
  11. #include "sapp.h"
  12. // Timer queues and associated synchronization
  13. typedef struct _TIMER_QUEUES {
  14. LIST_ENTRY hrQueue; // Hi-res quueue (msec)
  15. LIST_ENTRY lrQueue; // Lo-res queue (sec)
  16. HANDLE timer; // NT timer signalled when
  17. // one or more items in the
  18. // timer queue have expired
  19. CRITICAL_SECTION lock; // Protection
  20. } TIMER_QUEUES, *PTIMER_QUEUES;
  21. TIMER_QUEUES TimerQueues;
  22. /*++
  23. *******************************************************************
  24. C r e a t e T i m e r Q u e u e
  25. Routine Description:
  26. Allocates resources for timer queue
  27. Arguments:
  28. wakeObject - sync object, to be signalled when
  29. timer manager needs a shot process its timer queue
  30. Return Value:
  31. NO_ERROR - resources were allocated successfully
  32. other - reason of failure (windows error code)
  33. *******************************************************************
  34. --*/
  35. DWORD
  36. IpxSapCreateTimerQueue (
  37. HANDLE *wakeObject
  38. ) {
  39. DWORD status;
  40. status = NtCreateTimer (&TimerQueues.timer, TIMER_ALL_ACCESS,
  41. NULL, NotificationTimer);
  42. if (NT_SUCCESS (status)) {
  43. *wakeObject = TimerQueues.timer;
  44. InitializeCriticalSection (&TimerQueues.lock);
  45. InitializeListHead (&TimerQueues.hrQueue);
  46. InitializeListHead (&TimerQueues.lrQueue);
  47. return NO_ERROR;
  48. }
  49. else
  50. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  51. " Failed to create timer (nts:%lx).",
  52. __FILE__, __LINE__, status);
  53. return status;
  54. }
  55. /*++
  56. *******************************************************************
  57. E x p i r e T i m e r Q u e u e
  58. Routine Description:
  59. Expires (completes) all requests in timer queue
  60. Arguments:
  61. None
  62. Return Value:
  63. None
  64. *******************************************************************
  65. --*/
  66. VOID
  67. ExpireTimerQueue (
  68. void
  69. ) {
  70. BOOLEAN res;
  71. Trace (DEBUG_TIMER, "Expiring timer queue.");
  72. EnterCriticalSection (&TimerQueues.lock);
  73. while (!IsListEmpty (&TimerQueues.hrQueue)) {
  74. PTM_PARAM_BLOCK treq = CONTAINING_RECORD (TimerQueues.hrQueue.Flink,
  75. TM_PARAM_BLOCK,
  76. link);
  77. RemoveEntryList (&treq->link);
  78. ProcessCompletedTimerRequest (treq);
  79. }
  80. while (!IsListEmpty (&TimerQueues.lrQueue)) {
  81. PTM_PARAM_BLOCK treq = CONTAINING_RECORD (TimerQueues.lrQueue.Flink,
  82. TM_PARAM_BLOCK,
  83. link);
  84. RemoveEntryList (&treq->link);
  85. ProcessCompletedTimerRequest (treq);
  86. }
  87. LeaveCriticalSection (&TimerQueues.lock);
  88. }
  89. /*++
  90. *******************************************************************
  91. E x p i r e L R R e q u s t s
  92. Routine Description:
  93. Expires (completes) Low Resolution timer requests
  94. that return true from expiration check routine
  95. Arguments:
  96. context - context to pass to expiration check routine
  97. Return Value:
  98. None
  99. *******************************************************************
  100. --*/
  101. VOID
  102. ExpireLRRequests (
  103. PVOID context
  104. ) {
  105. BOOLEAN res;
  106. PLIST_ENTRY cur;
  107. Trace (DEBUG_TIMER, "Expire LR timer request call with context %08lx.", context);
  108. EnterCriticalSection (&TimerQueues.lock);
  109. cur = TimerQueues.lrQueue.Flink;
  110. while (cur!=&TimerQueues.lrQueue) {
  111. PTM_PARAM_BLOCK treq = CONTAINING_RECORD (cur,
  112. TM_PARAM_BLOCK,
  113. link);
  114. cur = cur->Flink;
  115. if ((treq->ExpirationCheckProc!=NULL)
  116. && (*treq->ExpirationCheckProc)(treq, context)) {
  117. RemoveEntryList (&treq->link);
  118. ProcessCompletedTimerRequest (treq);
  119. }
  120. }
  121. LeaveCriticalSection (&TimerQueues.lock);
  122. }
  123. /*++
  124. *******************************************************************
  125. D e l e t e T i m e r Q u e u e
  126. Routine Description:
  127. Release all resources associated with timer queue
  128. Arguments:
  129. None
  130. Return Value:
  131. NO_ERROR - operation completed OK
  132. *******************************************************************
  133. --*/
  134. VOID
  135. IpxSapDeleteTimerQueue (
  136. void
  137. ) {
  138. NtClose (TimerQueues.timer);
  139. DeleteCriticalSection (&TimerQueues.lock);
  140. }
  141. /*++
  142. *******************************************************************
  143. P r o c e s s T i m e r Q u e u e
  144. Routine Description:
  145. Process timer queues and moves expired requests to completion queue
  146. This routine should be called when wake object is signalled
  147. Arguments:
  148. None
  149. Return Value:
  150. None
  151. *******************************************************************
  152. --*/
  153. VOID
  154. ProcessTimerQueue (
  155. void
  156. ) {
  157. ULONG curTime = GetTickCount ();
  158. ULONG dueTime = curTime+MAXULONG/2;
  159. LONGLONG timeout;
  160. DWORD status;
  161. EnterCriticalSection (&TimerQueues.lock);
  162. while (!IsListEmpty (&TimerQueues.hrQueue)) {
  163. PTM_PARAM_BLOCK treq = CONTAINING_RECORD (TimerQueues.hrQueue.Flink,
  164. TM_PARAM_BLOCK,
  165. link);
  166. if (IsLater(curTime,treq->dueTime)) {
  167. RemoveEntryList (&treq->link);
  168. ProcessCompletedTimerRequest (treq);
  169. }
  170. else {
  171. dueTime = treq->dueTime;
  172. break;
  173. }
  174. }
  175. while (!IsListEmpty (&TimerQueues.lrQueue)) {
  176. PTM_PARAM_BLOCK treq = CONTAINING_RECORD (TimerQueues.lrQueue.Flink,
  177. TM_PARAM_BLOCK,
  178. link);
  179. if (IsLater(curTime,treq->dueTime)) {
  180. RemoveEntryList (&treq->link);
  181. ProcessCompletedTimerRequest (treq);
  182. }
  183. else {
  184. if (IsLater(dueTime,treq->dueTime))
  185. dueTime = treq->dueTime;
  186. break;
  187. }
  188. }
  189. timeout = ((LONGLONG)(dueTime-curTime))*(-10000);
  190. status = NtSetTimer (TimerQueues.timer,
  191. (PLARGE_INTEGER)&timeout,
  192. NULL, NULL, FALSE, 0, NULL);
  193. ASSERTMSG ("Could not set timer ", NT_SUCCESS (status));
  194. LeaveCriticalSection (&TimerQueues.lock);
  195. }
  196. /*++
  197. *******************************************************************
  198. A d d H R T i m e r R e q u e s t
  199. Routine Description:
  200. Enqueue request for hi-res timer (delay in order of msec)
  201. Arguments:
  202. treq - timer parameter block: dueTime field must be set
  203. Return Value:
  204. None
  205. *******************************************************************
  206. --*/
  207. VOID
  208. AddHRTimerRequest (
  209. PTM_PARAM_BLOCK treq
  210. ) {
  211. PLIST_ENTRY cur;
  212. EnterCriticalSection (&TimerQueues.lock);
  213. cur = TimerQueues.hrQueue.Blink;
  214. while (cur!=&TimerQueues.hrQueue) {
  215. PTM_PARAM_BLOCK node = CONTAINING_RECORD (cur, TM_PARAM_BLOCK, link);
  216. if (IsLater(treq->dueTime,node->dueTime))
  217. break;
  218. cur = cur->Blink;
  219. }
  220. InsertHeadList (cur, &treq->link);
  221. if (cur==&TimerQueues.hrQueue) {
  222. ULONG delay = treq->dueTime-GetTickCount ();
  223. LONGLONG timeout = (delay>MAXULONG/2) ? 0 : ((LONGLONG)delay*(-10000));
  224. DWORD status = NtSetTimer (TimerQueues.timer,
  225. (PLARGE_INTEGER)&timeout,
  226. NULL, NULL, FALSE, 0, NULL);
  227. ASSERTMSG ("Could not set timer ", NT_SUCCESS (status));
  228. }
  229. LeaveCriticalSection (&TimerQueues.lock);
  230. }
  231. /*++
  232. *******************************************************************
  233. A d d L R T i m e r R e q u e s t
  234. Routine Description:
  235. Enqueue request for lo-res timer (delay in order of sec)
  236. Arguments:
  237. treq - timer parameter block: dueTime field must be set
  238. Return Value:
  239. None
  240. *******************************************************************
  241. --*/
  242. VOID
  243. AddLRTimerRequest (
  244. PTM_PARAM_BLOCK treq
  245. ) {
  246. PLIST_ENTRY cur;
  247. RoundUpToSec (treq->dueTime);
  248. EnterCriticalSection (&TimerQueues.lock);
  249. cur = TimerQueues.lrQueue.Blink;
  250. while (cur!=&TimerQueues.lrQueue) {
  251. PTM_PARAM_BLOCK node = CONTAINING_RECORD (cur, TM_PARAM_BLOCK, link);
  252. if (IsLater(treq->dueTime,node->dueTime))
  253. break;
  254. cur = cur->Blink;
  255. }
  256. InsertHeadList (cur, &treq->link);
  257. if ((cur==&TimerQueues.lrQueue)
  258. && IsListEmpty (&TimerQueues.hrQueue)) {
  259. ULONG delay = treq->dueTime-GetTickCount ();
  260. LONGLONG timeout = (delay>MAXULONG/2) ? 0 : ((LONGLONG)delay*(-10000));
  261. DWORD status = NtSetTimer (TimerQueues.timer,
  262. (PLARGE_INTEGER)&timeout,
  263. NULL, NULL, FALSE, 0, NULL);
  264. ASSERTMSG ("Could not set timer ", NT_SUCCESS (status));
  265. }
  266. LeaveCriticalSection (&TimerQueues.lock);
  267. }