493 lines
10 KiB
C
493 lines
10 KiB
C
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cpuperf.c
|
|
|
|
Abstract:
|
|
|
|
Display Acpi 2.0 Processor Performance States
|
|
|
|
Author:
|
|
|
|
Todd Carpenter
|
|
|
|
Environment:
|
|
|
|
user mode
|
|
|
|
Notes:
|
|
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
PURPOSE.
|
|
|
|
Copyright (c) 2000 Microsoft Corporation. All Rights Reserved.
|
|
|
|
|
|
Revision History:
|
|
|
|
10-18-2000 : ToddCar - created
|
|
|
|
--*/
|
|
#include "cpuperf.h"
|
|
|
|
|
|
|
|
VOID
|
|
__cdecl
|
|
_tmain(
|
|
IN INT argc,
|
|
IN TCHAR *argv[]
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Main()
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
ULONG rc = (ULONG) 0xdeaddead;
|
|
ULONG status;
|
|
ULONG targetState;
|
|
PTSTR instanceName = NULL;
|
|
PPROCESSOR_WMI_STATUS_DATA processorData = NULL;
|
|
|
|
status = GetInstanceName(&instanceName);
|
|
_tprintf(TEXT("InstanceName == %s\n"), instanceName);
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
if (status == ERROR_WMI_GUID_NOT_FOUND) {
|
|
|
|
_tprintf(TEXT("\n"));
|
|
_tprintf(TEXT("This processor driver does not support WMI interface\n"));
|
|
_tprintf(TEXT("\n"));
|
|
|
|
} else {
|
|
|
|
_tprintf(TEXT("GetInstanceName() Failed! rc=0x%x\n"), status);
|
|
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// if called with "setstate X", call SetProcessorPerformanceState(X) first.
|
|
//
|
|
|
|
if (argc > 1) {
|
|
|
|
if ((_tcsstr(argv[1], TEXT("setstate"))) && argc > 2) {
|
|
|
|
targetState = _ttoi(argv[2]);
|
|
|
|
_tprintf(TEXT("\n"));
|
|
_tprintf(TEXT("Setting Processor Performance to state %u\n"), targetState);
|
|
|
|
status = SetProcessorPerformanceState(targetState, instanceName, &rc);
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
_tprintf(TEXT("SetProcessorPerformanceState() Failed! rc=0x%x\n"), rc);
|
|
return;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// display help? or just ignor and continue?
|
|
//
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
status = GetProcessorPerformanceStatusData(&processorData);
|
|
|
|
if (status == ERROR_SUCCESS) {
|
|
DisplayProcessorData(processorData, instanceName);
|
|
}
|
|
|
|
|
|
//FreeData(instanceName);
|
|
//FreeData(processorData);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
ULONG
|
|
GetProcessorPerformanceStatusData(
|
|
IN PPROCESSOR_WMI_STATUS_DATA *ProcessorData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
GetProcessorPerformanceStatusData()
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
ULONG status;
|
|
ULONG sizeNeeded;
|
|
PTSTR buffer = NULL;
|
|
PTSTR instanceName = NULL;
|
|
ULONG instanceNameOffset;
|
|
WMIHANDLE wmiStatusHandle;
|
|
PWNODE_ALL_DATA wmiAllData;
|
|
PPROCESSOR_WMI_STATUS_DATA processorStatusData;
|
|
|
|
|
|
status = WmiOpenBlock(&ProcessorStatusGuid,
|
|
GENERIC_READ,
|
|
&wmiStatusHandle);
|
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
_tprintf(TEXT("WmiOpenBlock() Failed! rc=0x%x\n"), status);
|
|
goto GetProcessorPerformanceStatusDataExit;
|
|
}
|
|
|
|
|
|
status = WmiQueryAllData(wmiStatusHandle,
|
|
&sizeNeeded,
|
|
0);
|
|
|
|
if (status != ERROR_INSUFFICIENT_BUFFER) {
|
|
_tprintf(TEXT("WmiQueryAllData() Failed! rc=0x%x\n"), status);
|
|
goto GetProcessorPerformanceStatusDataExit;
|
|
}
|
|
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeNeeded);
|
|
//_tprintf(TEXT("HeapAlloc(size=0x%x) allocated: %p\n"), sizeNeeded, buffer);
|
|
|
|
if (!buffer) {
|
|
_tprintf(TEXT("HeapAlloc(size=0x%x) Failed!\n"), sizeNeeded);
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
goto GetProcessorPerformanceStatusDataExit;
|
|
}
|
|
|
|
|
|
status = WmiQueryAllData(wmiStatusHandle,
|
|
&sizeNeeded,
|
|
buffer);
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
_tprintf(TEXT("WmiQueryAllData() Failed! rc=0x%x\n"), status);
|
|
goto GetProcessorPerformanceStatusDataExit;
|
|
}
|
|
|
|
|
|
wmiAllData = (PWNODE_ALL_DATA) buffer;
|
|
|
|
if (wmiAllData->WnodeHeader.Flags & WNODE_FLAG_FIXED_INSTANCE_SIZE) {
|
|
|
|
_tprintf(TEXT("WNODE_FLAG_FIXED_INSTANCE_SIZE\n"), sizeNeeded);
|
|
processorStatusData = (PPROCESSOR_WMI_STATUS_DATA) &buffer[wmiAllData->DataBlockOffset];
|
|
|
|
} else {
|
|
|
|
processorStatusData = (PPROCESSOR_WMI_STATUS_DATA) &buffer[wmiAllData->OffsetInstanceDataAndLength[0].OffsetInstanceData];
|
|
|
|
}
|
|
|
|
if (processorStatusData) {
|
|
*ProcessorData = processorStatusData;
|
|
}
|
|
|
|
|
|
GetProcessorPerformanceStatusDataExit:
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
ULONG
|
|
SetProcessorPerformanceState(
|
|
IN ULONG TargetState,
|
|
IN PTSTR InstanceName,
|
|
OUT PULONG ReturnedValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
SetProcessorPerformanceState()
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
ULONG status;
|
|
ULONG sizeReturned = sizeof(ULONG);
|
|
WMIHANDLE wmiMethodHandle;
|
|
|
|
|
|
|
|
status = WmiOpenBlock(&ProcessorMethodGuid,
|
|
GENERIC_EXECUTE,
|
|
&wmiMethodHandle);
|
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
_tprintf(TEXT("SetProcessorPerformanceState: WmiOpenBlock() Failed! rc=0x%x\n"), status);
|
|
return status;
|
|
}
|
|
|
|
|
|
status = WmiExecuteMethod(wmiMethodHandle,
|
|
InstanceName,
|
|
WmiSetProcessorPerfStateMethodId,
|
|
sizeof(ULONG),
|
|
(PVOID) &TargetState,
|
|
&sizeReturned,
|
|
(PVOID) ReturnedValue);
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
ULONG
|
|
GetInstanceName(
|
|
OUT PTSTR *Buffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
GetInstanceName()
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
ULONG status;
|
|
ULONG sizeNeeded;
|
|
PUCHAR buffer;
|
|
PTSTR instanceName;
|
|
ULONG instanceNameOffset;
|
|
WMIHANDLE wmiStatusHandle;
|
|
|
|
|
|
|
|
//
|
|
// NOTE: must use ProcessorMethodGuid to get Instance Name ... not
|
|
// sure why others guid don't work.
|
|
//
|
|
|
|
//
|
|
// Open connection
|
|
//
|
|
|
|
status = WmiOpenBlock(&ProcessorMethodGuid,
|
|
GENERIC_READ,
|
|
&wmiStatusHandle);
|
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
//_tprintf(TEXT("GetInstanceName: WmiOpenBlock() Failed! rc=0x%x\n"), status);
|
|
goto GetProcessorPerformanceStatusDataExit;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Query for buffer size needed
|
|
//
|
|
|
|
status = WmiQueryAllData(wmiStatusHandle,
|
|
&sizeNeeded,
|
|
0);
|
|
|
|
if (status != ERROR_INSUFFICIENT_BUFFER) {
|
|
_tprintf(TEXT("GetInstanceName:WmiQueryAllData(0) Failed! rc=0x%x\n"), status);
|
|
goto GetProcessorPerformanceStatusDataExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate buffer
|
|
//
|
|
|
|
buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeNeeded);
|
|
|
|
if (!buffer) {
|
|
_tprintf(TEXT("GetInstanceName: HeapAlloc(size=0x%x) Failed!\n"), sizeNeeded);
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
goto GetProcessorPerformanceStatusDataExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Retrieve Data
|
|
//
|
|
|
|
status = WmiQueryAllData(wmiStatusHandle,
|
|
&sizeNeeded,
|
|
buffer);
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
_tprintf(TEXT("GetInstanceName: WmiQueryAllData() Failed! rc=0x%x\n"), status);
|
|
goto GetProcessorPerformanceStatusDataExit;
|
|
}
|
|
|
|
//
|
|
// Get instance name.
|
|
//
|
|
|
|
instanceNameOffset = (ULONG) buffer[((PWNODE_ALL_DATA)buffer)->OffsetInstanceNameOffsets];
|
|
instanceName = (PTSTR) &buffer[instanceNameOffset + sizeof(USHORT)];
|
|
|
|
|
|
//
|
|
// Copy instance name
|
|
//
|
|
|
|
if (instanceName && Buffer) {
|
|
|
|
ULONG nameSize = lstrlen(instanceName) + sizeof(TCHAR);
|
|
|
|
*Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nameSize);
|
|
|
|
if (!(*Buffer)) {
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
goto GetProcessorPerformanceStatusDataExit;
|
|
}
|
|
|
|
lstrcpyn(*Buffer, instanceName, nameSize);
|
|
}
|
|
|
|
|
|
//
|
|
// Close connection
|
|
//
|
|
|
|
WmiCloseBlock(wmiStatusHandle);
|
|
|
|
|
|
|
|
GetProcessorPerformanceStatusDataExit:
|
|
|
|
if (buffer) {
|
|
//HeapFree(GetProcessHeap(), 0, buffer);
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
DisplayProcessorData (
|
|
IN PPROCESSOR_WMI_STATUS_DATA Data,
|
|
IN PTSTR InstanceName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
DisplayProcessorData()
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
ULONG index;
|
|
|
|
_tprintf(TEXT("\n"));
|
|
_tprintf(TEXT("Processor Performance States\n"));
|
|
_tprintf(TEXT(" Current Performance State: %u\n"), Data->CurrentPerfState);
|
|
_tprintf(TEXT(" Last Requested Throttle: %u%%\n"), Data->LastRequestedThrottle);
|
|
_tprintf(TEXT(" Last Transition Result: %s (0x%x)\n"), (Data->LastTransitionResult ? TEXT("Failed") : TEXT("Succeeded")),
|
|
Data->LastTransitionResult);
|
|
_tprintf(TEXT(" Current Throttle Value: %u\n"), Data->ThrottleValue);
|
|
_tprintf(TEXT(" Lowest Performance State: %u\n"), Data->LowestPerfState);
|
|
_tprintf(TEXT(" Using Legacy Interface: %s\n"), Data->UsingLegacyInterface ? TEXT("Yes") : TEXT("No"));
|
|
_tprintf(TEXT("\n"));
|
|
_tprintf(TEXT(" PerfStates:\n"));
|
|
_tprintf(TEXT(" Max Transition Latency: %u us\n"), Data->PerfStates.TransitionLatency);
|
|
_tprintf(TEXT(" Number of States: %u\n\n"), Data->PerfStates.Count);
|
|
|
|
_tprintf(TEXT(" State Speed (Mhz) Type\n"));
|
|
_tprintf(TEXT(" ----- ------------ ----\n"));
|
|
|
|
for (index = 0; index < Data->PerfStates.Count; index++) {
|
|
|
|
|
|
_tprintf(TEXT(" %-5u %4u (%3u%%) %-7s\n"),
|
|
index,
|
|
Data->PerfStates.State[index].Frequency,
|
|
Data->PerfStates.State[index].PercentFrequency,
|
|
(((Data->PerfStates.State[index].Flags) & PROCESSOR_STATE_TYPE_PERFORMANCE) ?
|
|
"Performance" : "Throttle"));
|
|
|
|
}
|
|
_tprintf(TEXT("\n"));
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeData(
|
|
IN PVOID Data
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
FreeInstanceName()
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
if (Data) {
|
|
HeapFree(GetProcessHeap(), 0, Data);
|
|
}
|
|
}
|