Old s-ultrix.c
  1 /*
  2  * System dependent file for Ultrix 4.2A
  3  */
  4 
  5 /* 
  6  * Ricardo E Gonzalez, Stanford University <recardog@chroma.stanford.edu>
  7  *      based on code by
  8  * Salvador P. Abreu, U.Nova de Lisboa, PORTUGAL <spa@fctunl.rccn.pt>
  9  *      based on code by
 10  * Chris Siebenmann, University of Toronto <cks@sys.toronto.edu>
 11  */
 12 
 13 /* LINTLIBRARY */
 14 #include <sys/param.h>
 15 #include <sys/dk.h>
 16 #include <machine/cpu.h>
 17 #include <sys/cpudata.h>
 18 #include <nlist.h>
 19 #include <stdio.h>
 20 #include <errno.h>
 21 
 22 #define kmseek(N) if (lseek(kmem, (long) (N), 0) != (long) (N)) perror ("lseek kmem");
 23 #define KMEM    "/dev/kmem"
 24 
 25 extern char *xmalloc(/* int nbytes */);
 26 
 27 extern int open(), read();
 28 extern long lseek();
 29 
 30 extern char *kernelSymbols;
 31 
 32 struct cpudata *cpu_data[MAXCPU];
 33 long **cptime_old = NULL;
 34 
 35 int     kmem;                   /* file descriptor of /dev/kmem. */
 36 struct nlist    nl[] = {
 37 #define X_ACTIVECPU 0
 38         { "_cpu_avail" },       /* number of active CPUs */
 39 #define X_CPUDATA 1
 40         { "_cpudata" },         /* cpudata[] array */
 41 #define X_LOWCPU 2
 42         { "_lowcpu" },          /* lowest cpu number */
 43 #define X_HIGHCPU 3
 44         { "_highcpu" },         /* highest cpu number */
 45         { 0 },
 46 };
 47 
 48 int activecpu;
 49 int lowcpu = 0;
 50 int highcpu = 0;
 51 static unsigned long cpudata_offset = 0;
 52 
 53 /* Called at the beginning to inquire how many bars are needed. */
 54 int
 55 num_bars()
 56 {
 57     if ((kmem = open("/dev/kmem", 0)) < 0) {
 58         perror("/dev/kmem");
 59         exit(1);
 60     }
 61     (void) nlist(kernelSymbols?kernelSymbols:"/vmunix", nl);
 62 
 63 /*
 64     printf("ACTIVE : %x\n", nl[X_ACTIVECPU].n_value);
 65     printf("CPUDATA: %x\n", nl[X_CPUDATA].n_value);
 66     fflush(stdout);
 67 */
 68 
 69     (void) getkval(nl[X_LOWCPU].n_value, (int *)(&lowcpu), sizeof(lowcpu),
 70         nl[X_LOWCPU].n_name);
 71     (void) getkval(nl[X_HIGHCPU].n_value, (int *)(&highcpu), sizeof(highcpu),
 72         nl[X_HIGHCPU].n_name);
 73     activecpu = highcpu - lowcpu + 1;
 74     cpudata_offset = nl[X_CPUDATA].n_value;
 75 
 76 /*
 77     printf("CPUS   : %d\n", activecpu);
 78     fflush(stdout);
 79     return (activecpu);
 80 */
 81 
 82 }
 83 
 84 /*
 85  * Indicates how many levels each bar has.  For most machines, each bar will
 86  * have the same stuff.  But one can, for instance, display memory use on one
 87  * bar, processor levels on others, etc.
 88  */
 89 void
 90 bar_items(nbars, items)
 91 int nbars;
 92 int items[];    /* nbars items in this */
 93 {
 94     int i;
 95 
 96     for(i = 0; i < nbars; i++)
 97         items[i] = CPUSTATES;
 98 }
 99 
