]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/log/src/timestamp.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / log / src / timestamp.cpp
CommitLineData
7c673cae
FG
1/*
2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
6 */
7/*!
8 * \file timestamp.cpp
9 * \author Andrey Semashev
10 * \date 31.07.2011
11 *
12 * \brief This header is the Boost.Log library implementation, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
14 */
15
16#include <boost/log/detail/config.hpp>
17#include <boost/log/detail/timestamp.hpp>
18
19#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
20#if !defined(BOOST_LOG_NO_THREADS)
21#include <boost/memory_order.hpp>
22#include <boost/atomic/atomic.hpp>
23#endif
b32b8144
FG
24#include <boost/winapi/dll.hpp>
25#include <boost/winapi/time.hpp>
7c673cae
FG
26#else
27#include <unistd.h> // for config macros
28#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
29#include <mach/mach_time.h>
30#include <mach/kern_return.h>
31#include <boost/log/utility/once_block.hpp>
32#include <boost/system/error_code.hpp>
33#endif
34#include <time.h>
35#include <errno.h>
36#include <boost/throw_exception.hpp>
37#include <boost/log/exceptions.hpp>
38#endif
39#include <boost/log/detail/header.hpp>
40
41namespace boost {
42
43BOOST_LOG_OPEN_NAMESPACE
44
45namespace aux {
46
47#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
48
49#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
50
51// Directly use API from Vista and later
b32b8144 52BOOST_LOG_API get_tick_count_t get_tick_count = &boost::winapi::GetTickCount64;
7c673cae
FG
53
54#else // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
55
56BOOST_LOG_ANONYMOUS_NAMESPACE {
57
58// Zero-initialized initially
59#if !defined(BOOST_LOG_NO_THREADS)
b32b8144 60BOOST_ALIGNMENT(BOOST_LOG_CPU_CACHE_LINE_SIZE) static boost::atomic< uint64_t > g_ticks;
7c673cae 61#else
b32b8144 62BOOST_ALIGNMENT(BOOST_LOG_CPU_CACHE_LINE_SIZE) static uint64_t g_ticks;
7c673cae
FG
63#endif
64
65//! Artifical implementation of GetTickCount64
66uint64_t WINAPI get_tick_count64()
67{
68#if !defined(BOOST_LOG_NO_THREADS)
69 uint64_t old_state = g_ticks.load(boost::memory_order_acquire);
70#else
71 uint64_t old_state = g_ticks;
72#endif
73
b32b8144 74 uint32_t new_ticks = boost::winapi::GetTickCount();
7c673cae
FG
75
76 uint32_t old_ticks = static_cast< uint32_t >(old_state & UINT64_C(0x00000000ffffffff));
77 uint64_t new_state = ((old_state & UINT64_C(0xffffffff00000000)) + (static_cast< uint64_t >(new_ticks < old_ticks) << 32)) | static_cast< uint64_t >(new_ticks);
78
79#if !defined(BOOST_LOG_NO_THREADS)
80 g_ticks.store(new_state, boost::memory_order_release);
81#else
82 g_ticks = new_state;
83#endif
84
85 return new_state;
86}
87
88uint64_t WINAPI get_tick_count_init()
89{
b32b8144 90 boost::winapi::HMODULE_ hKernel32 = boost::winapi::GetModuleHandleW(L"kernel32.dll");
7c673cae
FG
91 if (hKernel32)
92 {
b32b8144 93 get_tick_count_t p = (get_tick_count_t)boost::winapi::get_proc_address(hKernel32, "GetTickCount64");
7c673cae
FG
94 if (p)
95 {
96 // Use native API
97 get_tick_count = p;
98 return p();
99 }
100 }
101
102 // No native API available
103 get_tick_count = &get_tick_count64;
104 return get_tick_count64();
105}
106
107} // namespace
108
109BOOST_LOG_API get_tick_count_t get_tick_count = &get_tick_count_init;
110
111#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
112
113#elif (defined(_POSIX_TIMERS) && (_POSIX_TIMERS+0) > 0) /* POSIX timers supported */ \
114 || defined(__GNU__) || defined(__OpenBSD__) || defined(__CloudABI__) /* GNU Hurd, OpenBSD and Nuxi CloudABI don't support POSIX timers fully but do provide clock_gettime() */
115
116BOOST_LOG_API int64_t duration::milliseconds() const
117{
118 // Timestamps are always in nanoseconds
119 return m_ticks / INT64_C(1000000);
120}
121
122BOOST_LOG_ANONYMOUS_NAMESPACE {
123
124/*!
125 * \c get_timestamp implementation based on POSIX realtime clock.
126 * Note that this implementation is only used as a last resort since
127 * this timer can be manually set and may jump due to DST change.
128 */
129timestamp get_timestamp_realtime_clock()
130{
131 timespec ts;
132 if (BOOST_UNLIKELY(clock_gettime(CLOCK_REALTIME, &ts) != 0))
133 {
134 const int err = errno;
135 BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to acquire current time", (err));
136 }
137
138 return timestamp(static_cast< uint64_t >(ts.tv_sec) * UINT64_C(1000000000) + ts.tv_nsec);
139}
140
141# if defined(_POSIX_MONOTONIC_CLOCK)
142
143//! \c get_timestamp implementation based on POSIX monotonic clock
144timestamp get_timestamp_monotonic_clock()
145{
146 timespec ts;
147 if (BOOST_UNLIKELY(clock_gettime(CLOCK_MONOTONIC, &ts) != 0))
148 {
149 const int err = errno;
150 if (err == EINVAL)
151 {
152 // The current platform does not support monotonic timer.
153 // Fall back to realtime clock, which is not exactly what we need
154 // but is better than nothing.
155 get_timestamp = &get_timestamp_realtime_clock;
156 return get_timestamp_realtime_clock();
157 }
158 BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to acquire current time", (err));
159 }
160
161 return timestamp(static_cast< uint64_t >(ts.tv_sec) * UINT64_C(1000000000) + ts.tv_nsec);
162}
163
164# define BOOST_LOG_DEFAULT_GET_TIMESTAMP get_timestamp_monotonic_clock
165
166# else // if defined(_POSIX_MONOTONIC_CLOCK)
167# define BOOST_LOG_DEFAULT_GET_TIMESTAMP get_timestamp_realtime_clock
168# endif // if defined(_POSIX_MONOTONIC_CLOCK)
169
170} // namespace
171
172// Use POSIX API
173BOOST_LOG_API get_timestamp_t get_timestamp = &BOOST_LOG_DEFAULT_GET_TIMESTAMP;
174
175# undef BOOST_LOG_DEFAULT_GET_TIMESTAMP
176
177#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
178
179BOOST_LOG_API int64_t duration::milliseconds() const
180{
181 static mach_timebase_info_data_t timebase_info = {};
182 BOOST_LOG_ONCE_BLOCK()
183 {
184 kern_return_t err = mach_timebase_info(&timebase_info);
185 if (err != KERN_SUCCESS)
186 {
187 BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to initialize timebase info", (boost::system::errc::not_supported));
188 }
189 }
190
191 // Often the timebase rational equals 1, we can optimize for this case
192 if (timebase_info.numer == timebase_info.denom)
193 {
194 // Timestamps are in nanoseconds
195 return m_ticks / INT64_C(1000000);
196 }
197 else
198 {
199 return (m_ticks * timebase_info.numer) / (INT64_C(1000000) * timebase_info.denom);
200 }
201}
202
203BOOST_LOG_ANONYMOUS_NAMESPACE {
204
205//! \c get_timestamp implementation based on MacOS X absolute time
206timestamp get_timestamp_mach()
207{
208 return timestamp(mach_absolute_time());
209}
210
211} // namespace
212
213// Use MacOS X API
214BOOST_LOG_API get_timestamp_t get_timestamp = &get_timestamp_mach;
215
216#else
217
218# error Boost.Log: Timestamp generation is not supported for your platform
219
220#endif
221
222} // namespace aux
223
224BOOST_LOG_CLOSE_NAMESPACE // namespace log
225
226} // namespace boost
227
228#include <boost/log/detail/footer.hpp>