1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
/*
* Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Functions related to the Windows Management Instrumentation API.
*/
#include <Python.h>
#include <windows.h>
#include <pdh.h>
#include "../../arch/all/init.h"
// We use an exponentially weighted moving average, just like Unix systems do
// https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation
//
// These constants serve as the damping factor and are calculated with
// 1 / exp(sampling interval in seconds / window size in seconds)
//
// This formula comes from linux's include/linux/sched/loadavg.h
// https://github.com/torvalds/linux/blob/345671ea0f9258f410eb057b9ced9cefbbe5dc78/include/linux/sched/loadavg.h#L20-L23
#define LOADAVG_FACTOR_1F 0.9200444146293232478931553241
#define LOADAVG_FACTOR_5F 0.9834714538216174894737477501
#define LOADAVG_FACTOR_15F 0.9944598480048967508795473394
// The time interval in seconds between taking load counts, same as Linux
#define SAMPLING_INTERVAL 5
double load_avg_1m = 0;
double load_avg_5m = 0;
double load_avg_15m = 0;
#ifdef Py_GIL_DISABLED
static PyMutex mutex;
#define MUTEX_LOCK(m) PyMutex_Lock(m)
#define MUTEX_UNLOCK(m) PyMutex_Unlock(m)
#else
#define MUTEX_LOCK(m)
#define MUTEX_UNLOCK(m)
#endif
VOID CALLBACK LoadAvgCallback(PVOID hCounter, BOOLEAN timedOut) {
PDH_FMT_COUNTERVALUE displayValue;
double currentLoad;
PDH_STATUS err;
err = PdhGetFormattedCounterValue(
(PDH_HCOUNTER)hCounter, PDH_FMT_DOUBLE, 0, &displayValue);
// Skip updating the load if we can't get the value successfully
if (err != ERROR_SUCCESS) {
return;
}
currentLoad = displayValue.doubleValue;
MUTEX_LOCK(&mutex);
load_avg_1m = load_avg_1m * LOADAVG_FACTOR_1F + currentLoad * \
(1.0 - LOADAVG_FACTOR_1F);
load_avg_5m = load_avg_5m * LOADAVG_FACTOR_5F + currentLoad * \
(1.0 - LOADAVG_FACTOR_5F);
load_avg_15m = load_avg_15m * LOADAVG_FACTOR_15F + currentLoad * \
(1.0 - LOADAVG_FACTOR_15F);
MUTEX_UNLOCK(&mutex);
}
PyObject *
psutil_init_loadavg_counter(PyObject *self, PyObject *args) {
WCHAR *szCounterPath = L"\\System\\Processor Queue Length";
PDH_STATUS s;
BOOL ret;
HQUERY hQuery;
HCOUNTER hCounter;
HANDLE event;
HANDLE waitHandle;
if ((PdhOpenQueryW(NULL, 0, &hQuery)) != ERROR_SUCCESS) {
PyErr_Format(PyExc_RuntimeError, "PdhOpenQueryW failed");
return NULL;
}
s = PdhAddEnglishCounterW(hQuery, szCounterPath, 0, &hCounter);
if (s != ERROR_SUCCESS) {
PyErr_Format(
PyExc_RuntimeError,
"PdhAddEnglishCounterW failed. Performance counters may be disabled."
);
return NULL;
}
event = CreateEventW(NULL, FALSE, FALSE, L"LoadUpdateEvent");
if (event == NULL) {
psutil_PyErr_SetFromOSErrnoWithSyscall("CreateEventW");
return NULL;
}
s = PdhCollectQueryDataEx(hQuery, SAMPLING_INTERVAL, event);
if (s != ERROR_SUCCESS) {
PyErr_Format(PyExc_RuntimeError, "PdhCollectQueryDataEx failed");
return NULL;
}
ret = RegisterWaitForSingleObject(
&waitHandle,
event,
(WAITORTIMERCALLBACK)LoadAvgCallback,
(PVOID)
hCounter,
INFINITE,
WT_EXECUTEDEFAULT);
if (ret == 0) {
psutil_PyErr_SetFromOSErrnoWithSyscall("RegisterWaitForSingleObject");
return NULL;
}
Py_RETURN_NONE;
}
/*
* Gets the emulated 1 minute, 5 minute and 15 minute load averages
* (processor queue length) for the system.
* `init_loadavg_counter` must be called before this function to engage the
* mechanism that records load values.
*/
PyObject *
psutil_get_loadavg(PyObject *self, PyObject *args) {
MUTEX_LOCK(&mutex);
double load_avg_1m_l = load_avg_1m;
double load_avg_5m_l = load_avg_5m;
double load_avg_15m_l = load_avg_15m;
MUTEX_UNLOCK(&mutex);
return Py_BuildValue("(ddd)", load_avg_1m_l, load_avg_5m_l, load_avg_15m_l);
}
|