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 }