iglesias@draco.acs.uci.edu (Mike Iglesias) (11/10/90)
Recently, I posted a question about whether anyone had a rpc.rstatd (as Sun calls it) for Ultrix on DECstations. I didn't get any answers, so I started looking into it myself. I found a copy of the Sun RPC sources on uunet.uu.net in comp.sources.unix/volume13/rpc3.9 and started working from there. I found that the sources included the source for the rpc rstatd daemon, so I modified the code using the sources for 'top' that are on gatekeeper.dec.com as a guide. You need to do the following: Build rpcgen from the sources and put it in your path so it can be found in the next step. cd to the rpcsvc directory and type 'make'. Kill the make when it starts compiling the sources (let the rpcgen stuff finish!). Apply the patch at the end of this message to rstat_proc.c. Modify the Makefile CFLAGS to include -DULTRIXV4 (for Ultrix v4.x) or -DULTRIXV3 (for Ultrix v3.x). Type 'make' again and it should compile and link rstat_svc. I've run the daemon under Ultrix v3.1, v4.0, and v4.1, and it appears to work correctly. Please note that I've only run it on DECstation 3100s and 5000; we don't have any vaxen running Ultrix around here so I couldn't test it for those systems. I wasn't able to get the rpc library to compile correctly (dies in xdr_float.c), but the routines supplied by DEC (in libc.a) seem to work. I haven't been able to get any client programs (for example, xmeter) to work on the DECstations; they all complain that they can't decode the results from either my daemons or daemons running on Sun systems. I have no idea what the problem is, nor have I had time to look into it further. Clients running on Suns are able to get the data correctly from my daemons. Since I did the changes, I have found out that titan.rice.edu has a newer release of the RPC sources. I haven't had a chance to look at those and put my changes into them. If you try to put my changes into the newer sources, you're on your own! As always, use these changes at your own risk. I can't mail out the RPC sources; you'll have to get them from uunet yourself. Mike Iglesias University of California, Irvine Internet: iglesias@draco.acs.uci.edu BITNET: iglesias@uci uucp: ...!ucbvax!ucivax!iglesias *** rstat_proc.c.orig Fri Oct 19 10:53:59 1990 --- rstat_proc.c Fri Nov 9 10:25:54 1990 *************** *** 50,60 **** --- 50,73 ---- #include <sys/vmmeter.h> #include <net/if.h> #include <sys/time.h> + #ifdef ultrix + # include <sys/fixpoint.h> + # ifdef ULTRIXV4 + # include <sys/param.h> + # include <machine/cpu.h> + # include <sys/cpudata.h> + # endif + #endif #include "rstat.h" struct nlist nl[] = { + #ifdef ULTRIXV4 + #define X_CPUDATA 0 + { "_cpudata" }, + #else #define X_CPTIME 0 { "_cp_time" }, + #endif #define X_SUM 1 { "_sum" }, #define X_IFNET 2 *************** *** 67,72 **** --- 80,91 ---- { "_avenrun" }, #define X_HZ 6 { "_hz" }, + #ifdef ULTRIXV4 + #define X_LOWCPU 7 + { "_lowcpu" }, + #define X_HIGHCPU 8 + { "_highcpu" }, + #endif "", }; int kmem; *************** *** 73,78 **** --- 92,106 ---- int firstifnet, numintfs; /* chain of ethernet interfaces */ int stats_service(); + #ifdef ULTRIXV4 + struct cpudata *cpudata[MAXCPU]; + struct cpudata onecpu; + int ncpu; + int i; + int lowcpu = 0; + int highcpu = 0; + #endif + /* * Define EXIT_WHEN_IDLE if you are able to have this program invoked * automatically on demand (as from inetd). When defined, the service *************** *** 163,169 **** --- 191,201 ---- int off, i, hz; struct vmmeter sum; struct ifnet ifnet; + #if defined(ultrix) && defined(mips) + fix avrun[3]; + #else double avrun[3]; + #endif struct timeval tm, btm; #ifdef DEBUG *************** *** 186,191 **** --- 218,274 ---- fprintf(stderr, "rstat: can't read hz from kmem\n"); exit(1); } + #ifdef ULTRIXV4 + if (lseek(kmem, (long)nl[X_CPUDATA].n_value, 0) == -1) { + fprintf(stderr, "rstat: can't seek in kmem\n"); + exit(1); + } + if (read(kmem, (char *)cpudata, sizeof(cpudata)) != sizeof(cpudata)) { + fprintf(stderr, "rstat: can't read cpudata from kmem\n"); + exit(1); + } + if (lseek(kmem, (long)nl[X_LOWCPU].n_value, 0) == -1) { + fprintf(stderr, "rstat: can't seek in kmem\n"); + exit(1); + } + if (read(kmem, (char *)&lowcpu, sizeof(lowcpu)) != sizeof(lowcpu)) { + fprintf(stderr, "rstat: can't read lowcpu from kmem\n"); + exit(1); + } + + if (lseek(kmem, (long)nl[X_HIGHCPU].n_value, 0) == -1) { + fprintf(stderr, "rstat: can't seek in kmem\n"); + exit(1); + } + if (read(kmem, (char *)&highcpu, sizeof(highcpu)) != sizeof(highcpu)) { + fprintf(stderr, "rstat: can't read highcpu from kmem\n"); + exit(1); + } + + for (i = 0; i < CPUSTATES; ++i) + stats_all.s1.cp_time[i] = 0; + + stats_all.s1.v_intr = 0; + stats_all.s2.v_swtch = 0; + + for (ncpu = lowcpu; ncpu <= highcpu; ++ncpu) { + if (cpudata[ncpu]) { + if (lseek(kmem, cpudata[ncpu], 0) == -1) { + fprintf(stderr, "rstat: can't seek in kmem(cpudata)\n"); + exit(1); + } + if (read(kmem, (char *)&onecpu, sizeof (onecpu)) != sizeof(onecpu)) { + fprintf(stderr, "rstat: can't read *cpudata from kmem\n"); + exit(1); + } + stats_all.s1.v_intr += onecpu.cpu_intr; + stats_all.s2.v_swtch += onecpu.cpu_switch; + + for (i = 0; i < CPUSTATES; i++) + stats_all.s1.cp_time[i] += onecpu.cpu_cptime[i]; + } + } + #else if (lseek(kmem, (long)nl[X_CPTIME].n_value, 0) == -1) { fprintf(stderr, "rstat: can't seek in kmem\n"); exit(1); *************** *** 195,200 **** --- 278,284 ---- fprintf(stderr, "rstat: can't read cp_time from kmem\n"); exit(1); } + #endif if (lseek(kmem, (long)nl[X_AVENRUN].n_value, 0) ==-1) { fprintf(stderr, "rstat: can't seek in kmem\n"); exit(1); *************** *** 208,213 **** --- 292,306 ---- stats_all.s2.avenrun[1] = avrun[1] * FSCALE; stats_all.s2.avenrun[2] = avrun[2] * FSCALE; #endif + #if defined(ultrix) && defined(mips) + if (read(kmem, (char *)avrun, sizeof (avrun)) != sizeof (avrun)) { + fprintf(stderr, "rstat: can't read avenrun from kmem\n"); + exit(1); + } + stats_all.s2.avenrun[0] = avrun[0]; + stats_all.s2.avenrun[1] = avrun[1]; + stats_all.s2.avenrun[2] = avrun[2]; + #endif if (lseek(kmem, (long)nl[X_BOOTTIME].n_value, 0) == -1) { fprintf(stderr, "rstat: can't seek in kmem\n"); exit(1); *************** *** 238,248 **** stats_all.s1.v_pgpgout = sum.v_pgpgout; stats_all.s1.v_pswpin = sum.v_pswpin; stats_all.s1.v_pswpout = sum.v_pswpout; stats_all.s1.v_intr = sum.v_intr; gettimeofday(&tm, (struct timezone *) 0); stats_all.s1.v_intr -= hz*(tm.tv_sec - btm.tv_sec) + hz*(tm.tv_usec - btm.tv_usec)/1000000; ! stats_all.s2.v_swtch = sum.v_swtch; if (lseek(kmem, (long)nl[X_DKXFER].n_value, 0) == -1) { fprintf(stderr, "rstat: can't seek in kmem\n"); --- 331,345 ---- stats_all.s1.v_pgpgout = sum.v_pgpgout; stats_all.s1.v_pswpin = sum.v_pswpin; stats_all.s1.v_pswpout = sum.v_pswpout; + #ifndef ULTRIXV4 stats_all.s1.v_intr = sum.v_intr; + stats_all.s2.v_swtch = sum.v_swtch; + #endif + #ifndef ULTRIXV3 gettimeofday(&tm, (struct timezone *) 0); stats_all.s1.v_intr -= hz*(tm.tv_sec - btm.tv_sec) + hz*(tm.tv_usec - btm.tv_usec)/1000000; ! #endif if (lseek(kmem, (long)nl[X_DKXFER].n_value, 0) == -1) { fprintf(stderr, "rstat: can't seek in kmem\n");
frank@croton.enet.dec.com (Frank Wortner) (11/12/90)
> I wasn't able to get the rpc library to compile correctly (dies in > xdr_float.c), but the routines supplied by DEC (in libc.a) seem to > work. I haven't been able to get any client programs (for example, > xmeter) to work on the DECstations; they all complain that they can't > decode the results from either my daemons or daemons running on Sun > systems. I have no idea what the problem is, nor have I had time to > look into it further. Clients running on Suns are able to get the > data correctly from my daemons. xdr_float.o is broken on pre 4.x versions of ULTRIX software, so that might be your problem. The source version of xdr_float.c as distributed by Sun doesn't have support for little-endian IEEE machines. Funny, it does support VAXen, though! Anyway, here's a version I kludged together which compiles and works (for me, at least). Enjoy! Frank /* @(#)xdr_float.c 1.1 87/11/04 3.9 RPCSRC */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; #endif /* * xdr_float.c, Generic XDR routines impelmentation. * * Copyright (C) 1984, Sun Microsystems, Inc. * * These are the "floating point" xdr routines used to (de)serialize * most common data items. See xdr.h for more info on the interface to * xdr. */ #include <stdio.h> #include <rpc/types.h> #include <rpc/xdr.h> /* * NB: Not portable. * This routine works on Suns (Sky / 68000's) and Vaxen. * MIPSEL works now, too. --- 10-NOV-89 Frank Wortner */ #ifdef vax /* What IEEE single precision floating point looks like on a Vax */ struct ieee_single { unsigned int mantissa: 23; unsigned int exp : 8; unsigned int sign : 1; }; /* Vax single precision floating point */ struct vax_single { unsigned int mantissa1 : 7; unsigned int exp : 8; unsigned int sign : 1; unsigned int mantissa2 : 16; }; #define VAX_SNG_BIAS 0x81 #define IEEE_SNG_BIAS 0x7f static struct sgl_limits { struct vax_single s; struct ieee_single ieee; } sgl_limits[2] = { {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ { 0x0, 0xff, 0x0 }}, /* Max IEEE */ {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ { 0x0, 0x0, 0x0 }} /* Min IEEE */ }; #endif /* vax */ bool_t xdr_float(xdrs, fp) register XDR *xdrs; register float *fp; { #ifdef vax struct ieee_single is; struct vax_single vs, *vsp; struct sgl_limits *lim; int i; #endif /* vax */ switch (xdrs->x_op) { case XDR_ENCODE: #ifndef vax return (XDR_PUTLONG(xdrs, (long *)fp)); #else vs = *((struct vax_single *)fp); for (i = 0, lim = sgl_limits; i < sizeof(sgl_limits)/sizeof(struct sgl_limits); i++, lim++) { if ((vs.mantissa2 == lim->s.mantissa2) && (vs.exp == lim->s.exp) && (vs.mantissa1 == lim->s.mantissa1)) { is = lim->ieee; goto shipit; } } is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; shipit: is.sign = vs.sign; return (XDR_PUTLONG(xdrs, (long *)&is)); #endif /* ndef vax */ case XDR_DECODE: #ifndef vax return (XDR_GETLONG(xdrs, (long *)fp)); #else vsp = (struct vax_single *)fp; if (!XDR_GETLONG(xdrs, (long *)&is)) return (FALSE); for (i = 0, lim = sgl_limits; i < sizeof(sgl_limits)/sizeof(struct sgl_limits); i++, lim++) { if ((is.exp == lim->ieee.exp) && (is.mantissa == lim->ieee.mantissa)) { *vsp = lim->s; goto doneit; } } vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; vsp->mantissa2 = is.mantissa; vsp->mantissa1 = (is.mantissa >> 16); doneit: vsp->sign = is.sign; return (TRUE); #endif /* ndef vax */ case XDR_FREE: return (TRUE); } return (FALSE); } /* * This routine works on Suns (Sky / 68000's) and Vaxen. */ #ifdef vax /* What IEEE double precision floating point looks like on a Vax */ struct ieee_double { unsigned int mantissa1 : 20; unsigned int exp : 11; unsigned int sign : 1; unsigned int mantissa2 : 32; }; /* Vax double precision floating point */ struct vax_double { unsigned int mantissa1 : 7; unsigned int exp : 8; unsigned int sign : 1; unsigned int mantissa2 : 16; unsigned int mantissa3 : 16; unsigned int mantissa4 : 16; }; #define VAX_DBL_BIAS 0x81 #define IEEE_DBL_BIAS 0x3ff #define MASK(nbits) ((1 << nbits) - 1) static struct dbl_limits { struct vax_double d; struct ieee_double ieee; } dbl_limits[2] = { {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ }; #endif /* vax */ bool_t xdr_double(xdrs, dp) register XDR *xdrs; double *dp; { register long *lp; #ifdef vax struct ieee_double id; struct vax_double vd; register struct dbl_limits *lim; int i; #endif switch (xdrs->x_op) { case XDR_ENCODE: #ifndef vax lp = (long *)dp; #else vd = *((struct vax_double *)dp); for (i = 0, lim = dbl_limits; i < sizeof(dbl_limits)/sizeof(struct dbl_limits); i++, lim++) { if ((vd.mantissa4 == lim->d.mantissa4) && (vd.mantissa3 == lim->d.mantissa3) && (vd.mantissa2 == lim->d.mantissa2) && (vd.mantissa1 == lim->d.mantissa1) && (vd.exp == lim->d.exp)) { id = lim->ieee; goto shipit; } } id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | (vd.mantissa3 << 13) | ((vd.mantissa4 >> 3) & MASK(13)); shipit: id.sign = vd.sign; lp = (long *)&id; #endif /* ndef vax */ #ifdef MIPSEL return (XDR_PUTLONG(xdrs, lp+1) && XDR_PUTLONG(xdrs, lp)); #else return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp)); #endif /* MIPSEL */ case XDR_DECODE: #ifndef vax lp = (long *)dp; #ifdef MIPSEL return (XDR_GETLONG(xdrs, lp+1) && XDR_GETLONG(xdrs, lp)); #else /* MIPSEL */ return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp)); #endif /* MIPSEL */ #endif /* ndef vax */ #ifdef vax lp = (long *)&id; if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp)) return (FALSE); for (i = 0, lim = dbl_limits; i < sizeof(dbl_limits)/sizeof(struct dbl_limits); i++, lim++) { if ((id.mantissa2 == lim->ieee.mantissa2) && (id.mantissa1 == lim->ieee.mantissa1) && (id.exp == lim->ieee.exp)) { vd = lim->d; goto doneit; } } vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; vd.mantissa1 = (id.mantissa1 >> 13); vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | (id.mantissa2 >> 29); vd.mantissa3 = (id.mantissa2 >> 13); vd.mantissa4 = (id.mantissa2 << 3); doneit: vd.sign = id.sign; *dp = *((double *)&vd); return (TRUE); #endif /* vax */ case XDR_FREE: return (TRUE); } return (FALSE); }