ftp.nice.ch/pub/next/tools/performance/TimeMon.3.2.s.tar.gz#/TimeMon-3.2/loadave.c

This is loadave.c in view mode; [Download] [Up]

/* Copyright 1991, 1994 Scott Hess.  Permission to use, copy, modify,
 * and distribute this software and its documentation for any purpose
 * and without fee is hereby granted, provided that this copyright
 * notice appear in all copies.  The copyright notice need not appear
 * on binary-only distributions - just in source code.
 * 
 * Scott Hess makes no representations about the suitability of this
 * software for any purpose.  It is provided "as is" without express
 * or implied warranty.
 */
/* Get the current load average from the kernel.  Uses the undocumented
 * (and nearly non-existant in NS3.0) table() call if available.
 * Otherwise, is capable of falling back to direct /dev/kmem reading
 * if KMEM is defined (note that this requires the program to run
 * setgid to group kmem).
 */
#import "loadave.h"

    /* Preliminary gunk the routines want to see. */
#ifdef KMEM
    #import <libc.h>
    #import <nlist.h>
    #import <grp.h>
    static struct nlist nl[]={
	{{"_cp_time"}, 0, 0, 0, 0}, {{""}, 0, 0, 0, 0}
    };
    int kmem;			/* File descriptor for /dev/kmem. */
#else
    #import <strings.h>
    #if 0
	#import <sys/table.h>
    #else
	/* NS3.0 doesn't include the <sys/table.h> file.  Sigh.
	 * So, I've snarfed the following without permission from
	 * <sys/table.h> on an NS2.1 system.  The structure, prototype,
	 * and #define could also likely be found in Mach documentation
	 * somewhere.
	 */
	#define TBL_CPUINFO		12	/* (no index), generic CPU info */
	/*
	 * TBL_CPUINFO data layout
	 */
	struct tbl_cpuinfo
	{
	    int		ci_swtch;		/* # context switches */
	    int		ci_intr;		/* # interrupts */
	    int		ci_syscall;		/* # system calls */
	    int		ci_traps;		/* # system traps */
	    int		ci_hz;			/* # ticks per second */
	    int		ci_phz;			/* profiling hz */
	    int		ci_cptime[CPUSTATES];	/* cpu state times */
	};
    #endif
    extern int table( int, int, void *, int, int);
#endif

    /* Initialize the package and return the current CPU time values. */
int la_init( long *times)
{
#ifdef KMEM
	/* For reading kmem, have to poke through /mach to find
	 * locations for cp_time, and then open the kmem device for
	 * reading.
	 */
    if( nlist( "/mach", nl)) {
	return LA_NLIST;
    }
    if( (kmem=open( "/dev/kmem", O_RDONLY))<0) {
	gid_t gid=getegid();
	struct group *kmemgr=getgrnam( "kmem");
	if( kmemgr->gr_gid!=gid) {
	    return LA_PERM;
	} else {
	    return LA_KMEM;
	}
    }
#endif
    return la_read( times);
}

    /* Return the current CPU time values. */
int la_read( long *times)
{
#ifdef KMEM
	/* Seek in kmem to the location of cp_time. */
    if( lseek( kmem, nl[ 0].n_value, L_SET)!=nl[ 0].n_value) {
	return LA_SEEK;
    }
    
	/* Read the values for cp_time. */
    if( read( kmem, times, sizeof( long)*CPUSTATES)!=sizeof( long)*CPUSTATES) {
	return LA_READ;
    }
#else
	/* The table() version is a bit simpler - just ask table()
	 * for the appropriate values.
	 */
    struct tbl_cpuinfo tc;
    if( table( TBL_CPUINFO, 0, &tc, 1, sizeof( tc))>=0) {
	bcopy( tc.ci_cptime, times, sizeof( long)*CPUSTATES);
    } else {
	return LA_TABLE;
    }
#endif
    return LA_NOERR;
}

    /* Clean up after ourselves. */
void la_finish( void)
{
#ifdef KMEM
	/* Close up kmem and nuke the fd. */
    if( kmem>-1) {
	close( kmem);
	kmem=-1;
    }
#endif
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.