mirror of
https://github.com/moparisthebest/curl
synced 2024-11-16 14:35:03 -05:00
tool_util: Improve Windows version of tvnow()
- Change tool_util.c tvnow() for Windows to match more closely to timeval.c Curl_now(). - Create a win32 init function for the tool, since some initialization is required for the tvnow() changes. Prior to this change the monotonic time function used by curl in Windows was determined at build-time and not runtime. That was a problem because when curl was built targeted for compatibility with old versions of Windows (eg _WIN32_WINNT < 0x0600) it would use GetTickCount which wraps every 49.7 days that Windows has been running. This change makes curl behave similar to libcurl's tvnow function, which determines at runtime whether the OS is Vista+ and if so calls QueryPerformanceCounter instead. (Note QueryPerformanceCounter is used because it has higher resolution than the more obvious candidate GetTickCount64). The changes to tvnow are basically a copy and paste but the types in some cases are different. Ref: https://github.com/curl/curl/issues/3309 Closes https://github.com/curl/curl/pull/4847
This commit is contained in:
parent
3735107d62
commit
1fc0617dcc
@ -109,11 +109,11 @@ CURLcode Curl_win32_init(long flags)
|
|||||||
if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
|
if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
|
||||||
VERSION_GREATER_THAN_EQUAL)) {
|
VERSION_GREATER_THAN_EQUAL)) {
|
||||||
Curl_isVistaOrGreater = TRUE;
|
Curl_isVistaOrGreater = TRUE;
|
||||||
QueryPerformanceFrequency(&Curl_freq);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Curl_isVistaOrGreater = FALSE;
|
Curl_isVistaOrGreater = FALSE;
|
||||||
|
|
||||||
|
QueryPerformanceFrequency(&Curl_freq);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
extern LARGE_INTEGER Curl_freq;
|
extern LARGE_INTEGER Curl_freq;
|
||||||
extern bool Curl_isVistaOrGreater;
|
extern bool Curl_isVistaOrGreater;
|
||||||
|
|
||||||
|
/* In case of bug fix this function has a counterpart in tool_util.c */
|
||||||
struct curltime Curl_now(void)
|
struct curltime Curl_now(void)
|
||||||
{
|
{
|
||||||
struct curltime now;
|
struct curltime now;
|
||||||
|
@ -697,6 +697,32 @@ cleanup:
|
|||||||
return slist;
|
return slist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LARGE_INTEGER Curl_freq;
|
||||||
|
bool Curl_isVistaOrGreater;
|
||||||
|
|
||||||
|
CURLcode win32_init(void)
|
||||||
|
{
|
||||||
|
OSVERSIONINFOEXA osvi;
|
||||||
|
unsigned __int64 mask = 0;
|
||||||
|
unsigned char op = VER_GREATER_EQUAL;
|
||||||
|
|
||||||
|
memset(&osvi, 0, sizeof(osvi));
|
||||||
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||||||
|
osvi.dwMajorVersion = 6;
|
||||||
|
VER_SET_CONDITION(mask, VER_MAJORVERSION, op);
|
||||||
|
VER_SET_CONDITION(mask, VER_MINORVERSION, op);
|
||||||
|
|
||||||
|
if(VerifyVersionInfoA(&osvi, (VER_MAJORVERSION | VER_MINORVERSION), mask))
|
||||||
|
Curl_isVistaOrGreater = true;
|
||||||
|
else if(GetLastError() == ERROR_OLD_WIN_VERSION)
|
||||||
|
Curl_isVistaOrGreater = false;
|
||||||
|
else
|
||||||
|
return CURLE_FAILED_INIT;
|
||||||
|
|
||||||
|
QueryPerformanceFrequency(&Curl_freq);
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
#endif /* MSDOS || WIN32 */
|
#endif /* MSDOS || WIN32 */
|
||||||
|
@ -61,6 +61,7 @@ CURLcode FindWin32CACert(struct OperationConfig *config,
|
|||||||
curl_sslbackend backend,
|
curl_sslbackend backend,
|
||||||
const char *bundle_file);
|
const char *bundle_file);
|
||||||
struct curl_slist *GetLoadedModulePaths(void);
|
struct curl_slist *GetLoadedModulePaths(void);
|
||||||
|
CURLcode win32_init(void);
|
||||||
|
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
@ -279,6 +279,24 @@ int main(int argc, char *argv[])
|
|||||||
struct GlobalConfig global;
|
struct GlobalConfig global;
|
||||||
memset(&global, 0, sizeof(global));
|
memset(&global, 0, sizeof(global));
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/* Undocumented diagnostic option to list the full paths of all loaded
|
||||||
|
modules. This is purposely pre-init. */
|
||||||
|
if(argc == 2 && !strcmp(argv[1], "--dump-module-paths")) {
|
||||||
|
struct curl_slist *item, *head = GetLoadedModulePaths();
|
||||||
|
for(item = head; item; item = item->next)
|
||||||
|
printf("%s\n", item->data);
|
||||||
|
curl_slist_free_all(head);
|
||||||
|
return head ? 0 : 1;
|
||||||
|
}
|
||||||
|
/* win32_init must be called before other init routines. */
|
||||||
|
result = win32_init();
|
||||||
|
if(result) {
|
||||||
|
fprintf(stderr, "curl: (%d) Windows-specific init failed.\n", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Perform any platform-specific terminal configuration */
|
/* Perform any platform-specific terminal configuration */
|
||||||
configure_terminal();
|
configure_terminal();
|
||||||
|
|
||||||
@ -294,21 +312,6 @@ int main(int argc, char *argv[])
|
|||||||
/* Initialize the curl library - do not call any libcurl functions before
|
/* Initialize the curl library - do not call any libcurl functions before
|
||||||
this point */
|
this point */
|
||||||
result = main_init(&global);
|
result = main_init(&global);
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
/* Undocumented diagnostic option to list the full paths of all loaded
|
|
||||||
modules, regardless of whether or not initialization succeeded. */
|
|
||||||
if(argc == 2 && !strcmp(argv[1], "--dump-module-paths")) {
|
|
||||||
struct curl_slist *item, *head = GetLoadedModulePaths();
|
|
||||||
for(item = head; item; item = item->next) {
|
|
||||||
printf("%s\n", item->data);
|
|
||||||
}
|
|
||||||
curl_slist_free_all(head);
|
|
||||||
if(!result)
|
|
||||||
main_free(&global);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* WIN32 */
|
|
||||||
if(!result) {
|
if(!result) {
|
||||||
/* Start our curl operation */
|
/* Start our curl operation */
|
||||||
result = operate(&global, argc, argv);
|
result = operate(&global, argc, argv);
|
||||||
|
@ -27,27 +27,35 @@
|
|||||||
|
|
||||||
#if defined(WIN32) && !defined(MSDOS)
|
#if defined(WIN32) && !defined(MSDOS)
|
||||||
|
|
||||||
|
/* set in win32_init() */
|
||||||
|
extern LARGE_INTEGER Curl_freq;
|
||||||
|
extern bool Curl_isVistaOrGreater;
|
||||||
|
|
||||||
|
/* In case of bug fix this function has a counterpart in timeval.c */
|
||||||
struct timeval tvnow(void)
|
struct timeval tvnow(void)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
** GetTickCount() is available on _all_ Windows versions from W95 up
|
|
||||||
** to nowadays. Returns milliseconds elapsed since last system boot,
|
|
||||||
** increases monotonically and wraps once 49.7 days have elapsed.
|
|
||||||
**
|
|
||||||
** GetTickCount64() is available on Windows version from Windows Vista
|
|
||||||
** and Windows Server 2008 up to nowadays. The resolution of the
|
|
||||||
** function is limited to the resolution of the system timer, which
|
|
||||||
** is typically in the range of 10 milliseconds to 16 milliseconds.
|
|
||||||
*/
|
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) && \
|
if(Curl_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */
|
||||||
(!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR))
|
LARGE_INTEGER count;
|
||||||
ULONGLONG milliseconds = GetTickCount64();
|
QueryPerformanceCounter(&count);
|
||||||
#else
|
now.tv_sec = (long)(count.QuadPart / Curl_freq.QuadPart);
|
||||||
DWORD milliseconds = GetTickCount();
|
now.tv_usec = (long)((count.QuadPart % Curl_freq.QuadPart) * 1000000 /
|
||||||
|
Curl_freq.QuadPart);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Disable /analyze warning that GetTickCount64 is preferred */
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:28159)
|
||||||
#endif
|
#endif
|
||||||
|
DWORD milliseconds = GetTickCount();
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
now.tv_sec = (long)(milliseconds / 1000);
|
now.tv_sec = (long)(milliseconds / 1000);
|
||||||
now.tv_usec = (long)((milliseconds % 1000) * 1000);
|
now.tv_usec = (long)((milliseconds % 1000) * 1000);
|
||||||
|
}
|
||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user