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.

251 lines
4.7 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. timer.c
  5. Abstract:
  6. Wrap-proof timer routines.
  7. The purpose of this module is to create a timer function which
  8. returns a time in seconds and eliminates all timer wrapping issues.
  9. These routines are non-DNS specific and may be picked up
  10. cleanly by any module.
  11. For DNS the added instructions are well worth the cost in that it
  12. eliminates any issue involving cleaning packet queues or resetting
  13. cache timeouts when millisecond timer (GetCurrentTime) wraps.
  14. Author:
  15. Jim Gilroy (jamesg) 9-Sep-1995
  16. Environment:
  17. Win32 User Mode
  18. Project:
  19. Common Code for Internet Services
  20. Functions Exported:
  21. InitializeSecondsTimer()
  22. TerminateSecondsTimer()
  23. GetCurrentTimeInSeconds()
  24. GetCurrentTimeInMilliseconds()
  25. Revision History:
  26. MuraliK 14-Nov-1995 Made multi thread safe.
  27. --*/
  28. #include "precomp.hxx"
  29. //
  30. // Timer globals
  31. //
  32. CRITICAL_SECTION g_csTimerWrap;
  33. VOID
  34. InitializeSecondsTimer(
  35. VOID
  36. )
  37. /*++
  38. Routine Description:
  39. Initialize DNS timer.
  40. Arguments:
  41. None.
  42. Return Value:
  43. None.
  44. --*/
  45. {
  46. INITIALIZE_CRITICAL_SECTION( &g_csTimerWrap );
  47. } // InitializeSecondsTimer()
  48. VOID
  49. TerminateSecondsTimer(
  50. VOID
  51. )
  52. /*++
  53. Routine Description:
  54. Terminate DNS timer.
  55. Arguments:
  56. None.
  57. Return Value:
  58. None.
  59. --*/
  60. {
  61. DeleteCriticalSection( &g_csTimerWrap );
  62. } // TerminateSecondsTimer()
  63. DWORD
  64. GetCurrentTimeInSeconds(
  65. VOID
  66. )
  67. /*++
  68. Routine Description:
  69. Get current time in seconds.
  70. Arguments:
  71. None.
  72. Return Value:
  73. Time since boot in seconds.
  74. --*/
  75. {
  76. DWORD dwCurrentTime;
  77. static DWORD dwPreviousTime = 0; // previous GetCurrentTime()
  78. static DWORD dwWrapTime = 0; // accumulated time (s) from timer
  79. // wraps
  80. dwCurrentTime = GetCurrentTime();
  81. //
  82. // check for timer wrap
  83. //
  84. // Check that previous time is bigger, but since multi-threaded,
  85. // occasionally preempted before making test and another thread
  86. // may reset dwPreviousTime. So we also explicitly verify the
  87. // switch from a very large DWORD to a small one.
  88. //
  89. // Note: that we completely avoid using the CS, except right at
  90. // an actual timer wrap. Hence the cost for this function
  91. // remains low.
  92. //
  93. if ( dwPreviousTime > dwCurrentTime
  94. &&
  95. (LONG)dwPreviousTime < 0
  96. &&
  97. (LONG)dwCurrentTime > 0 )
  98. {
  99. //
  100. // detected timer wrap
  101. //
  102. // inside CS, verify actual wrap and reset dwPreviousTime
  103. // so other waiting threads will NOT count wrap
  104. //
  105. EnterCriticalSection( &g_csTimerWrap );
  106. if ( (LONG)dwPreviousTime < 0
  107. &&
  108. (LONG)dwCurrentTime > 0 )
  109. {
  110. dwPreviousTime = dwCurrentTime;
  111. dwWrapTime += (0xffffffff / 1000);
  112. }
  113. LeaveCriticalSection( &g_csTimerWrap );
  114. }
  115. dwPreviousTime = dwCurrentTime;
  116. return (dwCurrentTime / 1000 + dwWrapTime);
  117. }
  118. __int64
  119. GetCurrentTimeInMilliseconds(
  120. VOID
  121. )
  122. /*++
  123. Routine Description:
  124. Get current time in milliseconds.
  125. Arguments:
  126. None.
  127. Return Value:
  128. Time since boot in seconds.
  129. --*/
  130. {
  131. DWORD dwCurrentTime;
  132. static DWORD dwPreviousTime = 0; // previous GetCurrentTime()
  133. static DWORD dwWrapTime = 0; // accumulated time (s) from timer
  134. // wraps
  135. dwCurrentTime = GetTickCount();
  136. //
  137. // check for timer wrap
  138. //
  139. // Check that previous time is bigger, but since multi-threaded,
  140. // occasionally preempted before making test and another thread
  141. // may reset dwPreviousTime. So we also explicitly verify the
  142. // switch from a very large DWORD to a small one.
  143. //
  144. // Note: that we completely avoid using the CS, except right at
  145. // an actual timer wrap. Hence the cost for this function
  146. // remains low.
  147. //
  148. if ( dwPreviousTime > dwCurrentTime
  149. &&
  150. (LONG)dwPreviousTime < 0
  151. &&
  152. (LONG)dwCurrentTime > 0 )
  153. {
  154. //
  155. // detected timer wrap
  156. //
  157. // inside CS, verify actual wrap and reset dwPreviousTime
  158. // so other waiting threads will NOT count wrap
  159. //
  160. EnterCriticalSection( &g_csTimerWrap );
  161. if ( (LONG)dwPreviousTime < 0
  162. &&
  163. (LONG)dwCurrentTime > 0 )
  164. {
  165. dwPreviousTime = dwCurrentTime;
  166. ++dwWrapTime;
  167. }
  168. LeaveCriticalSection( &g_csTimerWrap );
  169. }
  170. dwPreviousTime = dwCurrentTime;
  171. return (((__int64)dwWrapTime)<<32) | dwCurrentTime;
  172. }
  173. //
  174. // End of timer.c
  175. //