//
// Copyright (c) 1994, 1995, 2006 by Mike Romberg ( mike.romberg@noaa.gov )
//
// This file may be distributed under terms of the GPL
//
//
// $Id$
//
#include "intmeter.h"
#include "xosview.h"
#include "cpumeter.h"
#include <fstream>
#include <sstream>
#include <stdlib.h>
#ifdef __alpha__
#include <asm/irq.h>
#endif
static const char *INTFILE = "/proc/interrupts";
static const char *VERSIONFILE = "/proc/version";
static int realintnum[1024];
IntMeter::IntMeter( XOSView *parent, int cpu)
: BitMeter( parent, "INTS", "", 1,
0, 0 ), _cpu(cpu), _old(true) {
if (getLinuxVersion() <= 2.0)
_old = true;
else
_old = false;
irqs_=lastirqs_=0;
initirqcount();
}
IntMeter::~IntMeter( void ){
if(irqs_)
delete [] irqs_;
if(lastirqs_)
delete [] lastirqs_;
}
void IntMeter::checkevent( void ){
getirqs();
for ( int i = 0 ; i < numBits() ; i++ ){
bits_[i] = ((irqs_[i] - lastirqs_[i]) != 0);
lastirqs_[i] = irqs_[i];
}
BitMeter::checkevent();
}
void IntMeter::checkResources( void ){
BitMeter::checkResources();
onColor_ = parent_->allocColor( parent_->getResource( "intOnColor" ) );
offColor_ = parent_->allocColor( parent_->getResource( "intOffColor" ) );
priority_ = atoi(parent_->getResource("intPriority"));
}
float IntMeter::getLinuxVersion(void) {
std::ifstream vfile(VERSIONFILE);
if (!vfile) {
std::cerr << "Can not open file : " << VERSIONFILE << std::endl;
exit(1);
}
char buffer[128];
vfile >> buffer >> buffer >> buffer;
*strrchr(buffer, '.') = '\0';
std::istringstream is(std::string(buffer, 128));
float rval = 0.0;
is >> rval;
return rval;
}
int IntMeter::countCPUs(void) {
return CPUMeter::countCPUs();
}
void IntMeter::getirqs( void ){
std::ifstream intfile( INTFILE );
int intno, count;
int idx;
if ( !intfile ){
std::cerr <<"Can not open file : " <<INTFILE << std::endl;
exit( 1 );
}
if (!_old)
intfile.ignore(1024, '\n');
while ( !intfile.eof() ){
intfile >> idx;
intno = realintnum[idx];
if(intno>=numBits())
updateirqcount(intno,false);
if (!intfile) break;
intfile.ignore(1);
if ( !intfile.eof() ){
for (int i = 0 ; i <= _cpu ; i++)
intfile >>count;
intfile.ignore(1024, '\n');
irqs_[intno] = count;
}
}
}
/* The highest numbered interrupts, the number of interrupts
* is going to be at least +1 (for int 0) and probably higher
* if interrupts numbered more than this one just aren't active.
* Must call with init = true the first time.
*/
void IntMeter::updateirqcount( int n, bool init ){
int old_bits=numBits();
setNumBits(n+1);
std::ostringstream os;
os << "INTs (0-16" ;
for (int i=16; i<1024; i++) {
if (realintnum[i])
os << ", " << (i) ;
}
os << ")" << std::ends;
legend(os.str().c_str());
unsigned long *old_irqs_=irqs_, *old_lastirqs_=lastirqs_;
irqs_=new unsigned long[n+1];
lastirqs_=new unsigned long[n+1];
/* If we are in init, set it to zero,
* otherwise copy over the old set */
if( init ) {
for( int i=0; i < n; i++)
irqs_[i]=lastirqs_[i]=0;
}
else {
for( int i=0; i < old_bits; i++) {
irqs_[i]=old_irqs_[i];
lastirqs_[i]=old_lastirqs_[i];
}
// zero to the end the irq's that haven't been seen before
for( int i=old_bits; i< numBits(); i++) {
irqs_[i]=lastirqs_[i]=0;
}
}
if(old_irqs_)
delete [] old_irqs_;
if(old_lastirqs_)
delete [] old_lastirqs_;
}
/* Find the highest number of interrupts and call updateirqcount to
* update the number of interrupts listed
*/
void IntMeter::initirqcount( void ){
std::ifstream intfile( INTFILE );
int intno = 0;
int i, idx;
if ( !intfile ){
std::cerr <<"Can not open file : " <<INTFILE << std::endl;
exit( 1 );
}
if (!_old) {
for (i=0; i<1024; i++) // init index into int array
if (i < 16) // first 16 map directly
realintnum[i] = i;
else
realintnum[i] = 0;
intfile.ignore(1024, '\n');
}
/* just looking for the highest number interrupt that
* is in use, ignore the rest of the data
*/
idx = 16;
while ( !intfile.eof() ){
intfile >> i;
if (i < 16)
intno = i;
else {
intno = idx;
realintnum[i] = idx++;
}
if (!intfile) break;
intfile.ignore(1024, '\n');
}
updateirqcount(intno, true);
}
syntax highlighted by Code2HTML, v. 0.9.1