[comp.unix.aix] loadave

dav@eleazar.dartmouth.edu (William David Haas) (04/17/91)

I am trying to get lwho (version of rwho) running on the RS/6000s.  Lwho
has the same function as rwho but instead of broadcasting host information
it saves it in a file in a shared file system.  This code works on VAXen,
Sun 4s, and RTs.  The trouble I am having on the 6000 is getting the
load average of the machine.  The standard way of reading the kernal
does not work and niether do the RPC routines:

    rstat(Host, p_statp); /* high level rpc call */

This fails because the linker cannot find rstat but an nm on the library
(-lrpcsvc) says it is there.

    if (callrpc(Host, RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS, xdr_void, 0,
      xdr_statstime, &statp) != 0) {
	/* mid level rpc call *.
    }

This fails returning an error.  It works on a SPARC.

Does anyone out there know how to get the load average on a 6000?

sanders@cactus.org (Tony Sanders) (04/18/91)

In article <1991Apr17.131722.25180@dartvax.dartmouth.edu> dav@eleazar.dartmouth.edu (William David Haas) writes:
>Does anyone out there know how to get the load average on a 6000?
This should be in the FAQ.  included is xload/get_load.c

I don't have any useful info on your other questions yet.

#if 0
From awdprime!auschs!romp!cs.utexas.edu!news-server.csri.toronto.edu!bonnie.concordia.ca!thunder.mcrcim.mcgill.edu!snorkelwacker.mit.edu!usc!sdd.hp.com!spool.mu.edu!uwm.edu!ux1.cso.uiuc.edu!kline Sat Feb 16 12:00:03 CST 1991
Article: 3176 of comp.unix.aix
Path: awdprime!auschs!romp!cs.utexas.edu!news-server.csri.toronto.edu!bonnie.concordia.ca!thunder.mcrcim.mcgill.edu!snorkelwacker.mit.edu!usc!sdd.hp.com!spool.mu.edu!uwm.edu!ux1.cso.uiuc.edu!kline
From: kline@ux1.cso.uiuc.edu (Charley Kline)
Newsgroups: comp.unix.aix
Subject: Re: X11R4 xload
Keywords: X11R4
Message-ID: <1991Jan31.195110.19739@ux1.cso.uiuc.edu>
Date: 31 Jan 91 19:51:10 GMT
References: <10133@ncar.ucar.edu>
Organization: University of Illinois at Urbana
Lines: 110

boote@bierstadt.scd.ucar.edu (Jeff W. Boote) writes:
>Has anyone successfully ported the xload client from R4?  If anyone out
>there has a patchfile for it I would be most appreciative!  If not, hints
>and any information from attempts would be nice.

AIX doesn't keep the load average information in the kernel, so you have to
do the math yourself. Just replace the get_load.c module with the one below
and you should be all set. You also need to include -lm in the libraries
since GetLoadPoint() calls the exp() function.

Good luck.

________________________________________________________________________
Charley Kline, KB9FFK, PP-ASEL                          c-kline@uiuc.edu
University of Illinois Computing Services            Packet: kb9ffk@w9yh
1304 W. Springfield Ave, Urbana IL  61801                 (217) 333-3339


----------------------------------------------------/begin included text
#endif /* 0 */
/*
 * This version of this module (get_load.c) is specifically for the IBM
 * S/6000 AIX 3.1 platform.
 *
 *  Charley Kline, University of Illinois Computing Services
 *  c-kline@uiuc.edu
 */


#include <stdio.h>
#include <X11/Xos.h>
#include <X11/Intrinsic.h>

#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include <nlist.h>

struct nlist kernelnames[] = {
    {"sysinfo", 0, 0, 0, 0, 0},
    {NULL, 0, 0, 0, 0, 0},
    };


/* ARGSUSED */
void GetLoadPoint(w, closure, call_data)
    Widget w;  /* unused */
    caddr_t closure;  /* unused */
    caddr_t call_data;  /* pointer to (double) return value */
    {
    static double avenrun = 0.;
    double loadav;
    struct sysinfo si;
    static int rq_old = 0, ro_old = 0;
    static initted = 0;
    static int fd;
    double multiplier;
    double t;

    /*
    ** Do stuff we only need to do once per invocation, like opening
    ** the kmem file and fetching the parts of the symbol table.
    */
    if (!initted) {
	initted = 1;
	knlist(kernelnames, 1, sizeof (struct nlist));
	fd = open("/dev/kmem", O_RDONLY);
	if (fd < 0) {
	    perror("kmem");
	    exit(1);
	    }
	}
    
    /*
    ** Get the system info structure from the running kernel.
    */
    lseek(fd, kernelnames[0].n_value, SEEK_SET);
    read(fd, &si, sizeof (struct sysinfo));

    /*
    ** AIX doesn't keep the load average variables in the kernel; all
    ** we can get is the current number of runnable processes by
    ** observing the difference between the runque and runocc values
    ** in sysinfo, and dividing. Having done this, however, we can apply
    ** a TENEX-style exponential time-average to it by computing an
    ** averaging multiplier based on the sampling interval. This is then
    ** used to factor in the current number of runnable processes to our
    ** running load average. The result "looks right" when observed in
    ** conjunction with the process table and user activity.
    **
    ** We subtract one from the number of running processes given us by
    ** the kernel because for some reason AIX always calls one of the
    ** kprocs "runnable" even though it uses very little CPU. Subtracting
    ** this out gives a load average near zero when the machine is mostly
    ** idle, which is more familiar to those of us who are used to
    ** bsd-style load averages.                   /cvk
    */
    t = (double)(si.runocc - ro_old);
    loadav = (double)(si.runque - rq_old) / t - 1.0;
    rq_old = si.runque;
    ro_old = si.runocc;
    multiplier = exp(-t/60.);
    avenrun = multiplier * avenrun + (1.0 - multiplier) * loadav;
    /* DEBUG
    printf("%d %d %f %f %f\n", si.runque, si.runocc, t, loadav, avenrun);
    */

    *(double *)call_data = avenrun;
}