/* * System dependent file for SunOS4.x machines, using the kvm library. /* John DiMarco, CSLab, University of Toronto */ /* LINTLIBRARY */ #define MULTIPROCESSOR #include #include #include #include #include #include #ifdef OMNI #include #include #include #include #include #include #include #include #include #include #include #include #include "/usr/sys/sundev/nereg.h" #define OMNICPU ns_st.nst_cpu_cur #define OMNISTATES 2 /* system, idle */ static int nomni = 0; #define NEMAX 16 #define NEBASE "/dev/ne" static int omfd[NEMAX]; static int omnum[NEMAX]; extern int omniflag; extern int open(); #endif #ifndef MAXHOSTNAMELEN /* Some U*x deviants managed to not have this in sys/param.h */ # define MAXHOSTNAMELEN 64 #endif /* define some extended processor states here, in case they're not defined in sys/dk.h (which is the case for 4.1.1 and below). */ #ifndef XPSTATES #define XPSTATES 8 #define XP_SPIN 0 #define XP_DISK 1 #define XP_SERV 2 #endif /* XPSTATES */ static int x_cp_time; static char *dk_name[DK_NDRIVE]; static int hz; static long dk_bps[DK_NDRIVE]; extern char *xmalloc(/* int nbytes */); extern void shorten(/* char *hname */); extern int diskflag; extern int cpuflag; extern char *kernelSymbols; #define NCPU 4 /* maximum possible number of CPUs. This isn't likely to */ /* change under SunOS4.x. SunOS5.x will require a new port */ /* of xcpustate anyways, so no need to think ahead here. */ #define DISKSTATES 3 /* idle, seek, transfer */ #define MPSTATES 6 /* idle, user, nice, system, spin, serv */ #define NULL (char *)0 static kvm_t *kd; int ncpu; /* number of CPUs */ int ndisk; /* number of disks */ int procset; /* flag of CPUs */ struct nlist nl[] = { #define N_NCPU 0 { "_ncpu" }, #define N_DK_BPS 1 { "_dk_bps" }, #define N_CP_TIME 2 { "_cp_time" }, #define N_DK_TIME 3 { "_dk_time" }, #define N_DK_WDS 4 { "_dk_wds" }, #define N_MP_TIME 5 { "_mp_time" }, #define N_XP_TIME 6 { "_xp_time" }, #define N_MBDINIT 7 { "_mbdinit" }, #define N_DK_IVEC 8 { "_dk_ivec" }, #define N_HZ 9 { "_hz" }, #define N_PROCSET 10 { "_procset" }, { "" }, }; #define DK_WDS_SIZE 64.0 #define BUFFSIZE 64 extern void draw_bar(/*int bar_num, int *states, int num_states*/); static char *kernel_getstring(address, info) char *address; char *info; { static char buff[BUFFSIZE]; if(kvm_read(kd, (u_long)address, (char *)buff, sizeof(buff)) != sizeof(buff)){ perror(info); } buff[BUFFSIZE-1]='\0'; /* just in case it's not null-terminated */ return(buff); } static void kernel_get(addr, dest, size, info) u_long addr; char *dest; u_int size; char *info; { /* get something from the kernel */ if(kvm_read(kd, addr, dest, size)!=size){ perror(info); exit(1); } } static void kernel_init(name) char *name; { /* initialize kernel */ if((kvm_t *)NULL==(kd=kvm_open(kernelSymbols, NULL, NULL, O_RDONLY, name))){ perror("kvm_open"); exit(1); } /* read namelist */ if(-1==kvm_nlist(kd, nl)){ perror("kvm_nlist"); exit(1); } } #ifdef OMNI static int omni_init() { /* count OMNI network coprocessors, initialize omfd/num tables */ char buff[BUFFSIZE]; int fd, there=0, i, n=0; /* probe /dev/ne0../dev/neNEMAX-1, check if present */ for(i=0;imaxlen) maxlen=tmp; } for(i=0;i0) { nbars += ncpu; } else { cpuflag=0; } } #ifdef OMNI if(omniflag){ nomni=omni_init(); if(nomni>0) { nbars += nomni; } else { omniflag=0; } } #endif /* OMNI */ if(diskflag){ ndisk=disk_init(); if(ndisk>0) { nbars += ndisk; } else { diskflag=0; } } return(nbars); } /* * 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, n=0; if(cpuflag){ for(i=0; i1)?MPSTATES:CPUSTATES; } } #ifdef OMNI if(omniflag){ for(i=0; igethostname(hname, MAXHOSTNAMELEN)) { perror("gethostname"); *hname = '\0'; } shorten(hname); names = (char **) xmalloc(nbars * sizeof(char *)); base=0; #ifdef OMNI if(omniflag) cpname="CP"; /* to distinguish main CPU(s) from nc400s */ #endif /* OMNI */ if(cpuflag) { /* do cpu names */ for(i=0, j=0; j> j) & 0x01) { (void) sprintf(buf, "%s%s%s%d", hname, hname[0]?" ":"", cpname, j); names[base+i] = strcpy(xmalloc(strlen(buf) + 1), buf); i++; } } base+=ncpu; } #ifdef OMNI if(omniflag) { /* do NC400 names */ for(i=0; i1){ x_cp_time=N_MP_TIME; } else { x_cp_time=N_CP_TIME; } } } #ifdef OMNI static void display_omni(base) int base; { /* display OMNI bars */ int states[OMNISTATES], nstates, i; struct ne_usrstat u; struct iovec iov; iov.iov_base=(char *)&u; iov.iov_len=sizeof(u); for(i=0;i1){ kernel_get(nl[N_XP_TIME].n_value, (char *)xp_time, sizeof(xp_time), "xp_time"); } #define xdelta(cpu, cpustate) ((int) (xp_time[cpu][(cpustate)] - \ xp_old[cpu][(cpustate)])) #define delta(cpu, cpustate) ((int) (cp_time[cpu][(cpustate)] - \ cp_old[cpu][(cpustate)])) for(p=0,i=0; i> i) & 0x01) { nstates=0; states[nstates++] = delta(i, CP_IDLE); states[nstates++] = delta(i, CP_USER); states[nstates++] = delta(i, CP_NICE); if(ncpu>1){ long sys, spin, serv; sys = delta(i, CP_SYS); spin = xdelta(i, XP_SPIN); serv = xdelta(i, XP_SERV); states[nstates++] = sys - (spin + serv); states[nstates++] = spin; states[nstates++] = serv; } else { states[nstates++] = delta(i, CP_SYS); } draw_bar(p+base, states, nstates); /* save old values */ for (j = 0; j < XPSTATES; j++){ xp_old[i][j] = xp_time[i][j]; } for (j = 0; j < CPUSTATES; j ++){ cp_old[i][j] = cp_time[i][j]; } p++; } } } static void display_disk(base) int base; { int states[DISKSTATES], i; long dk_time[DK_NDRIVE], dk_wds[DK_NDRIVE], dk_cp_time[CPUSTATES]; static long old_dk_time[DK_NDRIVE], old_dk_wds[DK_NDRIVE]; static double oldtime; double newtime, elapsedtime; /* compute elapsed time since last call */ kernel_get(nl[N_CP_TIME].n_value, (char *)dk_cp_time, sizeof(dk_cp_time), "dk_cp_time"); newtime=0.0; for(i=0;i 0.0){ transfertime = transfersize/diskrate; if(transfertime>1.0) transfertime=1.0; } else { transfertime = 0.0; } transfertime *= activetime; seektime = activetime - transfertime; if(seektime<0.0) seektime=0.0; idletime = elapsedtime - (transfertime + seektime); if(idletime<0.0) idletime=0.0; states[nstates++] = (long)(hz*idletime*elapsedtime); states[nstates++] = (long)(hz*seektime*elapsedtime); states[nstates++] = (long)(hz*transfertime*elapsedtime); draw_bar(i+base, states, nstates); old_dk_wds[i]=dk_wds[i]; old_dk_time[i]=dk_time[i]; } } /* * 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 nbars; { int n=0; if(cpuflag) { display_cpu(n); n+=ncpu; } #ifdef OMNI if(omniflag) { display_omni(n); n+=nomni; } #endif /* OMNI */ if(diskflag) { display_disk(n); n+=ndisk; } }