meggers@mothra.nts.uci.edu (Mark Eggers) (07/12/90)
Anyone have any hacks of getloadavg.c that will allow it to work on a Sun Sparc running 4.03c? I like the idea, and I was thinking about using the code to build part of a distributed database - if the load is too great, send a message back to the client, and the client goes to the next server type of stuff. thanks for any pointers - /mde/
Andy.Linton@comp.vuw.ac.nz (Andy Linton) (07/12/90)
I have posted a couple of bits and pieces on this and have eventually come down to the following strategy - throw away all the system dependent stuff inside conf.c for getting the load average and have a routine that will get the load average for lots of different systems. The X11 tool 'xload' has a routine which does this and I used this with minor mods and a patch to make it work on the HP Series 800 to produce a new getloadavg.c. I know this has slightly different semantics to the one in ../support but this works on a lot more systems. It also tidies up the code in conf.c by removing that horrible #if !defined(sun) section. I don't have all the machines (:-) so I can't vouch for this totally but it does run on: DEC 5400 (Mips) running Ultrix V3.1D (Rev. 54) HP Series 800 running HP-UX 7.0 HP Series 300 running HP-UX 7.0 HP Series 300 running Mt Xinu MORE/BSD Sun3 running 4.0.3_EXPORT Patch to conf.c and new getloadavg.c follow: -- *** /tmp/,RCSt1a17653 Thu Jul 12 13:31:51 1990 --- conf.c Fri Jul 6 16:50:14 1990 *************** *** 422,487 **** ** none. */ - #if !defined(sun) - getla() { ! double avenrun[3]; ! if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) return (0); ! return ((int) (avenrun[0] + 0.5)); ! } ! ! #else /* sun */ ! ! #include <nlist.h> ! ! struct nlist Nl[] = ! { ! {"_avenrun"}, ! #define X_AVENRUN 0 ! { 0 }, ! }; ! ! getla() ! { ! # ifdef sequent ! return (1); ! # else /* !sequent */ ! static int kmem = -1; ! long avenrun[3]; ! extern off_t lseek(); ! ! if (kmem < 0) ! { ! kmem = open("/dev/kmem", 0, 0); ! if (kmem < 0) ! return (-1); ! (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); ! (void) nlist ("/vmunix", Nl); ! if (Nl[0].n_type == 0) ! { ! /* ! * if nlist() has failed we can't use Nl to grope ! * about in kmem on subsequent calls to getla() ! */ ! close (kmem); ! kmem = -1; ! return (-1); ! } ! } ! if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || ! read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) ! { ! /* thank you Ian */ ! return (-1); ! } ! return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); ! # endif /* sequent */ } - #endif /* sun */ /* ** SHOULDQUEUE -- should this message be queued or sent? ** --- 529,543 ---- ** none. */ getla() { ! double avenrun; ! if (getloadavg(&avenrun) < 0) return (0); ! return ((int) (avenrun + 0.5)); } /* ** SHOULDQUEUE -- should this message be queued or sent? ** -- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: work/sendmail-5.64/src/getloadavg.c # Wrapped by asjl@tinakori.comp.vuw.ac.nz on Thu Jul 12 13:46:11 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'work/sendmail-5.64/src/getloadavg.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'work/sendmail-5.64/src/getloadavg.c'\" else echo shar: Extracting \"'work/sendmail-5.64/src/getloadavg.c'\" \(9617 characters\) sed "s/^X//" >'work/sendmail-5.64/src/getloadavg.c' <<'END_OF_FILE' X/* X * Copyright 1989 Massachusetts Institute of Technology X * X * Permission to use, copy, modify, distribute, and sell this software and its X * documentation for any purpose is hereby granted without fee, provided that X * the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of M.I.T. not be used in advertising or X * publicity pertaining to distribution of the software without specific, X * written prior permission. M.I.T. makes no representations about the X * suitability of this software for any purpose. It is provided "as is" X * without express or implied warranty. X * X * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. X * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION X * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X * X * Authors: Many and varied... X */ X X#include <stdio.h> X X/* X * Get open(2) constants X */ X#ifdef SYSV X#ifndef macII X#include <fcntl.h> X#endif X#endif /* SYSV */ X#include <sys/file.h> X#ifdef USG X#include <unistd.h> X#endif X X#ifdef att X#define LOADSTUB X#endif X X#ifdef apollo X#include <apollo/base.h> X#include <apollo/time.h> Xtypedef struct { X short state; /* ready, waiting, etc. */ X pinteger usr; /* user sr */ X linteger upc; /* user pc */ X linteger usp; /* user stack pointer */ X linteger usb; /* user sb ptr (A6) */ X time_$clock_t cpu_total; /* cumulative cpu used by process */ X unsigned short priority; /* process priority */ X } proc1_$info_t; X Xvoid proc1_$get_cput( X time_$clock_t *cput X); X Xvoid proc1_$get_info( X short &pid, X proc1_$info_t *info, X status_$t *sts X); X#endif /* apollo */ X X#ifndef macII X#ifndef apollo X#ifndef LOADSTUB X#include <nlist.h> X#endif /* LOADSTUB */ X#endif /* apollo */ X#endif /* macII */ X X#ifdef sun X# include <sys/param.h> X# ifdef i386 X# include <kvm.h> X# define KVM_ROUTINES X# endif /* i386 */ X#endif X X#ifdef mips X#include <sys/fixpoint.h> X#endif X X#ifdef CRAY X#include <sys/param.h> X#include <sys/sysinfo.h> X#undef n_type X#define n_type n_value X#endif /* CRAY */ X X#ifdef sequent X#include <sys/vm.h> X#endif /* sequent */ X X#ifdef macII X#include <a.out.h> X#include <sys/var.h> X#define X_AVENRUN 0 X#define fxtod(i) (vec[i].high+(vec[i].low/65536.0)) Xstruct lavnum { X unsigned short high; X unsigned short low; X}; X#endif /* macII */ X X#if defined(UTEK) || defined(alliant) X#define FSCALE 100.0 X#endif X X#ifdef sequent X#define FSCALE 1000.0 X#endif X X#ifdef hp9000 X#include <sys/param.h> X#endif X Xextern long lseek(); Xextern void exit(); X X#if apollo X/* ARGSUSED */ Xint getloadavg( call_data ) X caddr_t call_data; /* pointer to (double) return value */ X{ X static Bool firstTime = TRUE; X static int lastNullCpu; X static int lastClock; X time_$clock_t timeNow; X double temp; X proc1_$info_t info; X status_$t st; X X proc1_$get_info( (short) 2, &info, &st ); X time_$clock( &timeNow ); X X if (firstTime) X { X *(double *)call_data = 1.0; X firstTime = FALSE; X } X else { X temp = info.cpu_total.low32 - lastNullCpu; X *(double *)call_data = 1.0 - temp / (timeNow.low32 - lastClock); X } X X lastClock = timeNow.low32; X lastNullCpu = info.cpu_total.low32; X return(0); X} X#else X#ifdef KVM_ROUTINES X/* X * Sun 386i Code - abstracted to see the wood for the trees X */ X X/* ARGSUSED */ Xvoid Xgetloadavg( call_data ) X caddr_t call_data; /* pointer to (double) return value */ X{ X double *loadavg = (double *)call_data; X long temp; X static int init = 0; X static struct nlist nl[2]; X static kvm_t *kd; X X if (!init) { X kd = kvm_open("/vmunix", NULL, NULL, O_RDONLY, NULL); X if (kd == (kvm_t *)0) { X return (-1); X } X X nl[0].n_name = "avenrun"; X nl[1].n_name = NULL; X X if (kvm_nlist(kd, nl) != 0) { X return (-1); X } X init = 1; X } X X if (nl[0].n_value == 0) { X return (-1); X } X if (kvm_read(kd, nl[0].n_value, (char *)&temp, sizeof (temp)) != X sizeof (temp)) { X return (-1); X } X *loadavg = (double)temp/FSCALE; X return(0); X} X#else /* KVM_ROUTINES */ X#ifdef LOADSTUB X X/* ARGSUSED */ Xint getloadavg( call_data ) X caddr_t call_data; /* pointer to (double) return value */ X{ X *(double *)call_data = 1.0; X} X X#else /* LOADSTUB */ X X#ifndef KMEM_FILE X#define KMEM_FILE "/dev/kmem" X#endif X X#ifndef KERNEL_FILE X X#ifdef alliant X#define KERNEL_FILE "/unix" X#endif /* alliant */ X X#ifdef CRAY X#define KERNEL_FILE "/unicos" X#endif /* CRAY */ X X#ifdef hpux X#define KERNEL_FILE "/hp-ux" X#endif /* hpux */ X X#ifdef macII X#define KERNEL_FILE "/unix" X#endif /* macII */ X X#ifdef mips X# ifdef SYSTYPE_SYSV X# define KERNEL_FILE "/unix" X# else X# define KERNEL_FILE "/vmunix" X# endif /* SYSTYPE_SYSV */ X#endif /* mips */ X X#ifdef sequent X#define KERNEL_FILE "/dynix" X#endif /* sequent */ X X/* X * provide default for everyone else X */ X#ifndef KERNEL_FILE X#ifdef SYSV X#define KERNEL_FILE "/unix" X#else X#define KERNEL_FILE "/vmunix" X#endif /* SYSV */ X#endif /* KERNEL_FILE */ X#endif /* KERNEL_FILE */ X X#ifndef KERNEL_LOAD_VARIABLE X/* X * provide default X */ X# ifdef USG X# define KERNEL_LOAD_VARIABLE "sysinfo" X# define SYSINFO X# else X# define KERNEL_LOAD_VARIABLE "_avenrun" X# endif X X# ifdef alliant X# undef KERNEL_LOAD_VARIABLE X# define KERNEL_LOAD_VARIABLE "_Loadave" X# endif /* alliant */ X X# ifdef CRAY X# if defined(CRAY2) && OSMAJORVERSION == 4 X# undef KERNEL_LOAD_VARIABLE X# define KERNEL_LOAD_VARIABLE "avenrun" X# else X# undef KERNEL_LOAD_VARIABLE X# define KERNEL_LOAD_VARIABLE "sysinfo" X# define SYSINFO X# endif /* defined(CRAY2) && OSMAJORVERSION == 4 */ X# endif /* CRAY */ X X# ifdef hpux X# ifdef hp9000s800 X# undef KERNEL_LOAD_VARIABLE X# define KERNEL_LOAD_VARIABLE "avenrun" X# endif /* hp9000s800 */ X# endif /* hpux */ X X# ifdef mips X# ifdef SYSTYPE_SYSV X# undef KERNEL_LOAD_VARIABLE X# define KERNEL_LOAD_VARIABLE "avenrun" X# else X# undef KERNEL_LOAD_VARIABLE X# define KERNEL_LOAD_VARIABLE "_avenrun" X# endif /* SYSTYPE_SYSV */ X# endif /* mips */ X X# ifdef sequent X# define KERNEL_FILE "/dynix" X# endif /* sequent */ X#endif /* KERNEL_LOAD_VARIABLE */ X X#ifdef macII Xstruct var v; Xstatic int pad[2]; /* This padding is needed if getloadavg compiled on */ X /* a/ux 1.1 is executed on a/ux 1.0, because */ X /* the var structure had too much padding in 1.0, */ X /* so the 1.0 kernel writes past the end of the 1.1 */ X /* var structure in the uvar() call. */ Xstatic struct nlist nl[2]; Xstatic struct lavnum vec[3]; X#else /* not macII */ Xstatic struct nlist namelist[] = { /* namelist for vmunix grubbing */ X#define LOADAV 0 X {KERNEL_LOAD_VARIABLE}, X {0} X}; X#endif /* macII */ X X X/* ARGSUSED */ Xint getloadavg( call_data ) X caddr_t call_data; /* pointer to (double) return value */ X{ X double *loadavg = (double *)call_data; X static int init = 0; X static kmem; X static long loadavg_seek; X#ifdef macII X extern nlist(); X X if(!init) { X int i; X X strcpy(nl[0].n_name, "avenrun"); X nl[1].n_name[0] = '\0'; X X kmem = open(KMEM_FILE, O_RDONLY); X if (kmem < 0) { X return (-1); X } X X uvar(&v); X X if (nlist( KERNEL_FILE, nl) != 0) { X return (-1); X } X for (i = 0; i < 2; i++) { X nl[i].n_value = (int)nl[i].n_value - v.v_kvoffset; X } X init = 1; X } X#else /* not macII */ X extern void nlist(); X X if(!init) { X nlist( KERNEL_FILE, namelist); X/* X * Some systems appear to set only one of these to Zero if the entry could X * not be found, I hope no_one returns Zero as a good value, or bad things X * will happen to you. (I have a hard time believing the value will X * ever really be zero anyway). CDP 5/17/89. X */ X if (namelist[LOADAV].n_type == 0 || X namelist[LOADAV].n_value == 0) { X return (-1); X } X loadavg_seek = namelist[LOADAV].n_value; X#if defined(mips) && defined(SYSTYPE_SYSV) X loadavg_seek &= 0x7fffffff; X#endif /* mips && SYSTYPE_SYSV */ X#if (defined(CRAY) && defined(SYSINFO)) X loadavg_seek += ((char *) (((struct sysinfo *)NULL)->avenrun)) - X ((char *) NULL); X#endif /* SYSINFO */ X X kmem = open(KMEM_FILE, O_RDONLY); X if (kmem < 0) X return (-1); X init = 1; X } X X X (void) lseek(kmem, loadavg_seek, 0); X#endif /* macII */ X#if defined(sun) || defined (UTEK) || defined(sequent) || defined(alliant) || defined(hp9000) X { X long temp; X (void) read(kmem, (char *)&temp, sizeof(long)); X *loadavg = (double)temp/FSCALE; X } X#else /* else not sun */ X# ifdef macII X { X lseek(kmem, (long)nl[X_AVENRUN].n_value, 0); X read(kmem, vec, 3*sizeof(struct lavnum)); X *loadavg = fxtod(0); X } X# else /* else not macII */ X# ifdef mips X { X fix temp; X (void) read(kmem, (char *)&temp, sizeof(fix)); X *loadavg = FIX_TO_DBL(temp); X } X# else /* not mips */ X (void) read(kmem, (char *)loadavg, sizeof(double)); X# endif /* mips */ X# endif /* macII */ X#endif /* sun */ X return(0); X} X#endif /* LOADSTUB */ X#endif /* KVM_ROUTINES */ X#endif /* apollo */ X END_OF_FILE if test 9617 -ne `wc -c <'work/sendmail-5.64/src/getloadavg.c'`; then echo shar: \"'work/sendmail-5.64/src/getloadavg.c'\" unpacked with wrong size! fi # end of 'work/sendmail-5.64/src/getloadavg.c' fi echo shar: End of shell archive. exit 0