// Copyright (c) 2014, Intel Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Intel Corporation nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "PowerGadgetLib.h"
#include <Windows.h>
#include <string>
#include <vector>
using namespace std;
string g_lastError;
HMODULE g_hModule = NULL;
static bool split(const wstring& s, wstring &path)
{
bool bResult = false;
vector<wstring> output;
wstring::size_type prev_pos = 0, pos = 0;
while((pos = s.find(L';', pos)) != wstring::npos)
{
wstring substring( s.substr(prev_pos, pos-prev_pos) );
if (substring.find(L"Power Gadget 2.") != wstring::npos)
{
path = substring;
bResult = true;
break;
}
prev_pos = ++pos;
}
if (!bResult)
{
wstring substring(s.substr(prev_pos, pos-prev_pos));
if (substring.find(L"Power Gadget 2.") != wstring::npos)
{
path = substring;
bResult = true;
}
}
if (bResult)
{
basic_string <char>::size_type pos = path.rfind(L" ");
wstring version = path.substr(pos+1, path.length());
double fVer = _wtof(version.c_str());
if (fVer > 2.6)
bResult = true;
}
return bResult;
}
static bool GetLibraryLocation(wstring& strLocation)
{
TCHAR *pszPath = _wgetenv(L"IPG_Dir");
if (pszPath == NULL || wcslen(pszPath) == 0)
return false;
TCHAR *pszVersion = _wgetenv(L"IPG_Ver");
if (pszVersion == NULL || wcslen(pszVersion) == 0)
return false;
int version = _wtof(pszVersion) * 100;
if (version >= 270)
{
#if _M_X64
strLocation = wstring(pszPath) + L"\\EnergyLib64.dll";
#else
strLocation = wstring(pszPath) + L"\\EnergyLib32.dll";
#endif
return true;
}
else
return false;
}
CIntelPowerGadgetLib::CIntelPowerGadgetLib(void) :
pInitialize(NULL),
pGetNumNodes(NULL),
pGetMsrName(NULL),
pGetMsrFunc(NULL),
pGetIAFrequency(NULL),
pGetTDP(NULL),
pGetMaxTemperature(NULL),
pGetTemperature(NULL),
pReadSample(NULL),
pGetSysTime(NULL),
pGetRDTSC(NULL),
pGetTimeInterval(NULL),
pGetBaseFrequency(NULL),
pGetPowerData(NULL),
pStartLog(NULL),
pStopLog(NULL),
pGetNumMsrs(NULL)
{
wstring strLocation;
if (GetLibraryLocation(strLocation) == false)
{
g_lastError = "Intel Power Gadget 2.7 or higher not found. If unsure, check if the path is in the user's path environment variable";
return;
}
g_hModule = LoadLibrary(strLocation.c_str());
if (g_hModule == NULL)
{
g_lastError = "LoadLibrary failed";
return;
}
pInitialize = (IPGInitialize) GetProcAddress(g_hModule, "IntelEnergyLibInitialize");
pGetNumNodes = (IPGGetNumNodes) GetProcAddress(g_hModule, "GetNumNodes");
pGetMsrName = (IPGGetMsrName) GetProcAddress(g_hModule, "GetMsrName");
pGetMsrFunc = (IPGGetMsrFunc) GetProcAddress(g_hModule, "GetMsrFunc");
pGetIAFrequency = (IPGGetIAFrequency) GetProcAddress(g_hModule, "GetIAFrequency");
pGetTDP = (IPGGetTDP) GetProcAddress(g_hModule, "GetTDP");
pGetMaxTemperature = (IPGGetMaxTemperature) GetProcAddress(g_hModule, "GetMaxTemperature");
pGetTemperature = (IPGGetTemperature) GetProcAddress(g_hModule, "GetTemperature");
pReadSample = (IPGReadSample) GetProcAddress(g_hModule, "ReadSample");
pGetSysTime = (IPGGetSysTime) GetProcAddress(g_hModule, "GetSysTime");
pGetRDTSC = (IPGGetRDTSC) GetProcAddress(g_hModule, "GetRDTSC");
pGetTimeInterval = (IPGGetTimeInterval) GetProcAddress(g_hModule, "GetTimeInterval");
pGetBaseFrequency = (IPGGetBaseFrequency) GetProcAddress(g_hModule, "GetBaseFrequency");
pGetPowerData = (IPGGetPowerData) GetProcAddress(g_hModule, "GetPowerData");
pStartLog = (IPGStartLog) GetProcAddress(g_hModule, "StartLog");
pStopLog = (IPGStopLog) GetProcAddress(g_hModule, "StopLog");
pGetNumMsrs = (IPGGetNumMsrs) GetProcAddress(g_hModule, "GetNumMsrs");
}
CIntelPowerGadgetLib::~CIntelPowerGadgetLib(void)
{
if (g_hModule != NULL)
FreeLibrary(g_hModule);
}
string CIntelPowerGadgetLib::GetLastError()
{
return g_lastError;
}
bool CIntelPowerGadgetLib::IntelEnergyLibInitialize(void)
{
if (pInitialize == NULL)
return false;
bool bSuccess = pInitialize();
if (!bSuccess)
{
g_lastError = "Initializing the energy library failed";
return false;
}
return true;
}
bool CIntelPowerGadgetLib::GetNumNodes(int * nNodes)
{
return pGetNumNodes(nNodes);
}
bool CIntelPowerGadgetLib::GetNumMsrs(int * nMsrs)
{
return pGetNumMsrs(nMsrs);
}
bool CIntelPowerGadgetLib::GetMsrName(int iMsr, wchar_t *pszName)
{
return pGetMsrName(iMsr, pszName);
}
bool CIntelPowerGadgetLib::GetMsrFunc(int iMsr, int *funcID)
{
return pGetMsrFunc(iMsr, funcID);
}
bool CIntelPowerGadgetLib::GetIAFrequency(int iNode, int *freqInMHz)
{
return pGetIAFrequency(iNode, freqInMHz);
}
bool CIntelPowerGadgetLib::GetTDP(int iNode, double *TDP)
{
return pGetTDP(iNode, TDP);
}
bool CIntelPowerGadgetLib::GetMaxTemperature(int iNode, int *degreeC)
{
return pGetMaxTemperature(iNode, degreeC);
}
bool CIntelPowerGadgetLib::GetTemperature(int iNode, int *degreeC)
{
return pGetTemperature(iNode, degreeC);
}
bool CIntelPowerGadgetLib::ReadSample()
{
bool bSuccess = pReadSample();
if (bSuccess == false)
g_lastError = "MSR overflowed. You can safely discard this sample";
return bSuccess;
}
bool CIntelPowerGadgetLib::GetSysTime(SYSTEMTIME *sysTime)
{
return pGetSysTime(sysTime);
}
bool CIntelPowerGadgetLib::GetRDTSC(UINT64 *TSC)
{
return pGetRDTSC(TSC);
}
bool CIntelPowerGadgetLib::GetTimeInterval(double *offset)
{
return pGetTimeInterval(offset);
}
bool CIntelPowerGadgetLib::GetBaseFrequency(int iNode, double *baseFrequency)
{
return pGetBaseFrequency(iNode, baseFrequency);
}
bool CIntelPowerGadgetLib::GetPowerData(int iNode, int iMSR, double *results, int *nResult)
{
return pGetPowerData(iNode, iMSR, results, nResult);
}
bool CIntelPowerGadgetLib::StartLog(wchar_t *szFilename)
{
return pStartLog(szFilename);
}
bool CIntelPowerGadgetLib::StopLog()
{
return pStopLog();
}