]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/log/src/dump.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / log / src / dump.cpp
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))
21 #include <boost/winapi/dll.hpp>
22 #include <intrin.h> // __cpuid
23 #endif
24 #include <boost/log/detail/header.hpp>
25
26 namespace boost {
27
28 BOOST_LOG_OPEN_NAMESPACE
29
30 namespace aux {
31
32 #if defined(BOOST_LOG_USE_SSSE3)
33 extern dump_data_char_t dump_data_char_ssse3;
34 extern dump_data_wchar_t dump_data_wchar_ssse3;
35 #if !defined(BOOST_NO_CXX11_CHAR16_T)
36 extern dump_data_char16_t dump_data_char16_ssse3;
37 #endif
38 #if !defined(BOOST_NO_CXX11_CHAR32_T)
39 extern dump_data_char32_t dump_data_char32_ssse3;
40 #endif
41 #endif
42 #if defined(BOOST_LOG_USE_AVX2)
43 extern dump_data_char_t dump_data_char_avx2;
44 extern dump_data_wchar_t dump_data_wchar_avx2;
45 #if !defined(BOOST_NO_CXX11_CHAR16_T)
46 extern dump_data_char16_t dump_data_char16_avx2;
47 #endif
48 #if !defined(BOOST_NO_CXX11_CHAR32_T)
49 extern dump_data_char32_t dump_data_char32_avx2;
50 #endif
51 #endif
52
53 enum { stride = 256 };
54
55 extern 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
61 template< typename CharT >
62 void 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
110 BOOST_LOG_API dump_data_char_t* dump_data_char = &dump_data_generic< char >;
111 BOOST_LOG_API dump_data_wchar_t* dump_data_wchar = &dump_data_generic< wchar_t >;
112 #if !defined(BOOST_NO_CXX11_CHAR16_T)
113 BOOST_LOG_API dump_data_char16_t* dump_data_char16 = &dump_data_generic< char16_t >;
114 #endif
115 #if !defined(BOOST_NO_CXX11_CHAR32_T)
116 BOOST_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
121 BOOST_LOG_ANONYMOUS_NAMESPACE {
122
123 struct 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
162 boost::winapi::HMODULE_ hKernel32 = boost::winapi::GetModuleHandleW(L"kernel32.dll");
163 if (hKernel32)
164 {
165 typedef uint64_t (BOOST_WINAPI_WINAPI_CC* get_enabled_extended_features_t)(uint64_t);
166 get_enabled_extended_features_t get_enabled_extended_features = (get_enabled_extended_features_t)boost::winapi::get_proc_address(hKernel32, "GetEnabledExtendedFeatures");
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
191 private:
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(__VXWORKS__)) && (defined(__PIC__) || defined(__PIE__)) && !(defined(__clang__) || (defined(BOOST_GCC) && BOOST_GCC >= 50100))
196 // Unless the compiler can do it automatically, we have to backup ebx in 32-bit PIC/PIE code because it is reserved by the ABI.
197 // For VxWorks ebx is reserved on 64-bit as well.
198 #if defined(__x86_64__)
199 uint64_t rbx = ebx;
200 __asm__ __volatile__
201 (
202 "xchgq %%rbx, %0\n\t"
203 "cpuid\n\t"
204 "xchgq %%rbx, %0\n\t"
205 : "+DS" (rbx), "+a" (eax), "+c" (ecx), "+d" (edx)
206 );
207 ebx = static_cast< uint32_t >(rbx);
208 #else // defined(__x86_64__)
209 __asm__ __volatile__
210 (
211 "xchgl %%ebx, %0\n\t"
212 "cpuid\n\t"
213 "xchgl %%ebx, %0\n\t"
214 : "+DS" (ebx), "+a" (eax), "+c" (ecx), "+d" (edx)
215 );
216 #endif // defined(__x86_64__)
217 #else
218 __asm__ __volatile__
219 (
220 "cpuid\n\t"
221 : "+a" (eax), "+b" (ebx), "+c" (ecx), "+d" (edx)
222 );
223 #endif
224 #elif defined(_MSC_VER)
225 int regs[4] = {};
226 __cpuid(regs, eax);
227 eax = regs[0];
228 ebx = regs[1];
229 ecx = regs[2];
230 edx = regs[3];
231 #else
232 #error Boost.Log: Unexpected compiler
233 #endif
234 }
235
236 static void enable_ssse3()
237 {
238 dump_data_char = &dump_data_char_ssse3;
239 dump_data_wchar = &dump_data_wchar_ssse3;
240 #if !defined(BOOST_NO_CXX11_CHAR16_T)
241 dump_data_char16 = &dump_data_char16_ssse3;
242 #endif
243 #if !defined(BOOST_NO_CXX11_CHAR32_T)
244 dump_data_char32 = &dump_data_char32_ssse3;
245 #endif
246 }
247
248 #if defined(BOOST_LOG_USE_AVX2)
249 static void enable_avx2()
250 {
251 dump_data_char = &dump_data_char_avx2;
252 dump_data_wchar = &dump_data_wchar_avx2;
253 #if !defined(BOOST_NO_CXX11_CHAR16_T)
254 dump_data_char16 = &dump_data_char16_avx2;
255 #endif
256 #if !defined(BOOST_NO_CXX11_CHAR32_T)
257 dump_data_char32 = &dump_data_char32_avx2;
258 #endif
259 }
260 #endif // defined(BOOST_LOG_USE_AVX2)
261 };
262
263 static function_pointer_initializer g_function_pointer_initializer;
264
265 } // namespace
266
267 #endif // defined(BOOST_LOG_USE_SSSE3) || defined(BOOST_LOG_USE_AVX2)
268
269 } // namespace aux
270
271 BOOST_LOG_CLOSE_NAMESPACE // namespace log
272
273 } // namespace boost
274
275 #include <boost/log/detail/footer.hpp>