]> git.proxmox.com Git - ceph.git/blame - 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
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 {
92f5a8d4 165 typedef uint64_t (BOOST_WINAPI_WINAPI_CC* 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__)
92f5a8d4
TL
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;
7c673cae
FG
200 __asm__ __volatile__
201 (
92f5a8d4 202 "xchgq %%rbx, %0\n\t"
7c673cae 203 "cpuid\n\t"
92f5a8d4
TL
204 "xchgq %%rbx, %0\n\t"
205 : "+DS" (rbx), "+a" (eax), "+c" (ecx), "+d" (edx)
7c673cae 206 );
92f5a8d4
TL
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__)
7c673cae
FG
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
263static 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
271BOOST_LOG_CLOSE_NAMESPACE // namespace log
272
273} // namespace boost
274
275#include <boost/log/detail/footer.hpp>