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