Method implementation is: ``` steady_clock::time_point steady_clock::now() _NOEXCEPT { static LARGE_INTEGER freq; static BOOL initialized = FALSE; if (!initialized) initialized = QueryPerformanceFrequency(&freq); // always succceeds LARGE_INTEGER counter; QueryPerformanceCounter(&counter); return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart)); } ``` And seems like there is a race condition on `freq` and `initialized` variables if `steady_clock::now` has never been called before new threads creation. Possible fixes are: 1. use thread local storage for `freq` and `initialized`, but there might be some problems on Windows XP: https://reverseengineering.stackexchange.com/questions/14171/thread-local-storage-access-on-windows-xp 2. use `std::call_once` guard, but it is slightly slower than thread local due to atomic access.
This should fix the problem, but I don't have direct access to a Windows box to check. Can you let me know? Also, how did you discover this? diff --git a/libcxx/src/chrono.cpp b/libcxx/src/chrono.cpp index ea0a638acc5..d342ee32d6c 100644 --- a/libcxx/src/chrono.cpp +++ b/libcxx/src/chrono.cpp @@ -177,16 +177,21 @@ steady_clock::now() _NOEXCEPT #elif defined(_LIBCPP_WIN32API) +static LARGE_INTEGER +init_FREQ() +{ + LARGE_INTEGER val; + (void) QueryPerformanceFrequency(&val); + return val; +} + steady_clock::time_point steady_clock::now() _NOEXCEPT { - static LARGE_INTEGER freq; - static BOOL initialized = FALSE; - if (!initialized) - initialized = QueryPerformanceFrequency(&freq); // always succceeds + static const LARGE_INTEGER freq = init_FREQ(); LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); + (void) QueryPerformanceCounter(&counter); return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart)); }
Yes, this fix is ok. And it is cleaner than my proposals. > Can you let me know? Also, how did you discover this? Well, I do not have windows box too. I'm just reviewing libcpp code in order to understand how it is organized.
Fixed in r357413.
(In reply to Marshall Clow (home) from comment #3) > Fixed in r357413. r357413 changes a invocation of "QueryPerformanceCounter" to instead call "QueryPerformanceFrequency" (note Counter vs. Frequency). Seems like a mistake?
(In reply to ensadc from comment #4) > (In reply to Marshall Clow (home) from comment #3) > > Fixed in r357413. > > r357413 changes a invocation of "QueryPerformanceCounter" to instead call > "QueryPerformanceFrequency" (note Counter vs. Frequency). Seems like a > mistake? Oops. r357474