gettimeofday.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* Provide gettimeofday for systems that don't have it or for which it's broken.
  2. Copyright (C) 2001-2003, 2005-2007, 2009-2021 Free Software Foundation, Inc.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3, or (at your option)
  6. any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, see <https://www.gnu.org/licenses/>. */
  13. /* written by Jim Meyering */
  14. #include <config.h>
  15. /* Specification. */
  16. #include <sys/time.h>
  17. #include <time.h>
  18. #if defined _WIN32 && ! defined __CYGWIN__
  19. # define WINDOWS_NATIVE
  20. # include <windows.h>
  21. #endif
  22. #ifdef WINDOWS_NATIVE
  23. /* Don't assume that UNICODE is not defined. */
  24. # undef LoadLibrary
  25. # define LoadLibrary LoadLibraryA
  26. # if !(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
  27. /* Avoid warnings from gcc -Wcast-function-type. */
  28. # define GetProcAddress \
  29. (void *) GetProcAddress
  30. /* GetSystemTimePreciseAsFileTime was introduced only in Windows 8. */
  31. typedef void (WINAPI * GetSystemTimePreciseAsFileTimeFuncType) (FILETIME *lpTime);
  32. static GetSystemTimePreciseAsFileTimeFuncType GetSystemTimePreciseAsFileTimeFunc = NULL;
  33. static BOOL initialized = FALSE;
  34. static void
  35. initialize (void)
  36. {
  37. HMODULE kernel32 = LoadLibrary ("kernel32.dll");
  38. if (kernel32 != NULL)
  39. {
  40. GetSystemTimePreciseAsFileTimeFunc =
  41. (GetSystemTimePreciseAsFileTimeFuncType) GetProcAddress (kernel32, "GetSystemTimePreciseAsFileTime");
  42. }
  43. initialized = TRUE;
  44. }
  45. # else
  46. # define GetSystemTimePreciseAsFileTimeFunc GetSystemTimePreciseAsFileTime
  47. # endif
  48. #endif
  49. /* This is a wrapper for gettimeofday. It is used only on systems
  50. that lack this function, or whose implementation of this function
  51. causes problems.
  52. Work around the bug in some systems whereby gettimeofday clobbers
  53. the static buffer that localtime uses for its return value. The
  54. gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has
  55. this problem. */
  56. int
  57. gettimeofday (struct timeval *restrict tv, void *restrict tz)
  58. {
  59. #undef gettimeofday
  60. #ifdef WINDOWS_NATIVE
  61. /* On native Windows, there are two ways to get the current time:
  62. GetSystemTimeAsFileTime
  63. <https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime>
  64. or
  65. GetSystemTimePreciseAsFileTime
  66. <https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime>.
  67. GetSystemTimeAsFileTime produces values that jump by increments of
  68. 15.627 milliseconds (!) on average.
  69. Whereas GetSystemTimePreciseAsFileTime values usually jump by 1 or 2
  70. microseconds.
  71. More discussion on this topic:
  72. <http://www.windowstimestamp.com/description>. */
  73. FILETIME current_time;
  74. # if !(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
  75. if (!initialized)
  76. initialize ();
  77. # endif
  78. if (GetSystemTimePreciseAsFileTimeFunc != NULL)
  79. GetSystemTimePreciseAsFileTimeFunc (&current_time);
  80. else
  81. GetSystemTimeAsFileTime (&current_time);
  82. /* Convert from FILETIME to 'struct timeval'. */
  83. /* FILETIME: <https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-filetime> */
  84. ULONGLONG since_1601 =
  85. ((ULONGLONG) current_time.dwHighDateTime << 32)
  86. | (ULONGLONG) current_time.dwLowDateTime;
  87. /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89 leap
  88. years, in total 134774 days. */
  89. ULONGLONG since_1970 =
  90. since_1601 - (ULONGLONG) 134774 * (ULONGLONG) 86400 * (ULONGLONG) 10000000;
  91. ULONGLONG microseconds_since_1970 = since_1970 / (ULONGLONG) 10;
  92. tv->tv_sec = microseconds_since_1970 / (ULONGLONG) 1000000;
  93. tv->tv_usec = microseconds_since_1970 % (ULONGLONG) 1000000;
  94. return 0;
  95. #else
  96. # if HAVE_GETTIMEOFDAY
  97. # if defined timeval /* 'struct timeval' overridden by gnulib? */
  98. # undef timeval
  99. struct timeval otv;
  100. int result = gettimeofday (&otv, (struct timezone *) tz);
  101. if (result == 0)
  102. {
  103. tv->tv_sec = otv.tv_sec;
  104. tv->tv_usec = otv.tv_usec;
  105. }
  106. # else
  107. int result = gettimeofday (tv, (struct timezone *) tz);
  108. # endif
  109. return result;
  110. # else
  111. # if !defined OK_TO_USE_1S_CLOCK
  112. # error "Only 1-second nominal clock resolution found. Is that intended?" \
  113. "If so, compile with the -DOK_TO_USE_1S_CLOCK option."
  114. # endif
  115. tv->tv_sec = time (NULL);
  116. tv->tv_usec = 0;
  117. return 0;
  118. # endif
  119. #endif
  120. }