1a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin/*
2a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *
4a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  Use of this source code is governed by a BSD-style license
5a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  that can be found in the LICENSE file in the root of the source
6a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  tree. An additional intellectual property rights grant can be found
7a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  in the file PATENTS.  All contributing project authors may
8a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  be found in the AUTHORS file in the root of the source tree.
9a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin */
10a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
11a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "cpu_win.h"
12a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
13a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#define _WIN32_DCOM
14a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
15a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <assert.h>
16a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <iostream>
17a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <Wbemidl.h>
18a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
19a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#pragma comment(lib, "wbemuuid.lib")
20a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
21a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "condition_variable_wrapper.h"
22a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "critical_section_wrapper.h"
23a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "event_wrapper.h"
24a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "thread_wrapper.h"
25a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
26a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinnamespace webrtc {
27a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinWebRtc_Word32 CpuWindows::CpuUsage()
28a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
29a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (!has_initialized_)
30a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
31a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return -1;
32a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
33a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Last element is the average
34a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return cpu_usage_[number_of_objects_ - 1];
35a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
36a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
37a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinWebRtc_Word32 CpuWindows::CpuUsageMultiCore(WebRtc_UWord32& num_cores,
38a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                            WebRtc_UWord32*& cpu_usage)
39a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
40a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (has_terminated_) {
41a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        num_cores = 0;
42a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        cpu_usage = NULL;
43a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return -1;
44a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
45a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (!has_initialized_)
46a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
47a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        num_cores = 0;
48a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        cpu_usage = NULL;
49a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return -1;
50a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
51a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    num_cores = number_of_objects_ - 1;
52a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    cpu_usage = cpu_usage_;
53a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return cpu_usage_[number_of_objects_-1];
54a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
55a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
56a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinCpuWindows::CpuWindows()
57a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    : cpu_polling_thread(NULL),
58a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      initialize_(true),
59a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      has_initialized_(false),
60a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      terminate_(false),
61a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      has_terminated_(false),
62a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      cpu_usage_(NULL),
63a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      wbem_enum_access_(NULL),
64a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      number_of_objects_(0),
65a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      cpu_usage_handle_(0),
66a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      previous_processor_timestamp_(NULL),
67a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      timestamp_sys_100_ns_handle_(0),
68a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      previous_100ns_timestamp_(NULL),
69a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      wbem_service_(NULL),
70a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      wbem_service_proxy_(NULL),
71a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      wbem_refresher_(NULL),
72a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      wbem_enum_(NULL)
73a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
74a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // All resources are allocated in PollingCpu().
75a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (AllocateComplexDataTypes())
76a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
77a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        StartPollingCpu();
78a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
79a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    else
80a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
81a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        assert(false);
82a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
83a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
84a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
85a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinCpuWindows::~CpuWindows()
86a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
87a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // All resources are reclaimed in StopPollingCpu().
88a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    StopPollingCpu();
89a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    DeAllocateComplexDataTypes();
90a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
91a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
92a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool CpuWindows::AllocateComplexDataTypes()
93a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
94a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    cpu_polling_thread = ThreadWrapper::CreateThread(
95a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        CpuWindows::Process,
96a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        reinterpret_cast<void*>(this),
97a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        kNormalPriority,
98a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        "CpuWindows");
99a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    init_crit_ = CriticalSectionWrapper::CreateCriticalSection();
100a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    init_cond_ = ConditionVariableWrapper::CreateConditionVariable();
101a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    terminate_crit_ = CriticalSectionWrapper::CreateCriticalSection();
102a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    terminate_cond_ = ConditionVariableWrapper::CreateConditionVariable();
103a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    sleep_event = EventWrapper::Create();
104a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return (cpu_polling_thread != NULL) && (init_crit_ != NULL) &&
105a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin           (init_cond_ != NULL) && (terminate_crit_ != NULL) &&
106a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin           (terminate_cond_ != NULL) && (sleep_event != NULL);
107a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
108a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
109a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid CpuWindows::DeAllocateComplexDataTypes()
110a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
111a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (sleep_event != NULL)
112a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
113a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete sleep_event;
114a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        sleep_event = NULL;
115a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
116a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (terminate_cond_ != NULL)
117a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
118a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete terminate_cond_;
119a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        terminate_cond_ = NULL;
120a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
121a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (terminate_crit_ != NULL)
122a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
123a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete terminate_crit_;
124a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        terminate_crit_ = NULL;
125a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
126a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (init_cond_ != NULL)
127a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
128a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete init_cond_;
129a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        init_cond_ = NULL;
130a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
131a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (init_crit_ != NULL)
132a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
133a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete init_crit_;
134a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        init_crit_ = NULL;
135a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
136a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (cpu_polling_thread != NULL)
137a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
138a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete cpu_polling_thread;
139a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        cpu_polling_thread = NULL;
140a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
141a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
142a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
143a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid CpuWindows::StartPollingCpu()
144a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
145a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    unsigned int dummy_id = 0;
146a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (!cpu_polling_thread->Start(dummy_id))
147a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
148a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        initialize_ = false;
149a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        has_terminated_ = true;
150a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        assert(false);
151a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
152a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
153a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
154a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool CpuWindows::StopPollingCpu()
155a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
156a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
157a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // If StopPollingCpu is called immediately after StartPollingCpu() it is
158a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // possible that cpu_polling_thread is in the process of initializing.
159a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // Let initialization finish to avoid getting into a bad state.
160a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        CriticalSectionScoped cs(init_crit_);
161a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        while(initialize_)
162a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
163a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            init_cond_->SleepCS(*init_crit_);
164a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
165a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
166a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
167a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    CriticalSectionScoped cs(terminate_crit_);
168a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    terminate_ = true;
169a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    sleep_event->Set();
170a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    while (!has_terminated_)
171a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
172a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        terminate_cond_->SleepCS(*terminate_crit_);
173a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
174a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    cpu_polling_thread->Stop();
175a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    delete cpu_polling_thread;
176a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    cpu_polling_thread = NULL;
177a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return true;
178a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
179a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
180a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool CpuWindows::Process(void* thread_object)
181a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
182a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return reinterpret_cast<CpuWindows*>(thread_object)->ProcessImpl();
183a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
184a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
185a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool CpuWindows::ProcessImpl()
186a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
187a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
188a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        CriticalSectionScoped cs(terminate_crit_);
189a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (terminate_)
190a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
191a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            Terminate();
192a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            terminate_cond_->WakeAll();
193a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            return false;
194a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
195a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
196a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Initialize on first iteration
197a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (initialize_)
198a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
199a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        CriticalSectionScoped cs(init_crit_);
200a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        initialize_ = false;
201a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        const bool success = Initialize();
202a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        init_cond_->WakeAll();
203a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (!success || !has_initialized_)
204a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
205a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            has_initialized_ = false;
206a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            terminate_ = true;
207a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            return true;
208a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
209a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
210a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Approximately one seconds sleep for each CPU measurement. Precision is
211a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // not important. 1 second refresh rate is also used by Performance Monitor
212a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // (perfmon).
213a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if(kEventTimeout != sleep_event->Wait(1000))
214a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
215a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // Terminating. No need to update CPU usage.
216a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        assert(terminate_);
217a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return true;
218a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
219a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
220a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // UpdateCpuUsage() returns false if a single (or more) CPU read(s) failed.
221a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Not a major problem if it happens.
222a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    UpdateCpuUsage();
223a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return true;
224a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
225a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
226a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool CpuWindows::CreateWmiConnection()
227a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
228a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    IWbemLocator* service_locator = NULL;
229a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    HRESULT hr = CoCreateInstance(CLSID_WbemLocator, NULL,
230a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                  CLSCTX_INPROC_SERVER, IID_IWbemLocator,
231a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                  reinterpret_cast<void**> (&service_locator));
232a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (FAILED(hr))
233a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
234a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
235a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
236a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // To get the WMI service specify the WMI namespace.
237a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    BSTR wmi_namespace = SysAllocString(L"\\\\.\\root\\cimv2");
238a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (wmi_namespace == NULL)
239a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
240a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // This type of failure signifies running out of memory.
241a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        service_locator->Release();
242a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
243a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
244a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    hr = service_locator->ConnectServer(wmi_namespace, NULL, NULL, NULL, 0L,
245a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                        NULL, NULL, &wbem_service_);
246a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    SysFreeString(wmi_namespace);
247a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    service_locator->Release();
248a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return !FAILED(hr);
249a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
250a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
251a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Sets up WMI refresher and enum
252a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool CpuWindows::CreatePerfOsRefresher()
253a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
254a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Create refresher.
255a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    HRESULT hr = CoCreateInstance(CLSID_WbemRefresher, NULL,
256a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                  CLSCTX_INPROC_SERVER, IID_IWbemRefresher,
257a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                  reinterpret_cast<void**> (&wbem_refresher_));
258a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (FAILED(hr))
259a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
260a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
261a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
262a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Create PerfOS_Processor enum.
263a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    IWbemConfigureRefresher* wbem_refresher_config = NULL;
264a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    hr = wbem_refresher_->QueryInterface(
265a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        IID_IWbemConfigureRefresher,
266a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        reinterpret_cast<void**> (&wbem_refresher_config));
267a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (FAILED(hr))
268a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
269a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
270a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
271a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
272a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Create a proxy to the IWbemServices so that a local authentication
273a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // can be set up (this is needed to be able to successfully call
274a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // IWbemConfigureRefresher::AddEnum). Setting authentication with
275a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // CoInitializeSecurity is process-wide (which is too intrusive).
276a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    hr = CoCopyProxy(static_cast<IUnknown*> (wbem_service_),
277a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                     reinterpret_cast<IUnknown**> (&wbem_service_proxy_));
278a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if(FAILED(hr))
279a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
280a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
281a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
282a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Set local authentication.
283a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // RPC_C_AUTHN_WINNT means using NTLM instead of Kerberos which is default.
284a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    hr = CoSetProxyBlanket(static_cast<IUnknown*> (wbem_service_proxy_),
285a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                           RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
286a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                           RPC_C_AUTHN_LEVEL_DEFAULT,
287a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                           RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
288a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if(FAILED(hr))
289a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
290a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
291a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
292a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
293a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Don't care about the particular id for the enum.
294a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    long enum_id = 0;
295a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    hr = wbem_refresher_config->AddEnum(wbem_service_proxy_,
296a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                        L"Win32_PerfRawData_PerfOS_Processor",
297a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                        0, NULL, &wbem_enum_, &enum_id);
298a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    wbem_refresher_config->Release();
299a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    wbem_refresher_config = NULL;
300a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return !FAILED(hr);
301a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
302a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
303a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Have to pull the first round of data to be able set the handles.
304a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool CpuWindows::CreatePerfOsCpuHandles()
305a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
306a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Update the refresher so that there is data available in wbem_enum_.
307a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    wbem_refresher_->Refresh(0L);
308a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
309a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // The number of enumerators is the number of processor + 1 (the total).
310a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // This is unknown at this point.
311a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    DWORD number_returned = 0;
312a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    HRESULT hr = wbem_enum_->GetObjects(0L, number_of_objects_,
313a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                        wbem_enum_access_, &number_returned);
314a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // number_returned indicates the number of enumerators that are needed.
315a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (hr == WBEM_E_BUFFER_TOO_SMALL &&
316a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        number_returned > number_of_objects_)
317a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
318a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // Allocate the number IWbemObjectAccess asked for by the
319a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // GetObjects(..) function.
320a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_enum_access_ = new IWbemObjectAccess*[number_returned];
321a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        cpu_usage_ = new WebRtc_UWord32[number_returned];
322a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        previous_processor_timestamp_ = new unsigned __int64[number_returned];
323a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        previous_100ns_timestamp_ = new unsigned __int64[number_returned];
324a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if ((wbem_enum_access_ == NULL) || (cpu_usage_ == NULL) ||
325a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            (previous_processor_timestamp_ == NULL) ||
326a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            (previous_100ns_timestamp_ == NULL))
327a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
328a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            // Out of memory.
329a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            return false;
330a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
331a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
332a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        SecureZeroMemory(wbem_enum_access_, number_returned *
333a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                         sizeof(IWbemObjectAccess*));
334a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        memset(cpu_usage_, 0, sizeof(int) * number_returned);
335a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        memset(previous_processor_timestamp_, 0, sizeof(unsigned __int64) *
336a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin               number_returned);
337a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        memset(previous_100ns_timestamp_, 0, sizeof(unsigned __int64) *
338a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin               number_returned);
339a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
340a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        number_of_objects_ = number_returned;
341a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // Read should be successfull now that memory has been allocated.
342a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        hr = wbem_enum_->GetObjects(0L, number_of_objects_, wbem_enum_access_,
343a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                    &number_returned);
344a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (FAILED(hr))
345a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
346a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            return false;
347a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
348a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
349a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    else
350a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
351a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // 0 enumerators should not be enough. Something has gone wrong here.
352a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
353a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
354a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
355a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Get the enumerator handles that are needed for calculating CPU usage.
356a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    CIMTYPE cpu_usage_type;
357a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    hr = wbem_enum_access_[0]->GetPropertyHandle(L"PercentProcessorTime",
358a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                                 &cpu_usage_type,
359a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                                 &cpu_usage_handle_);
360a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (FAILED(hr))
361a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
362a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
363a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
364a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    CIMTYPE timestamp_sys_100_ns_type;
365a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    hr = wbem_enum_access_[0]->GetPropertyHandle(L"TimeStamp_Sys100NS",
366a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                                 &timestamp_sys_100_ns_type,
367a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                                 &timestamp_sys_100_ns_handle_);
368a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return !FAILED(hr);
369a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
370a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
371a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool CpuWindows::Initialize()
372a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
373a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (terminate_)
374a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
375a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
376a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
377a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Initialize COM library.
378a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    HRESULT hr = CoInitializeEx(NULL,COINIT_MULTITHREADED);
379a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (FAILED(hr))
380a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
381a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
382a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
383a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (FAILED(hr))
384a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
385a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
386a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
387a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
388a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (!CreateWmiConnection())
389a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
390a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
391a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
392a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (!CreatePerfOsRefresher())
393a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
394a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
395a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
396a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (!CreatePerfOsCpuHandles())
397a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
398a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
399a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
400a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    has_initialized_ = true;
401a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return true;
402a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
403a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
404a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool CpuWindows::Terminate()
405a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
406a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (has_terminated_)
407a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
408a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
409a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
410a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Reverse order of Initialize().
411a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Some compilers complain about deleting NULL though it's well defined
412a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (previous_100ns_timestamp_ != NULL)
413a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
414a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete[] previous_100ns_timestamp_;
415a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        previous_100ns_timestamp_ = NULL;
416a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
417a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (previous_processor_timestamp_ != NULL)
418a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
419a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete[] previous_processor_timestamp_;
420a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        previous_processor_timestamp_ = NULL;
421a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
422a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (cpu_usage_ != NULL)
423a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
424a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete[] cpu_usage_;
425a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        cpu_usage_ = NULL;
426a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
427a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (wbem_enum_access_ != NULL)
428a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
429a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        for (DWORD i = 0; i < number_of_objects_; i++)
430a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
431a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            if(wbem_enum_access_[i] != NULL)
432a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            {
433a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                wbem_enum_access_[i]->Release();
434a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            }
435a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
436a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete[] wbem_enum_access_;
437a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_enum_access_ = NULL;
438a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
439a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (wbem_enum_ != NULL)
440a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
441a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_enum_->Release();
442a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_enum_ = NULL;
443a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
444a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (wbem_refresher_ != NULL)
445a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
446a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_refresher_->Release();
447a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_refresher_ = NULL;
448a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
449a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (wbem_service_proxy_ != NULL)
450a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
451a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_service_proxy_->Release();
452a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_service_proxy_ = NULL;
453a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
454a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (wbem_service_ != NULL)
455a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
456a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_service_->Release();
457a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_service_ = NULL;
458a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
459a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // CoUninitialized should be called once for every CoInitializeEx.
460a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Regardless if it failed or not.
461a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    CoUninitialize();
462a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    has_terminated_ = true;
463a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return true;
464a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
465a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
466a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool CpuWindows::UpdateCpuUsage()
467a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
468a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    wbem_refresher_->Refresh(0L);
469a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    DWORD number_returned = 0;
470a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    HRESULT hr = wbem_enum_->GetObjects(0L, number_of_objects_,
471a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                        wbem_enum_access_,&number_returned);
472a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (FAILED(hr))
473a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
474a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // wbem_enum_access_ has already been allocated. Unless the number of
475a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // CPUs change runtime this should not happen.
476a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
477a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
478a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    unsigned __int64 cpu_usage = 0;
479a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    unsigned __int64 timestamp_100ns = 0;
480a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    bool returnValue = true;
481a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    for (DWORD i = 0; i < number_returned; i++)
482a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
483a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        hr = wbem_enum_access_[i]->ReadQWORD(cpu_usage_handle_,&cpu_usage);
484a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (FAILED(hr))
485a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
486a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            returnValue = false;
487a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
488a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        hr = wbem_enum_access_[i]->ReadQWORD(timestamp_sys_100_ns_handle_,
489a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                             &timestamp_100ns);
490a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (FAILED(hr))
491a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
492a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            returnValue = false;
493a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
494a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_enum_access_[i]->Release();
495a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        wbem_enum_access_[i] = NULL;
496a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
497a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        const bool wrapparound =
498a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            (previous_processor_timestamp_[i] > cpu_usage) ||
499a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            (previous_100ns_timestamp_[i] > timestamp_100ns);
500a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        const bool first_time = (previous_processor_timestamp_[i] == 0) ||
501a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                (previous_100ns_timestamp_[i] == 0);
502a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (wrapparound || first_time)
503a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
504a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            previous_processor_timestamp_[i] = cpu_usage;
505a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            previous_100ns_timestamp_[i] = timestamp_100ns;
506a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            continue;
507a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
508a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        const unsigned __int64 processor_timestamp_delta =
509a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            cpu_usage - previous_processor_timestamp_[i];
510a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        const unsigned __int64 timestamp_100ns_delta =
511a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            timestamp_100ns - previous_100ns_timestamp_[i];
512a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
513a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (processor_timestamp_delta >= timestamp_100ns_delta)
514a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
515a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            cpu_usage_[i] = 0;
516a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        } else {
517a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            // Quotient must be float since the division is guaranteed to yield
518a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            // a value between 0 and 1 which is 0 in integer division.
519a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            const float delta_quotient =
520a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                static_cast<float>(processor_timestamp_delta) /
521a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                static_cast<float>(timestamp_100ns_delta);
522a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            cpu_usage_[i] = 100 - static_cast<WebRtc_UWord32>(delta_quotient *
523a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                                              100);
524a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
525a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        previous_processor_timestamp_[i] = cpu_usage;
526a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        previous_100ns_timestamp_[i] = timestamp_100ns;
527a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
528a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return returnValue;
529a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
530a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} // namespace webrtc
531