Leaked source code of windows server 2003
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.

261 lines
5.5 KiB

  1. /*
  2. Copyright (c) 1998, Microsoft Corporation, all rights reserved
  3. Description:
  4. History:
  5. */
  6. #include "timer_.h"
  7. LONG g_TimerLockUninit = 0;
  8. /*
  9. Returns:
  10. Win 32 error
  11. Notes:
  12. Its a good idea to always call RasDhcpTimerUninitialize after calling
  13. RasDhcpTimerInitialize, even if RasDhcpTimerInitialize failed.
  14. */
  15. DWORD
  16. RasDhcpTimerInitialize(
  17. VOID
  18. )
  19. {
  20. NTSTATUS Status;
  21. DWORD dwErr = NO_ERROR;
  22. g_TimerLockUninit = 0;
  23. RasDhcpTimerShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
  24. if (NULL == RasDhcpTimerShutdown)
  25. {
  26. dwErr = GetLastError();
  27. goto LEnd;
  28. }
  29. Status = RtlCreateTimerQueue(&RasDhcpTimerQueueHandle);
  30. if (STATUS_SUCCESS != Status)
  31. {
  32. RasDhcpTimerQueueHandle = NULL;
  33. dwErr = Status;
  34. TraceHlp("RtlCreateTimerQueue failed and returned %d", dwErr);
  35. goto LEnd;
  36. }
  37. RasDhcpTimerPrevTime = time(NULL);
  38. Status = RtlCreateTimer(RasDhcpTimerQueueHandle, &RasDhcpTimerHandle,
  39. RasDhcpTimerFunc, NULL, 0, TIMER_PERIOD,
  40. WT_EXECUTELONGFUNCTION);
  41. if (STATUS_SUCCESS != Status)
  42. {
  43. dwErr = Status;
  44. TraceHlp("RtlCreateTimer failed and returned %d", dwErr);
  45. goto LEnd;
  46. }
  47. LEnd:
  48. if (NO_ERROR != dwErr)
  49. {
  50. if (NULL != RasDhcpTimerQueueHandle)
  51. {
  52. Status = RtlDeleteTimerQueueEx(RasDhcpTimerQueueHandle, (HANDLE)-1);
  53. RTASSERT(STATUS_SUCCESS == Status);
  54. RasDhcpTimerQueueHandle = NULL;
  55. }
  56. if (NULL != RasDhcpTimerShutdown)
  57. {
  58. CloseHandle(RasDhcpTimerShutdown);
  59. RasDhcpTimerShutdown = NULL;
  60. }
  61. }
  62. return(dwErr);
  63. }
  64. /*
  65. Returns:
  66. VOID
  67. Notes:
  68. RasDhcpTimerUninitialize can be called even if RasDhcpTimerInitialize
  69. failed.
  70. */
  71. VOID
  72. RasDhcpTimerUninitialize(
  73. VOID
  74. )
  75. {
  76. NTSTATUS Status;
  77. DWORD dwRet;
  78. LONG lPrev = 1;
  79. // Signal the timer thread to shutdown.
  80. lPrev = InterlockedExchangeAdd(&g_TimerLockUninit, 1);
  81. if ( lPrev > 0 )
  82. {
  83. InterlockedDecrement(&g_TimerLockUninit);
  84. return;
  85. }
  86. if (NULL != RasDhcpTimerQueueHandle)
  87. {
  88. RTASSERT(NULL != RasDhcpTimerShutdown);
  89. SetEvent(RasDhcpTimerShutdown);
  90. Status = RtlDeleteTimerQueueEx(RasDhcpTimerQueueHandle, (HANDLE)-1);
  91. RTASSERT(STATUS_SUCCESS == Status);
  92. RasDhcpTimerQueueHandle = NULL;
  93. }
  94. if (NULL != RasDhcpTimerShutdown)
  95. {
  96. CloseHandle(RasDhcpTimerShutdown);
  97. RasDhcpTimerShutdown = NULL;
  98. }
  99. // timer.c didn't alloc the nodes in the linked list.
  100. // So we don't free them here.
  101. RasDhcpTimerListHead = NULL;
  102. }
  103. /*
  104. Returns:
  105. Notes:
  106. */
  107. VOID
  108. RasDhcpTimerFunc(
  109. IN VOID* pArg1,
  110. IN BOOLEAN fArg2
  111. )
  112. {
  113. TIMERLIST* pTimer;
  114. TIMERLIST* pTmp;
  115. TIMERFUNCTION TimerFunc;
  116. time_t now = time(NULL);
  117. LONG lElapsedTime;
  118. LONG lTime;
  119. if (0 == TryEnterCriticalSection(&RasTimrCriticalSection))
  120. {
  121. // Another thread already owns the critical section
  122. return;
  123. }
  124. lElapsedTime = (LONG)(now - RasDhcpTimerPrevTime);
  125. RasDhcpTimerPrevTime = now;
  126. pTimer = NULL;
  127. while (RasDhcpTimerListHead != NULL)
  128. {
  129. lTime = RasDhcpTimerListHead->tmr_Delta;
  130. if ( lTime > 0)
  131. {
  132. RasDhcpTimerListHead->tmr_Delta -= lElapsedTime;
  133. lElapsedTime -= lTime;
  134. }
  135. if (RasDhcpTimerListHead->tmr_Delta <= 0)
  136. {
  137. pTmp = pTimer;
  138. pTimer = RasDhcpTimerListHead;
  139. RasDhcpTimerListHead = pTimer->tmr_Next;
  140. pTimer->tmr_Next = pTmp;
  141. }
  142. else
  143. {
  144. break;
  145. }
  146. }
  147. while (pTimer != NULL)
  148. {
  149. pTmp = pTimer->tmr_Next;
  150. TimerFunc = pTimer->tmr_TimerFunc;
  151. pTimer->tmr_TimerFunc = NULL;
  152. (*TimerFunc)(RasDhcpTimerShutdown, pTimer);
  153. pTimer = pTmp;
  154. }
  155. LeaveCriticalSection(&RasTimrCriticalSection);
  156. }
  157. /*
  158. Returns:
  159. VOID
  160. Notes:
  161. Once the timer thread starts, only it can call RasDhcpTimerSchedule (to
  162. avoid race conditions). The timer thread will call rasDhcpMonitorAddresses
  163. (and hence rasDhcpAllocateAddress), and rasDhcpRenewLease. These functions
  164. will call RasDhcpTimerSchedule. No one else should call these functions or
  165. RasDhcpTimerSchedule. The only exception is RasDhcpInitialize, which can
  166. call RasDhcpTimerSchedule before it creates the timer thread.
  167. */
  168. VOID
  169. RasDhcpTimerSchedule(
  170. IN TIMERLIST* pNewTimer,
  171. IN LONG DeltaTime,
  172. IN TIMERFUNCTION TimerFunc
  173. )
  174. {
  175. TIMERLIST** ppTimer;
  176. TIMERLIST* pTimer;
  177. pNewTimer->tmr_TimerFunc = TimerFunc;
  178. for (ppTimer = &RasDhcpTimerListHead;
  179. (pTimer = *ppTimer) != NULL;
  180. ppTimer = &pTimer->tmr_Next)
  181. {
  182. if (DeltaTime <= pTimer->tmr_Delta)
  183. {
  184. pTimer->tmr_Delta -= DeltaTime;
  185. break;
  186. }
  187. DeltaTime -= pTimer->tmr_Delta;
  188. }
  189. pNewTimer->tmr_Delta = DeltaTime;
  190. pNewTimer->tmr_Next = *ppTimer;
  191. *ppTimer = pNewTimer;
  192. }
  193. /*
  194. Returns:
  195. Notes:
  196. */
  197. VOID
  198. RasDhcpTimerRunNow(
  199. VOID
  200. )
  201. {
  202. RtlUpdateTimer(RasDhcpTimerQueueHandle, RasDhcpTimerHandle, 0,
  203. TIMER_PERIOD);
  204. }