diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index cd069e82..628b71b6 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -284,7 +284,6 @@ alias thread_sources win32/thread.cpp win32/tss_dll.cpp win32/tss_pe.cpp - win32/gettickcount64.cpp future.cpp : ## requirements ## win32 diff --git a/include/boost/thread/win32/gettickcount64.hpp b/include/boost/thread/win32/gettickcount64.hpp deleted file mode 100644 index 06abbd23..00000000 --- a/include/boost/thread/win32/gettickcount64.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef BOOST_WIN32_GET_TICK_COUNT_HPP -#define BOOST_WIN32_GET_TICK_COUNT_HPP - -// (C) Copyright 2014 Vicente J. Botet Escriba -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost -{ - namespace detail - { - namespace win32 - { - typedef unsigned long long ticks_type; - typedef ticks_type (__stdcall *gettickcount64fn)(); - typedef unsigned long (__stdcall *gettickcount32fn)(); - ticks_type BOOST_THREAD_DECL GetTickCount64(); - } - } -} - -#include - -#endif diff --git a/include/boost/thread/win32/thread_data.hpp b/include/boost/thread/win32/thread_data.hpp index b916901d..152c8020 100644 --- a/include/boost/thread/win32/thread_data.hpp +++ b/include/boost/thread/win32/thread_data.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include @@ -186,14 +185,14 @@ namespace boost static unsigned long const max_non_infinite_wait=0xfffffffe; timeout(uintmax_t milliseconds_): - start(win32::GetTickCount64()), + start(win32::GetTickCount64()()), milliseconds(milliseconds_), relative(true), abs_time(boost::get_system_time()) {} timeout(boost::system_time const& abs_time_): - start(win32::GetTickCount64()), + start(win32::GetTickCount64()()), milliseconds(0), relative(false), abs_time(abs_time_) @@ -218,7 +217,7 @@ namespace boost } else if(relative) { - win32::ticks_type const now=win32::GetTickCount64(); + win32::ticks_type const now=win32::GetTickCount64()(); win32::ticks_type const elapsed=now-start; return remaining_time((elapsed #endif -//#ifndef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64 -//#if _WIN32_WINNT >= 0x0600 && ! defined _WIN32_WINNT_WS08 -//#define BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64 -//#endif -//#endif - #if defined( BOOST_USE_WINDOWS_H ) # include @@ -38,14 +32,9 @@ namespace boost { namespace win32 { -//#ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64 -// typedef unsigned long long ticks_type; -//#else -// typedef unsigned long ticks_type; -//#endif - typedef ULONG_PTR ulong_ptr; typedef HANDLE handle; typedef SYSTEM_INFO system_info; + typedef unsigned __int64 ticks_type; unsigned const infinite=INFINITE; unsigned const timeout=WAIT_TIMEOUT; handle const invalid_handle_value=INVALID_HANDLE_VALUE; @@ -67,6 +56,7 @@ namespace boost using ::CreateMutexExW; using ::CreateEventExW; using ::CreateSemaphoreExW; + namespace detail { using ::GetTickCount64; } # endif using ::OpenEventW; # else @@ -97,12 +87,6 @@ namespace boost using ::Sleep; using ::QueueUserAPC; #endif -// using ::GetTickCount; -//#ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64 -// using ::GetTickCount64; -//#else -// inline ticks_type GetTickCount64() { return GetTickCount(); } -//#endif } } } @@ -143,11 +127,6 @@ namespace boost { namespace win32 { -//#ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64 -// typedef unsigned long long ticks_type; -//#else -// typedef unsigned long ticks_type; -//#endif # ifdef _WIN64 typedef unsigned __int64 ulong_ptr; # else @@ -155,6 +134,7 @@ namespace boost # endif typedef void* handle; typedef _SYSTEM_INFO system_info; + typedef unsigned __int64 ticks_type; unsigned const infinite=~0U; unsigned const timeout=258U; handle const invalid_handle_value=(handle)(-1); @@ -178,6 +158,7 @@ namespace boost __declspec(dllimport) void* __stdcall CreateMutexExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long); __declspec(dllimport) void* __stdcall CreateEventExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long); __declspec(dllimport) void* __stdcall CreateSemaphoreExW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*,unsigned long,unsigned long); + namespace detail { __declspec(dllimport) ticks_type __stdcall GetTickCount64(); } # endif __declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*); # else @@ -204,10 +185,6 @@ namespace boost __declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr); #endif -// __declspec(dllimport) unsigned long __stdcall GetTickCount(); -//# ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64 -// __declspec(dllimport) ticks_type __stdcall GetTickCount64(); -//# endif # ifndef UNDER_CE __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId(); __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(); @@ -224,9 +201,6 @@ namespace boost using ::ResetEvent; # endif } -//# ifndef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64 -// inline ticks_type GetTickCount64() { return GetTickCount(); } -//# endif } } } @@ -242,7 +216,96 @@ namespace boost { namespace win32 { - enum event_type + namespace detail { typedef int (__stdcall *farproc_t)(); typedef ticks_type (__stdcall *gettickcount64_t)(); } +#if !BOOST_PLAT_WINDOWS_RUNTIME + extern "C" + { + __declspec(dllimport) detail::farproc_t __stdcall GetProcAddress(void *, const char *); +#if !defined(BOOST_NO_ANSI_APIS) + __declspec(dllimport) void * __stdcall GetModuleHandleA(const char *); +#else + __declspec(dllimport) void * __stdcall GetModuleHandleW(const wchar_t *); +#endif + int __stdcall GetTickCount(); + long _InterlockedCompareExchange(long volatile *, long, long); +#pragma intrinsic(_InterlockedCompareExchange) + } + // Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar + inline ticks_type __stdcall GetTickCount64emulation() + { + static volatile long count = 0xFFFFFFFF; + unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone; + ticks_type current_tick64; + + previous_count = (unsigned long) _InterlockedCompareExchange(&count, 0, 0); + current_tick32 = GetTickCount(); + + if(previous_count == 0xFFFFFFFF) + { + // count has never been written + unsigned long initial_count; + initial_count = current_tick32 >> 28; + previous_count = (unsigned long) _InterlockedCompareExchange(&count, initial_count, 0xFFFFFFFF); + + current_tick64 = initial_count; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + previous_count_zone = previous_count & 15; + current_tick32_zone = current_tick32 >> 28; + + if(current_tick32_zone == previous_count_zone) + { + // The top four bits of the 32-bit tick count haven't changed since count was last written. + current_tick64 = previous_count; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + if(current_tick32_zone == previous_count_zone + 1 || (current_tick32_zone == 0 && previous_count_zone == 15)) + { + // The top four bits of the 32-bit tick count have been incremented since count was last written. + _InterlockedCompareExchange(&count, previous_count + 1, previous_count); + current_tick64 = previous_count + 1; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + // Oops, we weren't called often enough, we're stuck + return 0xFFFFFFFF; + } +#endif + inline detail::gettickcount64_t GetTickCount64() + { + static detail::gettickcount64_t gettickcount64impl; + if(gettickcount64impl) + return gettickcount64impl; + + // GetTickCount and GetModuleHandle are not allowed in the Windows Runtime, + // and kernel32 isn't used in Windows Phone. +#if BOOST_PLAT_WINDOWS_RUNTIME + gettickcount64impl = &::boost::detail::win32::detail::GetTickCount64; +#else + detail::farproc_t addr=GetProcAddress( +#if !defined(BOOST_NO_ANSI_APIS) + GetModuleHandleA("KERNEL32.DLL"), +#else + GetModuleHandleW(L"KERNEL32.DLL"), +#endif + "GetTickCount64"); + if(addr) + gettickcount64impl=(detail::gettickcount64_t) addr; + else + gettickcount64impl=&GetTickCount64emulation; +#endif + return gettickcount64impl; + } + + enum event_type { auto_reset_event=false, manual_reset_event=true @@ -351,9 +414,9 @@ namespace boost else { #if BOOST_PLAT_WINDOWS_RUNTIME - detail::win32::WaitForSingleObjectEx(detail::win32::GetCurrentThread(), milliseconds, 0); + ::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0); #else - detail::win32::Sleep(milliseconds); + ::boost::detail::win32::Sleep(milliseconds); #endif } } @@ -367,7 +430,7 @@ namespace boost ~scoped_winrt_thread() { - if (m_completionHandle != detail::win32::invalid_handle_value) + if (m_completionHandle != ::boost::detail::win32::invalid_handle_value) { CloseHandle(m_completionHandle); } @@ -378,7 +441,7 @@ namespace boost handle waitable_handle() const { - BOOST_ASSERT(m_completionHandle != detail::win32::invalid_handle_value); + BOOST_ASSERT(m_completionHandle != ::boost::detail::win32::invalid_handle_value); return m_completionHandle; } diff --git a/src/win32/gettickcount64.cpp b/src/win32/gettickcount64.cpp deleted file mode 100644 index 80859ea1..00000000 --- a/src/win32/gettickcount64.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// (C) Copyright 2014 Vicente J. Botet Escriba -// Use, modification and distribution are subject to the -// Boost Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include - -#include -#include - -#ifdef BOOST_USE_WINDOWS_H -#include -#else -extern "C" -{ -#if BOOST_PLAT_WINDOWS_RUNTIME - __declspec(dllimport) unsigned long long __stdcall GetTickCount64(); -#else - __declspec(dllimport) boost::detail::win32::gettickcount32fn __stdcall GetProcAddress(void *, const char *); - __declspec(dllimport) void * __stdcall GetModuleHandleW(const wchar_t *); -#endif -} -#endif - -namespace boost -{ - namespace detail - { - namespace win32 - { -#if !BOOST_PLAT_WINDOWS_RUNTIME - namespace - { - gettickcount64fn gettickcount64 = NULL; - gettickcount32fn gettickcount32 = NULL; - ::boost::once_flag initfnonce = BOOST_ONCE_INIT; - - void init_gettickcount64() - { - gettickcount64 = reinterpret_cast (::GetProcAddress(::GetModuleHandleW(L"Kernel32.dll"), - "GetTickCount64")); - if (!gettickcount64) gettickcount32 = reinterpret_cast (::GetProcAddress( - ::GetModuleHandleW(L"Kernel32.dll"), "GetTickCount")); - } - } -#endif - - ticks_type GetTickCount64() - { -#if BOOST_PLAT_WINDOWS_RUNTIME - return ::GetTickCount64(); -#else - ::boost::call_once(&init_gettickcount64, initfnonce); - return gettickcount64 ? gettickcount64() : static_cast (gettickcount32()); -#endif - } - } - } -} diff --git a/src/win32/thread.cpp b/src/win32/thread.cpp index d2a272ee..93a75ab7 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -227,7 +227,7 @@ namespace boost // Add a reference since we need to access the completionHandle after the thread_start_function. // This is to handle cases where detach() was called and run_thread_exit_callbacks() would end // up closing the handle. - detail::thread_data_base* const thread_info(reinterpret_cast(parameter)); + ::boost::detail::thread_data_base* const thread_info(reinterpret_cast<::boost::detail::thread_data_base*>(parameter)); intrusive_ptr_add_ref(thread_info); __try @@ -584,7 +584,7 @@ namespace boost LARGE_INTEGER due_time={{0,0}}; if(target_time.relative) { - unsigned long const elapsed_milliseconds=detail::win32::GetTickCount64()-target_time.start; + detail::win32::ticks_type const elapsed_milliseconds=detail::win32::GetTickCount64()()-target_time.start; LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds); LONGLONG const hundred_nanoseconds_in_one_millisecond=10000; diff --git a/src/win32/tss_pe.cpp b/src/win32/tss_pe.cpp index 053ee900..5fd53b6f 100644 --- a/src/win32/tss_pe.cpp +++ b/src/win32/tss_pe.cpp @@ -287,10 +287,10 @@ extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NU } #if (_MSC_VER >= 1500) - if( _pRawDllMainOrig ) - { - return _pRawDllMainOrig(hInstance, dwReason, lpReserved); - } + if( _pRawDllMainOrig ) + { + return _pRawDllMainOrig(hInstance, dwReason, lpReserved); + } #endif return true; }