Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(585)

Side by Side Diff: snapshot/win/system_snapshot_win.cc

Issue 936333004: win: Add implementation of system_snapshot for Windows (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@add-time-win
Patch Set: . Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "snapshot/win/system_snapshot_win.h"
16
17 #include <immintrin.h>
Mark Mentovai 2015/02/27 22:27:42 Just <intrin.h>? I don’t see you using any multime
scottmg 2015/02/28 00:37:32 Done.
18 #include <powrprof.h>
19 #include <windows.h>
20
21 #include <algorithm>
22 #include <vector>
23
24 #include "base/numerics/safe_conversions.h"
25 #include "base/strings/stringprintf.h"
26 #include "base/strings/utf_string_conversions.h"
27 #include "compat/win/processor_power_information.h"
Mark Mentovai 2015/02/27 22:27:42 Things in compat should be treated as system heade
scottmg 2015/02/28 00:37:32 Done.
28
29 namespace crashpad {
30
31 namespace internal {
32
33 SystemSnapshotWin::SystemSnapshotWin()
34 : SystemSnapshot(),
35 os_version_full_(),
36 os_version_build_(),
37 process_reader_(nullptr),
38 os_version_major_(0),
39 os_version_minor_(0),
40 os_version_bugfix_(0),
41 os_server_(false),
42 initialized_() {
43 }
44
45 SystemSnapshotWin::~SystemSnapshotWin() {
46 }
47
48 void SystemSnapshotWin::Initialize(ProcessReaderWin* process_reader) {
49 INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
50
51 process_reader_ = process_reader;
52
53 OSVERSIONINFOEX version_info = {sizeof(version_info)};
54 if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info))) {
Mark Mentovai 2015/02/27 22:27:42 The only concern here is that if the manifest does
scottmg 2015/02/28 00:37:32 Understood. I hunted a bit more and it seems the
55 PLOG(WARNING) << "GetVersionEx";
56 } else {
57 os_version_major_ = version_info.dwMajorVersion;
58 os_version_minor_ = version_info.dwMinorVersion;
59 os_version_bugfix_ = version_info.dwBuildNumber;
60 if (version_info.wServicePackMajor != 0) {
61 os_version_build_ =
62 base::StringPrintf("Service Pack %u", version_info.wServicePackMajor);
63 if (version_info.wServicePackMinor != 0) {
64 os_version_build_ +=
65 base::StringPrintf(".%u", version_info.wServicePackMinor);
66 }
67 }
68 os_server_ = version_info.wProductType != VER_NT_WORKSTATION;
69 // TODO(scottmg): Is there something more we can retrieve here?
70 os_version_full_ = base::StringPrintf("Windows %d.%d.%d",
Mark Mentovai 2015/02/27 22:27:42 I asked if this should be Windows NT or if there w
scottmg 2015/02/28 00:37:32 Switched to using the dwFileOS field.
71 os_version_major_,
72 os_version_minor_,
73 os_version_bugfix_);
74 if (!os_version_build_.empty())
75 os_version_full_ += std::string(" ") + os_version_build_;
76 }
77
78 INITIALIZATION_STATE_SET_VALID(initialized_);
79 }
80
81 CPUArchitecture SystemSnapshotWin::GetCPUArchitecture() const {
82 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
83
84 return process_reader_->Is64Bit() ? kCPUArchitectureX86_64
85 : kCPUArchitectureX86;
86 }
87
88 uint32_t SystemSnapshotWin::CPURevision() const {
89 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
90
91 uint32_t raw = CPUX86Signature();
92 uint32_t stepping = raw & 0xf;
Mark Mentovai 2015/02/27 22:27:42 If you can stick this into a uint8_t… Same with 8
scottmg 2015/02/28 00:37:32 Done.
93 uint32_t model = (raw & 0xf0) >> 4;
94 uint32_t family = (raw & 0xf00) >> 8;
95 uint32_t extended_model = (raw & 0xf0000) >> 16;
96 uint32_t extended_family = (raw & 0xff00000) >> 20;
97
98 if (family < 15) {
99 // For families before 15, these are simply reserved bits so ignore them.
100 extended_model = 0;
Mark Mentovai 2015/02/27 22:27:42 extended_model is valid when family is 15 or 6.
scottmg 2015/02/28 00:37:32 Done.
101 extended_family = 0;
Mark Mentovai 2015/02/27 22:27:42 but this is correct for extended_family. See Inte
scottmg 2015/02/28 00:37:32 Oops, that'll teach me to use Wikipedia! http://en
102 }
103
104 uint32_t adjusted_family = family + extended_family;
105 uint32_t adjusted_model = model + (extended_model << 4);
106 return (adjusted_family << 16) | (adjusted_model << 8) | stepping;
107 }
108
109 uint8_t SystemSnapshotWin::CPUCount() const {
110 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
111
112 SYSTEM_INFO system_info;
113 GetSystemInfo(&system_info);
114 if (!base::IsValueInRangeForNumericType<uint8_t>(
115 system_info.dwNumberOfProcessors)) {
116 LOG(WARNING) << "dwNumberOfProcessors exceeds uint8_t storage";
117 }
118 return base::saturated_cast<uint8_t>(system_info.dwNumberOfProcessors);
119 }
120
121 std::string SystemSnapshotWin::CPUVendor() const {
122 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
123
124 int cpu_info[4];
125 __cpuid(cpu_info, 0);
126 char vendor[12];
127 *reinterpret_cast<int*>(vendor) = cpu_info[1];
128 *reinterpret_cast<int*>(vendor + 4) = cpu_info[3];
129 *reinterpret_cast<int*>(vendor + 8) = cpu_info[2];
130 return std::string(vendor, sizeof(vendor));
131 }
132
133 void SystemSnapshotWin::CPUFrequency(uint64_t* current_hz,
134 uint64_t* max_hz) const {
135 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
136
137 int num_cpus = CPUCount();
138 DCHECK_GT(num_cpus, 0);
139 std::vector<PROCESSOR_POWER_INFORMATION> info(num_cpus);
140 if (CallNtPowerInformation(ProcessorInformation,
141 nullptr,
142 0,
143 &info[0],
144 sizeof(PROCESSOR_POWER_INFORMATION) * num_cpus) !=
145 0) {
146 *current_hz = 0;
147 *max_hz = 0;
148 return;
149 }
150 const uint64_t kMhzToHz = static_cast<uint64_t>(1E6);
151 *current_hz = std::max_element(info.begin(),
Mark Mentovai 2015/02/27 22:27:42 #include <utility>
scottmg 2015/02/28 00:37:32 Done.
152 info.end(),
153 [](const PROCESSOR_POWER_INFORMATION& a,
154 const PROCESSOR_POWER_INFORMATION& b) {
155 return a.CurrentMhz < b.CurrentMhz;
156 })->CurrentMhz *
157 kMhzToHz;
158 *max_hz = std::max_element(info.begin(),
159 info.end(),
160 [](const PROCESSOR_POWER_INFORMATION& a,
161 const PROCESSOR_POWER_INFORMATION& b) {
162 return a.MaxMhz < b.MaxMhz;
163 })->MaxMhz *
164 kMhzToHz;
165 }
166
167 uint32_t SystemSnapshotWin::CPUX86Signature() const {
168 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
169
170 int cpu_info[4];
171 // We will never run on any processors that don't support at least function 1.
172 __cpuid(cpu_info, 1);
173 return cpu_info[0];
174 }
175
176 uint64_t SystemSnapshotWin::CPUX86Features() const {
177 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
178
179 int cpu_info[4];
180 // We will never run on any processors that don't support at least function 1.
181 __cpuid(cpu_info, 1);
182 return (static_cast<uint64_t>(cpu_info[2]) << 32) |
183 static_cast<uint64_t>(cpu_info[3]);
184 }
185
186 uint64_t SystemSnapshotWin::CPUX86ExtendedFeatures() const {
187 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
188
189 int cpu_info[4];
190 // We will never run on any processors that don't support at least extended
191 // function 1.
192 __cpuid(cpu_info, 0x80000001);
193 return (static_cast<uint64_t>(cpu_info[2]) << 32) |
194 static_cast<uint64_t>(cpu_info[3]);
195 }
196
197 uint32_t SystemSnapshotWin::CPUX86Leaf7Features() const {
198 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
199
200 int cpu_info[4];
201
202 // Make sure leaf 7 can be called.
203 __cpuid(cpu_info, 0);
204 if (cpu_info[0] < 7)
205 return 0;
206
207 __cpuidex(cpu_info, 7, 0);
208 return cpu_info[1];
209 }
210
211 bool SystemSnapshotWin::CPUX86SupportsDAZ() const {
212 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
213
214 // The correct way to check for denormals-as-zeros (DAZ) support is to examine
215 // mxcsr mask, which can be done with fxsave. See Intel Software Developer's
216 // Manual, Volume 1: Basic Architecture (253665-051), 11.6.3 "Checking for the
217 // DAZ Flag in the MXCSR Register". Note that since this function tests for
218 // DAZ support in the CPU, it checks the mxcsr mask. Testing mxcsr would
219 // indicate whether DAZ is actually enabled, which is a per-thread context
220 // concern.
221
222 // Test for fxsave support.
223 uint64_t features = CPUX86Features();
224 if (!(features & (UINT64_C(1) << 24))) {
225 return false;
226 }
227
228 // Call fxsave.
229 __declspec(align(16)) uint32_t extended_registers[128];
230 _fxsave(&extended_registers);
231 uint32_t mxcsr_mask = extended_registers[7];
232
233 // Test the DAZ bit.
234 return mxcsr_mask & (1 << 6);
235 }
236
237 SystemSnapshot::OperatingSystem SystemSnapshotWin::GetOperatingSystem() const {
238 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
239 return kOperatingSystemWindows;
240 }
241
242 bool SystemSnapshotWin::OSServer() const {
243 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
244 return os_server_;
245 }
246
247 void SystemSnapshotWin::OSVersion(int* major,
248 int* minor,
249 int* bugfix,
250 std::string* build) const {
251 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
252 *major = os_version_major_;
253 *minor = os_version_minor_;
254 *bugfix = os_version_bugfix_;
255 build->assign(os_version_build_);
256 }
257
258 std::string SystemSnapshotWin::OSVersionFull() const {
259 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
260 return os_version_full_;
261 }
262
263 std::string SystemSnapshotWin::MachineDescription() const {
264 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
265 // TODO(scottmg): Not sure if there's anything sensible to put here.
266 return std::string();
267 }
268
269 bool SystemSnapshotWin::NXEnabled() const {
270 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
271 return IsProcessorFeaturePresent(PF_NX_ENABLED);
272 }
273
274 void SystemSnapshotWin::TimeZone(DaylightSavingTimeStatus* dst_status,
275 int* standard_offset_seconds,
276 int* daylight_offset_seconds,
277 std::string* standard_name,
278 std::string* daylight_name) const {
279 // This returns the current time zone status rather than the status at the
280 // time of the snapshot. This differs from the Mac implementation.
281 TIME_ZONE_INFORMATION time_zone_information;
282 *dst_status = static_cast<DaylightSavingTimeStatus>(
283 GetTimeZoneInformation(&time_zone_information));
284 *standard_offset_seconds =
285 (time_zone_information.Bias + time_zone_information.StandardBias) * -60;
286 *daylight_offset_seconds =
287 (time_zone_information.Bias + time_zone_information.DaylightBias) * -60;
288 *standard_name = base::UTF16ToUTF8(time_zone_information.StandardName);
289 *daylight_name = base::UTF16ToUTF8(time_zone_information.DaylightName);
290 }
291
292 } // namespace internal
293 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698