Old s-solbourne.c
  1 /* System dependent file for Solbourne workstations running OS/MP.      */
  2 /*
  3  * Copyright 1990 Solbourne Computer, Inc.
  4  *
  5  * Permission to use, copy, modify, distribute, and sell this software and its
  6  * documentation for any purpose is hereby granted without fee, provided that
  7  * the above copyright notice appear in all copies and that both that
  8  * copyright notice and this permission notice appear in supporting
  9  * documentation, and that the name of Solbourne not be used in advertising or
 10  * publicity pertaining to distribution of the software without specific,
 11  * written prior permission.  Solbourne Computer, Inc. makes no representations 
 12  * about the suitability of this software for any purpose.  It is provided 
 13  * "as is" without express or implied warranty.
 14  *
 15  * SOLBOURNE COMPUTER, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 
 17  * IN NO EVENT SHALL SOLBOURNE COMPUTER, INC. BE LIABLE FOR ANY SPECIAL,
 18  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 19  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 20  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 21  * PERFORMANCE OF THIS SOFTWARE.
 22  *
 23  * Author:  William Kucharski, Solbourne Computer, Inc.
 24  *          kucharsk@Solbourne.COM
 25  *          ...!{boulder,sun,uunet}!stan!kucharsk
 26  */
 27 /* LINTLIBRARY */
 28 
 29 #include <sys/syscall.h>
 30 #include <sys/param.h>
 31 #include <sys/dk.h>
 32 #include <nlist.h>
 33 
 34 extern char *xmalloc(/* int nbytes */);
 35 
 36 extern int open(), read();
 37 extern long lseek();
 38 
 39 extern char *kernelSymbols();
 40 
 41 long    cp_time[MAXNCPUS][CPUSTATES];
 42 long    cp_old[MAXNCPUS][CPUSTATES];
 43 int     kmem;                   /* file descriptor of /dev/kmem. */
 44 struct nlist    nl[] = {
 45 #define X_CP_TIME       0
 46         { "_cp_mp_time" },
 47         { "" },
 48 };
 49 
 50 /* Called at the beginning to inquire how many bars are needed. */
 51 
 52 int
 53 num_bars()
 54 {
 55         unsigned int    status;
 56         unsigned int    width;
 57         unsigned int    type;
 58 
 59         int     numcpus = 0;
 60         int     proc;
 61 
 62         if (syscall(SYS_getcpustatus, &status, &width, &type) < 0) {
 63                 perror("getcpustatus");
 64                 exit(1);
 65         }
 66 
 67         for (proc = 0; proc < width; proc++)
 68                 if ((status >> proc) & 1)
 69                         numcpus++;
 70 
 71         return(numcpus);
 72 }
 73 
 74 /*
 75  * Indicates how many levels each bar has.  For most machines, each bar will
 76  * have the same stuff.  But one can, for instance, display memory use on one
 77  * bar, processor levels on others, etc.
 78  */
 79 void
 80 bar_items(nbars, items)
 81 int nbars;
 82 int items[];    /* nbars items in this */
 83 {
 84     int i;
 85 
 86     for(i = 0; i < nbars; i++)
 87         items[i] = CPUSTATES;
 88 }
 89 
 90 /* Called after num_bars to ask for the bar names */
 91 /* ARGSUSED */
 92 char **
 93 label_bars(nbars)
 94 {
 95     extern char *strcpy(/* char *, const char * */);
 96 
 97     char **names;
 98     int i;
 99 
100     static char hname[MAXHOSTNAMELEN];
101 
102     if (gethostname(hname, MAXHOSTNAMELEN) < 0) {
103         perror("gethostname");
104         hname[0] = '\0';
105     }
106 
107     names = (char **) xmalloc(nbars * sizeof(char *));
108     if (nbars == 1) {
109             char buf[MAXHOSTNAMELEN + 3];
110             (void) sprintf(buf, "%s: ", hname);
111             names[0] = strcpy(xmalloc(strlen(buf) + 1), buf);
112     } else {
113     for(i = 0; i < nbars; i++) {
114         char buf[MAXHOSTNAMELEN + 6];
115 
116                     /* 
117                      * Use bar number % 10 in case someone someday can stuff
118                      * more than 9 CPUs into a Solbourne box...
119                      */
120 
121                     (void) sprintf(buf, "%s(%d): ", hname, (i % 10));
122         names[i] = strcpy(xmalloc(strlen(buf) + 1), buf);
123             }
124     }
125     return names;
126 }
127 
128 /* 
129  *  Called after the bars are created to perform any machine dependent
130  *  initializations.
131  */
132 /* ARGSUSED */
133 void
134 init_bars(nbars)
135 int nbars;
136 {
137     
138     if ((kmem = open("/dev/kmem", 0)) < 0) {
139             perror("/dev/kmem");
140             exit(1);
141     }
142     (void)nlist(kernelSymbols?kernelSymbols:"/vmunix", nl);
143     if (lseek(kmem, (long) nl[X_CP_TIME].n_value, 0) !=
144         (long) nl[X_CP_TIME].n_value)
145             perror("lseek");
146     if (read(kmem, (char *) cp_old, sizeof(cp_old)) !=
147         sizeof(cp_old))
148             perror("read");
149 }
150 
151 /* 
152  *  This procedure gets called every interval to compute and display the
153  *  bars. It should call draw_bar() with the bar number, the array of
154  *  integer values to display in the bar, and the number of values in
155  *  the array.
156  */
157 /* ARGSUSED */
158 void
159 display_bars(nbars)
160 {
161         int     nstates;
162         int     states[CPUSTATES];
163         int     i;
164         int     proc;
165 
166         extern void draw_bar(/*int bar_num, int *states, int num_states*/);
167         
168         if (lseek(kmem, (long) nl[X_CP_TIME].n_value, 0) !=
169             (long) nl[X_CP_TIME].n_value)
170                 perror("lseek");
171         if (read(kmem, (char *) cp_time, sizeof(cp_time)) !=
172             sizeof(cp_time))
173                 perror("read");
174         
175 #define delta(cpu, cpustate) ((int) (cp_time[cpu][(cpustate)] - \
176         cp_old[cpu][(cpustate)]))
177 
178         for (proc = 0; proc < nbars; proc++) {
179                 nstates = 0;
180                 states[nstates++] = delta(proc, CP_IDLE);
181                 states[nstates++] = delta(proc, CP_USER);
182                 states[nstates++] = delta(proc, CP_NICE);
183                 states[nstates++] = delta(proc, CP_SYS);
184                 draw_bar(proc, states, nstates);
185                 for (i = 0; i < CPUSTATES; i ++)
186                         cp_old[proc][i] = cp_time[proc][i];
187         }
188 }