/*
* AIX CPU support (including SMP for AIX 4.x)
*
* John DiMarco <jdd@cs.toronto.edu>, University of Toronto, CSLab
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/sysinfo.h>
#include <nlist.h>
extern char *kernelSymbols;
extern int sep_wait, cpuflag;
#ifndef MAXCPU
#define MAXCPU 64
#endif /* MAXCPU */
#ifndef KMEM
#define KMEM "/dev/kmem"
#endif /* KMEM */
#ifndef KSYMS
#define KSYMS "/unix"
#endif /* KSYMS */
#ifdef SMP
#define NPROCS MAXCPU
#define CPUINFO "cpuinfo"
#else
#define cpuinfo sysinfo
#define CPUINFO "sysinfo"
#define NPROCS 1
#endif
#define BUFFSIZE 64
int ncpus;
struct cpuinfo cpu[MAXCPU];
long cp_time[NPROCS][CPU_NTIMES];
long cp_old [NPROCS][CPU_NTIMES];
int kmem; /* file descriptor for /dev/kmem. */
struct nlist nl[] = {
#define N_NCPU 0
{ "number_of_cpus" },
#define N_CPUINFO 1
{ CPUINFO },
{ "" },
};
/* Called by -version */
void
version()
{
printf("AIX: maxcpu=%d, maxdisk=0\n", NPROCS);
}
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars()
{
if(!cpuflag) return 0;
if (0>(kmem = open(KMEM, O_RDONLY))){
perror(KMEM);
exit(1);
}
if (0>nlist(kernelSymbols?kernelSymbols:KSYMS, nl)){
perror(kernelSymbols?kernelSymbols:KSYMS);
exit(1);
}
#if 1==NPROCS
ncpus=1;
return NPROCS;
/* NOTREACHED */
#endif
if ((off_t)nl[N_NCPU].n_value !=
lseek(kmem,(off_t)nl[N_NCPU].n_value, SEEK_SET)){
perror("lseek _number_of_cpus");
exit(1);
}
if (sizeof(ncpus) != read(kmem, (char *)&ncpus, sizeof(ncpus))){
perror("read _number_of_cpus");
exit(1);
}
return ncpus;
}
/*
* Indicates how many levels each bar has. For most machines, each bar will
* have the same stuff. But one can, for instance, display memory use on one
* bar, processor levels on others, etc.
*/
void
bar_items(nbars, items)
int nbars;
int items[]; /* nbars items in this */
{
int i;
for(i=0; i<nbars; i++){
items[i] = CPU_NTIMES;
}
}
/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
char **names;
int i;
static char hname[MAXHOSTNAMELEN + 1];
char buf[MAXHOSTNAMELEN + 1 + BUFFSIZE];
char *cpname="";
hname[MAXHOSTNAMELEN] = '\0';
if (0 >gethostname(hname, MAXHOSTNAMELEN)) {
perror("gethostname");
*hname = '\0';
}
shorten(hname);
names = (char **) xmalloc(nbars * sizeof(char *));
/* do cpu names */
for(i=0; i<ncpus; i++) {
(void) sprintf(buf, "%s%s%s%d", hname,
hname[0]?" ":"", cpname, i);
names[i] = (char *)xmalloc(strlen(buf)+1);
(void) strcpy(names[i], buf);
}
return names;
}
/*
* Called after the bars are created to perform any machine dependent
* initializations.
*/
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
int i,j;
if ((off_t)nl[N_CPUINFO].n_value !=
lseek(kmem,(off_t)nl[N_CPUINFO].n_value, SEEK_SET)){
perror("lseek _cpuinfo");
exit(1);
}
if ((ncpus * sizeof(struct cpuinfo)) !=
read(kmem, (char *)cpu, ncpus * sizeof(struct cpuinfo))){
perror("read _cpuinfo");
exit(1);
}
for (i=0;i<ncpus;i++) {
for(j=0;j<CPU_NTIMES;j++){
cp_old[i][j]=cpu[i].cpu[j];
}
}
}
/*
* This procedure gets called every interval to compute and display the
* bars. It should call draw_bar() with the bar number, the array of
* integer values to display in the bar, and the number of values in
* the array.
*/
/* ARGSUSED */
void
display_bars(nbars)
{
int states[CPU_NTIMES];
int nstates;
int i,j;
if ((off_t)nl[N_CPUINFO].n_value !=
lseek(kmem,(off_t)nl[N_CPUINFO].n_value, SEEK_SET)){
perror("lseek _cpuinfo");
exit(1);
}
if ((ncpus * sizeof(struct cpuinfo)) !=
read(kmem, (char *)cpu, ncpus * sizeof(struct cpuinfo))){
perror("read _cpuinfo");
exit(1);
}
#define delta(c) ((int) (cp_time[i][(c)] - cp_old[i][(c)]))
for (i=0; i<ncpus; i++) {
for(j=0;j<CPU_NTIMES;j++){
cp_time[i][j]=cpu[i].cpu[j];
}
nstates = 0;
if(sep_wait){
states[nstates++] = delta(CPU_IDLE);
states[nstates++] = delta(CPU_WAIT);
} else {
states[nstates++] = delta(CPU_IDLE) + delta(CPU_WAIT);
}
states[nstates++] = delta(CPU_USER);
states[nstates++] = delta(CPU_KERNEL);
draw_bar(i, states, nstates);
}
for (i=0; i<ncpus; i++){
for (j=0; j<CPU_NTIMES; j++){
cp_old[i][j] = cp_time[i][j];
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1