100 
101 /* Called after num_bars to ask for the bar names */
102 /* ARGSUSED */
103 char **
104 label_bars(nbars)
105 {
106     static char **names;
107     static char hname[MAXHOSTNAMELEN];
108     int i;
109 
110     names = (char **) malloc (nbars * sizeof (char *));
111     for (i=0; i<nbars; i++) {
112         names[i] = (char *) malloc (strlen("cpuxxx")+1);
113         (void) sprintf (names[i], "cpu%d", i);
114     }
115     return names;
116 }
117 
118 /* 
119  *  Called after the bars are created to perform any machine dependent
120  *  initializations.
121  */
122 /* ARGSUSED */
123 void init_bars(nbars)
124     int nbars;
125 {
126     int ncpu, i;
127     register struct cpudata cpu;
128 
129     (void) getkval(cpudata_offset, cpu_data, sizeof(cpu_data), "_cpudata");
130         
131     cptime_old = (long **) malloc (nbars * sizeof (long *));
132     for (ncpu=lowcpu; ncpu<=highcpu; ++ncpu) {
133         if (cpu_data[ncpu] != NULL) {
134             (void) getkval(cpu_data[ncpu], &cpu, sizeof(cpu), "???");
135             cptime_old[ncpu] = (long *) malloc (CPUSTATES * sizeof (long));
136             if (cpu.cpu_state & CPU_RUN) {
137                 for (i = 0; i < CPUSTATES; i ++) {
138                     cptime_old[ncpu][i] = cpu.cpu_cptime[i];
139                 }
140             }
141         }
142     }
143 }
144 
145 /* 
146  *  This procedure gets called every interval to compute and display the
147  *  bars. It should call draw_bar() with the bar number, the array of
148  *  integer values to display in the bar, and the number of values in
149  *  the array.
150  */
151 #define delta(ncpu, cpustate) \
152     ((int) (cpu.cpu_cptime[(cpustate)] - cptime_old[ncpu][(cpustate)]))
153 
154 /* ARGSUSED */
155 void
156 display_bars(nbars)
157 {
158     int states[CPUSTATES];
159     int nstates;
160     int i, ncpu;
161     int status;
162     register struct cpudata cpu;
163     extern void draw_bar(       /*int bar_num, int *states, int num_states*/);
164         
165 
166     (void) getkval(cpudata_offset, cpu_data, sizeof(cpu_data), "_cpudata");
167     for (ncpu = lowcpu; ncpu <= highcpu; ++ncpu) {
168         if (cpu_data[ncpu] != NULL) {
169             (void) getkval(cpu_data[ncpu], &cpu, sizeof(cpu), "???");
170             if (cpu.cpu_state & CPU_RUN) {
171                 nstates = 0;
172                 states[nstates++] = delta(ncpu, CP_IDLE);
173                 states[nstates++] = delta(ncpu, CP_USER);
174                 states[nstates++] = delta(ncpu, CP_NICE);
175                 states[nstates++] = delta(ncpu, CP_SYS);
176 
177                 draw_bar(ncpu, states, nstates);
178 
179                 for (i = 0; i < CPUSTATES; i ++) {
180                     cptime_old[ncpu][i] = cpu.cpu_cptime[i];
181 /*                  printf ("%d\t", cptime_old[ncpu][i]); */
182                 }
183 /*              printf ("\n"); */
184             }
185         }
186     }
187 }
188 
189 
190 /*
191  *  getkval(offset, ptr, size, refstr) - get a value out of the kernel.
192  *      "offset" is the byte offset into the kernel for the desired value,
193  *      "ptr" points to a buffer into which the value is retrieved,
194  *      "size" is the size of the buffer (and the object to retrieve),
195  *      "refstr" is a reference string used when printing error meessages,
196  *          if "refstr" starts with a '!', then a failure on read will not
197  *          be fatal (this may seem like a silly way to do things, but I
198  *          really didn't want the overhead of another argument).
199  *  
200  */
201 
202 getkval(offset, ptr, size, refstr)
203 
204 unsigned long offset;
205 int *ptr;
206 int size;
207 char *refstr;
208 
209 {
210     if (lseek(kmem, (long)offset, SEEK_SET) == -1) {
211         if (*refstr == '!')
212             refstr++;
213         (void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM, 
214                        refstr, strerror(errno));
215         exit(23);
216     }
217     if (read(kmem, (char *) ptr, size) == -1) {
218         if (*refstr == '!') 
219             return(0);
220         else {
221             (void) fprintf(stderr, "%s: reading %s: %s\n", KMEM, 
222                            refstr, strerror(errno));
223             exit(23);
224         }
225     }
226     return(1);
227 }