windows: add support for cpu times to uv_cpu_info()
* Also cleans up the code and makes it use unicode APIs consistently. * Credits go to Brian White for creating an earlier version of this patch. Closes #327
This commit is contained in:
parent
4252240e54
commit
1d64a36caa
154
src/win/util.c
154
src/win/util.c
@ -47,7 +47,6 @@
|
||||
*/
|
||||
#define MAX_TITLE_LENGTH 8192
|
||||
|
||||
|
||||
static char *process_title;
|
||||
static uv_once_t uv_process_title_init_guard_ = UV_ONCE_INIT;
|
||||
static CRITICAL_SECTION process_title_lock;
|
||||
@ -488,81 +487,148 @@ uv_err_t uv_uptime(double* uptime) {
|
||||
|
||||
|
||||
uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
uv_err_t err;
|
||||
char key[128];
|
||||
HKEY processor_key = NULL;
|
||||
DWORD cpu_speed = 0;
|
||||
DWORD cpu_speed_length = sizeof(cpu_speed);
|
||||
char cpu_brand[256];
|
||||
DWORD cpu_brand_length = sizeof(cpu_brand);
|
||||
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
|
||||
DWORD sppi_size;
|
||||
SYSTEM_INFO system_info;
|
||||
DWORD cpu_count, i, r;
|
||||
ULONG result_size;
|
||||
size_t size;
|
||||
uv_err_t err;
|
||||
uv_cpu_info_t* cpu_info;
|
||||
unsigned int i;
|
||||
|
||||
*cpu_infos = NULL;
|
||||
*count = 0;
|
||||
|
||||
uv__once_init();
|
||||
|
||||
GetSystemInfo(&system_info);
|
||||
cpu_count = system_info.dwNumberOfProcessors;
|
||||
|
||||
*cpu_infos = (uv_cpu_info_t*)malloc(system_info.dwNumberOfProcessors *
|
||||
sizeof(uv_cpu_info_t));
|
||||
if (!(*cpu_infos)) {
|
||||
size = cpu_count * sizeof(uv_cpu_info_t);
|
||||
*cpu_infos = (uv_cpu_info_t*) malloc(size);
|
||||
if (*cpu_infos == NULL) {
|
||||
err = uv__new_artificial_error(UV_ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
memset(*cpu_infos, 0, size);
|
||||
|
||||
sppi_size = sizeof(*sppi) * cpu_count;
|
||||
sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*) malloc(sppi_size);
|
||||
if (!sppi) {
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
||||
}
|
||||
|
||||
*count = 0;
|
||||
r = pNtQuerySystemInformation(SystemProcessorPerformanceInformation,
|
||||
sppi,
|
||||
sppi_size,
|
||||
&result_size);
|
||||
if (r != ERROR_SUCCESS || result_size != sppi_size) {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < system_info.dwNumberOfProcessors; i++) {
|
||||
_snprintf(key, sizeof(key), "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d", i);
|
||||
for (i = 0; i < cpu_count; i++) {
|
||||
WCHAR key_name[128];
|
||||
HKEY processor_key;
|
||||
DWORD cpu_speed;
|
||||
DWORD cpu_speed_size = sizeof(cpu_speed);
|
||||
WCHAR cpu_brand[256];
|
||||
DWORD cpu_brand_size = sizeof(cpu_brand);
|
||||
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE,
|
||||
&processor_key) != ERROR_SUCCESS) {
|
||||
if (i == 0) {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
goto done;
|
||||
}
|
||||
_snwprintf(key_name,
|
||||
ARRAY_SIZE(key_name),
|
||||
L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d",
|
||||
i);
|
||||
|
||||
continue;
|
||||
r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
||||
key_name,
|
||||
0,
|
||||
KEY_QUERY_VALUE,
|
||||
&processor_key);
|
||||
if (r != ERROR_SUCCESS) {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (RegQueryValueEx(processor_key, "~MHz", NULL, NULL,
|
||||
(LPBYTE)&cpu_speed, &cpu_speed_length)
|
||||
!= ERROR_SUCCESS) {
|
||||
if (RegQueryValueExW(processor_key,
|
||||
L"~MHz",
|
||||
NULL, NULL,
|
||||
(BYTE*) &cpu_speed,
|
||||
&cpu_speed_size) != ERROR_SUCCESS) {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
goto done;
|
||||
RegCloseKey(processor_key);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (RegQueryValueEx(processor_key, "ProcessorNameString", NULL, NULL,
|
||||
(LPBYTE)&cpu_brand, &cpu_brand_length)
|
||||
!= ERROR_SUCCESS) {
|
||||
if (RegQueryValueExW(processor_key,
|
||||
L"ProcessorNameString",
|
||||
NULL, NULL,
|
||||
(BYTE*) &cpu_brand,
|
||||
&cpu_brand_size) != ERROR_SUCCESS) {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
goto done;
|
||||
RegCloseKey(processor_key);
|
||||
goto out;
|
||||
}
|
||||
|
||||
RegCloseKey(processor_key);
|
||||
processor_key = NULL;
|
||||
|
||||
cpu_info = &(*cpu_infos)[i];
|
||||
|
||||
/* $TODO: find times on windows */
|
||||
cpu_info->cpu_times.user = 0;
|
||||
cpu_info->cpu_times.nice = 0;
|
||||
cpu_info->cpu_times.sys = 0;
|
||||
cpu_info->cpu_times.idle = 0;
|
||||
cpu_info->cpu_times.irq = 0;
|
||||
|
||||
cpu_info->model = strdup(cpu_brand);
|
||||
cpu_info->speed = cpu_speed;
|
||||
cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000;
|
||||
cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart -
|
||||
sppi[i].IdleTime.QuadPart) / 10000;
|
||||
cpu_info->cpu_times.idle = sppi[i].IdleTime.QuadPart / 10000;
|
||||
cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000;
|
||||
cpu_info->cpu_times.nice = 0;
|
||||
|
||||
size = uv_utf16_to_utf8(cpu_brand,
|
||||
cpu_brand_size / sizeof(WCHAR),
|
||||
NULL,
|
||||
0);
|
||||
if (size == 0) {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Allocate 1 extra byte for the null terminator. */
|
||||
cpu_info->model = (char*) malloc(size + 1);
|
||||
if (cpu_info->model == NULL) {
|
||||
err = uv__new_artificial_error(UV_ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (uv_utf16_to_utf8(cpu_brand,
|
||||
cpu_brand_size / sizeof(WCHAR),
|
||||
cpu_info->model,
|
||||
size) == 0) {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ensure that cpu_info->model is null terminated. */
|
||||
cpu_info->model[size] = '\0';
|
||||
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
err = uv_ok_;
|
||||
|
||||
done:
|
||||
if (processor_key) {
|
||||
RegCloseKey(processor_key);
|
||||
out:
|
||||
if (sppi) {
|
||||
free(sppi);
|
||||
}
|
||||
|
||||
if (err.code != UV_OK) {
|
||||
if (err.code != UV_OK &&
|
||||
*cpu_infos != NULL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < *count; i++) {
|
||||
/* This is safe because the cpu_infos memory area is zeroed out */
|
||||
/* immediately after allocating it. */
|
||||
free((*cpu_infos)[i].model);
|
||||
}
|
||||
free(*cpu_infos);
|
||||
|
||||
*cpu_infos = NULL;
|
||||
*count = 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user