]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/log/src/dump.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / log / src / dump.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 dump.cpp
9 * \author Andrey Semashev
10 * \date 03.05.2013
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 <ostream>
18#include <boost/cstdint.hpp>
19#include <boost/log/utility/manipulators/dump.hpp>
20#if defined(_MSC_VER) && (defined(BOOST_LOG_USE_SSSE3) || defined(BOOST_LOG_USE_AVX2))
b32b8144 21#include <boost/winapi/dll.hpp>
7c673cae
FG
22#include <intrin.h> // __cpuid
23#endif
24#include <boost/log/detail/header.hpp>
25
26namespace boost {
27
28BOOST_LOG_OPEN_NAMESPACE
29
30namespace aux {
31
32#if defined(BOOST_LOG_USE_SSSE3)
33extern dump_data_char_t dump_data_char_ssse3;
34extern dump_data_wchar_t dump_data_wchar_ssse3;
35#if !defined(BOOST_NO_CXX11_CHAR16_T)
36extern dump_data_char16_t dump_data_char16_ssse3;
37#endif
38#if !defined(BOOST_NO_CXX11_CHAR32_T)
39extern dump_data_char32_t dump_data_char32_ssse3;
40#endif
41#endif
42#if defined(BOOST_LOG_USE_AVX2)
43extern dump_data_char_t dump_data_char_avx2;
44extern dump_data_wchar_t dump_data_wchar_avx2;
45#if !defined(BOOST_NO_CXX11_CHAR16_T)
46extern dump_data_char16_t dump_data_char16_avx2;
47#endif
48#if !defined(BOOST_NO_CXX11_CHAR32_T)
49extern dump_data_char32_t dump_data_char32_avx2;
50#endif
51#endif
52
53enum { stride = 256 };
54
55extern const char g_hex_char_table[2][16] =
56{
57 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' },
58 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }
59};
60
61template< typename CharT >
62void dump_data_generic(const void* data, std::size_t size, std::basic_ostream< CharT >& strm)
63{
64 typedef CharT char_type;
65
66 char_type buf[stride * 3u];
67
68 const char* const char_table = g_hex_char_table[(strm.flags() & std::ios_base::uppercase) != 0];
69 const std::size_t stride_count = size / stride, tail_size = size % stride;
70
71 const uint8_t* p = static_cast< const uint8_t* >(data);
72 char_type* buf_begin = buf + 1u; // skip the first space of the first chunk
73 char_type* buf_end = buf + sizeof(buf) / sizeof(*buf);
74
75 for (std::size_t i = 0; i < stride_count; ++i)
76 {
77 char_type* b = buf;
78 for (unsigned int j = 0; j < stride; ++j, b += 3u, ++p)
79 {
80 uint32_t n = *p;
81 b[0] = static_cast< char_type >(' ');
82 b[1] = static_cast< char_type >(char_table[n >> 4]);
83 b[2] = static_cast< char_type >(char_table[n & 0x0F]);
84 }
85
86 strm.write(buf_begin, buf_end - buf_begin);
87 buf_begin = buf;
88 }
89
90 if (tail_size > 0)
91 {
92 char_type* b = buf;
93 unsigned int i = 0;
94 do
95 {
96 uint32_t n = *p;
97 b[0] = static_cast< char_type >(' ');
98 b[1] = static_cast< char_type >(char_table[n >> 4]);
99 b[2] = static_cast< char_type >(char_table[n & 0x0F]);
100 ++i;
101 ++p;
102 b += 3u;
103 }
104 while (i < tail_size);
105
106 strm.write(buf_begin, b - buf_begin);
107 }
108}
109
110BOOST_LOG_API dump_data_char_t* dump_data_char = &dump_data_generic< char >;
111BOOST_LOG_API dump_data_wchar_t* dump_data_wchar = &dump_data_generic< wchar_t >;
112#if !defined(BOOST_NO_CXX11_CHAR16_T)
113BOOST_LOG_API dump_data_char16_t* dump_data_char16 = &dump_data_generic< char16_t >;
114#endif
115#if !defined(BOOST_NO_CXX11_CHAR32_T)
116BOOST_LOG_API dump_data_char32_t* dump_data_char32 = &dump_data_generic< char32_t >;
117#endif
118
119#if defined(BOOST_LOG_USE_SSSE3) || defined(BOOST_LOG_USE_AVX2)
120
121BOOST_LOG_ANONYMOUS_NAMESPACE {
122
123struct function_pointer_initializer
124{
125 function_pointer_initializer()
126 {
127 // First, let's check for the max supported cpuid function
128 uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
129 cpuid(eax, ebx, ecx, edx);
130
131 const uint32_t max_cpuid_function = eax;
132 if (max_cpuid_function >= 1)
133 {
134 eax = 1;
135 ebx = ecx = edx = 0;
136 cpuid(eax, ebx, ecx, edx);
137
138 // Check for SSSE3 support
139 if (ecx & (1u << 9))
140 enable_ssse3();
141
142#if defined(BOOST_LOG_USE_AVX2)
143 if (max_cpuid_function >= 7)
144 {
145 // To check for AVX2 availability we also need to verify that OS supports it
146 // Check that OSXSAVE is supported by CPU
147 if (ecx & (1u << 27))
148 {
149 // Check that it is used by the OS
150 bool mmstate = false;
151#if defined(__GNUC__)
152 // Get the XFEATURE_ENABLED_MASK register
153 __asm__ __volatile__
154 (
155 "xgetbv\n\t"
156 : "=a" (eax), "=d" (edx)
157 : "c" (0)
158 );
159 mmstate = (eax & 6U) == 6U;
160#elif defined(BOOST_WINDOWS)
161 // MSVC does not have an intrinsic for xgetbv, we have to query OS
b32b8144 162 boost::winapi::HMODULE_ hKernel32 = boost::winapi::GetModuleHandleW(L"kernel32.dll");
7c673cae
FG
163 if (hKernel32)
164 {
165 typedef uint64_t (WINAPI* get_enabled_extended_features_t)(uint64_t);
b32b8144 166 get_enabled_extended_features_t get_enabled_extended_features = (get_enabled_extended_features_t)boost::winapi::get_proc_address(hKernel32, "GetEnabledExtendedFeatures");
7c673cae
FG
167 if (get_enabled_extended_features)
168 {
169 // XSTATE_MASK_LEGACY_SSE | XSTATE_MASK_GSSE == 6
170 mmstate = get_enabled_extended_features(6u) == 6u;
171 }
172 }
173#endif
174
175 if (mmstate)
176 {
177 // Finally, check for AVX2 support in CPU
178 eax = 7;
179 ebx = ecx = edx = 0;
180 cpuid(eax, ebx, ecx, edx);
181
182 if (ebx & (1U << 5))
183 enable_avx2();
184 }
185 }
186 }
187#endif // defined(BOOST_LOG_USE_AVX2)
188 }
189 }
190
191private:
192 static void cpuid(uint32_t& eax, uint32_t& ebx, uint32_t& ecx, uint32_t& edx)
193 {
194#if defined(__GNUC__)
195#if defined(__i386__) && defined(__PIC__) && __PIC__ != 0
196 // We have to backup ebx in 32 bit PIC code because it is reserved by the ABI
197 uint32_t ebx_backup;
198 __asm__ __volatile__
199 (
200 "movl %%ebx, %0\n\t"
201 "movl %1, %%ebx\n\t"
202 "cpuid\n\t"
203 "movl %%ebx, %1\n\t"
204 "movl %0, %%ebx\n\t"
205 : "=m" (ebx_backup), "+m" (ebx), "+a" (eax), "+c" (ecx), "+d" (edx)
206 );
207#else
208 __asm__ __volatile__
209 (
210 "cpuid\n\t"
211 : "+a" (eax), "+b" (ebx), "+c" (ecx), "+d" (edx)
212 );
213#endif
214#elif defined(_MSC_VER)
215 int regs[4] = {};
216 __cpuid(regs, eax);
217 eax = regs[0];
218 ebx = regs[1];
219 ecx = regs[2];
220 edx = regs[3];
221#else
222#error Boost.Log: Unexpected compiler
223#endif
224 }
225
226 static void enable_ssse3()
227 {
228 dump_data_char = &dump_data_char_ssse3;
229 dump_data_wchar = &dump_data_wchar_ssse3;
230#if !defined(BOOST_NO_CXX11_CHAR16_T)
231 dump_data_char16 = &dump_data_char16_ssse3;
232#endif
233#if !defined(BOOST_NO_CXX11_CHAR32_T)
234 dump_data_char32 = &dump_data_char32_ssse3;
235#endif
236 }
237
238#if defined(BOOST_LOG_USE_AVX2)
239 static void enable_avx2()
240 {
241 dump_data_char = &dump_data_char_avx2;
242 dump_data_wchar = &dump_data_wchar_avx2;
243#if !defined(BOOST_NO_CXX11_CHAR16_T)
244 dump_data_char16 = &dump_data_char16_avx2;
245#endif
246#if !defined(BOOST_NO_CXX11_CHAR32_T)
247 dump_data_char32 = &dump_data_char32_avx2;
248#endif
249 }
250#endif // defined(BOOST_LOG_USE_AVX2)
251};
252
253static function_pointer_initializer g_function_pointer_initializer;
254
255} // namespace
256
257#endif // defined(BOOST_LOG_USE_SSSE3) || defined(BOOST_LOG_USE_AVX2)
258
259} // namespace aux
260
261BOOST_LOG_CLOSE_NAMESPACE // namespace log
262
263} // namespace boost
264
265#include <boost/log/detail/footer.hpp>