From b903d2d6cdf9a9efac181a21e95ea93dc8a864dd Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Fri, 15 Mar 2013 19:04:40 +0100 Subject: Backported patch for #64370 --- NEWS | 5 ++ ext/standard/tests/bug64370_var1.phpt | 26 +++++++ ext/standard/tests/bug64370_var2.phpt | 23 ++++++ win32/globals.c | 2 - win32/php_win32_globals.h | 4 - win32/time.c | 133 +++++++++++----------------------- 6 files changed, 96 insertions(+), 97 deletions(-) create mode 100644 ext/standard/tests/bug64370_var1.phpt create mode 100644 ext/standard/tests/bug64370_var2.phpt diff --git a/NEWS b/NEWS index fb877c0185..41f5eab4e7 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,11 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2013, PHP 5.3.24 + +- Core + . Fixed bug #64370 (microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT']). + (Anatol) + - PCRE: . Merged PCRE 8.32). (Anatol) diff --git a/ext/standard/tests/bug64370_var1.phpt b/ext/standard/tests/bug64370_var1.phpt new file mode 100644 index 0000000000..ff64d61616 --- /dev/null +++ b/ext/standard/tests/bug64370_var1.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test bug #64370 microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT'] +--SKIPIF-- += 0)) . "\n"; +?> +===DONE=== +--EXPECTF-- +$_SERVER['REQUEST_TIME']: %d +$_SERVER['REQUEST_TIME_FLOAT']: %f +time(): %d +microtime(true): %f +created in %f ms +1 +===DONE=== diff --git a/ext/standard/tests/bug64370_var2.phpt b/ext/standard/tests/bug64370_var2.phpt new file mode 100644 index 0000000000..d0d3590ea7 --- /dev/null +++ b/ext/standard/tests/bug64370_var2.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test bug #64370 sequential microtime(true) calls +--FILE-- + $i++) { + $m0 = microtime(true); + $m1 = microtime(true); + $d = $m1 - $m0; + + /*echo "$d\n";*/ + + if ($d < 0) { + die("failed in {$i}th iteration"); + } +} +echo "ok\n"; +?> +===DONE=== +--EXPECT-- +ok +===DONE=== diff --git a/win32/globals.c b/win32/globals.c index 1bbb3b4481..b381cc1237 100644 --- a/win32/globals.c +++ b/win32/globals.c @@ -65,8 +65,6 @@ PHP_RSHUTDOWN_FUNCTION(win32_core_globals) ; closelog(); - wg->starttime.tv_sec = 0; - wg->lasttime = 0; return SUCCESS; } diff --git a/win32/php_win32_globals.h b/win32/php_win32_globals.h index 1686e5df63..b2b07f68e1 100644 --- a/win32/php_win32_globals.h +++ b/win32/php_win32_globals.h @@ -38,10 +38,6 @@ struct _php_win32_core_globals { char *log_header; HANDLE log_source; - /* time */ - struct timeval starttime; - __int64 lasttime, freq; - HKEY registry_key; HANDLE registry_event; HashTable *registry_directories; diff --git a/win32/time.c b/win32/time.c index 391a8a81e9..77e4504cd1 100644 --- a/win32/time.c +++ b/win32/time.c @@ -12,13 +12,6 @@ /* $Id$ */ - /** - * - * 04-Feb-2001 - * - Added patch by "Vanhanen, Reijo" - * Improves accuracy of msec - */ - /* Include stuff ************************************************************ */ #include @@ -32,98 +25,56 @@ #include #include "php_win32_globals.h" -int getfilesystemtime(struct timeval *time_Info) +typedef VOID (WINAPI *MyGetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime); + +static MyGetSystemTimeAsFileTime get_time_func(void) { - FILETIME ft; - __int64 ff; - ULARGE_INTEGER convFromft; - - GetSystemTimeAsFileTime(&ft); /* 100 ns blocks since 01-Jan-1641 */ - /* resolution seems to be 0.01 sec */ - /* - * Do not cast a pointer to a FILETIME structure to either a - * ULARGE_INTEGER* or __int64* value because it can cause alignment faults on 64-bit Windows. - * via http://technet.microsoft.com/en-us/library/ms724284(v=vs.85).aspx - */ - convFromft.HighPart = ft.dwHighDateTime; - convFromft.LowPart = ft.dwLowDateTime; - ff = convFromft.QuadPart; - - time_Info->tv_sec = (int)(ff/(__int64)10000000-(__int64)11644473600); - time_Info->tv_usec = (int)(ff % 10000000)/10; - return 0; + MyGetSystemTimeAsFileTime timefunc = NULL; + HMODULE hMod = LoadLibrary("kernel32.dll"); + + if (hMod) { + /* Max possible resolution <1us, win8/server2012 */ + timefunc = (MyGetSystemTimeAsFileTime)GetProcAddress(hMod, "GetSystemTimePreciseAsFileTime"); + + if(!timefunc) { + /* 100ns blocks since 01-Jan-1641 */ + timefunc = (MyGetSystemTimeAsFileTime)GetProcAddress(hMod, "GetSystemTimeAsFileTime"); + } + } + + return timefunc; } - +int getfilesystemtime(struct timeval *tv) +{ + FILETIME ft; + unsigned __int64 ff = 0; + MyGetSystemTimeAsFileTime timefunc; + + timefunc = get_time_func(); + if (timefunc) { + timefunc(&ft); + } else { + GetSystemTimeAsFileTime(&ft); + } + + ff |= ft.dwHighDateTime; + ff <<= 32; + ff |= ft.dwLowDateTime; + ff /= 10; /* convert to microseconds */ + ff -= 11644473600000000Ui64; /* convert to unix epoch */ + + tv->tv_sec = (long)(ff / 1000000UL); + tv->tv_usec = (long)(ff % 1000000UL); + + return 0; +} PHPAPI int gettimeofday(struct timeval *time_Info, struct timezone *timezone_Info) { - __int64 timer; - LARGE_INTEGER li; - BOOL b; - double dt; - TSRMLS_FETCH(); - /* Get the time, if they want it */ if (time_Info != NULL) { - if (PW32G(starttime).tv_sec == 0) { - b = QueryPerformanceFrequency(&li); - if (!b) { - PW32G(starttime).tv_sec = -1; - } - else { - PW32G(freq) = li.QuadPart; - b = QueryPerformanceCounter(&li); - if (!b) { - PW32G(starttime).tv_sec = -1; - } - else { - getfilesystemtime(&PW32G(starttime)); - timer = li.QuadPart; - dt = (double)timer/PW32G(freq); - PW32G(starttime).tv_usec -= (int)((dt-(int)dt)*1000000); - if (PW32G(starttime).tv_usec < 0) { - PW32G(starttime).tv_usec += 1000000; - --PW32G(starttime).tv_sec; - } - PW32G(starttime).tv_sec -= (int)dt; - } - } - } - if (PW32G(starttime).tv_sec > 0) { - b = QueryPerformanceCounter(&li); - if (!b) { - PW32G(starttime).tv_sec = -1; - } - else { - timer = li.QuadPart; - if (timer < PW32G(lasttime)) { - getfilesystemtime(time_Info); - dt = (double)timer/PW32G(freq); - PW32G(starttime) = *time_Info; - PW32G(starttime).tv_usec -= (int)((dt-(int)dt)*1000000); - if (PW32G(starttime).tv_usec < 0) { - PW32G(starttime).tv_usec += 1000000; - --PW32G(starttime).tv_sec; - } - PW32G(starttime).tv_sec -= (int)dt; - } - else { - PW32G(lasttime) = timer; - dt = (double)timer/PW32G(freq); - time_Info->tv_sec = PW32G(starttime).tv_sec + (int)dt; - time_Info->tv_usec = PW32G(starttime).tv_usec + (int)((dt-(int)dt)*1000000); - if (time_Info->tv_usec >= 1000000) { - time_Info->tv_usec -= 1000000; - ++time_Info->tv_sec; - } - } - } - } - if (PW32G(starttime).tv_sec < 0) { - getfilesystemtime(time_Info); - } - + getfilesystemtime(time_Info); } /* Get the timezone, if they want it */ if (timezone_Info != NULL) { -- cgit v1.2.1