1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/api/system_cpu/cpu_info_provider.h"
6
7#include <windows.h>
8#include <winternl.h>
9
10#include "base/sys_info.h"
11
12namespace extensions {
13
14namespace {
15
16const wchar_t kNtdll[] = L"ntdll.dll";
17const char kNtQuerySystemInformationName[] = "NtQuerySystemInformation";
18
19// See MSDN about NtQuerySystemInformation definition.
20typedef DWORD (WINAPI *NtQuerySystemInformationPF)(DWORD system_info_class,
21                                                   PVOID system_info,
22                                                   ULONG system_info_length,
23                                                   PULONG return_length);
24
25}  // namespace
26
27bool CpuInfoProvider::QueryCpuTimePerProcessor(
28    std::vector<linked_ptr<api::system_cpu::ProcessorInfo> >* infos) {
29  DCHECK(infos);
30
31  HMODULE ntdll = GetModuleHandle(kNtdll);
32  CHECK(ntdll != NULL);
33  NtQuerySystemInformationPF NtQuerySystemInformation =
34      reinterpret_cast<NtQuerySystemInformationPF>(
35          ::GetProcAddress(ntdll, kNtQuerySystemInformationName));
36
37  CHECK(NtQuerySystemInformation != NULL);
38
39  int num_of_processors = base::SysInfo::NumberOfProcessors();
40  scoped_ptr<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[]> processor_info(
41      new SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[num_of_processors]);
42
43  ULONG returned_bytes = 0, bytes =
44      sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * num_of_processors;
45  if (!NT_SUCCESS(NtQuerySystemInformation(
46          SystemProcessorPerformanceInformation,
47          processor_info.get(), bytes, &returned_bytes)))
48    return false;
49
50  int returned_num_of_processors =
51      returned_bytes / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
52
53  if (returned_num_of_processors != num_of_processors)
54    return false;
55
56  DCHECK_EQ(num_of_processors, static_cast<int>(infos->size()));
57  for (int i = 0; i < returned_num_of_processors; ++i) {
58    double kernel = static_cast<double>(processor_info[i].KernelTime.QuadPart),
59        user = static_cast<double>(processor_info[i].UserTime.QuadPart),
60        idle = static_cast<double>(processor_info[i].IdleTime.QuadPart);
61
62    // KernelTime needs to be fixed-up, because it includes both idle time and
63    // real kernel time.
64    infos->at(i)->usage.kernel = kernel - idle;
65    infos->at(i)->usage.user = user;
66    infos->at(i)->usage.idle = idle;
67    infos->at(i)->usage.total = kernel + user;
68  }
69
70  return true;
71}
72
73}  // namespace extensions
74