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

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>
18 #include <powrprof.h>
19 #include <windows.h>
20
21 #include <vector>
22
23 #include "base/numerics/safe_conversions.h"
24 #include "base/strings/stringprintf.h"
25 #include "base/strings/utf_string_conversions.h"
26
27 namespace crashpad {
28
29 namespace internal {
30
31 SystemSnapshotWin::SystemSnapshotWin()
32 : SystemSnapshot(),
33 os_version_full_(),
34 os_version_build_(),
35 process_reader_(nullptr),
36 os_version_major_(0),
37 os_version_minor_(0),
38 os_version_bugfix_(0),
39 os_server_(false),
40 initialized_() {
41 }
42
43 SystemSnapshotWin::~SystemSnapshotWin() {
44 }
45
46 void SystemSnapshotWin::Initialize(ProcessReaderWin* process_reader) {
47 INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
48
49 process_reader_ = process_reader;
50
51 OSVERSIONINFOEX version_info = {sizeof(version_info)};
52 if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info))) {
Mark Mentovai 2015/02/20 18:58:52 Looking at the docs for GetVersionEx(), I’m learni
scottmg 2015/02/20 22:00:44 GetVersionEx works as long as the manifest is set
53 PLOG(WARNING) << "GetVersionEx";
54 }
55 os_version_major_ = version_info.dwMajorVersion;
56 os_version_minor_ = version_info.dwMinorVersion;
57 os_version_bugfix_ = version_info.dwBuildNumber;
58 os_version_build_ =
59 base::StringPrintf("Service Pack %d", version_info.wServicePackMajor);
Mark Mentovai 2015/02/20 18:58:52 If GetVersionEx() failed, you shouldn’t do this.
scottmg 2015/02/20 22:00:45 Done.
60 if (version_info.wServicePackMinor != 0) {
61 os_version_build_ +=
62 base::StringPrintf(".%d", version_info.wServicePackMinor);
63 }
64 os_server_ = version_info.wProductType != VER_NT_WORKSTATION;
65 // TODO(scottmg): Is there something more we can retrieve here?
66 os_version_full_ = base::StringPrintf("Windows %d.%d.%d %s",
Mark Mentovai 2015/02/20 18:58:52 Should this be Windows NT instead of Windows? Avoi
scottmg 2015/02/20 22:00:45 Changed in Service Pack, but not here. They're pri
67 os_version_major_,
68 os_version_minor_,
69 os_version_bugfix_,
70 os_version_build_.c_str());
71
72 INITIALIZATION_STATE_SET_VALID(initialized_);
73 }
74
75 CPUArchitecture SystemSnapshotWin::GetCPUArchitecture() const {
76 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
77
78 return process_reader_->Is64Bit() ? kCPUArchitectureX86_64
79 : kCPUArchitectureX86;
80 }
81
82 uint32_t SystemSnapshotWin::CPURevision() const {
83 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
84
85 // TODO(scottmg): How does this differ from CPUX86Signature below?
Mark Mentovai 2015/02/20 18:58:52 CPURevision() is not CPU architecture-specific, bu
scottmg 2015/02/20 22:00:45 Thanks for the explanation. Done.
86 CHECK(false) << "TODO: family << 16 | model << 8 | stepping";
87 return 0;
88 }
89
90 uint8_t SystemSnapshotWin::CPUCount() const {
91 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
92
93 SYSTEM_INFO system_info;
94 GetSystemInfo(&system_info);
95 return base::saturated_cast<uint8_t>(system_info.dwNumberOfProcessors);
Mark Mentovai 2015/02/20 18:58:52 Log a warning if this saturates.
scottmg 2015/02/20 22:00:45 Done.
96 }
97
98 std::string SystemSnapshotWin::CPUVendor() const {
99 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
100
101 int cpu_info[4];
102 __cpuid(cpu_info, 0);
103 char vendor[13] = {0};
104 *reinterpret_cast<int*>(vendor) = cpu_info[1];
105 *reinterpret_cast<int*>(vendor + 4) = cpu_info[3];
106 *reinterpret_cast<int*>(vendor + 8) = cpu_info[2];
107 return vendor;
Mark Mentovai 2015/02/20 18:58:52 std::string(vendor, 12) or make vendor be size 12
scottmg 2015/02/20 22:00:45 Done.
108 }
109
110 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa373184.aspx:
111 // "Note that this structure definition was accidentally omitted from WinNT.h."
Mark Mentovai 2015/02/20 18:58:52 Belongs in compat then?
scottmg 2015/02/20 22:00:45 Done.
112 struct PROCESSOR_POWER_INFORMATION {
113 ULONG Number;
114 ULONG MaxMhz;
115 ULONG CurrentMhz;
116 ULONG MhzLimit;
117 ULONG MaxIdleState;
118 ULONG CurrentIdleState;
119 };
120
121 void SystemSnapshotWin::CPUFrequency(uint64_t* current_hz,
122 uint64_t* max_hz) const {
123 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
124
125 int num_cpus = CPUCount();
126 std::vector<PROCESSOR_POWER_INFORMATION> info(num_cpus);
127 if (CallNtPowerInformation(ProcessorInformation,
128 nullptr,
129 0,
130 &info[0],
131 sizeof(PROCESSOR_POWER_INFORMATION) * num_cpus) !=
132 0) {
133 *current_hz = 0;
134 *max_hz = 0;
135 return;
136 }
137 // TODO(scottmg): Return all? Average? Current?
Mark Mentovai 2015/02/20 18:58:52 Good question. Max of current and max of max?
scottmg 2015/02/20 22:00:45 Done.
138 const uint64_t kMhzToHz = 1000000;
Mark Mentovai 2015/02/20 18:58:52 1E6
scottmg 2015/02/20 22:00:45 Done.
139 *current_hz = info[0].CurrentMhz * kMhzToHz;
140 *max_hz = info[0].MaxMhz * kMhzToHz;
141 }
142
143 uint32_t SystemSnapshotWin::CPUX86Signature() const {
144 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
145
146 int cpu_info[4];
147 // We will never run on any processors that don't support at least function 1.
148 __cpuid(cpu_info, 1);
149 return cpu_info[0];
150 }
151
152 uint64_t SystemSnapshotWin::CPUX86Features() const {
153 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
154
155 int cpu_info[4];
156 // We will never run on any processors that don't support at least function 1.
157 __cpuid(cpu_info, 1);
158 return (static_cast<uint64_t>(cpu_info[2]) << 32) |
159 static_cast<uint64_t>(cpu_info[3]);
160 }
161
162 uint64_t SystemSnapshotWin::CPUX86ExtendedFeatures() const {
163 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
164
165 int cpu_info[4];
166 // We will never run on any processors that don't support at least extended
167 // function 1.
168 __cpuid(cpu_info, 0x80000001);
169 return (static_cast<uint64_t>(cpu_info[2]) << 32) |
170 static_cast<uint64_t>(cpu_info[3]);
171 return (static_cast<uint64_t>(cpu_info[2]) << 32) |
Mark Mentovai 2015/02/20 18:58:52 You already returned this.
scottmg 2015/02/20 22:00:45 Hm, maybe I should look into enabling the unreacha
172 static_cast<uint64_t>(cpu_info[3]);
173 }
174
175 uint32_t SystemSnapshotWin::CPUX86Leaf7Features() const {
176 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
177
178 int cpu_info[4];
179
180 // Make sure leaf 7 can be called.
181 __cpuid(cpu_info, 0);
182 if (cpu_info[0] < 7)
183 return 0;
184
185 __cpuidex(cpu_info, 7, 0);
186 return cpu_info[1];
187 }
188
189 bool SystemSnapshotWin::CPUX86SupportsDAZ() const {
190 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
191
192 // The correct way to check for denormals-as-zeros (DAZ) support is to examine
193 // mxcsr mask, which can be done with fxsave. See Intel Software Developer's
194 // Manual, Volume 1: Basic Architecture (253665-051), 11.6.3 "Checking for the
195 // DAZ Flag in the MXCSR Register". Note that since this function tests for
196 // DAZ support in the CPU, it checks the mxcsr mask. Testing mxcsr would
197 // indicate whether DAZ is actually enabled, which is a per-thread context
198 // concern.
199
200 // Test for fxsave support.
201 uint64_t features = CPUX86Features();
202 if (!(features & (UINT64_C(1) << 24))) {
203 return false;
204 }
205
206 // Call fxsave.
207 __declspec(align(16)) uint32_t extended_registers[128];
208 _fxsave(&extended_registers);
209 uint32_t mxcsr_mask = extended_registers[7];
210
211 // Test the DAZ bit.
212 return mxcsr_mask & (1 << 6);
213 }
214
215 SystemSnapshot::OperatingSystem SystemSnapshotWin::GetOperatingSystem() const {
216 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
217 return kOperatingSystemWindows;
218 }
219
220 bool SystemSnapshotWin::OSServer() const {
221 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
222 return os_server_;
223 }
224
225 void SystemSnapshotWin::OSVersion(int* major,
226 int* minor,
227 int* bugfix,
228 std::string* build) const {
229 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
230 *major = os_version_major_;
231 *minor = os_version_minor_;
232 *bugfix = os_version_bugfix_;
233 build->assign(os_version_build_);
234 }
235
236 std::string SystemSnapshotWin::OSVersionFull() const {
237 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
238 return os_version_full_;
239 }
240
241 std::string SystemSnapshotWin::MachineDescription() const {
242 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
243 // TODO(scottmg): Not sure if there's anything sensible to put here.
244 return "";
Mark Mentovai 2015/02/20 18:58:52 std::string() (I was reminded of this during the r
scottmg 2015/02/20 22:00:45 Done.
245 }
246
247 bool SystemSnapshotWin::NXEnabled() const {
248 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
249 return IsProcessorFeaturePresent(PF_NX_ENABLED);
250 }
251
252 void SystemSnapshotWin::TimeZone(DaylightSavingTimeStatus* dst_status,
253 int* standard_offset_seconds,
254 int* daylight_offset_seconds,
255 std::string* standard_name,
256 std::string* daylight_name) const {
257 TIME_ZONE_INFORMATION time_zone_information;
Mark Mentovai 2015/02/20 18:58:52 Comment that this returns the current time zone st
scottmg 2015/02/20 22:00:45 Done.
258 *dst_status = static_cast<DaylightSavingTimeStatus>(
259 GetTimeZoneInformation(&time_zone_information));
260 *standard_offset_seconds =
261 (time_zone_information.Bias + time_zone_information.StandardBias) * -60;
262 *daylight_offset_seconds =
263 (time_zone_information.Bias + time_zone_information.DaylightBias) * -60;
264 *standard_name = base::UTF16ToUTF8(time_zone_information.StandardName);
265 *daylight_name = base::UTF16ToUTF8(time_zone_information.DaylightName);
266 }
267
268 } // namespace internal
269 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698