#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#if defined (unix) || defined (__unix)
# include <sys/param.h>
#endif
#include <errno.h>
#ifndef errno
extern int errno;
#endif
#ifndef HAVE_GETLOADAVG
# if !defined(LDAV_CVT) && defined(LOAD_AVE_CVT)
# define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0)
# endif
# if !defined (BSD) && defined (ultrix)
# define BSD
# endif
# ifdef NeXT
# undef BSD
# undef FSCALE
# endif
# ifdef __GNU__
# undef BSD
# undef FSCALE
# endif
# if defined (HPUX) && !defined (hpux)
# define hpux
# endif
# if defined (__hpux) && !defined (hpux)
# define hpux
# endif
# if defined (__sun) && !defined (sun)
# define sun
# endif
# if defined(hp300) && !defined(hpux)
# define MORE_BSD
# endif
# if defined(ultrix) && defined(mips)
# define decstation
# endif
# if defined (__SVR4) && !defined (SVR4)
# define SVR4
# endif
# if (defined(sun) && defined(SVR4)) || defined (SOLARIS2)
# define SUNOS_5
# endif
# if defined (__osf__) && (defined (__alpha) || defined (__alpha__))
# define OSF_ALPHA
# include <sys/mbuf.h>
# include <sys/socket.h>
# include <net/route.h>
# include <sys/table.h>
# endif
# if defined (__osf__) && (defined (mips) || defined (__mips__))
# define OSF_MIPS
# include <sys/table.h>
# endif
# if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES)
# define tek4300
# endif
# ifndef LOAD_AVE_TYPE
# ifdef MORE_BSD
# define LOAD_AVE_TYPE long
# endif
# ifdef sun
# define LOAD_AVE_TYPE long
# endif
# ifdef decstation
# define LOAD_AVE_TYPE long
# endif
# ifdef _SEQUENT_
# define LOAD_AVE_TYPE long
# endif
# ifdef sgi
# define LOAD_AVE_TYPE long
# endif
# ifdef SVR4
# define LOAD_AVE_TYPE long
# endif
# ifdef sony_news
# define LOAD_AVE_TYPE long
# endif
# ifdef sequent
# define LOAD_AVE_TYPE long
# endif
# ifdef OSF_ALPHA
# define LOAD_AVE_TYPE long
# endif
# if defined (ardent) && defined (titan)
# define LOAD_AVE_TYPE long
# endif
# ifdef tek4300
# define LOAD_AVE_TYPE long
# endif
# if defined(alliant) && defined(i860)
# define LOAD_AVE_TYPE long
# endif
# ifdef _AIX
# define LOAD_AVE_TYPE long
# endif
# ifdef convex
# define LOAD_AVE_TYPE double
# ifndef LDAV_CVT
# define LDAV_CVT(n) (n)
# endif
# endif
# endif
# ifdef OSF_ALPHA
# undef FSCALE
# define FSCALE 1024.0
# endif
# if defined(alliant) && defined(i860)
# undef FSCALE
# define FSCALE 100.0
# endif
# ifndef FSCALE
# ifdef MORE_BSD
# define FSCALE 2048.0
# endif
# if defined(MIPS) || defined(SVR4) || defined(decstation)
# define FSCALE 256
# endif
# if defined (sgi) || defined (sequent)
# undef FSCALE
# define FSCALE 1000.0
# endif
# if defined (ardent) && defined (titan)
# define FSCALE 65536.0
# endif
# ifdef tek4300
# define FSCALE 100.0
# endif
# ifdef _AIX
# define FSCALE 65536.0
# endif
# endif
# if !defined (LDAV_CVT) && defined (FSCALE)
# define LDAV_CVT(n) (((double) (n)) / FSCALE)
# endif
# if defined(sgi) || (defined(mips) && !defined(BSD))
# define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31))
# endif
# if !defined (KERNEL_FILE) && defined (sequent)
# define KERNEL_FILE "/dynix"
# endif
# if !defined (KERNEL_FILE) && defined (hpux)
# define KERNEL_FILE "/hp-ux"
# endif
# if !defined(KERNEL_FILE) && (defined(_SEQUENT_) || defined(MIPS) || defined(SVR4) || defined(ISC) || defined (sgi) || (defined (ardent) && defined (titan)))
# define KERNEL_FILE "/unix"
# endif
# if !defined (LDAV_SYMBOL) && defined (alliant)
# define LDAV_SYMBOL "_Loadavg"
# endif
# if !defined(LDAV_SYMBOL) && ((defined(hpux) && !defined(hp9000s300)) || defined(_SEQUENT_) || defined(SVR4) || defined(ISC) || defined(sgi) || (defined (ardent) && defined (titan)) || defined (_AIX))
# define LDAV_SYMBOL "avenrun"
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
# include <stdio.h>
# if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL))
# define LOAD_AVE_TYPE double
# endif
# ifdef LOAD_AVE_TYPE
# ifndef VMS
# ifndef __linux__
# ifndef NLIST_STRUCT
# include <a.out.h>
# else
# include <nlist.h>
# endif
# ifdef SUNOS_5
# include <fcntl.h>
# include <kvm.h>
# include <kstat.h>
# endif
# if defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC)
# include <sys/pstat.h>
# endif
# ifndef KERNEL_FILE
# define KERNEL_FILE "/vmunix"
# endif
# ifndef LDAV_SYMBOL
# define LDAV_SYMBOL "_avenrun"
# endif
# endif
# else
# ifndef eunice
# include <iodef.h>
# include <descrip.h>
# else
# include <vms/iodef.h>
# endif
# endif
# ifndef LDAV_CVT
# define LDAV_CVT(n) ((double) (n))
# endif
# endif
# if defined(__GNU__) && !defined (NeXT)
# define NeXT
# define host_self mach_host_self
# endif
# if defined(NeXT) || defined(RHAPSODY) || defined(DARWIN)
# ifdef HAVE_MACH_MACH_H
# include <mach/mach.h>
# else
# include <mach.h>
# endif
# endif
# ifdef sgi
# include <sys/sysmp.h>
# endif
# ifdef UMAX
# include <stdio.h>
# include <signal.h>
# include <sys/time.h>
# include <sys/wait.h>
# include <sys/syscall.h>
# ifdef UMAX_43
# include <machine/cpu.h>
# include <inq_stats/statistics.h>
# include <inq_stats/sysstats.h>
# include <inq_stats/cpustats.h>
# include <inq_stats/procstats.h>
# else
# include <sys/sysdefs.h>
# include <sys/statistics.h>
# include <sys/sysstats.h>
# include <sys/cpudefs.h>
# include <sys/cpustats.h>
# include <sys/procstats.h>
# endif
# endif
# ifdef DGUX
# include <sys/dg_sys_info.h>
# endif
# if defined(HAVE_FCNTL_H) || defined(_POSIX_VERSION)
# include <fcntl.h>
# else
# include <sys/file.h>
# endif
# if defined(NeXT) || defined(RHAPSODY) || defined(DARWIN)
static processor_set_t default_set;
static int getloadavg_initialized;
# endif
# ifdef UMAX
static unsigned int cpus = 0;
static unsigned int samples;
# endif
# ifdef DGUX
static struct dg_sys_info_load_info load_info;
# endif
#if !defined(HAVE_LIBKSTAT) && defined(LOAD_AVE_TYPE)
static int channel;
static int getloadavg_initialized;
static long offset;
#if !defined(VMS) && !defined(sgi) && !defined(__linux__)
static struct nlist nl[2];
#endif
#ifdef SUNOS_5
static kvm_t *kd;
#endif
#endif
#ifdef __APPLE_CC__
__private_extern__
#endif
int
getloadavg (loadavg, nelem)
double loadavg[];
int nelem;
{
int elem = 0;
# ifdef NO_GET_LOAD_AVG
# define LDAV_DONE
errno = 0;
elem = -1;
# endif
# if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT)
# define LDAV_DONE
kstat_ctl_t *kc;
kstat_t *ksp;
kstat_named_t *kn;
kc = kstat_open ();
if (kc == 0)
return -1;
ksp = kstat_lookup (kc, "unix", 0, "system_misc");
if (ksp == 0 )
return -1;
if (kstat_read (kc, ksp, 0) == -1)
return -1;
kn = kstat_data_lookup (ksp, "avenrun_1min");
if (kn == 0)
{
nelem = 0;
elem = -1;
}
if (nelem >= 1)
loadavg[elem++] = (double) kn->value.ul/FSCALE;
if (nelem >= 2)
{
kn = kstat_data_lookup (ksp, "avenrun_5min");
if (kn != 0)
{
loadavg[elem++] = (double) kn->value.ul/FSCALE;
if (nelem >= 3)
{
kn = kstat_data_lookup (ksp, "avenrun_15min");
if (kn != 0)
loadavg[elem++] = (double) kn->value.ul/FSCALE;
}
}
}
kstat_close (kc);
# endif
# if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC)
# define LDAV_DONE
# undef LOAD_AVE_TYPE
struct pst_dynamic dyn_info;
if (pstat_getdynamic (&dyn_info, sizeof (dyn_info), 0, 0) < 0)
return -1;
if (nelem > 0)
loadavg[elem++] = dyn_info.psd_avg_1_min;
if (nelem > 1)
loadavg[elem++] = dyn_info.psd_avg_5_min;
if (nelem > 2)
loadavg[elem++] = dyn_info.psd_avg_15_min;
# endif
# if !defined (LDAV_DONE) && defined (__linux__)
# define LDAV_DONE
# undef LOAD_AVE_TYPE
# ifndef LINUX_LDAV_FILE
# define LINUX_LDAV_FILE "/proc/loadavg"
# endif
char ldavgbuf[40];
double load_ave[3];
int fd, count;
fd = open (LINUX_LDAV_FILE, O_RDONLY);
if (fd == -1)
return -1;
count = read (fd, ldavgbuf, 40);
(void) close (fd);
if (count <= 0)
return -1;
count = sscanf (ldavgbuf, "%lf %lf %lf",
&load_ave[0], &load_ave[1], &load_ave[2]);
if (count < 1)
return -1;
for (elem = 0; elem < nelem && elem < count; elem++)
loadavg[elem] = load_ave[elem];
return elem;
# endif
# if !defined (LDAV_DONE) && defined (__NetBSD__)
# define LDAV_DONE
# undef LOAD_AVE_TYPE
# ifndef NETBSD_LDAV_FILE
# define NETBSD_LDAV_FILE "/kern/loadavg"
# endif
unsigned long int load_ave[3], scale;
int count;
FILE *fp;
fp = fopen (NETBSD_LDAV_FILE, "r");
if (fp == NULL)
return -1;
count = fscanf (fp, "%lu %lu %lu %lu\n",
&load_ave[0], &load_ave[1], &load_ave[2],
&scale);
(void) fclose (fp);
if (count != 4)
return -1;
for (elem = 0; elem < nelem; elem++)
loadavg[elem] = (double) load_ave[elem] / (double) scale;
return elem;
# endif
# if !defined (LDAV_DONE) && (defined(NeXT) || defined(RHAPSODY) || defined(DARWIN))
# define LDAV_DONE
if (!getloadavg_initialized)
{
if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS)
getloadavg_initialized = 1;
}
#ifndef DARWIN
#define processor_set_load_info processor_set_basic_info
#define PROCESSOR_SET_LOAD_INFO PROCESSOR_SET_BASIC_INFO
#define PROCESSOR_SET_LOAD_INFO_COUNT PROCESSOR_SET_BASIC_INFO_COUNT
#endif
if (getloadavg_initialized)
{
struct processor_set_load_info info;
host_t host;
unsigned info_count = PROCESSOR_SET_LOAD_INFO_COUNT;
if (processor_set_info (default_set, PROCESSOR_SET_LOAD_INFO, &host,
(processor_set_info_t) &info, &info_count)
!= KERN_SUCCESS)
getloadavg_initialized = 0;
else
{
if (nelem > 0)
loadavg[elem++] = (double) info.load_average / LOAD_SCALE;
}
}
if (!getloadavg_initialized)
return -1;
# endif
# if !defined (LDAV_DONE) && defined (UMAX)
# define LDAV_DONE
struct proc_summary proc_sum_data;
struct stat_descr proc_info;
double load;
register unsigned int i, j;
if (cpus == 0)
{
register unsigned int c, i;
struct cpu_config conf;
struct stat_descr desc;
desc.sd_next = 0;
desc.sd_subsys = SUBSYS_CPU;
desc.sd_type = CPUTYPE_CONFIG;
desc.sd_addr = (char *) &conf;
desc.sd_size = sizeof conf;
if (inq_stats (1, &desc))
return -1;
c = 0;
for (i = 0; i < conf.config_maxclass; ++i)
{
struct class_stats stats;
bzero ((char *) &stats, sizeof stats);
desc.sd_type = CPUTYPE_CLASS;
desc.sd_objid = i;
desc.sd_addr = (char *) &stats;
desc.sd_size = sizeof stats;
if (inq_stats (1, &desc))
return -1;
c += stats.class_numcpus;
}
cpus = c;
samples = cpus < 2 ? 3 : (2 * cpus / 3);
}
proc_info.sd_next = 0;
proc_info.sd_subsys = SUBSYS_PROC;
proc_info.sd_type = PROCTYPE_SUMMARY;
proc_info.sd_addr = (char *) &proc_sum_data;
proc_info.sd_size = sizeof (struct proc_summary);
proc_info.sd_sizeused = 0;
if (inq_stats (1, &proc_info) != 0)
return -1;
load = proc_sum_data.ps_nrunnable;
j = 0;
for (i = samples - 1; i > 0; --i)
{
load += proc_sum_data.ps_nrun[j];
if (j++ == PS_NRUNSIZE)
j = 0;
}
if (nelem > 0)
loadavg[elem++] = load / samples / cpus;
# endif
# if !defined (LDAV_DONE) && defined (DGUX)
# define LDAV_DONE
dg_sys_info ((long int *) &load_info,
DG_SYS_INFO_LOAD_INFO_TYPE,
DG_SYS_INFO_LOAD_VERSION_0);
if (nelem > 0)
loadavg[elem++] = load_info.one_minute;
if (nelem > 1)
loadavg[elem++] = load_info.five_minute;
if (nelem > 2)
loadavg[elem++] = load_info.fifteen_minute;
# endif
# if !defined (LDAV_DONE) && defined (apollo)
# define LDAV_DONE
extern void proc1_$get_loadav ();
unsigned long load_ave[3];
proc1_$get_loadav (load_ave);
if (nelem > 0)
loadavg[elem++] = load_ave[0] / 65536.0;
if (nelem > 1)
loadavg[elem++] = load_ave[1] / 65536.0;
if (nelem > 2)
loadavg[elem++] = load_ave[2] / 65536.0;
# endif
# if !defined (LDAV_DONE) && defined (OSF_MIPS)
# define LDAV_DONE
struct tbl_loadavg load_ave;
table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
loadavg[elem++]
= (load_ave.tl_lscale == 0
? load_ave.tl_avenrun.d[0]
: (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale));
# endif
# if !defined (LDAV_DONE) && (defined (__MSDOS__) || defined (WINDOWS32))
# define LDAV_DONE
for ( ; elem < nelem; elem++)
{
loadavg[elem] = 0.0;
}
# endif
# if !defined (LDAV_DONE) && defined (OSF_ALPHA)
# define LDAV_DONE
struct tbl_loadavg load_ave;
table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
for (elem = 0; elem < nelem; elem++)
loadavg[elem]
= (load_ave.tl_lscale == 0
? load_ave.tl_avenrun.d[elem]
: (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale));
# endif
# if !defined (LDAV_DONE) && defined (VMS)
LOAD_AVE_TYPE load_ave[3];
static int getloadavg_initialized = 0;
# ifdef eunice
struct
{
int dsc$w_length;
char *dsc$a_pointer;
} descriptor;
# endif
if (!getloadavg_initialized)
{
# ifdef eunice
descriptor.dsc$w_length = 18;
descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE";
# else
$DESCRIPTOR (descriptor, "LAV0:");
# endif
if (sys$assign (&descriptor, &channel, 0, 0) & 1)
getloadavg_initialized = 1;
}
if (getloadavg_initialized
&& !(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0,
load_ave, 12, 0, 0, 0, 0) & 1))
{
sys$dassgn (channel);
getloadavg_initialized = 0;
}
if (!getloadavg_initialized)
return -1;
# endif
# if !defined (LDAV_DONE) && defined(LOAD_AVE_TYPE) && !defined(VMS)
# define LDAV_PRIVILEGED
LOAD_AVE_TYPE load_ave[3];
if (offset == 0)
{
# ifndef sgi
# ifndef NLIST_STRUCT
strcpy (nl[0].n_name, LDAV_SYMBOL);
strcpy (nl[1].n_name, "");
# else
# ifdef NLIST_NAME_UNION
nl[0].n_un.n_name = LDAV_SYMBOL;
nl[1].n_un.n_name = 0;
# else
nl[0].n_name = LDAV_SYMBOL;
nl[1].n_name = 0;
# endif
# endif
# ifndef SUNOS_5
if (
# if !(defined (_AIX) && !defined (ps2))
nlist (KERNEL_FILE, nl)
# else
knlist (nl, 1, sizeof (nl[0]))
# endif
>= 0)
{
# ifdef FIXUP_KERNEL_SYMBOL_ADDR
FIXUP_KERNEL_SYMBOL_ADDR (nl);
# endif
offset = nl[0].n_value;
}
# endif
# else
int ldav_off;
ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN);
if (ldav_off != -1)
offset = (long) ldav_off & 0x7fffffff;
# endif
}
if (!getloadavg_initialized)
{
# ifndef SUNOS_5
channel = open ("/dev/kmem", 0);
if (channel >= 0)
{
# ifdef F_SETFD
# ifndef FD_CLOEXEC
# define FD_CLOEXEC 1
# endif
(void) fcntl (channel, F_SETFD, FD_CLOEXEC);
# endif
getloadavg_initialized = 1;
}
# else
kd = kvm_open (0, 0, 0, O_RDONLY, 0);
if (kd != 0)
{
kvm_nlist (kd, nl);
offset = nl[0].n_value;
getloadavg_initialized = 1;
}
# endif
}
if (offset && getloadavg_initialized)
{
# ifndef SUNOS_5
if (lseek (channel, offset, 0) == -1L
|| read (channel, (char *) load_ave, sizeof (load_ave))
!= sizeof (load_ave))
{
close (channel);
getloadavg_initialized = 0;
}
# else
if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave))
!= sizeof (load_ave))
{
kvm_close (kd);
getloadavg_initialized = 0;
}
# endif
}
if (offset == 0 || !getloadavg_initialized)
return -1;
# endif
# if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE)
if (nelem > 0)
loadavg[elem++] = LDAV_CVT (load_ave[0]);
if (nelem > 1)
loadavg[elem++] = LDAV_CVT (load_ave[1]);
if (nelem > 2)
loadavg[elem++] = LDAV_CVT (load_ave[2]);
# define LDAV_DONE
# endif
# ifdef LDAV_DONE
return elem;
# else
errno = 0;
return -1;
# endif
}
#endif
#ifdef TEST
int
main (argc, argv)
int argc;
char **argv;
{
int naptime = 0;
if (argc > 1)
naptime = atoi (argv[1]);
while (1)
{
double avg[3];
int loads;
errno = 0;
loads = getloadavg (avg, 3);
if (loads == -1)
{
perror ("Error getting load average");
exit (1);
}
if (loads > 0)
printf ("1-minute: %f ", avg[0]);
if (loads > 1)
printf ("5-minute: %f ", avg[1]);
if (loads > 2)
printf ("15-minute: %f ", avg[2]);
if (loads > 0)
putchar ('\n');
if (naptime == 0)
break;
sleep (naptime);
}
exit (0);
}
#endif