Home | History | Annotate | Download | only in make-3.81
      1 /* Get the system load averages.
      2 Copyright (C) 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
      3 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free
      4 Software Foundation, Inc.
      5 
      6 This program is free software; you can redistribute it and/or modify
      7 it under the terms of the GNU General Public License as published by
      8 the Free Software Foundation; either version 2, or (at your option)
      9 any later version.
     10 
     11 This program is distributed in the hope that it will be useful,
     12 but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 GNU General Public License for more details.
     15 
     16 You should have received a copy of the GNU General Public License along with
     17 this program; see the file COPYING.  If not, write to the Free Software
     18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
     19 
     20 /* Compile-time symbols that this file uses:
     21 
     22    HAVE_PSTAT_GETDYNAMIC	Define this if your system has the
     23                                 pstat_getdynamic function.  I think it
     24 				is unique to HPUX9.  The best way to get the
     25 				definition is through the AC_FUNC_GETLOADAVG
     26 				macro that comes with autoconf 2.13 or newer.
     27 				If that isn't an option, then just put
     28 				AC_CHECK_FUNCS(pstat_getdynamic) in your
     29 				configure.in file.
     30    FIXUP_KERNEL_SYMBOL_ADDR()	Adjust address in returned struct nlist.
     31    KERNEL_FILE			Pathname of the kernel to nlist.
     32    LDAV_CVT()			Scale the load average from the kernel.
     33 				Returns a double.
     34    LDAV_SYMBOL			Name of kernel symbol giving load average.
     35    LOAD_AVE_TYPE		Type of the load average array in the kernel.
     36 				Must be defined unless one of
     37 				apollo, DGUX, NeXT, or UMAX is defined;
     38                                 or we have libkstat;
     39 				otherwise, no load average is available.
     40    NLIST_STRUCT			Include nlist.h, not a.out.h, and
     41 				the nlist n_name element is a pointer,
     42 				not an array.
     43    HAVE_STRUCT_NLIST_N_UN_N_NAME struct nlist has an n_un member, not n_name.
     44    LINUX_LDAV_FILE		[__linux__]: File containing load averages.
     45 
     46    Specific system predefines this file uses, aside from setting
     47    default values if not emacs:
     48 
     49    apollo
     50    BSD				Real BSD, not just BSD-like.
     51    convex
     52    DGUX
     53    eunice			UNIX emulator under VMS.
     54    hpux
     55    __MSDOS__			No-op for MSDOS.
     56    NeXT
     57    sgi
     58    sequent			Sequent Dynix 3.x.x (BSD)
     59    _SEQUENT_			Sequent DYNIX/ptx 1.x.x (SYSV)
     60    sony_news                    NEWS-OS (works at least for 4.1C)
     61    UMAX
     62    UMAX4_3
     63    VMS
     64    WINDOWS32			No-op for Windows95/NT.
     65    __linux__			Linux: assumes /proc filesystem mounted.
     66    				Support from Michael K. Johnson.
     67    __NetBSD__			NetBSD: assumes /kern filesystem mounted.
     68 
     69    In addition, to avoid nesting many #ifdefs, we internally set
     70    LDAV_DONE to indicate that the load average has been computed.
     71 
     72    We also #define LDAV_PRIVILEGED if a program will require
     73    special installation to be able to call getloadavg.  */
     74 
     75 /* This should always be first.  */
     76 #ifdef HAVE_CONFIG_H
     77 # include <config.h>
     78 #endif
     79 
     80 #include <sys/types.h>
     81 
     82 /* Both the Emacs and non-Emacs sections want this.  Some
     83    configuration files' definitions for the LOAD_AVE_CVT macro (like
     84    sparc.h's) use macros like FSCALE, defined here.  */
     85 #if defined (unix) || defined (__unix)
     86 # include <sys/param.h>
     87 #endif
     88 
     89 
     90 /* Exclude all the code except the test program at the end
     91    if the system has its own `getloadavg' function.
     92 
     93    The declaration of `errno' is needed by the test program
     94    as well as the function itself, so it comes first.  */
     95 
     96 #include <errno.h>
     97 
     98 #ifndef errno
     99 extern int errno;
    100 #endif
    101 
    102 #if HAVE_LOCALE_H
    103 # include <locale.h>
    104 #endif
    105 #if !HAVE_SETLOCALE
    106 # define setlocale(Category, Locale) /* empty */
    107 #endif
    108 
    109 #ifndef HAVE_GETLOADAVG
    110 
    111 
    112 /* The existing Emacs configuration files define a macro called
    113    LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and
    114    returns the load average multiplied by 100.  What we actually want
    115    is a macro called LDAV_CVT, which returns the load average as an
    116    unmultiplied double.
    117 
    118    For backwards compatibility, we'll define LDAV_CVT in terms of
    119    LOAD_AVE_CVT, but future machine config files should just define
    120    LDAV_CVT directly.  */
    121 
    122 # if !defined(LDAV_CVT) && defined(LOAD_AVE_CVT)
    123 #  define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0)
    124 # endif
    125 
    126 # if !defined (BSD) && defined (ultrix)
    127 /* Ultrix behaves like BSD on Vaxen.  */
    128 #  define BSD
    129 # endif
    130 
    131 # ifdef NeXT
    132 /* NeXT in the 2.{0,1,2} releases defines BSD in <sys/param.h>, which
    133    conflicts with the definition understood in this file, that this
    134    really is BSD. */
    135 #  undef BSD
    136 
    137 /* NeXT defines FSCALE in <sys/param.h>.  However, we take FSCALE being
    138    defined to mean that the nlist method should be used, which is not true.  */
    139 #  undef FSCALE
    140 # endif
    141 
    142 /* Same issues as for NeXT apply to the HURD-based GNU system.  */
    143 # ifdef __GNU__
    144 #  undef BSD
    145 #  undef FSCALE
    146 # endif /* __GNU__ */
    147 
    148 /* Set values that are different from the defaults, which are
    149    set a little farther down with #ifndef.  */
    150 
    151 
    152 /* Some shorthands.  */
    153 
    154 # if defined (HPUX) && !defined (hpux)
    155 #  define hpux
    156 # endif
    157 
    158 # if defined (__hpux) && !defined (hpux)
    159 #  define hpux
    160 # endif
    161 
    162 # if defined (__sun) && !defined (sun)
    163 #  define sun
    164 # endif
    165 
    166 # if defined(hp300) && !defined(hpux)
    167 #  define MORE_BSD
    168 # endif
    169 
    170 # if defined(ultrix) && defined(mips)
    171 #  define decstation
    172 # endif
    173 
    174 # if defined (__SVR4) && !defined (SVR4)
    175 #  define SVR4
    176 # endif
    177 
    178 # if (defined(sun) && defined(SVR4)) || defined (SOLARIS2)
    179 #  define SUNOS_5
    180 # endif
    181 
    182 # if defined (__osf__) && (defined (__alpha) || defined (__alpha__))
    183 #  define OSF_ALPHA
    184 #  include <sys/mbuf.h>
    185 #  include <sys/socket.h>
    186 #  include <net/route.h>
    187 #  include <sys/table.h>
    188 # endif
    189 
    190 # if defined (__osf__) && (defined (mips) || defined (__mips__))
    191 #  define OSF_MIPS
    192 #  include <sys/table.h>
    193 # endif
    194 
    195 /* UTek's /bin/cc on the 4300 has no architecture specific cpp define by
    196    default, but _MACH_IND_SYS_TYPES is defined in <sys/types.h>.  Combine
    197    that with a couple of other things and we'll have a unique match.  */
    198 # if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES)
    199 #  define tek4300			/* Define by emacs, but not by other users.  */
    200 # endif
    201 
    202 /* AC_FUNC_GETLOADAVG thinks QNX is SVR4, but it isn't. */
    203 # if defined(__QNX__)
    204 #  undef SVR4
    205 # endif
    206 
    207 /* VAX C can't handle multi-line #ifs, or lines longer than 256 chars.  */
    208 # ifndef LOAD_AVE_TYPE
    209 
    210 #  ifdef MORE_BSD
    211 #   define LOAD_AVE_TYPE long
    212 #  endif
    213 
    214 #  ifdef sun
    215 #   define LOAD_AVE_TYPE long
    216 #  endif
    217 
    218 #  ifdef decstation
    219 #   define LOAD_AVE_TYPE long
    220 #  endif
    221 
    222 #  ifdef _SEQUENT_
    223 #   define LOAD_AVE_TYPE long
    224 #  endif
    225 
    226 #  ifdef sgi
    227 #   define LOAD_AVE_TYPE long
    228 #  endif
    229 
    230 #  ifdef SVR4
    231 #   define LOAD_AVE_TYPE long
    232 #  endif
    233 
    234 #  ifdef sony_news
    235 #   define LOAD_AVE_TYPE long
    236 #  endif
    237 
    238 #  ifdef sequent
    239 #   define LOAD_AVE_TYPE long
    240 #  endif
    241 
    242 #  ifdef OSF_ALPHA
    243 #   define LOAD_AVE_TYPE long
    244 #  endif
    245 
    246 #  if defined (ardent) && defined (titan)
    247 #   define LOAD_AVE_TYPE long
    248 #  endif
    249 
    250 #  ifdef tek4300
    251 #   define LOAD_AVE_TYPE long
    252 #  endif
    253 
    254 #  if defined(alliant) && defined(i860) /* Alliant FX/2800 */
    255 #   define LOAD_AVE_TYPE long
    256 #  endif
    257 
    258 #  ifdef _AIX
    259 #   define LOAD_AVE_TYPE long
    260 #  endif
    261 
    262 #  ifdef convex
    263 #   define LOAD_AVE_TYPE double
    264 #   ifndef LDAV_CVT
    265 #    define LDAV_CVT(n) (n)
    266 #   endif
    267 #  endif
    268 
    269 # endif /* No LOAD_AVE_TYPE.  */
    270 
    271 # ifdef OSF_ALPHA
    272 /* <sys/param.h> defines an incorrect value for FSCALE on Alpha OSF/1,
    273    according to ghazi (at) noc.rutgers.edu.  */
    274 #  undef FSCALE
    275 #  define FSCALE 1024.0
    276 # endif
    277 
    278 # if defined(alliant) && defined(i860) /* Alliant FX/2800 */
    279 /* <sys/param.h> defines an incorrect value for FSCALE on an
    280    Alliant FX/2800 Concentrix 2.2, according to ghazi (at) noc.rutgers.edu.  */
    281 #  undef FSCALE
    282 #  define FSCALE 100.0
    283 # endif
    284 
    285 
    286 # ifndef	FSCALE
    287 
    288 /* SunOS and some others define FSCALE in sys/param.h.  */
    289 
    290 #  ifdef MORE_BSD
    291 #   define FSCALE 2048.0
    292 #  endif
    293 
    294 #  if defined(MIPS) || defined(SVR4) || defined(decstation)
    295 #   define FSCALE 256
    296 #  endif
    297 
    298 #  if defined (sgi) || defined (sequent)
    299 /* Sometimes both MIPS and sgi are defined, so FSCALE was just defined
    300    above under #ifdef MIPS.  But we want the sgi value.  */
    301 #   undef FSCALE
    302 #   define	FSCALE 1000.0
    303 #  endif
    304 
    305 #  if defined (ardent) && defined (titan)
    306 #   define FSCALE 65536.0
    307 #  endif
    308 
    309 #  ifdef tek4300
    310 #   define FSCALE 100.0
    311 #  endif
    312 
    313 #  ifdef _AIX
    314 #   define FSCALE 65536.0
    315 #  endif
    316 
    317 # endif	/* Not FSCALE.  */
    318 
    319 # if !defined (LDAV_CVT) && defined (FSCALE)
    320 #  define	LDAV_CVT(n) (((double) (n)) / FSCALE)
    321 # endif
    322 
    323 
    324 # if defined(sgi) || (defined(mips) && !defined(BSD))
    325 #  define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31))
    326 # endif
    327 
    328 
    329 # if !defined (KERNEL_FILE) && defined (sequent)
    330 #  define KERNEL_FILE "/dynix"
    331 # endif
    332 
    333 # if !defined (KERNEL_FILE) && defined (hpux)
    334 #  define KERNEL_FILE "/hp-ux"
    335 # endif
    336 
    337 # if !defined(KERNEL_FILE) && (defined(_SEQUENT_) || defined(MIPS) || defined(SVR4) || defined(ISC) || defined (sgi) || (defined (ardent) && defined (titan)))
    338 #  define KERNEL_FILE "/unix"
    339 # endif
    340 
    341 
    342 # if !defined (LDAV_SYMBOL) && defined (alliant)
    343 #  define LDAV_SYMBOL "_Loadavg"
    344 # endif
    345 
    346 # if !defined(LDAV_SYMBOL) && ((defined(hpux) && !defined(hp9000s300)) || defined(_SEQUENT_) || defined(SVR4) || defined(ISC) || defined(sgi) || (defined (ardent) && defined (titan)) || defined (_AIX))
    347 #  define LDAV_SYMBOL "avenrun"
    348 # endif
    349 
    350 # ifdef HAVE_UNISTD_H
    351 #  include <unistd.h>
    352 # endif
    353 
    354 # include <stdio.h>
    355 
    356 /* LOAD_AVE_TYPE should only get defined if we're going to use the
    357    nlist method.  */
    358 # if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL)) && !defined(__riscos__)
    359 #  define LOAD_AVE_TYPE double
    360 # endif
    361 
    362 # ifdef LOAD_AVE_TYPE
    363 
    364 #  ifndef VMS
    365 #   ifndef __linux__
    366 #    ifdef HAVE_NLIST_H
    367 #     include <nlist.h>
    368 #    else
    369 #     include <a.out.h>
    370 #    endif
    371 
    372 #    ifdef SUNOS_5
    373 #     include <fcntl.h>
    374 #     include <kvm.h>
    375 #     include <kstat.h>
    376 #    endif
    377 
    378 #    if defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC)
    379 #     include <sys/pstat.h>
    380 #    endif
    381 
    382 #    ifndef KERNEL_FILE
    383 #     define KERNEL_FILE "/vmunix"
    384 #    endif /* KERNEL_FILE */
    385 
    386 #    ifndef LDAV_SYMBOL
    387 #     define LDAV_SYMBOL "_avenrun"
    388 #    endif /* LDAV_SYMBOL */
    389 #   endif /* __linux__ */
    390 
    391 #  else /* VMS */
    392 
    393 #   ifndef eunice
    394 #    include <iodef.h>
    395 #    include <descrip.h>
    396 #   else /* eunice */
    397 #    include <vms/iodef.h>
    398 #   endif /* eunice */
    399 #  endif /* VMS */
    400 
    401 #  ifndef LDAV_CVT
    402 #   define LDAV_CVT(n) ((double) (n))
    403 #  endif /* !LDAV_CVT */
    404 
    405 # endif /* LOAD_AVE_TYPE */
    406 
    407 # if defined(__GNU__) && !defined (NeXT)
    408 /* Note that NeXT Openstep defines __GNU__ even though it should not.  */
    409 /* GNU system acts much like NeXT, for load average purposes,
    410    but not exactly.  */
    411 #  define NeXT
    412 #  define host_self mach_host_self
    413 # endif
    414 
    415 # ifdef NeXT
    416 #  ifdef HAVE_MACH_MACH_H
    417 #   include <mach/mach.h>
    418 #  else
    419 #   include <mach.h>
    420 #  endif
    421 # endif /* NeXT */
    422 
    423 # ifdef sgi
    424 #  include <sys/sysmp.h>
    425 # endif /* sgi */
    426 
    427 # ifdef UMAX
    428 #  include <stdio.h>
    429 #  include <signal.h>
    430 #  include <sys/time.h>
    431 #  include <sys/wait.h>
    432 #  include <sys/syscall.h>
    433 
    434 #  ifdef UMAX_43
    435 #   include <machine/cpu.h>
    436 #   include <inq_stats/statistics.h>
    437 #   include <inq_stats/sysstats.h>
    438 #   include <inq_stats/cpustats.h>
    439 #   include <inq_stats/procstats.h>
    440 #  else /* Not UMAX_43.  */
    441 #   include <sys/sysdefs.h>
    442 #   include <sys/statistics.h>
    443 #   include <sys/sysstats.h>
    444 #   include <sys/cpudefs.h>
    445 #   include <sys/cpustats.h>
    446 #   include <sys/procstats.h>
    447 #  endif /* Not UMAX_43.  */
    448 # endif /* UMAX */
    449 
    450 # ifdef DGUX
    451 #  include <sys/dg_sys_info.h>
    452 # endif
    453 
    454 # if defined(HAVE_FCNTL_H) || defined(_POSIX_VERSION)
    455 #  include <fcntl.h>
    456 # else
    457 #  include <sys/file.h>
    458 # endif
    459 
    460 
    462 /* Avoid static vars inside a function since in HPUX they dump as pure.  */
    463 
    464 # ifdef NeXT
    465 static processor_set_t default_set;
    466 static int getloadavg_initialized;
    467 # endif /* NeXT */
    468 
    469 # ifdef UMAX
    470 static unsigned int cpus = 0;
    471 static unsigned int samples;
    472 # endif /* UMAX */
    473 
    474 # ifdef DGUX
    475 static struct dg_sys_info_load_info load_info;	/* what-a-mouthful! */
    476 # endif /* DGUX */
    477 
    478 #if !defined(HAVE_LIBKSTAT) && defined(LOAD_AVE_TYPE)
    479 /* File descriptor open to /dev/kmem or VMS load ave driver.  */
    480 static int channel;
    481 /* Nonzero iff channel is valid.  */
    482 static int getloadavg_initialized;
    483 /* Offset in kmem to seek to read load average, or 0 means invalid.  */
    484 static long offset;
    485 
    486 #if !defined(VMS) && !defined(sgi) && !defined(__linux__)
    487 static struct nlist nl[2];
    488 #endif /* Not VMS or sgi */
    489 
    490 #ifdef SUNOS_5
    491 static kvm_t *kd;
    492 #endif /* SUNOS_5 */
    493 
    494 #endif /* LOAD_AVE_TYPE && !HAVE_LIBKSTAT */
    495 
    496 /* Put the 1 minute, 5 minute and 15 minute load averages
    498    into the first NELEM elements of LOADAVG.
    499    Return the number written (never more than 3, but may be less than NELEM),
    500    or -1 if an error occurred.  */
    501 
    502 int
    503 getloadavg (double loadavg[], int nelem)
    504 {
    505   int elem = 0;			/* Return value.  */
    506 
    507 # ifdef NO_GET_LOAD_AVG
    508 #  define LDAV_DONE
    509   /* Set errno to zero to indicate that there was no particular error;
    510      this function just can't work at all on this system.  */
    511   errno = 0;
    512   elem = -1;
    513 # endif
    514 
    515 # if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT)
    516 /* Use libkstat because we don't have to be root.  */
    517 #  define LDAV_DONE
    518   kstat_ctl_t *kc;
    519   kstat_t *ksp;
    520   kstat_named_t *kn;
    521 
    522   kc = kstat_open ();
    523   if (kc == 0)
    524     return -1;
    525   ksp = kstat_lookup (kc, "unix", 0, "system_misc");
    526   if (ksp == 0 )
    527     return -1;
    528   if (kstat_read (kc, ksp, 0) == -1)
    529     return -1;
    530 
    531 
    532   kn = kstat_data_lookup (ksp, "avenrun_1min");
    533   if (kn == 0)
    534     {
    535       /* Return -1 if no load average information is available.  */
    536       nelem = 0;
    537       elem = -1;
    538     }
    539 
    540   if (nelem >= 1)
    541     loadavg[elem++] = (double) kn->value.ul/FSCALE;
    542 
    543   if (nelem >= 2)
    544     {
    545       kn = kstat_data_lookup (ksp, "avenrun_5min");
    546       if (kn != 0)
    547 	{
    548 	  loadavg[elem++] = (double) kn->value.ul/FSCALE;
    549 
    550 	  if (nelem >= 3)
    551 	    {
    552 	      kn = kstat_data_lookup (ksp, "avenrun_15min");
    553 	      if (kn != 0)
    554 		loadavg[elem++] = (double) kn->value.ul/FSCALE;
    555 	    }
    556 	}
    557     }
    558 
    559   kstat_close (kc);
    560 # endif /* HAVE_LIBKSTAT */
    561 
    562 # if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC)
    563 /* Use pstat_getdynamic() because we don't have to be root.  */
    564 #  define LDAV_DONE
    565 #  undef LOAD_AVE_TYPE
    566 
    567   struct pst_dynamic dyn_info;
    568   if (pstat_getdynamic (&dyn_info, sizeof (dyn_info), 0, 0) < 0)
    569     return -1;
    570   if (nelem > 0)
    571     loadavg[elem++] = dyn_info.psd_avg_1_min;
    572   if (nelem > 1)
    573     loadavg[elem++] = dyn_info.psd_avg_5_min;
    574   if (nelem > 2)
    575     loadavg[elem++] = dyn_info.psd_avg_15_min;
    576 
    577 # endif /* hpux && HAVE_PSTAT_GETDYNAMIC */
    578 
    579 # if !defined (LDAV_DONE) && defined (__linux__)
    580 #  define LDAV_DONE
    581 #  undef LOAD_AVE_TYPE
    582 
    583 #  ifndef LINUX_LDAV_FILE
    584 #   define LINUX_LDAV_FILE "/proc/loadavg"
    585 #  endif
    586 
    587   char ldavgbuf[40];
    588   double load_ave[3];
    589   int fd, count;
    590 
    591   fd = open (LINUX_LDAV_FILE, O_RDONLY);
    592   if (fd == -1)
    593     return -1;
    594   count = read (fd, ldavgbuf, 40);
    595   (void) close (fd);
    596   if (count <= 0)
    597     return -1;
    598 
    599   /* The following sscanf must use the C locale.  */
    600   setlocale (LC_NUMERIC, "C");
    601   count = sscanf (ldavgbuf, "%lf %lf %lf",
    602 		  &load_ave[0], &load_ave[1], &load_ave[2]);
    603   setlocale (LC_NUMERIC, "");
    604   if (count < 1)
    605     return -1;
    606 
    607   for (elem = 0; elem < nelem && elem < count; elem++)
    608     loadavg[elem] = load_ave[elem];
    609 
    610   return elem;
    611 
    612 # endif /* __linux__ */
    613 
    614 # if !defined (LDAV_DONE) && defined (__NetBSD__)
    615 #  define LDAV_DONE
    616 #  undef LOAD_AVE_TYPE
    617 
    618 #  ifndef NETBSD_LDAV_FILE
    619 #   define NETBSD_LDAV_FILE "/kern/loadavg"
    620 #  endif
    621 
    622   unsigned long int load_ave[3], scale;
    623   int count;
    624   FILE *fp;
    625 
    626   fp = fopen (NETBSD_LDAV_FILE, "r");
    627   if (fp == NULL)
    628     return -1;
    629   count = fscanf (fp, "%lu %lu %lu %lu\n",
    630 		  &load_ave[0], &load_ave[1], &load_ave[2],
    631 		  &scale);
    632   (void) fclose (fp);
    633   if (count != 4)
    634     return -1;
    635 
    636   for (elem = 0; elem < nelem; elem++)
    637     loadavg[elem] = (double) load_ave[elem] / (double) scale;
    638 
    639   return elem;
    640 
    641 # endif /* __NetBSD__ */
    642 
    643 # if !defined (LDAV_DONE) && defined (NeXT)
    644 #  define LDAV_DONE
    645   /* The NeXT code was adapted from iscreen 3.2.  */
    646 
    647   host_t host;
    648   struct processor_set_basic_info info;
    649   unsigned info_count;
    650 
    651   /* We only know how to get the 1-minute average for this system,
    652      so even if the caller asks for more than 1, we only return 1.  */
    653 
    654   if (!getloadavg_initialized)
    655     {
    656       if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS)
    657 	getloadavg_initialized = 1;
    658     }
    659 
    660   if (getloadavg_initialized)
    661     {
    662       info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
    663       if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host,
    664 			      (processor_set_info_t) &info, &info_count)
    665 	  != KERN_SUCCESS)
    666 	getloadavg_initialized = 0;
    667       else
    668 	{
    669 	  if (nelem > 0)
    670 	    loadavg[elem++] = (double) info.load_average / LOAD_SCALE;
    671 	}
    672     }
    673 
    674   if (!getloadavg_initialized)
    675     return -1;
    676 # endif /* NeXT */
    677 
    678 # if !defined (LDAV_DONE) && defined (UMAX)
    679 #  define LDAV_DONE
    680 /* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not
    681    have a /dev/kmem.  Information about the workings of the running kernel
    682    can be gathered with inq_stats system calls.
    683    We only know how to get the 1-minute average for this system.  */
    684 
    685   struct proc_summary proc_sum_data;
    686   struct stat_descr proc_info;
    687   double load;
    688   register unsigned int i, j;
    689 
    690   if (cpus == 0)
    691     {
    692       register unsigned int c, i;
    693       struct cpu_config conf;
    694       struct stat_descr desc;
    695 
    696       desc.sd_next = 0;
    697       desc.sd_subsys = SUBSYS_CPU;
    698       desc.sd_type = CPUTYPE_CONFIG;
    699       desc.sd_addr = (char *) &conf;
    700       desc.sd_size = sizeof conf;
    701 
    702       if (inq_stats (1, &desc))
    703 	return -1;
    704 
    705       c = 0;
    706       for (i = 0; i < conf.config_maxclass; ++i)
    707 	{
    708 	  struct class_stats stats;
    709 	  bzero ((char *) &stats, sizeof stats);
    710 
    711 	  desc.sd_type = CPUTYPE_CLASS;
    712 	  desc.sd_objid = i;
    713 	  desc.sd_addr = (char *) &stats;
    714 	  desc.sd_size = sizeof stats;
    715 
    716 	  if (inq_stats (1, &desc))
    717 	    return -1;
    718 
    719 	  c += stats.class_numcpus;
    720 	}
    721       cpus = c;
    722       samples = cpus < 2 ? 3 : (2 * cpus / 3);
    723     }
    724 
    725   proc_info.sd_next = 0;
    726   proc_info.sd_subsys = SUBSYS_PROC;
    727   proc_info.sd_type = PROCTYPE_SUMMARY;
    728   proc_info.sd_addr = (char *) &proc_sum_data;
    729   proc_info.sd_size = sizeof (struct proc_summary);
    730   proc_info.sd_sizeused = 0;
    731 
    732   if (inq_stats (1, &proc_info) != 0)
    733     return -1;
    734 
    735   load = proc_sum_data.ps_nrunnable;
    736   j = 0;
    737   for (i = samples - 1; i > 0; --i)
    738     {
    739       load += proc_sum_data.ps_nrun[j];
    740       if (j++ == PS_NRUNSIZE)
    741 	j = 0;
    742     }
    743 
    744   if (nelem > 0)
    745     loadavg[elem++] = load / samples / cpus;
    746 # endif /* UMAX */
    747 
    748 # if !defined (LDAV_DONE) && defined (DGUX)
    749 #  define LDAV_DONE
    750   /* This call can return -1 for an error, but with good args
    751      it's not supposed to fail.  The first argument is for no
    752      apparent reason of type `long int *'.  */
    753   dg_sys_info ((long int *) &load_info,
    754 	       DG_SYS_INFO_LOAD_INFO_TYPE,
    755 	       DG_SYS_INFO_LOAD_VERSION_0);
    756 
    757   if (nelem > 0)
    758     loadavg[elem++] = load_info.one_minute;
    759   if (nelem > 1)
    760     loadavg[elem++] = load_info.five_minute;
    761   if (nelem > 2)
    762     loadavg[elem++] = load_info.fifteen_minute;
    763 # endif /* DGUX */
    764 
    765 # if !defined (LDAV_DONE) && defined (apollo)
    766 #  define LDAV_DONE
    767 /* Apollo code from lisch (at) mentorg.com (Ray Lischner).
    768 
    769    This system call is not documented.  The load average is obtained as
    770    three long integers, for the load average over the past minute,
    771    five minutes, and fifteen minutes.  Each value is a scaled integer,
    772    with 16 bits of integer part and 16 bits of fraction part.
    773 
    774    I'm not sure which operating system first supported this system call,
    775    but I know that SR10.2 supports it.  */
    776 
    777   extern void proc1_$get_loadav ();
    778   unsigned long load_ave[3];
    779 
    780   proc1_$get_loadav (load_ave);
    781 
    782   if (nelem > 0)
    783     loadavg[elem++] = load_ave[0] / 65536.0;
    784   if (nelem > 1)
    785     loadavg[elem++] = load_ave[1] / 65536.0;
    786   if (nelem > 2)
    787     loadavg[elem++] = load_ave[2] / 65536.0;
    788 # endif /* apollo */
    789 
    790 # if !defined (LDAV_DONE) && defined (OSF_MIPS)
    791 #  define LDAV_DONE
    792 
    793   struct tbl_loadavg load_ave;
    794   table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
    795   loadavg[elem++]
    796     = (load_ave.tl_lscale == 0
    797        ? load_ave.tl_avenrun.d[0]
    798        : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale));
    799 # endif	/* OSF_MIPS */
    800 
    801 # if !defined (LDAV_DONE) && (defined (__MSDOS__) || defined (WINDOWS32))
    802 #  define LDAV_DONE
    803 
    804   /* A faithful emulation is going to have to be saved for a rainy day.  */
    805   for ( ; elem < nelem; elem++)
    806     {
    807       loadavg[elem] = 0.0;
    808     }
    809 # endif  /* __MSDOS__ || WINDOWS32 */
    810 
    811 # if !defined (LDAV_DONE) && defined (OSF_ALPHA)
    812 #  define LDAV_DONE
    813 
    814   struct tbl_loadavg load_ave;
    815   table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
    816   for (elem = 0; elem < nelem; elem++)
    817     loadavg[elem]
    818       = (load_ave.tl_lscale == 0
    819        ? load_ave.tl_avenrun.d[elem]
    820        : (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale));
    821 # endif /* OSF_ALPHA */
    822 
    823 # if !defined (LDAV_DONE) && defined (VMS)
    824   /* VMS specific code -- read from the Load Ave driver.  */
    825 
    826   LOAD_AVE_TYPE load_ave[3];
    827   static int getloadavg_initialized = 0;
    828 #  ifdef eunice
    829   struct
    830   {
    831     int dsc$w_length;
    832     char *dsc$a_pointer;
    833   } descriptor;
    834 #  endif
    835 
    836   /* Ensure that there is a channel open to the load ave device.  */
    837   if (!getloadavg_initialized)
    838     {
    839       /* Attempt to open the channel.  */
    840 #  ifdef eunice
    841       descriptor.dsc$w_length = 18;
    842       descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE";
    843 #  else
    844       $DESCRIPTOR (descriptor, "LAV0:");
    845 #  endif
    846       if (sys$assign (&descriptor, &channel, 0, 0) & 1)
    847 	getloadavg_initialized = 1;
    848     }
    849 
    850   /* Read the load average vector.  */
    851   if (getloadavg_initialized
    852       && !(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0,
    853 		     load_ave, 12, 0, 0, 0, 0) & 1))
    854     {
    855       sys$dassgn (channel);
    856       getloadavg_initialized = 0;
    857     }
    858 
    859   if (!getloadavg_initialized)
    860     return -1;
    861 # endif /* VMS */
    862 
    863 # if !defined (LDAV_DONE) && defined(LOAD_AVE_TYPE) && !defined(VMS)
    864 
    865   /* UNIX-specific code -- read the average from /dev/kmem.  */
    866 
    867 #  define LDAV_PRIVILEGED		/* This code requires special installation.  */
    868 
    869   LOAD_AVE_TYPE load_ave[3];
    870 
    871   /* Get the address of LDAV_SYMBOL.  */
    872   if (offset == 0)
    873     {
    874 #  ifndef sgi
    875 #   ifndef NLIST_STRUCT
    876       strcpy (nl[0].n_name, LDAV_SYMBOL);
    877       strcpy (nl[1].n_name, "");
    878 #   else /* NLIST_STRUCT */
    879 #    ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME
    880       nl[0].n_un.n_name = LDAV_SYMBOL;
    881       nl[1].n_un.n_name = 0;
    882 #    else /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
    883       nl[0].n_name = LDAV_SYMBOL;
    884       nl[1].n_name = 0;
    885 #    endif /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
    886 #   endif /* NLIST_STRUCT */
    887 
    888 #   ifndef SUNOS_5
    889       if (
    890 #    if !(defined (_AIX) && !defined (ps2))
    891 	  nlist (KERNEL_FILE, nl)
    892 #    else  /* _AIX */
    893 	  knlist (nl, 1, sizeof (nl[0]))
    894 #    endif
    895 	  >= 0)
    896 	  /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i.  */
    897 	  {
    898 #    ifdef FIXUP_KERNEL_SYMBOL_ADDR
    899 	    FIXUP_KERNEL_SYMBOL_ADDR (nl);
    900 #    endif
    901 	    offset = nl[0].n_value;
    902 	  }
    903 #   endif /* !SUNOS_5 */
    904 #  else  /* sgi */
    905       int ldav_off;
    906 
    907       ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN);
    908       if (ldav_off != -1)
    909 	offset = (long) ldav_off & 0x7fffffff;
    910 #  endif /* sgi */
    911     }
    912 
    913   /* Make sure we have /dev/kmem open.  */
    914   if (!getloadavg_initialized)
    915     {
    916 #  ifndef SUNOS_5
    917       channel = open ("/dev/kmem", 0);
    918       if (channel >= 0)
    919 	{
    920 	  /* Set the channel to close on exec, so it does not
    921 	     litter any child's descriptor table.  */
    922 #   ifdef F_SETFD
    923 #    ifndef FD_CLOEXEC
    924 #     define FD_CLOEXEC 1
    925 #    endif
    926 	  (void) fcntl (channel, F_SETFD, FD_CLOEXEC);
    927 #   endif
    928 	  getloadavg_initialized = 1;
    929 	}
    930 #  else /* SUNOS_5 */
    931       /* We pass 0 for the kernel, corefile, and swapfile names
    932 	 to use the currently running kernel.  */
    933       kd = kvm_open (0, 0, 0, O_RDONLY, 0);
    934       if (kd != 0)
    935 	{
    936 	  /* nlist the currently running kernel.  */
    937 	  kvm_nlist (kd, nl);
    938 	  offset = nl[0].n_value;
    939 	  getloadavg_initialized = 1;
    940 	}
    941 #  endif /* SUNOS_5 */
    942     }
    943 
    944   /* If we can, get the load average values.  */
    945   if (offset && getloadavg_initialized)
    946     {
    947       /* Try to read the load.  */
    948 #  ifndef SUNOS_5
    949       if (lseek (channel, offset, 0) == -1L
    950 	  || read (channel, (char *) load_ave, sizeof (load_ave))
    951 	  != sizeof (load_ave))
    952 	{
    953 	  close (channel);
    954 	  getloadavg_initialized = 0;
    955 	}
    956 #  else  /* SUNOS_5 */
    957       if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave))
    958 	  != sizeof (load_ave))
    959         {
    960           kvm_close (kd);
    961           getloadavg_initialized = 0;
    962 	}
    963 #  endif /* SUNOS_5 */
    964     }
    965 
    966   if (offset == 0 || !getloadavg_initialized)
    967     return -1;
    968 # endif /* LOAD_AVE_TYPE and not VMS */
    969 
    970 # if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS.  */
    971   if (nelem > 0)
    972     loadavg[elem++] = LDAV_CVT (load_ave[0]);
    973   if (nelem > 1)
    974     loadavg[elem++] = LDAV_CVT (load_ave[1]);
    975   if (nelem > 2)
    976     loadavg[elem++] = LDAV_CVT (load_ave[2]);
    977 
    978 #  define LDAV_DONE
    979 # endif /* !LDAV_DONE && LOAD_AVE_TYPE */
    980 
    981 # ifdef LDAV_DONE
    982   return elem;
    983 # else
    984   /* Set errno to zero to indicate that there was no particular error;
    985      this function just can't work at all on this system.  */
    986   errno = 0;
    987   return -1;
    988 # endif
    989 }
    990 
    991 #endif /* ! HAVE_GETLOADAVG */
    992 
    993 #ifdef TEST
    995 #include "make.h"
    996 
    997 int
    998 main (int argc, char **argv)
    999 {
   1000   int naptime = 0;
   1001 
   1002   if (argc > 1)
   1003     naptime = atoi (argv[1]);
   1004 
   1005   while (1)
   1006     {
   1007       double avg[3];
   1008       int loads;
   1009 
   1010       errno = 0;		/* Don't be misled if it doesn't set errno.  */
   1011       loads = getloadavg (avg, 3);
   1012       if (loads == -1)
   1013 	{
   1014 	  perror ("Error getting load average");
   1015 	  exit (1);
   1016 	}
   1017       if (loads > 0)
   1018 	printf ("1-minute: %f  ", avg[0]);
   1019       if (loads > 1)
   1020 	printf ("5-minute: %f  ", avg[1]);
   1021       if (loads > 2)
   1022 	printf ("15-minute: %f  ", avg[2]);
   1023       if (loads > 0)
   1024 	putchar ('\n');
   1025 
   1026       if (naptime == 0)
   1027 	break;
   1028       sleep (naptime);
   1029     }
   1030 
   1031   exit (0);
   1032 }
   1033 #endif /* TEST */
   1034