How to access CPU's heat sensors? How to access CPU's heat sensors? windows windows

How to access CPU's heat sensors?


Without a specific kernel driver, it's difficult to query the temperature, other than through WMI. Here is a piece of C code that does it, based on WMI's MSAcpi_ThermalZoneTemperature class:

HRESULT GetCpuTemperature(LPLONG pTemperature){    if (pTemperature == NULL)        return E_INVALIDARG;    *pTemperature = -1;    HRESULT ci = CoInitialize(NULL); // needs comdef.h    HRESULT hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);    if (SUCCEEDED(hr))    {        IWbemLocator *pLocator; // needs Wbemidl.h & Wbemuuid.lib        hr = CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLocator);        if (SUCCEEDED(hr))        {            IWbemServices *pServices;            BSTR ns = SysAllocString(L"root\\WMI");            hr = pLocator->ConnectServer(ns, NULL, NULL, NULL, 0, NULL, NULL, &pServices);            pLocator->Release();            SysFreeString(ns);            if (SUCCEEDED(hr))            {                BSTR query = SysAllocString(L"SELECT * FROM MSAcpi_ThermalZoneTemperature");                BSTR wql = SysAllocString(L"WQL");                IEnumWbemClassObject *pEnum;                hr = pServices->ExecQuery(wql, query, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pEnum);                SysFreeString(wql);                SysFreeString(query);                pServices->Release();                if (SUCCEEDED(hr))                {                    IWbemClassObject *pObject;                    ULONG returned;                    hr = pEnum->Next(WBEM_INFINITE, 1, &pObject, &returned);                    pEnum->Release();                    if (SUCCEEDED(hr))                    {                        BSTR temp = SysAllocString(L"CurrentTemperature");                        VARIANT v;                        VariantInit(&v);                        hr = pObject->Get(temp, 0, &v, NULL, NULL);                        pObject->Release();                        SysFreeString(temp);                        if (SUCCEEDED(hr))                        {                            *pTemperature = V_I4(&v);                        }                        VariantClear(&v);                    }                }            }            if (ci == S_OK)            {                CoUninitialize();            }        }    }    return hr;}

and some test code:

HRESULT GetCpuTemperature(LPLONG pTemperature);int _tmain(int argc, _TCHAR* argv[]){    LONG temp;    HRESULT hr = GetCpuTemperature(&temp);    printf("hr=0x%08x temp=%i\n", hr, temp);}


I assume you are interested in a IA-32 (Intel Architecture, 32-bit) CPU and Microsoft Windows.

The Model Specific Register (MSR) IA32_THERM_STATUS has 7 bits encoding the "Digital Readout (bits 22:16, RO) — Digital temperature reading in 1 degree Celsius relative to the TCC activation temperature." (see "14.5.5.2 Reading the Digital Sensor" in "Intel® 64 and IA-32 Architectures - Software Developer’s Manual - Volume 3 (3A & 3B): System Programming Guide" http://www.intel.com/Assets/PDF/manual/325384.pdf).

So IA32_THERM_STATUS will not give you the "CPU temperature" but some proxy for it.

In order to read the IA32_THERM_STATUS register you use the asm instruction rdmsr, now rdmsr cannot be called from user space code and so you need some kernel space code (maybe a device driver?).

You can also use the intrinsic __readmsr (see http://msdn.microsoft.com/en-us/library/y55zyfdx(v=VS.100).aspx) which has anyway the same limitation: "This function is only available in kernel mode".

Every CPU cores has its own Digital Thermal Sensors (DTS) and so some more code is needed to get all the temperatures (maybe with the affinity mask? see Win32 API SetThreadAffinityMask).

I did some tests and actually found a correlation between the IA32_THERM_STATUS DTS readouts and the Prime95 "In-place large FFTs (maximum heat, power consumption, some RAM tested)" test. Prime95 is ftp://mersenne.org/gimps/p95v266.zip

I did not find a formula to get the "CPU temperature" (whatever that may mean) from the DTS readout.

Edit:

Quoting from an interesting post TJunction Max? #THERMTRIP? #PROCHOT? by "fgw" (December 2007):

there is no way to find tjmax of a certain processor in any register. thus no software can read this value. what various software developers are doing, is they simply assume a certain tjunction for a certain processor and hold this information in a table within the program. besides that, tjmax is not even the correct value they are after. in fact they are looking for TCC activacion temperature threshold. this temperature threshold is used to calculate current absolute coretemperatures from. theoretical you can say: absolute coretemperature = TCC activacion temperature threshold - DTS i had to say theoretically because, as stated above, this TCC activacion temperature threshold cant be read by software and has to be assumed by the programmer. in most situations (coretemp, everest, ...) they assume a value of 85C or 100C depending on processor family and revision. as this TCC activacion temperature threshold is calibrated during manufacturing individually per processor, it could be 83C for one processor but may be 87C for the other. taking into account the way those programms are calculating coretemperatures, you can figure out at your own, how accurate absolute coretemperatures are! neither tjmax nor the "most wanted" TCC activacion temperature threshold can be found in any public intel documents. following some discussions over on the intel developer forum, intel shows no sign to make this information available.


You can read it from the MSAcpi_ThermalZoneTemperature in WMI

Using WMI from C++ is a bit involved, see MSDN explanantion and examples

note: changed original unhelpful answer