# -*-Perl-*- # instances allowed: one # (single instance modules would be silly to use more than one of # anyway, so we use package local storage. This is faster and places # less artificial load on the machine than doing everything through # the object hash) package MGMmodule::cpustat; use vars qw($numcpus $statcpus $xpath $graph @load @total @prevload @prevtotal $lastmod); # class init sub module_init{ my$this=shift; my$xclass=$this->{"xclass"}; # how many CPUs? Get this from /proc/cpuinfo then /proc/stat. # /proc/stat only sees multiple CPUs as of late 2.1, but we # at least want to mark the single bar as SMP under 2.0 $lastmod=-1; $numcpus=1; $statcpus=1; my $countedcpus=0; if(defined($MGMmodule::helperST::proc{"cpu"}) && open(PROC,"){ if(m/processor\s*:\s*(\d*)/){ $numcpus=$1+1 if ($numcpus<$1+1); } if(m/cpu\S*\s*:/){ $countedcpus++; } } $numcpus=$countedcpus if ($numcpus<$countedcpus); close PROC; # now check /proc/stat to see how many cpus it reports $this->read_proc; }else{ $this->{"toplevel"}->optionAdd("$xclass.active",0,21); } $this->{"toplevel"}->optionAdd("$xclass.order", 1,21); $this; } # instance init sub module_instance{ my$this=shift; my$toplevel=$this->{"toplevel"}; return undef if(defined($xpath)); $xpath=$this->{"xpath"}; ($minx,$miny)=MGM::Graph::calcxysize($this,100,'%',$statcpus); if($numcpus>1 && $statcpus==1){ $toplevel->optionAdd("$xpath.bar.0.label", "cpus 0-".($numcpus-1),22); }else{ for(my$i=0;$i<$numcpus;$i++){ $toplevel->optionAdd("$xpath.bar.$i.label", "cpu$i",22); } } $toplevel->optionAdd("$xpath.scalerefresh", 500,21); # faster $toplevel->optionAdd("$xpath.scalewidadj", 100*$statcpus,21); $toplevel->optionAdd("$xpath.scalelenadj", 100,21); $toplevel->optionAdd("$xpath.minx", $minx,21); $toplevel->optionAdd("$xpath.miny", $miny,21); $this; } # instance widget build sub module_run{ my($this)=@_; if($statcpus==1){ $graph=MGM::Graph->new($this,num=>1,fixed=>'1', prompt=>"%",rangecurrent=>100*$numcpus, rangesetting=>100*$numcpus); }else{ $graph=MGM::Graph->new($this,num=>$statcpus,fixed=>'1', prompt=>"%",rangecurrent=>100, rangesetting=>100); } $lastmod=-1; $graph->{"widget"}; # must return widget } sub module_update{ my$this=shift; if($lastmod!=$MGMmodule::helperST::lastmod){ # don't update unless the helper has $lastmod=$MGMmodule::helperST::lastmod; $this->read_proc; if(defined(@prevload)){ my@vals; if($statcpus==1){ my$tot=$total[0]-$prevtotal[0]; if($tot>0){ $vals[0]=100*($load[0]-$prevload[0])/$tot; $vals[0]=100*$numcpus if $vals[0]>100*$numcpus; }else{ $vals[0]=0; } }else{ for(my$i=0;$i<$statcpus;$i++){ my$tot=$total[$i+1]-$prevtotal[$i+1]; if($tot>0){ $vals[$i]=100*($load[$i+1]-$prevload[$i+1])/$tot; $vals[$i]=100 if $vals[$i]>100; }else{ $vals[$i]=0; } } } $graph->set(@vals); } @prevload=@load; @prevtotal=@total; } } sub read_proc{ # now uses the 00helper to save on opens # in late 2.1+ kernels, each CPU has an entry in /proc/stat along with # a common entry. Earlier, only the common entry. # collective cpu entry $MGMmodule::helperST::proc{"cpu"}=~m/^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/; $load[0]=$1+$2+$3; $total[0]=$load[0]+$4; for(my$i=0;defined(my$line=$MGMmodule::helperST::proc{"cpu$i"});$i++){ $line=~m/^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/; # per-cpu entry $total[$i+1]=($load[$i+1]=$1+$2+$3)+$4; $numcpus=$statcpus=$i+1 if($i+1>$statcpus); } } sub destroy{ undef $xpath; } bless {};