in source/code/scxsystemlib/cpu/cpuenumeration.cpp [660:1419]
void CPUEnumeration::Update(bool updateInstances)
{
SCXCoreLib::SCXThreadLock lock(m_lock);
#if defined(hpux)
// Note: The HPUX implementation can't use ProcessorCountLogical because
// code below requires some of the intermediate values ("psp", for example)
struct pst_dynamic psd;
if (m_deps->pstat_getdynamic(&psd, sizeof (psd), (size_t)1, 0) == -1)
{
// !!!!!! Should we throw here?
throw SCXInternalErrorException(L"pstat_getdynamic() failed", SCXSRCLOCATION);
}
// Get the number of maximum CPUs that can be active on this platform
size_t max_cpus = psd.psd_max_proc_cnt;
std::vector<struct pst_processor> psp_vector(max_cpus);
struct pst_processor* psp = &psp_vector[0];
// Get the processor info, count will contain the number of CPUs, active AND in-active.
size_t count = m_deps->pstat_getprocessor(psp, sizeof (struct pst_processor), max_cpus, 0);
if ( count <= 0)
{
throw SCXInternalErrorException(L"pstat_getprocessor() failed", SCXSRCLOCATION);
}
#else
size_t count = ProcessorCountLogical(m_deps);
#endif // defined(hpux)
SCX_LOGTRACE(m_log, StrAppend(StrAppend(L"CPUEnumeration Update() - ", updateInstances).append(L" - "), count));
#if defined(linux) || defined(WIN32)
// add cpus if needed
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - begin Add loop for Linux CPU enumeration. (size = ", Size()).append(L")"));
for (size_t i=Size(); i<count; i++)
{
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - Adding CPU ", i));
AddInstance(SCXCoreLib::SCXHandle<CPUInstance>(new CPUInstance(static_cast<unsigned int>(i), m_sampleSize)));
}
SCX_LOGTRACE(m_log, L"CPUEnumeration Update() - end Add loop for Linux CPU enumeration.");
// remove cpus if needed
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - begin Remove outer loop for Linux CPU enumeration. (size = ", Size()).append(L")"));
while (count < Size())
{
bool found = false;
SCX_LOGTRACE(m_log, L"CPUEnumeration Update() - begin Remove inner loop for Linux CPU enumeration.");
for (EntityIterator iter = Begin(); !found && iter != End(); iter++)
{
SCXCoreLib::SCXHandle<CPUInstance> inst = *iter;
if (inst->GetProcNumber() == Size()-1)
{
found = true;
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - Removing CPU ", inst->GetProcNumber()));
RemoveInstance(iter);
}
}
SCX_LOGTRACE(m_log, L"CPUEnumeration Update() - end Remove inner loop for Linux CPU enumeration.");
if (!found)
{
throw SCXInternalErrorException(L"CPU with expected Proc Number not found in internal list",
SCXSRCLOCATION);
}
}
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - end Remove outer loop for Linux CPU enumeration. (size = ", Size()).append(L")"));
#elif defined(sun) || defined(hpux)
// Remove CPUs no longer available and enabled
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - begin Remove outer loop for Solaris/HPUX CPU enumeration. (size = ", Size()).append(L")"));
EntityIterator iter = Begin();
while (iter != End())
{
SCXCoreLib::SCXHandle<CPUInstance> inst = *iter;
if (IsCPUEnabled(inst->GetProcNumber()))
{
SCX_LOGHYSTERICAL(m_log, StrAppend(L"CPUEnumeration Update() - Keeping CPU", inst->GetProcNumber()));
++iter;
}
else
{
// This will advance iter to next item after removal
SCX_LOGHYSTERICAL(m_log, StrAppend(L"CPUEnumeration Update() - Removing CPU", inst->GetProcNumber()));
iter = RemoveInstance(iter);
}
}
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - end Remove outer loop for Solaris/HPUX CPU enumeration. (size = ", Size()).append(L")"));
// add cpus if needed
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - begin Add loop for Solaris/HPUX CPU enumeration. (size = ", Size()).append(L")"));
#if defined(hpux)
size_t ix = 0; // index used to get the logical id of a cpu
for (size_t i = 0; i = static_cast<size_t>(psp[ix].psp_logical_id), ix < max_cpus; ix++)
{
#elif defined(sun)
// Enumerate all possible CPUs allowed by the system and add any new instances that
// are enabled.
size_t num_cpu_avail = 0;
// Refresh the Kstat chain - adding/removing instances
m_kstatHandle->Update();
for (kstat_t* cur = m_kstatHandle->ResetInternalIterator(); cur; cur = m_kstatHandle->AdvanceInternalIterator())
{
if (strcmp(cur->ks_module, "cpu_info") != 0 || cur->ks_type != KSTAT_TYPE_NAMED )
continue;
// Look up instance ID for consistency with existing code
size_t i = cur->ks_instance;
// a given processor ID is assigned by the OS as "available" if it has a status
// that is != -1
SCX_LOGHYSTERICAL(m_log, StrAppend(L"CPUEnumeration::Update() - calling p_online(", i).append(L", P_STATUS)"));
int status = m_deps->p_online(i, P_STATUS);
SCX_LOGHYSTERICAL(m_log, StrAppend(L"CPUEnumeration::Update() - p_online status: ", status));
if (-1 == status)
{
if (EINVAL == errno)
{
// not currently assigned, so ignore it
continue;
}
else
{
SCX_LOGWARNING(m_log, StrAppend(L"CPUEnumeration::Update() - p_online status: -1 (", errno).append(L"), the CPU is in an error state"));
throw SCXErrnoException(L"p_online", errno, SCXSRCLOCATION);
}
}
// avail, check below to determine if enabled
num_cpu_avail++;
#else
#error "This code is only for hpux & sun"
#endif
if (IsCPUEnabled(i))
{
bool found = false;
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - begin Search loop for CPU ", i));
for (iter = Begin(); !found && iter != End(); iter++)
{
SCXCoreLib::SCXHandle<CPUInstance> inst = *iter;
if (inst->GetProcNumber() == i)
{
SCX_LOGHYSTERICAL(m_log, StrAppend(L"CPUEnumeration Update() - Tracking CPU ", i));
found = true;
}
}
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - end Search loop for CPU ", i));
if (!found)
{
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - Adding CPU ", i));
AddInstance(SCXCoreLib::SCXHandle<CPUInstance>(new CPUInstance(i, m_sampleSize)));
}
}
}
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - end Add loop for Solaris/HPUX CPU enumeration. (size = ", Size()).append(L")"));
#if defined(sun)
// Keep track of how often the number of CPU enumerated is different
// than what was expected. The code should handle this descrepancy, but
// it is usefull to know how often it happens.
size_t cpu_configured = m_deps->sysconf(_SC_NPROCESSORS_CONF);
if (num_cpu_avail != cpu_configured)
{
SCX_LOGTRACE(m_log, StrAppend(StrAppend(L"CPUEnumeration Update() - the enumeration contains ", num_cpu_avail).append(L", but expected "), cpu_configured));
}
#endif
#elif defined(aix)
/* There is nothing to do here for AIX. All instance maintenance is done
in the updater thread. The actual instances update themselves
through the code below.
*/
#else
#error "Not implemented for this platform"
#endif
if (updateInstances)
{
UpdateInstances();
}
}
/*----------------------------------------------------------------------------*/
/**
Cleanup
*/
void CPUEnumeration::CleanUp()
{
SCX_LOGTRACE(m_log, L"CPUEnumeration CleanUp()");
m_dataAquisitionThread->RequestTerminate();
m_dataAquisitionThread->Wait();
}
/*----------------------------------------------------------------------------*/
/**
Store new data for all instances
*/
void CPUEnumeration::SampleData()
{
#if defined(sun)
// Update our collection so we sample something rational
// This is needed to handle dynamic CPUs on Solaris, which
// may have added new CPUs (and removed all old CPUs) since
// our last update. At least this way, we sample something
// rational ...
//
// Note: Need to do this before grabbing SCXThreadLock!
Update();
#endif
SCX_LOGTRACE(m_log, L"CPUEnumeration - Start SampleData");
SCX_LOGHYSTERICAL(m_log, L"CPUEnumeration SampleData - Acquire lock ");
SCXCoreLib::SCXThreadLock lock(m_lock);
SCX_LOGHYSTERICAL(m_log, L"CPUEnumeration SampleData - Lock acquired, get data ");
#if defined(linux) || defined(WIN32)
SCXHandle<std::wistream> statFile = m_deps->OpenStatFile();
wstring line;
SCXCoreLib::SCXStream::NLF nlf;
for (SCXCoreLib::SCXStream::ReadLine(*statFile, line, nlf);
SCXCoreLib::SCXStream::IsGood(*statFile);
SCXCoreLib::SCXStream::ReadLine(*statFile, line, nlf))
{
vector<wstring> tokens;
SCXCoreLib::SCXHandle<CPUInstance> inst(0);
SCX_LOGHYSTERICAL(m_log, wstring(L"CPUEnumeration SampleData - Read line: ").append(line));
StrTokenize(line, tokens);
if (tokens.size() > 0)
{
// See example of stat file at the end of this source code file
if (StrIsPrefix(tokens[0], L"cpu"))
{
if (tokens[0].compare(L"cpu") == 0)
{
inst = GetTotalInstance();
SCX_LOGHYSTERICAL(m_log, L"CPUEnumeration SampleData - Found total row");
}
for (size_t i = 0; inst == NULL && i < Size(); i++)
{
SCXCoreLib::SCXHandle<CPUInstance> tmp_inst = GetInstance(i);
// Concatinate a string to match representing a specific CPU
if (tokens[0].compare(wstring(L"cpu").append(tmp_inst->GetProcName())) == 0)
{
inst = tmp_inst;
SCX_LOGHYSTERICAL(m_log, StrAppend(L"CPUEnumeration SampleData - Found instance row - ", inst->GetProcNumber()));
}
}
if (inst != NULL)
{
scxulong user = 0;
scxulong nice = 0;
scxulong system = 0;
scxulong idle = 0;
scxulong iowait = 0;
scxulong irq = 0;
scxulong softirq = 0;
if (tokens.size() >= 5)
{
try
{
user = StrToULong(tokens[1]);
SCX_LOGHYSTERICAL(m_log, StrAppend(L" Read user = ", user));
nice = StrToULong(tokens[2]);
SCX_LOGHYSTERICAL(m_log, StrAppend(L" Read nice = ", nice));
system = StrToULong(tokens[3]);
SCX_LOGHYSTERICAL(m_log, StrAppend(L" Read system = ", system));
idle = StrToULong(tokens[4]);
SCX_LOGHYSTERICAL(m_log, StrAppend(L" Read idle = ", idle));
}
catch (const SCXNotSupportedException& e)
{
SCX_LOGWARNING(m_log, wstring(L"Could not parse line from stat file: ").append(line).append(L" - ").append(e.What()));
}
if (tokens.size() >= 8)
{
try
{
iowait = StrToULong(tokens[5]);
SCX_LOGHYSTERICAL(m_log, StrAppend(L" Read iowait = ", iowait));
irq = StrToULong(tokens[6]);
SCX_LOGHYSTERICAL(m_log, StrAppend(L" Read irq = ", irq));
softirq = StrToULong(tokens[7]);
SCX_LOGHYSTERICAL(m_log, StrAppend(L" Read softirq = ", softirq));
}
catch (const SCXNotSupportedException& e)
{
SCX_LOGWARNING(m_log, wstring(L"Could not parse line from stat file: ").append(line).append(L" - ").append(e.What()));
}
}
else
{
iowait = irq = softirq = 0;
}
scxulong total_tics = user + nice + system + iowait + irq + softirq + idle;
SCX_LOGHYSTERICAL(m_log, StrAppend(L" Calculate total = ", total_tics));
// Add new values using friendship declared on the
// instance class (the m_*_tics properties are private)
inst->m_UserCPU_tics.AddSample(user);
inst->m_NiceCPU_tics.AddSample(nice);
inst->m_SystemCPUTime_tics.AddSample(system);
inst->m_IdleCPU_tics.AddSample(idle);
inst->m_IOWaitTime_tics.AddSample(iowait);
inst->m_IRQTime_tics.AddSample(irq);
inst->m_SoftIRQTime_tics.AddSample(softirq);
inst->m_Total_tics.AddSample(total_tics);
SCX_LOGHYSTERICAL(m_log, L"CPUEnumeration SampleData - All Values stored");
}
else
{
SCX_LOGERROR(m_log, StrAppend(L"CPUEnumeration SampleData - Too few column in data file - ", tokens.size()));
}
}
else
{
SCX_LOGERROR(m_log, wstring(L"CPUEnumeration SampleData - No CPU in list found that match row in data file - ").append(tokens[0]));
}
}
}
}
#elif defined(sun) || defined(hpux)
SCX_LOGTRACE(m_log, L"CPUEnumeration::SampleData() entry");
scxulong user_tot = 0;
scxulong system_tot = 0;
scxulong idle_tot = 0;
scxulong iowait_tot = 0;
scxulong nice_tot = 0;
scxulong irq_tot = 0;
scxulong softirq_tot = 0;
#if defined(sun)
// Refresh the Kstat chain - adding/removing instances
m_kstatHandle->Update();
#endif
for (EntityIterator iter = Begin(); iter != End(); iter++)
{
SCXCoreLib::SCXHandle<CPUInstance> inst = *iter;
if (IsCPUEnabled(inst->GetProcNumber()))
{
try
{
#if defined(sun)
CPUStatHelper stat(inst->GetProcNumber(), m_kstatHandle, m_deps);
#else /* hp */
CPUStatHelper stat(inst->GetProcNumber(), m_deps);
#endif
user_tot += stat.User;
system_tot += stat.System;
idle_tot += stat.Idle;
iowait_tot += stat.IOWait;
nice_tot += stat.Nice;
irq_tot += stat.Irq;
softirq_tot += stat.SoftIrq;
wostringstream output;
output << L"Instance: " << inst->GetProcNumber()
<< L", Total tics: " << stat.Total
<< L", User: " << stat.User
<< L", System: " << stat.System
<< L", Idle: " << stat.Idle;
SCX_LOGHYSTERICAL(m_log, L"CPUEnumeration::SampleData(): " + output.str());
// Add new values using friendship declared on the
// instance class (the m_*_tics properties are private)
inst->m_UserCPU_tics.AddSample(stat.User);
inst->m_NiceCPU_tics.AddSample(stat.Nice);
inst->m_SystemCPUTime_tics.AddSample(stat.System);
inst->m_IdleCPU_tics.AddSample(stat.Idle);
inst->m_IOWaitTime_tics.AddSample(stat.IOWait);
inst->m_IRQTime_tics.AddSample(stat.Irq);
inst->m_SoftIRQTime_tics.AddSample(stat.SoftIrq);
inst->m_Total_tics.AddSample(stat.Total);
}
catch (const SCXException& e)
{
SCX_LOGWARNING(m_log, StrAppend(L"CPUStatHelper failed for CPU: ", inst->GetProcNumber()).append(L" - ").append(e.What()));
}
}
else
{
SCX_LOGINFO(m_log, StrAppend(L"Processor no longer online: ", inst->GetProcNumber()));
}
}
SCXCoreLib::SCXHandle<CPUInstance> inst = GetTotalInstance();
scxulong total_tics = user_tot + nice_tot + system_tot +
iowait_tot + irq_tot + softirq_tot + idle_tot;
wostringstream totals;
totals << L"Instance: _total"
<< L", Total tics: " << total_tics
<< L", User: " << user_tot
<< L", System: " << system_tot
<< L", Idle: " << idle_tot;
SCX_LOGHYSTERICAL(m_log, StrAppend(L"CPUEnumeration::SampleData(): ", totals.str()));
// Add new values using friendship declared on the
// instance class (the m_*_tics properties are private)
inst->m_UserCPU_tics.AddSample(user_tot);
inst->m_NiceCPU_tics.AddSample(nice_tot);
inst->m_SystemCPUTime_tics.AddSample(system_tot);
inst->m_IdleCPU_tics.AddSample(idle_tot);
inst->m_IOWaitTime_tics.AddSample(iowait_tot);
inst->m_IRQTime_tics.AddSample(irq_tot);
inst->m_SoftIRQTime_tics.AddSample(softirq_tot);
inst->m_Total_tics.AddSample(total_tics);
#elif defined(aix)
unsigned int conf_cpus = m_deps->sysconf(_SC_NPROCESSORS_CONF);
unsigned int cpucount = ProcessorCountLogical(m_deps);
/* Sanity check: The number of CPUs online can never be greater than
the number of configured CPUs. This is a fatal error. */
if (cpucount > conf_cpus)
{
throw SCXInternalErrorException(L"Number of actual CPUs is greater that the"
L"number of configured CPUs", SCXSRCLOCATION);
}
/* Here we increase the number of managed instances to match the number of
online (logical) CPUs. This cannot happen during normal execution according
to the documentation; Once a CPU goes offline it won't come back until reboot.
But it will happen the first time this code is executed since the set of
instances is initially empty.
*/
for (unsigned int i = Size(); i < cpucount; i++)
{
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - Adding CPU ", i));
AddInstance(SCXCoreLib::SCXHandle<CPUInstance>(new CPUInstance(i, m_sampleSize)));
}
/* Remove instances that has gone off-line. AIX guarantees that it always
the highest numbered (logical) CPU that disappears. This has the side-effect
that statistics that was accumulated for one (physical) processor is suddently
reported reported for another processor. But this can only happen if a
processor malfunction. There are no admin tools that take CPUs offline or online.
*/
while (Size() > cpucount)
{
// This is a bit iffy way to remove the last instance, but the services
// provided by the EntityEnumeration class are rather limited.
unsigned int i = Size();
EntityIterator iter = Begin();
SCX_LOGTRACE(m_log, StrAppend(L"CPUEnumeration Update() - Removing CPU ", i - 1));
while (--i != 0)
{
++iter;
}
RemoveInstance(iter);
}
/* Extract the real CPU statistics. */
int res = m_deps->perfstat_cpu(&m_cpuid, &m_dataarea[0], sizeof (perfstat_cpu_t), cpucount);
if (res < 0)
{
throw SCXErrnoException(L"perfstat_cpu", errno, SCXSRCLOCATION);
}
/* Unlike on Sun and HPUX, we iterate over the most recent CPU statistics
and match it to the existing list of managed CPUs. */
for (int i = 0; i < cpucount; i++)
{
SCXCoreLib::SCXHandle<CPUInstance> inst = GetInstance(i);
inst->UpdateDataSampler(&m_dataarea[i]);
}
/* Update the total instance. On AIX there is a special syscall to get the
total CPU data. */
res = m_deps->perfstat_cpu_total(NULL, &m_dataarea_total, sizeof (perfstat_cpu_total_t), 1);
if (res < 0)
{
throw SCXErrnoException(L"perfstat_cpu_total", errno, SCXSRCLOCATION);
}
SCXCoreLib::SCXHandle<CPUInstance> inst = GetTotalInstance();
inst->UpdateDataSampler(&m_dataarea_total);
#else
#error "Not implemented for this platform"
#endif
SCX_LOGTRACE(m_log, L"CPUEnumeration - End SampleData");
}
/*----------------------------------------------------------------------------*/
/**
Thread body that updates all values
\param[in] param Must contain a parameter named "ParamValues" of type CPUEnumerationThreadParam*
The thread stores new values in all instances once every 10 seconds.
*/
void CPUEnumeration::DataAquisitionThreadBody(SCXCoreLib::SCXThreadParamHandle& param)
{
SCXLogHandle log = SCXLogHandleFactory::GetLogHandle(L"scx.core.common.pal.system.cpu.cpuenumeration");
SCX_LOGTRACE(log, L"CPUEnumeration::DataAquisitionThreadBody()");
if (0 == param)
{
SCXASSERT( ! "No parameters to DataAquisitionThreadBody");
return;
}
CPUEnumerationThreadParam* params = static_cast<CPUEnumerationThreadParam*>(param.GetData());
if (0 == params)
{
SCXASSERT( ! "Invalid parameters to DataAquisitionThreadBody");
return;
}
CPUEnumeration* cpuenum = params->GetCPUEnumeration();
if (0 == cpuenum)
{
SCXASSERT( ! "CPU Enumeration not set");
return;
}
bool bUpdate = true;
// Sleep for sample seconds (generally CPU_SECONDS_PER_SAMPLE,
// unless using 'real time' provider instance)
params->m_cond.SetSleep(cpuenum->m_sampleSecs * 1000);
{
SCXConditionHandle h(params->m_cond);
while ( ! params->GetTerminateFlag())
{
if (bUpdate)
{
cpuenum->SampleData();
bUpdate = false;
}
SCX_LOGHYSTERICAL(log, L"CPUEnumeration DataAquisition - Sleep ");
enum SCXCondition::eConditionResult r = h.Wait();
if (SCXCondition::eCondTimeout == r)
{
bUpdate = true;
}
}
}
SCX_LOGHYSTERICAL(log, L"CPUEnumeration DataAquisition - Ending ");
}
#if defined(sun) || defined(hpux)
/*----------------------------------------------------------------------------*/
/**
Constructor that instantiates any needed api's/objects that are needed for
the current platform and then reads the available CPU counters.
\param[in] cpuid The id of the CPU you want to read the counters from.
\param[in] kstatHandle Handle to an SCXKstat instance to use
\param[in] deps Dependencies for the CPU Enumeration.
\throws SCXInternalErrorException if pstat fails.
\throws SCXKstatErrorException if kstat internal error.
\throws SCXKstatNotFoundException if requested kstat is not found in kstat system.
*/
#if defined(sun)
CPUEnumeration::CPUStatHelper::CPUStatHelper(unsigned int cpuid, SCXCoreLib::SCXHandle<SCXKstat> kstatHandle, SCXHandle<CPUPALDependencies> deps)
:User(0), System(0), Idle(0), IOWait(0), Nice(0), Irq(0), SoftIrq(0), Total(0)
,m_cpuid(cpuid), m_deps(deps)
,m_kstat(kstatHandle)
#else /* hp */
CPUEnumeration::CPUStatHelper::CPUStatHelper(unsigned int cpuid, SCXHandle<CPUPALDependencies> deps)
:User(0), System(0), Idle(0), IOWait(0), Nice(0), Irq(0), SoftIrq(0), Total(0)
,m_cpuid(cpuid), m_deps(deps)
#endif
{
m_log = SCXLogHandleFactory::GetLogHandle(L"scx.core.common.pal.system.cpu.cpuenumeration.cpustathelper");
SCX_LOGTRACE(m_log, L"CPUStatHelper constructor");
// Initialize
Init();
#if defined(sun)
wostringstream id;
id << "cpu_stat" << cpuid;
// This will actually change the state of the CPUStatHelper instance to point at a specific CPU
// Necessary due to the commonality with HP
m_kstat->Lookup(L"cpu_stat", id.str(), cpuid);
#endif
// Read values;
Update();
}
#if defined(sun)
/*----------------------------------------------------------------------------*/
/**
Retrieves a CPU statistic counter from kstat.
\param[in] statistic The name of the CPU counter to read.
\returns The contents of the counter if it exists, otherwise 0.
*/
scxulong CPUEnumeration::CPUStatHelper::GetValue(const wstring & statistic)
{
try
{
return m_kstat->GetValue(statistic);
}
catch (const SCXKstatException& e)
{
SCX_LOGWARNING(m_log, StrAppend(L"kstat.GetValue() failed for " + statistic + L" for CPU: ", m_cpuid).append(L" - ").append(e.What()));
}
return 0;
}
#endif
/*----------------------------------------------------------------------------*/
/**
Initializes necessary APIs.
*/
void CPUEnumeration::CPUStatHelper::Init()
{
#if defined(sun)
// Nothing to do...
#elif defined(hpux)
struct pst_dynamic psd;
if (m_deps->pstat_getdynamic(&psd, sizeof (psd), (size_t)1, 0) == -1)
{
// !!!!!! Should we throw here?
throw SCXInternalErrorException(L"pstat_getdynamic() failed", SCXSRCLOCATION);
}
size_t cpu_count = psd.psd_max_proc_cnt;
std::vector<struct pst_processor> psp_vector(cpu_count);
struct pst_processor* psp = &psp_vector[0];
cpu_count = m_deps->pstat_getprocessor(psp, sizeof (pst_processor), cpu_count, 0);
if (0 >= cpu_count)
{
throw SCXInternalErrorException(L"pstat_getprocessor() failed", SCXSRCLOCATION);
}
size_t i;
for (i = 0; i < cpu_count; i++)
{
if (psp[i].psp_logical_id == static_cast<int>(m_cpuid) && psp[i].psp_processor_state == PSP_SPU_ENABLED)
{
memcpy(&m_pst_processor, &psp[i], sizeof (m_pst_processor));
break;
}
}
// Didn't find the CPU.
if (cpu_count == i)
{
memset(&m_pst_processor, 0, sizeof (m_pst_processor));
m_pst_processor.psp_logical_id = m_cpuid;
m_pst_processor.psp_processor_state = PSP_SPU_DISABLED;
User = 0;
System = 0;
Idle = 0;
IOWait = 0;
Nice = 0;
Irq = 0;
SoftIrq = 0;
SCX_LOGWARNING(m_log, StrAppend(L"Can't find CPU with logical id: ", m_cpuid));
}
#else
#error "Not implemented for this platform"
#endif
}
/*----------------------------------------------------------------------------*/
/**
Retrieves all counters relevant for the platform.
*/
void CPUEnumeration::CPUStatHelper::Update()
{
#if defined(sun)
// The Solaris V10 implementation
// User = GetValue(L"cpu_ticks_user");
// System = GetValue(L"cpu_ticks_kernel");
// Idle = GetValue(L"cpu_ticks_idle");
// IOWait = GetValue(L"cpu_ticks_wait");
const cpu_stat *cpu_stat_p = 0;
m_kstat->GetValueRaw(cpu_stat_p);
User = cpu_stat_p->cpu_sysinfo.cpu[CPU_USER];
System = cpu_stat_p->cpu_sysinfo.cpu[CPU_KERNEL];
Idle = cpu_stat_p->cpu_sysinfo.cpu[CPU_IDLE];
IOWait = cpu_stat_p->cpu_sysinfo.cpu[CPU_WAIT];
#elif defined(hpux)
Init();
User = m_pst_processor.psp_cpu_time[CP_USER];
Nice = m_pst_processor.psp_cpu_time[CP_NICE];
Idle = m_pst_processor.psp_cpu_time[CP_IDLE];
System = m_pst_processor.psp_cpu_time[CP_SYS];
IOWait = m_pst_processor.psp_cpu_time[CP_WAIT];
#else
#error "Not implemented for this platform"
#endif
// cout << " User " << User
// << " System " << System
// << " Idle " << Idle
// << " IOWait " << IOWait << endl;
// Calculate total
Total = User + Nice + Idle + System + IOWait + Irq + SoftIrq;
}
/*----------------------------------------------------------------------------*/
/**
Destructor.
*/
CPUEnumeration::CPUStatHelper::~CPUStatHelper()
{
}
#endif
}