| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "extensions/browser/api/system_cpu/cpu_info_provider.h" |
| |
| #include <windows.h> |
| #include <winternl.h> |
| |
| #include <memory> |
| |
| #include "base/containers/heap_array.h" |
| #include "base/system/sys_info.h" |
| |
| namespace extensions { |
| |
| namespace { |
| |
| const wchar_t kNtdll[] = L"ntdll.dll"; |
| const char kNtQuerySystemInformationName[] = "NtQuerySystemInformation"; |
| |
| // See MSDN about NtQuerySystemInformation definition. |
| typedef DWORD(WINAPI* NtQuerySystemInformationPF)(DWORD system_info_class, |
| PVOID system_info, |
| ULONG system_info_length, |
| PULONG return_length); |
| |
| } // namespace |
| |
| bool CpuInfoProvider::QueryCpuTimePerProcessor( |
| std::vector<api::system_cpu::ProcessorInfo>* infos) { |
| DCHECK(infos); |
| |
| HMODULE ntdll = GetModuleHandle(kNtdll); |
| CHECK(ntdll != NULL); |
| NtQuerySystemInformationPF NtQuerySystemInformation = |
| reinterpret_cast<NtQuerySystemInformationPF>( |
| ::GetProcAddress(ntdll, kNtQuerySystemInformationName)); |
| |
| CHECK(NtQuerySystemInformation != NULL); |
| |
| int num_of_processors = base::SysInfo::NumberOfProcessors(); |
| auto processor_info = |
| base::HeapArray<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION>::Uninit( |
| num_of_processors); |
| |
| ULONG returned_bytes = 0, |
| bytes = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * |
| num_of_processors; |
| if (!NT_SUCCESS(NtQuerySystemInformation( |
| SystemProcessorPerformanceInformation, processor_info.data(), bytes, |
| &returned_bytes))) { |
| return false; |
| } |
| |
| int returned_num_of_processors = |
| returned_bytes / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); |
| |
| if (returned_num_of_processors != num_of_processors) { |
| return false; |
| } |
| |
| DCHECK_EQ(num_of_processors, static_cast<int>(infos->size())); |
| for (size_t i = 0; i < processor_info.size(); ++i) { |
| double kernel = static_cast<double>(processor_info[i].KernelTime.QuadPart), |
| user = static_cast<double>(processor_info[i].UserTime.QuadPart), |
| idle = static_cast<double>(processor_info[i].IdleTime.QuadPart); |
| |
| // KernelTime needs to be fixed-up, because it includes both idle time and |
| // real kernel time. |
| infos->at(i).usage.kernel = kernel - idle; |
| infos->at(i).usage.user = user; |
| infos->at(i).usage.idle = idle; |
| infos->at(i).usage.total = kernel + user; |
| } |
| |
| return true; |
| } |
| |
| } // namespace extensions |